在使用 go
工具一段时间后,它看起来像 go get
:
(可选)下载、编译和安装
一个软件,而 go install
只是
编译并安装
它。在这种情况下,为什么 go install
命令存在,因为 go get
取代了它?
go get
来构建和安装软件包。在未来的版本中,-d 标志将始终启用。” 因此,go get
现在仅供下载.
go install
是本地工作时工作流程的一部分。假设您想使用一个库,但由于某种原因需要进行更改。你会这样做:
go get -d library,它只下载它;
对下载的包进行更改;
go install library 安装本地版本。
据我所知,go get
没有任何标志表明它应该不下载,因此它不能在这里替换 go install
。
当您从头开始开发新包时,使用相同的工作流程。
编辑:六年后,Go 1.16 更新并阐明了 go install
和 go get
的用法:https://tip.golang.org/doc/go1.16#modules
go install,带或不带版本后缀(如上所述),现在是在模块模式下构建和安装包的推荐方式。 go get 应该与 -d 标志一起使用来调整当前模块的依赖关系而不构建包,并且不推荐使用 go get 来构建和安装包。在未来的版本中,-d 标志将始终启用。
go get
按此顺序执行两项主要操作:
下载并保存在 $GOPATH/src/
执行 go install
-d
标志 (go get -d
) 指示 go get
在下载软件包后停止;也就是说,它指示 go get
不要做 go install
区别:
go get
// 验证是否需要下载包,如果需要就下载然后编译
go install
// 跳过下载包的部分,只编译(如果缺少任何包,这将引发错误)
关于 GOPATH
个环境变量
Go 工具使用 GOPATH
环境变量。必须设置它才能进行 get
、build
和 install
包,它指定工作区的位置。它可能是您在开发 Go 代码时需要设置的唯一环境变量。
同样,GOPATH
不应指向 Go 安装,而应指向您的工作区。
例如,在 Windows 上,如果您决定工作区位于 c:\gowork\
,则需要将 GOPATH
值设置为 c:\gowork
https://i.stack.imgur.com/iOQEJ.png
您的源代码应位于 c:\gowork\src\<some project folder>\
,在 c:\gowork\src\<some project folder>\
内的命令提示符下运行 go get
后,您将看到正在创建的 c:\gowork\bin\
和 c:\gowork\pkg\
。
go install
在模块感知设置中下载包。
请注意,使用 CL 266360 作为 issue 40276 的一部分实现的 go 1.16 (Q1 2021) 将使这种区别更加清晰:
go install 现在接受带有版本后缀的参数(例如,go install example.com/cmd@v1.0.0)。这会导致 go install 以模块感知模式构建和安装包,忽略当前目录或任何父目录中的 go.mod 文件(如果有的话)。这对于在不影响主模块依赖关系的情况下安装可执行文件很有用。 go install,带或不带版本后缀(如上所述),现在是在模块模式下构建和安装包的推荐方式。 go get 应该与 -d 标志一起使用来调整当前模块的依赖关系而不构建包,并且不推荐使用 go get 来构建和安装包。在未来的版本中,-d 标志将始终启用。
2022 年 6 月(1.19 之前的 Go 1.18),Chris Siebenmann 详细说明了“a limitation on what 'go install
' can install”。
它涉及一个带有 replace
directive 的模块:
如果你克隆存储库并在其中运行“go install”,一切正常,你会在 $HOME/go/bin 中得到一个 gospy 二进制文件。但是,正如我们在此处看到的那样,'go install ...@latest' 的工作方式不同,替换指令会导致此错误。
这会触发错误消息:
go: github.com/monsterxx03/gospy@latest (in github.com/monsterxx03/gospy@v0.5.0):
The go.mod file for the module providing named packages contains one or
more replace directives. It must not contain directives that would cause
it to be interpreted differently than if it were the main module.
help for 'go install' 明确说明了这种模式:
没有模块被视为“主”模块。如果包含在命令行中命名的包的模块有一个 go.mod 文件,则它不能包含会导致其解释与主模块不同的指令(替换和排除)。该模块不得要求其自身的更高版本。
看:
问题 44840:cmd/go:当带有主包的模块具有替换指令时,安装 cmd@version 错误
问题 40276:cmd/go:go install 应该在模块外以模块模式安装可执行文件
问题 45099:x/tools/gopls:无法安装 gopls v0.6.8(说明问题)
推荐:
切换到使用 Go 工作区进行本地开发并完全删除 go.mod 替换指令。
如 Beth Brown 在“Get familiar with workspaces”中所述:
以前,要将功能添加到一个模块并在另一个模块中使用它,您需要将更改发布到第一个模块,或者使用替换指令编辑依赖模块的 go.mod 文件以用于本地未发布的模块更改.为了发布没有错误,您必须在发布对第一个模块的本地更改后,从依赖模块的 go.mod 文件中删除 replace 指令。使用 Go 工作区,您可以使用工作区目录根目录中的 go.work 文件来控制所有依赖项。 go.work 文件具有覆盖各个 go.mod 文件的 use 和 replace 指令,因此无需单独编辑每个 go.mod 文件。
go install
。它会这样做,以特定版本安装软件包,而不管当前模块上下文如何。与旧的 go get
相比,这是一个改进。
go get ./path/to/local_package
,它的行为与我使用go install ./path/to/local_package
的行为相同,对吧?由于在这种情况下没有下载过程。go install
使您的目标更加明确,但我想两者都会实现相同的目标。我测试了几个包,包括声明为main
的包,它们看起来是等价的。该命令非常缺乏文档。go get
而不是go install
的 gcc。这与这个描述有什么关系?go get
而不是go install
,因为go get
不会重新下载库(除非您添加-u
)。从头开始编写库时,您也可以使用go get
。go install
似乎完全多余。