ChatGPT解决这个技术问题 Extra ChatGPT

What is the difference between go get and go install?

go

After playing with the go tool for a while, it looks like go get:

(optionally) downloads, compiles, and installs

a piece of software, while go install simply

compiles and installs

it. In this case, why does the go install command exist, since go get supersedes it?

for future people: "use of go get to build and install packages is deprecated. In a future release, the -d flag will always be enabled." So, go get is only for download now.

b
blackgreen

go install is part of the workflow when working locally. Say you want to use a library, but for some reason a change is required. You would do:

go get -d library, which only downloads it;

make the change on the downloaded package;

go install library to install the local version.

As far as I know go get has no flags to indicate it should not download, so it can't replace go install here.

The same workflow is used when you develop a new package from scratch.

EDIT: six years later, Go 1.16 has updated and clarified the usage of go install and go get: https://tip.golang.org/doc/go1.16#modules

go install, with or without a version suffix (as described above), is now the recommended way to build and install packages in module mode. go get should be used with the -d flag to adjust the current module's dependencies without building packages, and use of go get to build and install packages is deprecated. In a future release, the -d flag will always be enabled.


Nice, I think I understand now thanks to your first example. However, in your second one (developing a new package from scratch) I could use go get ./path/to/local_package too, and it would behave the same as if I used go install ./path/to/local_package, right? Since there is no download process in this case.
go install makes your goal more explicit, but I suppose both would achieve the same thing. I tested with a few packages, including ones declared as main and they seemed equivalent. The docs are very lacking on this command.
Here it says, you need gcc for go get but not for go install. How does that relate to this description?
I disagree with this answer. You can use go get instead of go install in your third bullet point too, since go get will not re-download the library (unless you add -u). You can also use go get when writing a library from scratch. go install seems completely redundant.
A
Alex Baban

go get does two main things in this order:

downloads and saves in $GOPATH/src/ the packages (source code) named in the import paths, along with their dependencies, then

executes a go install

The -d flag (go get -d) instructs go get to stop after downloading the packages; that is, it instructs go get not to do go install

the difference:

go get // verify if packages need to be downloaded, download if needed then compile

go install // skip the part with packages download, just compile (this will throw an error if any packages are missing)

about GOPATH environment variable

The GOPATH environment variable is used by the Go tools. It must be set in order to be able to get, build and install packages, and it specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code.

Again, the GOPATH should not point to the Go installation, but rather to your workspace.

For example, on Windows, if you decide that your workspace is at c:\gowork\, you will need to set GOPATH value as c:\gowork

https://i.stack.imgur.com/iOQEJ.png

Your source code should be at c:\gowork\src\<some project folder>\ and after you run go get at command prompt from within c:\gowork\src\<some project folder>\ you will see the c:\gowork\bin\ and c:\gowork\pkg\ being created.


go install does download the package in module-aware set-up.
V
VonC

Note that go 1.16 (Q1 2021) will make that difference clearer, implemented with CL 266360 as part of issue 40276:

go install now accepts arguments with version suffixes (for example, go install example.com/cmd@v1.0.0). This causes go install to build and install packages in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for installing executables without affecting the dependencies of the main module. go install, with or without a version suffix (as described above), is now the recommended way to build and install packages in module mode. go get should be used with the -d flag to adjust the current module's dependencies without building packages, and use of go get to build and install packages is deprecated. In a future release, the -d flag will always be enabled.

In June 2022 (Go 1.18 right before 1.19), Chris Siebenmann details "a limitation on what 'go install' can install".

It involves a module with a replace directive:

If you clone the repository and run 'go install' inside it, everything works and you wind up with a gospy binary in your $HOME/go/bin. However, as we see here 'go install ...@latest' works differently enough that the replace directive causes this error.

That triggers the error message:

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.

The help for 'go install' explicitly says about this mode:

No module is considered the "main" module. If the module containing packages named on the command line has a go.mod file, it must not contain directives (replace and exclude) that would cause it to be interpreted differently than if it were the main module. The module must not require a higher version of itself.

See:

issue 44840: cmd/go: go install cmd@version errors out when module with main package has replace directive

issue 40276: cmd/go: go install should install executables in module mode outside a module

issue 45099: x/tools/gopls: cannot install gopls v0.6.8 (illustrates the issue)

Recommendation:

switch to using Go workspaces for local development and drop the go.mod replace directives entirely.

As mentioned in "Get familiar with workspaces" by Beth Brown:

Previously, to add a feature to one module and use it in another module, you needed to either publish the changes to the first module, or edit the go.mod file of the dependent module with a replace directive for your local, unpublished module changes. In order to publish without errors, you had to remove the replace directive from the dependent module’s go.mod file after you published the local changes to the first module. With Go workspaces, you control all your dependencies using a go.work file in the root of your workspace directory. The go.work file has use and replace directives that override the individual go.mod files, so there is no need to edit each go.mod file individually.


maybe I just don't know the reasoning behind this... but I don't see why you would want to disable a single build/install command. this is different from any other package manager I've seen
@TrevorJex re-reading github.com/golang/go/issues/40276, there still is a single build/install command: go install. And it does so, installing packages at specific versions, regardless of the current module context. That is an improvment compared to the old go get.