GO1.11 Module全攻略

为了不再每次新建工程都要拷贝一大堆Github的库文件。特意学习了下1.11的最新库文件管理模块,Module。

之前的管理方式有Vendor,GoVendor,GoDep,Dep,Glide等等。因为官方说1.12还会迟滞Modue这个功能,所以之前的就不必学了,况且之前的这些Github项目的上传者看到Go出了官方工具后,纷纷表态不再更新自己的库管理项目,最多维护一段时间。

所以来Go Module。一劳永逸。

1.先说GOPATH环境变量。理解了GOPATH变量,就明白启用GOModule之前和之后的变化。

GOPATH用来解析import语句。列出了查找Go代码的位置。如果设置就是设置的值,如果没有设置则使用默认值,默认值使用go env GOPATH可查看值。GOPATH设置的目录下有固定结构:

src:目录包含源代码。src下面的路径确定导入路径或可执行文件名。

pkg:目录包含已安装的包对象。每个目标操作系统和体系结构对都有自己的子目录pkg(pkg / GOOS_GOARCH)。

bin目录保存已编译的命令。每个命令都以其源目录命名,但仅以最终元素命名,而不是整个路径。

也就是说,DIR / src / foo / quux中带有源的命令安装在DIR / bin / quux中,而不是DIR / bin / foo / quux中。剥离“foo /”前缀,以便您可以将DIR / bin添加到PATH以获取已安装的命令。如果设置了GOBIN环境变量,则命令将安装到它命名的目录而不是DIR / bin。GOBIN必须是绝对的道路。

在某些IDE中除了会引入环境变量的GOPATH所代表的值,还可以设置属于当前项目自己的多个GOPATH值。

Go搜索GOPATH中列出的每个目录以查找源代码,但新包始终下载到列表中的第一个目录中。

需要注意的是:在1.11版本中,GOPATH不再用于解析。但仍然用于存储下载的源代码(在GOPATH / pkg / mod中)和编译的命令(在GOPATH / bin中)。

2.先设置GO111MODULE,有三个值,on, off , auto, on 是强制所有Go项目都启用Module,off相反,auto则根据当前项目是否在GOPATH / src下,是则不开启,否在开启。

3.在这里Go module的使用分为几种情况,

a.1.10使用非Go Module的管理模式,现在要改造成符合GoModule管理的形式。

b.直接新建工程,使用GoModule模式。

其实这两种情况大同小异,唯一不同的是目录结构,旧的项目中肯定包含src目录,新的目录不必再必须新建src这个目录。

下面就以第一种方式a的情况为例。看看怎么使用go module.

A.第一种方式直接在之前旧目录的src下main.go所在的目录中 打开cmd,输入 go init module名,这里以X5为例, 就可以了会发现新生成了一个go.mod文件,里面第一行内容为 module x5.

PS:值得一提的是在已经使用现有依赖关系管理工具(如godep,glide或dep)的项目中,“go mod init”还将添加与现有配置匹配的require语句。

B.一旦go.mod文件存在,就不需要额外的步骤:像'go build','go test',甚至'go list'这样的命令会根据需要自动添加新的依赖项来满足导入。

这些命令一旦运行,(在包含让main函数运行的目录中运行),则开始在当前目录查找mod文件,或者当前目录的父目录,或父目录的父目录,来查找各个模块的根目录,最后根据代码中的引用确定在mod文件中加入哪些依赖项。

需要注意的是依赖模块中的任何replace和exclude语句都将被忽略。因此,replace和exclude语句允许主模块完全控制其自己的构建,而不受依赖项的完全控制。所以,主模块依赖的包里的库版本其实是不起作用的,最终起作用的是放在主模块的mod文件中的版本。

mod文件 通过 require,replace,exclude三个命令来使用精确的软件包。

提供构建包的模块集称为“构建列表”。构建列表最初仅包含主模块。然后,go命令以递归方式向列表添加列表中已有模块所需的确切模块版本,直到没有任何内容可添加到列表中。如果将特定模块的多个版本添加到列表中,则最后仅保留最新版本(根据语义版本排序)以用于构建。

'go list'命令提供有关主模块和构建列表的信息。例如:

go list -m#主模块的打印路径
go list -m -f = {{.dir}} #print主模块的根目录
go list -m all #print build list

