Why "go get" broke and how to fix it?
\nIf you've ever wondered "How can I install a package with go get?" — you're not alone. This question has thousands of views on Stack Overflow, and for good reason. It used to be simple: go get github.com/some/package — and the library would be in your $GOPATH/src. But after Go 1.16, everything changed. Now go get no longer installs packages in the traditional sense. Instead, it only updates go.mod. And for installing binaries, the go install command was introduced.
In this article, we'll figure out what happened, how to properly install packages and dependencies now, and why beginners get so confused. Let's go!
\n\nA Brief History: From GOPATH to Modules
\nBefore Go 1.11, all code lived in GOPATH — a special folder where all your projects and third-party packages were stored. The go get command downloaded sources directly there. It was convenient, but it caused versioning problems: if two projects required different versions of the same library — chaos ensued.
With the arrival of Go modules (starting from Go 1.11 and stable since 1.16), each project got its own go.mod — a file specifying dependencies and their versions. Now go get works differently:
- \n
- Adds a dependency to
go.mod\n - Downloads it to the cache (usually
$GOPATH/pkg/mod) \n - Does not create a binary in
$GOPATH/bin\n
If you need to install a ready-made program (e.g., a command-line utility) — use go install.
How go get works now: Step-by-step breakdown
\nOpen a terminal and create a new module:
\nmkdir myproject\ncd myproject\ngo mod init myproject\nNow let's add, say, the popular gorilla/mux library for routing. Previously we would write:
go get github.com/gorilla/mux\nAnd it will work — the library will be downloaded. But look at what happened:
\n- \n
- A line appeared in
go.mod:require github.com/gorilla/mux v1.8.0\n - A
go.sumfile appeared in the project folder — a file with checksums for security \n - The library sources are in the cache, not next to the project \n
Now in your code you can import the package:
\npackage main\n\nimport (\n "fmt"\n "github.com/gorilla/mux"\n)\n\nfunc main() {\n r := mux.NewRouter()\n fmt.Println("Router created!")\n}\nRun go run main.go — everything works. But if you wanted to get a binary (a compiled program) — go get won't give you one.
Installing binaries: go install to the rescue
\nLet's say you found a cool Go utility, for example golangci-lint — a linter for code. To install it as a system command, you used to write:
go get github.com/golangci/golangci-lint/cmd/golangci-lint\nNow this won't work (it will give a warning). The correct way is:
\ngo install github.com/golangci/golangci-lint/cmd/golangci-lint@latest\nWhat will happen:
\n- \n
- Go will download the utility's sources \n
- Compile them \n
- Place the resulting binary in
$GOPATH/bin(or$GOBIN, if the variable is set) \n
Make sure $GOPATH/bin is added to your PATH — otherwise the command won't be available. You can check it like this:
echo $GOPATH\n# usually /home/user/go\nls ~/go/bin/\nIf your binary is there — everything is fine.
\n\nCommon beginner mistakes (and how to avoid them)
\nOn Stack Overflow, people most often ask about these pitfalls:
\n- \n
- "go get doesn't create a src folder"
Blogs
Book Recommendations
Read also
How setOnClickListener works in Kotlin: under the hood
Security of Go Applications: Top 10 Vulnerabilities for Beginners
JSON or Serialize: What to Choose for Storing PHP Arrays? (Complete Guide)
Kotlin: Functional or OOP? Choosing the Right Approach
C# for Machine Learning: Capabilities and Limitations in Practice