ChatGPT解决这个技术问题 Extra ChatGPT

go get 和 go install 有什么区别?

go

在使用 go 工具一段时间后,它看起来像 go get

(可选)下载、编译和安装

一个软件,而 go install 只是

编译并安装

它。在这种情况下,为什么 go install 命令存在,因为 go get 取代了它?

对于未来的人:“不推荐使用 go get 来构建和安装软件包。在未来的版本中,-d 标志将始终启用。” 因此,go get 现在仅供下载.

b
blackgreen

go install 是本地工作时工作流程的一部分。假设您想使用一个库,但由于某种原因需要进行更改。你会这样做:

go get -d library,它只下载它;

对下载的包进行更改;

go install library 安装本地版本。

据我所知,go get 没有任何标志表明它应该下载,因此它不能在这里替换 go install

当您从头开始开发新包时,使用相同的工作流程。

编辑:六年后,Go 1.16 更新并阐明了 go installgo get 的用法:https://tip.golang.org/doc/go1.16#modules

go install,带或不带版本后缀(如上所述),现在是在模块模式下构建和安装包的推荐方式。 go get 应该与 -d 标志一起使用来调整当前模块的依赖关系而不构建包,并且不推荐使用 go get 来构建和安装包。在未来的版本中,-d 标志将始终启用。


很好,我想我现在明白了,感谢你的第一个例子。但是,在您的第二个(从头开始开发新包)中,我也可以使用 go get ./path/to/local_package,它的行为与我使用 go install ./path/to/local_package 的行为相同,对吧?由于在这种情况下没有下载过程。
go install 使您的目标更加明确,但我想两者都会实现相同的目标。我测试了几个包,包括声明为 main 的包,它们看起来是等价的。该命令非常缺乏文档。
Here 它说,您需要为 go get 而不是 go install 的 gcc。这与这个描述有什么关系?
我不同意这个答案。您也可以在第三个要点中使用 go get 而不是 go install,因为 go get 不会重新下载库(除非您添加 -u)。从头开始编写库时,您也可以使用 go getgo install 似乎完全多余。
A
Alex Baban

go get 按此顺序执行两项主要操作:

下载并保存在 $GOPATH/src/ 在导入路径中命名的包(源代码)及其依赖项,然后

执行 go install

-d 标志 (go get -d) 指示 go get 在下载软件包后停止;也就是说,它指示 go get 不要做 go install

区别:

go get // 验证是否需要下载包,如果需要就下载然后编译

go install // 跳过下载包的部分,只编译(如果缺少任何包,这将引发错误)

关于 GOPATH 个环境变量

Go 工具使用 GOPATH 环境变量。必须设置它才能进行 getbuildinstall 包,它指定工作区的位置。它可能是您在开发 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 在模块感知设置中下载包。
V
VonC

请注意,使用 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 文件。


也许我只是不知道这背后的原因......但我不明白你为什么要禁用单个构建/安装命令。这与我见过的任何其他包管理器都不同
@TrevorJex 重新阅读 github.com/golang/go/issues/40276,仍然有一个构建/安装命令:go install。它会这样做,以特定版本安装软件包,而不管当前模块上下文如何。与旧的 go get 相比,这是一个改进。