4.go.mod文件是程序员和工具可读和可编辑的。go命令本身会自动更新go.mod文件,以维护标准格式和require语句的准确性。

任何之前不存在的import导入,go命令都会查找包含该导入的模块,并自动将该模块的最新版本添加到go.mod中。因此,在大多数情况下,只需在源代码中添加导入并运行“go build”,“go test”,甚至“go list”即可:作为分析包的一部分,go命令将发现并解析导入并更新go.mod文件。

任何Go命令都可以确定缺少哪些模块,并且必须添加。如果确定不再需要某个包,在通过各种编译参数编译全部模块之后(架构,操作系统,构建参数),想要删除这些包,使用go mod tidy,这个命令,它会添加任何缺少的模块并删除不必要的模块。

// indirect命令,是不是由主mod直接引用的包,而是由其他mod间接引用的包。由这个标记的时候,如果之后新增了直接引用的该mod,会删除上面的间接引用。

原文 Indirect requirements only arise when using modules that fail to state some of their own dependencies or when explicitly upgrading a module's dependencies ahead of its own stated requirements. 不太明白。

因为这种自动维护,go.mod中总是最新的。

'go get'命令更新go.mod以更改构建中使用的模块版本。升级一个模块可能意味着升级其他模块,同样一个模块的降级可能意味着降级其他模块。'go get'命令也会产生这些隐含的变化。如果直接编辑go.mod,“go build”或“go list”等命令将假定默认是要升级的,并自动进行任何隐含的升级并更新go.mod以反映它们。

'go mod'命令提供了用于维护和理解模块和go.mod文件的其他功能。

go build -mod 标志提供了对go.mod更新和使用的额外控制。

-mod=readonly 不允许自动更新。但当对go.mod需要有任何修改时,会失败。

即使使用-mod = readonly,“go get”命令仍然允许更新go.mod,

并且“go mod”命令不接受-mod标志(或任何其他构建标志)。

如果使用-mod = vendor调用,则go命令假定供应商目录包含正确的依赖项副本,并忽略go.mod中的依赖项描述。

就是不再在GOPATH中查找了,而在执行go命令的目录中的vendor目录中查找。

5.mod中的文件版本。

go.mod文件和go命令通常使用语义版本作为描述模块版本的标准形式,因此可以比较版本以确定哪个版本应该比其他版本更早或更晚。通过在底层源存储库中标记修订版来引入类似v1.2.3的模块版本。可以使用像v0.0.0-yyyymmddhhmmss-abcdefabcdef这样的“伪版本”来引用未标记的修订,其中时间是UTC的提交时间,最后的后缀是提交哈希的前缀。时间部分确保可以比较两个伪版本以确定稍后发生的版本,提交哈希标识基础提交,并且前缀(在此示例中为v0.0.0-)是从提交图中的最新标记版本派生的在此提交之前。

有三种伪版本形式:

当目标提交之前没有具有适当主要版本的早期版本化提交时,将使用vX.0.0-yyyymmddhhmmss-abcdefabcdef。(这最初是唯一的形式,所以一些较旧的go.mod文件使用这种形式,即使对于跟随标签的提交也是如此。)

当目标提交之前的最新版本化提交是vX.YZ-pre时,使用vX.YZ-pre.0.yyyymmddhhmmss-abcdefabcdef。

当目标提交之前的最新版本化提交是vX.YZ时,使用vX.Y.(Z + 1)-0.yyyymmddhhmmss-abcdefabcdef。

伪版本永远不需要手动输入:go命令将接受普通提交哈希并自动将其转换为伪版本(或标记版本,如果可用)。此转换是模块查询的示例。

这种版本是和已标记的版本相对的,已标记的版本很明确的指出,v1.2.3但未标明的就要用上面这种形式的版本。

 

6.模块验证和下载

go命令和go.mod一起维护一个名为go.sum的文件。

其中包含特定模块版本内容的预期加密校验和。每次使用依赖项时,如果缺少,则将其校验和添加到go.sum,或者需要匹配go.sum中的现有条目。

go命令维护下载包的缓存,并在下载时计算并记录每个包的加密校验和。在正常操作中,go命令会针对主模块的go.sum文件检查这些预先计算的校验和,而不是在每次命令调用时重新计算它们。'go mod verify'命令检查模块下载的缓存副本是否仍然匹配记录的校验和和go.sum中的条目。

