go get和go build
Go 1.16中包含了大量的 Modules 相关的更新,详细内容可直接查看其 Release Note。完整版本特性:https://tip.golang.org/doc/devel/release
Go 1.16中 go install 和 go get 方面有些不兼容的变更。1.16 中模块更加简洁,减少了使用时的心智负担。
包含以下要点:
- GO111MODULE 默认为 on ,如果要恢复到之前的行为,则需要将 GO111MODULE 设置为 auto ,这差不多意味着 GOPATH 模式要逐步淡出人们的视野了;
- go install 命令可以接受一个版本后缀(例如,go install sigs.k8s.io/kind@v0.9.0),并且它是在模块感知的模式下运行,可忽略当前目录或上层目录的go.mod 文件。这对于在不影响主模块依赖的情况下,安装二进制很方便;
- 在将来,go install 被设计为“用于构建和安装二进制文件”, go get则被设计为 “用于编辑 go.mod 变更依赖”,并且使用时,应该与 -d 参数共用,在将来版本中 -d 可能会默认启用;
- go build 和 go test 默认情况下不再修改 go.mod 和 go.sum。可通过 go mod tidy ,go get或者手动完成;
总结而言,关于go install 和 go get 必须要注意的是:
- 基本上go install <package>@<version> 用于命令的全局安装,例如:go install sigs.k8s.io/kind@v0.9.0;
- go get 安装二进制的功能后续版本将会删除;
- go get 主要被设计为修改 go.mod 追加依赖之类的,但还存在类似 go mod tidy 之类的命令,所以使用频率可能不会很高;
Go 1.16 中已解决的工具安装问题
到目前为止,Go 一直使用 go get 命令,将需要的工具安装到 $GOPATH/bin 目录下,但这种方式存在一个很严重的问题。go get 由于具备更改 go.mod 文件的能力,因此要避免执行 go get 命令时,让它接触到go.mod 文件 ,否则它会将安装的(可执行)工具作为一个依赖。
目前的解决方案通常是:
cd $(mktemp -d); GO111MODULE=on go get sigs.k8s.io/kind@v0.9.0
自1.16 开始,可以直接使用下面的方式:
go install sigs.k8s.io/kind@v0.9.0
简单直观。
go install <package>@<version> 是从 1.16 开始增加的,无论当前是否在一个模块下,此命令都会在 $GOPATH/bin 下安装指定版本的工具。
Go 1.16 中GO111MODULE 默认是打开的,go install不会修改 go.mod 之类的文件,不会造成任何意外。
注意:
@version 只能安装主软件包。非主程序包不受此格式约束。
不带@version的go install
在模块外,不带@version 是无法安装的,会有如下错误:
go install -v sigs.k8s.io/kind # 错误信息 go install: version is required when current directory is not in a module Try 'go install sigs.k8s.io/kind@latest' to install the latest version
如果在模块目录中不带 @version 执行安装,只能安装 go.mod 中已经包含的版本。
(MoeLove) ➜ mkdir -p /go/src/github.com/moelove/iris (MoeLove) ➜ cd /go/src/github.com/moelove/iris # 初始化模块 (MoeLove) ➜ /go/src/github.com/moelove/iris go mod init go: creating new go.mod: module github.com/moelove/iris (MoeLove) ➜ /go/src/github.com/moelove/iris cat go.mod module github.com/moelove/iris go 1.16 # 不带 @version 无法安装 (MoeLove) ➜ /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind no required module provides package sigs.k8s.io/kind; try 'go get -d sigs.k8s.io/kind' to add it # 用 go get -d 下载 (MoeLove) ➜ /go/src/github.com/moelove/iris go get -d sigs.k8s.io/kind go get: added sigs.k8s.io/kind v0.9.0 # 可以看到已经被添加到了模块依赖中 (MoeLove) ➜ /go/src/github.com/moelove/iris cat go.mod module github.com/moelove/iris go 1.16 require sigs.k8s.io/kind v0.9.0 // indirect # 删除本地的 kind 工具 (MoeLove) ➜ /go/src/github.com/moelove/iris which kind /go/bin/kind (MoeLove) ➜ /go/src/github.com/moelove/iris rm /go/bin/kind (MoeLove) ➜ /go/src/github.com/moelove/iris which kind # 不带 @version 进行安装 (MoeLove) ➜ /go/src/github.com/moelove/iris go install -v sigs.k8s.io/kind (MoeLove) ➜ /go/src/github.com/moelove/iris which kind /go/bin/kind (MoeLove) ➜ /go/src/github.com/moelove/iris kind version kind v0.9.0 go1.16beta1 linux/amd64
go get和go.mod
go get 将二进制安装相关的功能都转移到了go install,仅作为用于编辑 go.mod 文件的命令存在。在后续版本(Go 1.18)中删掉 go get 安装二进制的功能,接下来 go get 的行为就等同于现在执行 go get -d 命令了,仅需下载源码,并将依赖添加至 go.mod 即可。
go.mod如何编辑
Go 1.16 中,另一个行为变更是 go build 和 go test 不会自动编辑 go.mod 了。
Go 1.16 中将进行如下处理:
通过在代码中修改 import 语句,来修改 go.mod:
- go get 可用于添加新模块;
- go mod tidy 删除掉无用的模块;
将未导入的模块写入 go.mod:
- go get <package>[@<version>];
- go mod tidy 也可以;
- 手动编辑;
Go 1.18正式移除go get的安装功能。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2023/09/06/go-get-and-go-build/