最近在配置 VSCode 的 Go 插件时,总是报错找不到包之类的,发现时 GOPATH 和 GOROOT 在该编辑器中没有配置,借此了解一下两个环境变量。目前笔者用系统是 macOS BigSur,Go 版本 1.16.6

GOROOT

$GOROOT,便是 Go 的安装路径,存放 Go 的内置程序库。通常你安装完后,你电脑的环境变量就会设好 GOROOT 路径。当你开发 Go 程序的时候,当你 import 内置程序库的时候,并不需要额外安装,而当程序运行后, 默认也会先去 GOROOT 路径下寻找相对应的库来运行。

通过 go env 可以查看有关 Go 语言的相关环境变量设定。通常如果你是初次安装 Go,并且没做什么环境变量设定的话,GOROOT 设定路径就是你当初安装 Go 语言的路径,通常类似于 /usr/local/go/usr/local/Cellar/go/1.xx.x/libexec,一般为前者做软连接到后者。而 GOPATH 通常默认会是用户目录下的 go 文件夹,通常类似于 $HOME/go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# realyee @ 192 in /usr/local/Cellar/go/1.16.6/libexec
$ tree ./ -L 1
./
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── PATENTS
├── SECURITY.md
├── VERSION
├── api
├── bin
├── doc
├── favicon.ico
├── lib
├── misc
├── pkg
├── robots.txt
├── src
└── test

8 directories, 7 files

上述文件,有三点可了解: bin 目录:执行文件:go、gofmt,甚至 godoc doc 目录:Go 各个版本的文档 src 目录:go 标准库源码

GOPATH

Go 采用包管理,没有项目的概念。Go 工作区是 Go 管理我们的源文件、编译的二进制文件和缓存对象的地方,缓存对象用于以后更快的编译。虽然也可以有多个工作区,但通常建议只有一个。GOPATH 便充当工作区的根文件夹。

GOPATH,也叫工作区目录(workspace directory),是 Go 代码所在的目录, Go 寻找 Go 工作区的位置。如果未设置环境变量,默认情况下,Go 假定我们的 GOPATH 位置在 $HOME/go,其中 $HOME 是我们计算机上用户帐户的根目录。 我们可以通过设置 $GOPATH 环境变量来改变它。 如需进一步学习,请按照本教程阅读和设置 Linux 中的环境变量。 要检查这一点,请输入以下命令:go env GOPATH

1
2
$ go env GOPATH
/Users/realyee/go

一个 GOPATH 工作区,一般这样:

1
2
3
4
5
6
./
├── bin
├── pkg
└── src
├── hello_github
└── hello_router.go
  1. bin:保存编译后生成的可执行文件。我们的操作系统使用$PATH环境变量来查找无需完整路径即可执行的二进制应用程序,建议将此目录:$GOPATH/bin添加到我们的全局 $PATH 变量中。
  2. pkg:它保存已安装的包对象(比如:.a)。每个目标操作系统和体系结构对都有自己的 pkg 子目录。 Go 编译包时生成的中间文件,用来缓存提高编译效率。
  3. src:包含源代码(比如:.go .c .h .s 等)。 该路径决定 import 包时的导入路径或可执行文件名称。 import 包的搜索顺序:
    1. GOROOT/src:该目录保存了 Go 标准库代码。
    2. GOPATH/src:该目录保存了应用自身的代码和第三方依赖的代码。

GOROOT 和 GOPATH 配置

  1. 查看二者的环境变量 go env 查看 Go 相关全部环境变量 go env 变量名,如:go env GOROOTgo env GOPATH

  2. 配置 GOROOT 一般情况下 GOROOT 无需配置,但是如果你看到 GOROOT 为空,那可以:

    1. which go 查看 go 的位置
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      $ go env GOROOT
      /usr/local/Cellar/go/1.16.6/libexec
      (base)
      # realyee @ 192 in ~/go/src [15:40:34]
      $ which go
      /usr/local/bin/go
      (base)
      # realyee @ 192 in ~/go/src [15:41:41]
      $ ll /usr/local/bin/go
      lrwxr-xr-x 1 realyee admin 26B Aug 8 21:08 /usr/local/bin/go -> ../Cellar/go/1.16.6/bin/go
    2. 设置环境变量 export GOROOT=/usr/local/bin/go
  3. 配置 GOPATH

    1. 在电脑上任意位置创建工作区目录,例如:~/GO_PROJECTS
    2. 设置环境变量 export GOPATH=~/GO_PROJECTS

go run、go build 和 go get

go run

go run,简单理解就像是解释的方式来执行代码,而在细节上它其实会将代码进行编译,最后产生可执行文件,然后运行该可执行文件,产生程序执行后的结果,而可执行文件会放在特定的临时文件里面,执行完就会自动删除了。 通常开发上就是用于假设只是要测试一段代码,那就会用 go run 来执行。

go build

go build 仅仅编译以导入路径命名的包及其依赖项,将其放到本地。通常在 $GOPATH 目录下执行 go build,Go 会自动去 src 下寻找对应项目目录,默认是在当前目录下生成可执行文件。

go build 缺点:每次编译代码,比较没有效率,当项目架构越来越大,build 的速度也就越来越慢。

go install

因为 go build 的缺点,因此有 go install 指令,go install 可以做两件事情:

  • 将包编译成.a 中间缓存对象,如果源码尚未更改,将在下一次编译期间使用缓存。
  • 如果是 main 包,并将其编译成可执行文件
1
2
3
4
5
6
7
.
├── bin
│ └── hello # by go install
└── src
└── hello
├── hello # by go build
└── hello.go

注意:

  • go install 如果要在非 GOPATH 路径下使用的话,要先设定 GOBIN 环境变量,否则会出现错误
  • 通常 GOBIN 环境变量就是设定 GOPATH/bin。

go get(deprecated in go1.16)

GOPATH 很大的缺点,就是相关第三方包只要不是官方库,都需要放置在 GOPATH/src 的路径下才可使用。通常我们会使用 go get 指令来获取网络上的第三方包,并安装到本地,例如:

1
go get github.com/gin-gonic/gin

当我们从 Github 上下载第三方包多了之后,会发现 GOPATH/src 下的代码会很复杂,除了有你自己开发的项目文件夹,也包含其他第三方库的项目文件夹。

此外,如果你开发的项目采用第三方套件是不同版本也很棘手。以往的解决方法是要设定多组不同的 GOPATH。 虽然社群也有开发相对应的 package manager,如 Vendor、Dep 来解决该问题,但毕竟不是官方主导的。因此,有了 Go Modules 的诞生,我们下一篇文章再讲。

但是从 Go 1.16 开始逐渐废弃 go get 安装包的功能,详细见New module changes in Go 1.16 - go.dev官方推荐使用 go install 带版本安装, 使用示例:

1
2
go install golang.org/x/tools/gopls@latest
go install golang.org/x/tools/gopls@v0.6.5

go doc

可以使用 go doc [包][.函数名]查看包或函数的详细源码,经常查看源码方便理解 Go 函数的原理 例如:go doc fmtgo doc fmt.Printfln

参考资料

  1. go cmd/go pkg.go.dev
  2. go - What should be the values of GOPATH and GOROOT? - Stack Overflow
  3. Golang — GOROOT、GOPATH、Go-Modules-三者的關係介紹 | by 陳冠億 Kenny | 企鵝也懂程式設計 | Medium
  4. go - What should be the values of GOPATH and GOROOT? - Stack Overflow