分享
  1. 首页
  2. 文章

也许 Go 开发可以更简单!Go += Package Versioning

缪斯的情人 · · 2516 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

简评:对于Go来说一直以来依赖包的版本控制上没有一个好的方案,尽管社区诞生了不下十余个解决该问题的工具,但一直以来没有一个官方的支持。这个提案有望在Go
的下个版本中看到官方的包版本控制了,去除了GOPATH依赖,同时还引入了module 的概念,真正意义上实现了重编译,可谓一次大的变更

编译:缪斯的情人

是时候为 Go 添加包版本控制了!

更确切地说,我们需要把包版本的概念普及到Go 开发者和工具常用词汇中,以便在后续的相互沟通时能准确一致的表达哪些程序代码需要编译、运行和解析。同样,go 命令也需要准确的告诉开发者在编译中使用了哪个包的哪个版本。

版本控制可以让我们能够实现重编译。当我让你试用我程序最新版本时,我清楚的知道你不仅仅获取到的是我最新程序的代码,还包括我代码所依赖的相同版本的包,这样才能编译出完全一样的二进制包。

版本控制还能让我们不同阶段保持同样的编译方式,即使我们的依赖包可能有新版本了,只要我们的配置未允许使用,go 命令也不会使用新版本的包。

尽管添加版本控制是必须的功能,但同时我们也不能失去go 命令行现有的优秀特性:简单、高效、易懂。目前来看,很多程序员还是不太重视版本控制,主要是大部分情况下也都没出现什么问题。试想如果我们有一个合理模式的设计和默认配置,让开发者不需要太多关注版本控制的东西,程序仍然能很好的工作,并且对现有工程影响较小,发布新版本足够简单,甚至日常开发中可以忽略掉版本控制的工作,这样的版本控制模式才是我们想要的。

简而言之,版本控制是必须的,但是应该足够透明不能破坏掉go get 本身功能。这篇文章探讨了一个能完全实现这些的提案,并且提供了一个现在可用的原型demo,希望这能为集成到go命令奠定基础。我打算通过这篇文章讨论下在产品化过程中哪些是需要做的,哪些是不需要做的,基于这个讨论,我将对提案和原型做进一步调整,并且提交一个官方提案,作为可选功能集成到Go 1.11版本中。

这个提案保留了go get的精华部分,增加了重复构建,采用了语义化的版本控制,弃用了vendor,废弃了基础工程创建时依赖GOPATH,并且提供了老项目平滑迁移的方式,目前这个提案还处于初级阶段,如果细节上有问题,我们会在Go主版本发布前修复掉

背景

在我们讨论这个提案之前,先了解下当下的现状。讲起来可能会很长,但历史的教训对现在有很重要的参考意义,并且让我们能够清楚的知道这个提案改变了什么。如果你觉得没意思,那么可以直接跳到demo

Makefiles, goinstall, 和 go get

2009年11月,Go 发布了带有编译器、链接器和一些内置库的初代版本,在当时你必须通过运行6g6l 来编译和链接你的程序,还包含一些简单的makefiles。大多数情况下,通过简单包装的gobuild可以编译一个单包程序并且生成对应的makefile。在当时,也没有一个合适的方式把代码分享给其他人。尽管还有很多功能没提供,但是仍然发布了,并且Go 计划将一些剩余的功能放到社区去做。

2010年2月,我们介绍了go命令中使用 go get 来替换goinstall

总的来说,go get 是变革性的,它让 Go 开发者能够共享代码和相互构建,并且通过工具隔离了 go 命令编译系统中的细节,但是,go get 缺少版本控制的概念,实际上在goinstall第一次讨论中就清楚的意识到需要版本控制相关的功能。不幸的是,至少在当时我们的 Go 团队中还不清楚应该怎么去做。当go get需要一个包时,总是从像 Git 或者 Mercurial 这样的远程版本控制系统中下载最新的副本,包版本管理上的缺失至少导致了两个重大的缺陷。

Versioning 和 API 的稳定性

首先在没有版本控制时go get 的一个重大缺陷是对于给定的更新无法知道是否是用户所期望的。

在2013年11月,Go 1.2 添加了一个发关于包版本控制基本建议的FAQ:

公共发布的包应该保持向后兼容性。gopkg.in,倡导"Go语言稳定性API"。这个网站其实是个感知 GitHub 版本变化的重定向器,你可以通过gopkg.in/yaml.v1gopkg.in/yaml.v2 的这样的导入方式来指向Git库的不同提交版本(也可能在不同分支)。按照这个思路,依赖库的功能有了重大改变后你可以把之前的 v1 版本导入路径作为备用,然后创建一个新版本 v2,通过v2 导入路径引入完全不同的API。

2015年8月,Dave Cheney 提出了Glide in the Sea of Go Package Managers" 比较了godep和很多后来出现的工具,其中最为突出的是glide

2015年4月,Dave Cheney 介绍了dep,相关背景信息请查看Sam 在2016年2月发布的文章"The Saga of Go Dependency Management" 以及2017年7月GopherCon 的分享"examples)。

Goinstall 和旧的 go get 通过像git 和hg 这样的版本控制工具直接下载代码,这种方式存在很多问题,其中包括碎片化严重:用户如果没有bzr 就没法下载托管在Bazaar 资源库的代码。相比之下,模块则是通过HTTP 下载zip 包的方式。之前,遇到特殊需求的包 go get 通过版本控制的命令行工具去主流的代码托管网站下载,现在vgo 直接通过网站提供的 API 下载需要的包。

模块统一通过zip包的形式提供可以让下载协议更简单,公司或者个人可以处于任何原因考虑(安全或者想要缓存副本防止源被删除)自己做下载代理,使用代理来确保可用性并且通过go.mod定义了哪些代码需要用到,vendor 目录也就不再需要了。

go 命令

go 命令必须更新才能使用模块功能。一个重要的变化就是常用的构建命令,像 gobuild, go install, go run, 和 go test 将需要按指定需求解析对应的依赖关系了,在新模块中使用golang.org/x/text 时只需在Go 源码中导入编译就可以了,无需单独关注版本问题。

但是,最重要的变化还是终结了GOPATH作为Go 代码工作空间的设置,由于go.mod文件包含了完整的模块路径并且还定义了每个使用的依赖的版本,因此包含go.mod文件的目录就可以被认为是一个目录树的根目录了,该目录树作用于自身的工作空间,并且和其他类似的目录彼此隔离。现在你只需git clone然后cd就可以直接撸代码了,不再需要GOPATH

下一步计划?

我还发布了一篇文章"vgo吧,开始在你的版本库中通过tag标记版本吧,创建并检入go.mod文件。注意如果你的资源库有一个空的go.mod但是存在dep, glide, glock, godep, godeps, govend,govendor 或者 gvt配置文件的话,vgo将会使用它们填充go.mod文件。

原文:https://research.swtch.com/vg...

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:缪斯的情人

查看原文:也许 Go 开发可以更简单!Go += Package Versioning

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2516 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