根据GOPROXY环境变量的设置,go命令可以从代理获取模块,而不是直接连接到源控制系统。

关于GOPROXY,go 命令默认从版本控制系统中下载modules,就像go get一样。GOPROXY允许对数据源的更深的控制。

如果GOPROXY 没设置值,或设为空字符串,或者 “direct”,downloads还是会直接从版本控制系统中下载。

GOPROXY身为off,则停止从任何地方下载。

否则GOPROXY则被期望作为module代理的URL,这样go命令将会从从这个代理获取全部的modules。不管数据源地址如何,但下载的modules必须符合go.sum中已经出现的记录。

一个Go module代理是一个具有特定形式的URL,且可响应GET请求的Web服务器。请求没有任何参数,所以即使是一个文件系统的网络服务(file://URL)也可以做module代理。


GET $GOPROXY/<module>/@v/list returns a list of all known versions of the
given module, one per line.

GET $GOPROXY/<module>/@v/<version>.info returns JSON-formatted metadata
about that version of the given module.

GET $GOPROXY/<module>/@v/<version>.mod returns the go.mod file
for that version of the given module.

GET $GOPROXY/<module>/@v/<version>.zip returns the zip archive
for that version of the given module.

为了避免在大小写敏感的文件系统中出现问题,<module>和<version>元素被大小写编码,使用!+对应的小写字母替换 每一个大写字母。如:github.com/Azure ->github.com/!azure

未来对于某个模块的数据结构,可能会被扩展为JSON形式的元数据,

type Info struct {

Version string // version string

Time time.Time // commit time

}

 

某个模块的某个版本的压缩文件,是一个标准的zip文件,包括文件树响应返回的module的源代码和关联文件。压缩文件使用严格分开的路径,并且压缩文件中的每个文件的路径都以 <module>@<version>/开头,module和version被直接替换,且没有大小写转化。Module的根目录文件系统响应在压缩文件中的<module>@<version>/前缀。

每次从版本控制系统中直接下载,go 命令综合了具体的info,mod和zip文件。并且把他们保存在本地cache$GOPATH/pkg/mod/cache/download中,就像是直接从代理中下载下来一样。

缓存的布局和代理的URL空间一模一样,如果使用$GOPATH/pkg/mod/cache/download作为目录,使用https://example.com/proxy 可以让其他用户访问那些已经缓存的modules通过设置GOPROXY=“https://example.com/proxy.”

7.Module和Vendor

当使用go module时,还记得之前的GO111MODULE环境变量吗?

go命令完全忽略vendor目录。

默认情况下,go命令通过从其源下载模块并使用下载的副本来满足依赖性(在验证之后,如上一节中所述)。为了允许与旧版本的Go进行互操作,或者为了确保用于构建的所有文件一起存储在单个文件树中,“go mod vendor”在主模块的根目录中创建一个名为vendor的目录并存储在那里来自依赖模块的包,这些包是支持主模块中包的构建和测试所需的。

要使用主模块的顶级供应商目录来构建以满足依赖性(禁止使用常用网络源和本地缓存),请使用“go build -mod = vendor”。请注意,仅使用主模块的顶级供应商目录; 其他位置的供应商目录仍被忽略。

8.模块感知go get

'go get'命令根据go命令是在模块感知模式还是传统GOPATH模式下运行来改变行为。即使在传统GOPATH模式下,此帮助文本也可以作为“go help module-get”访问,它描述了“go get”,因为它在模块感知模式下运行。

用法:go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

获取解析并将依赖项添加到当前开发模块,然后构建并安装它们。

第一步是解决要添加的依赖项。

对于每个命名的包或包模式,get必须决定使用哪个版本的相应模块。默认情况下,get选择最新的标记发行版本,例如v0.4.5或v1.2.3。如果没有标记的发行版本,请选择最新的标记预发布版本,例如v0.0.1-pre1。如果根本没有标记版本,请选择最新的已知提交。

可以通过在package参数中添加@version后缀来覆盖此默认版本选择,如“go get golang.org/x/text@v0.3.0”。对于存储在源控制存储库中的模块,版本后缀也可以是提交哈希,分支标识符或源控制系统已知的其他语法,如'go get golang.org/x/text@master'。版本后缀@latest显式请求上述默认行为。

如果正在考虑的模块已经是当前开发模块的依赖项,则get将更新所需的版本。指定早于当前所需版本的版本是有效的,并降低依赖性。版本后缀@none表示应完全删除依赖项。

虽然默认使用包含命名包的模块的最新版本,但它不使用该模块的最新版本的依赖项。相反,它更喜欢使用该模块请求的特定依赖版本。例如,如果最新的A需要模块B v1.2.3,而B v1.2.4和v1.3.1也可用,那么'go get A'将使用最新的A但是然后使用B v1.2.3,按照A的要求。(如果对特定模块有竞争要求,那么'go get'通过获取最大请求版本来解决这些要求。)

-u标志指示get更新依赖关系以在可用时使用较新的次要或补丁版本。继续前面的例子,'go get -u A'将使用最新的A与B v1.3.1(不是B v1.2.3)。

-u = patch标志(不是-u patch)指示获取更新依赖关系以在可用时使用更新的补丁版本。继续前面的例子,'go get -u = patch A'将使用最新的A和B v1.2.4(不是B v1.2.3)。

通常,添加新的依赖项可能需要升级现有的依赖项以保持工作的构建,并且“go get”会自动执行此操作。同样,降级一个依赖关系可能需要降低其他依赖关系,“go get”也会自动执行此操作。

在解析,升级和降级模块以及更新go.mod之后,-m标志指示get停在这里。使用-m时,每个指定的包路径也必须是模块路径,而不是模块根目录下的包的导入路径。

-insecure标志允许从存储库中获取并使用不安全的方案(如HTTP)解析自定义域。谨慎使用。

第二步是下载(如果需要),构建和安装命名包。

如果参数命名模块但不命名包(因为模块的根目录中没有Go源代码),则跳过该参数的安装步骤,而不是导致构建失败。例如,即使没有与该导入路径对应的代码,'go get golang.org/x/perf'也会成功。

请注意,允许使用包模式,并在解析模块版本后进行扩展。例如,'go get golang.org/x/perf/cmd / ...'添加最新的golang.org/x/perf,然后在最新版本中安装命令。

-d标志指示get下载构建命名包所需的源代码,包括下载必要的依赖项,但不构建和安装它们。

如果没有包参数,则“go get”将应用于主模块,并应用于当前目录中的Go包(如果有)。特别是,'go get -u'和'go get -u = patch'更新主模块的所有依赖项。没有包参数也没有-u,'go get'不仅仅是'go install','go get -d'不仅仅是'go list'。

有关模块的更多信息,请参阅“go help modules”。

有关指定包的更多信息,请参阅“go help packages”。

本文描述了使用模块管理源代码和依赖项的行为。如果go命令在GOPATH模式下运行,则get的标志和效果的细节会发生变化,就像'go help get'一样。请参阅'go help modules'和'go help gopath-get'。

另见:go build,go install,go clean,go mod。

 

PS:有些go库文件下载失败,ru golang.org/x/image

这是后可以通过设置代理proxier和 shadowsocket来访问,如果设置好之后,cmd不起作用。

在cmd运行以下代码。

netsh winhttp import proxy source=ie

上面的是自己写的,翻译的Golang 1.11版本的的发布日志。

 

更新库:

 

go get github.com/jtianling/goModule@latest 的形式更新到最新版
go get -u 的形式升级所有的依赖库

 

下面为转载。

====================================================================================

为CMD设置代理

公司网络出口有代理服务器。通常Windows界面使用Proxifier同一处理代理。但是cmd命令行模式运行pip显示超时,Proxifier监控网络端口没有代理阻断。

临时代理方案

打开cmd设置代理:

set http_proxy=http://0.0.0.0:8000
set https_proxy=http://0.0.0.0:8000

设置完成后问题解决
***0.0.0.0改成自己的代理服务器和端口

永久设置方案

先设置好IE代理。
cmd执行如下命令:

netsh winhttp import proxy source=ie

Atom代理

Atom是个不错的ide工具,如果给atom设置代理,也要用cmd设置代理的方式



posted on 2018-12-12 10:54  &大飞  阅读(2483)  评论(0编辑  收藏  举报

导航