驯服 go get:Go 语言新手包安装指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么 "go get" 失效了以及如何修复?

\n

如果你曾经问过 "How can I install a package with go get?" — 你并不孤单。这个问题在 Stack Overflow 上获得了数千次浏览,这并非没有原因。以前一切都很简单:go get github.com/some/package — 然后库就会出现在你的 $GOPATH/src 中。但在 Go 1.16 发布之后,一切都变了。现在 go get 不再以传统意义安装包。相反,它只更新 go.mod。而安装二进制文件则出现了 go install 命令。

\n

在本文中,我们将探讨发生了什么,现在如何正确地安装包和依赖项,以及为什么新手经常感到困惑。我们开始吧!

\n\n

简史:从 GOPATH 到模块

\n

在 Go 1.11 版本之前,所有代码都存在于 GOPATH 中——一个存放你所有项目和第三方包的特殊文件夹。go get 命令会直接将源代码下载到那里。这很方便,但带来了版本问题:如果两个项目需要同一个库的不同版本——麻烦就开始了。

\n

随着 Go 模块(从 Go 1.11 开始,并在 1.16 中稳定)的到来,每个项目都拥有了自己的 go.mod 文件——其中列出了依赖项及其版本。现在 go get 的工作方式不同了:

\n
    \n
  • 添加依赖项到 go.mod
  • \n
  • 下载到缓存(通常是 $GOPATH/pkg/mod)
  • \n
  • 不在 $GOPATH/bin 中创建二进制文件
  • \n
\n

如果你需要安装一个现成的程序(例如,命令行工具)——请使用 go install。

\n\n

go get 现在如何工作:逐步解析

\n

打开终端并创建一个新模块:

\n
mkdir myproject\ncd myproject\ngo mod init myproject
\n

现在假设我们想添加一个流行的路由库 gorilla/mux。以前我们会写:

\n
go get github.com/gorilla/mux
\n

这仍然有效——库会被下载。但看看发生了什么:

\n
    \n
  1. 在 go.mod 中出现了一行:require github.com/gorilla/mux v1.8.0
  2. \n
  3. 在项目文件夹中出现了 go.sum 文件——用于安全性的校验和文件
  4. \n
  5. 库的源代码位于缓存中,而不是项目旁边
  6. \n
\n

现在你可以在代码中导入该包:

\n
package main\n\nimport (\n    "fmt"\n    "github.com/gorilla/mux"\n)\n\nfunc main() {\n    r := mux.NewRouter()\n    fmt.Println("Router created!")\n}
\n

运行 go run main.go — 一切正常。但如果你想要一个二进制文件(编译后的程序)—— go get 不会提供给你。

\n\n

安装二进制文件:go install 前来帮忙

\n

假设你找到了一个很棒的 Go 工具,例如 golangci-lint —— 一个代码检查工具。要将其作为系统命令安装,以前会写:

\n
go get github.com/golangci/golangci-lint/cmd/golangci-lint
\n

现在这不会起作用(会发出警告)。正确的方法是:

\n
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
\n

会发生什么:

\n
    \n
  • Go 会下载该工具的源代码
  • \n
  • 编译它们
  • \n
  • 将生成的二进制文件放入 $GOPATH/bin(如果设置了环境变量,则放入 $GOBIN)
  • \n
\n

确保 $GOPATH/bin 已添加到 PATH 中——否则该命令将不可用。可以这样检查:

\n
echo $GOPATH\n# 通常是 /home/user/go\nls ~/go/bin/
\n

如果那里有你的二进制文件——那就没问题了。

\n\n

新手常见错误(以及如何避免)

\n

在 Stack Overflow 上,最常见的问题是关于这些陷阱:

\n