GOROOT、GOPATH、Go Modules 三者的关系介绍
GOROOT
GOROOT路径即为存放Golang语言内建的程序库的所在位置,简单地说就是Golang的安装路径
若按照Folang-Download and install流程,则由go env
命令查询到的结果为GOROOT="/usr/local/go"
GOPATH 和 Go Modules
GOPATH 是一个路径,若初次安装Golang且未修改环境变量,则GOPATH默认为用户目录下的go文件夹(例如root用户的默认GOPATH为
/root/go
,普通用户user的默认GOPATH为/home/user/go
)
Go Modules 是Go 1.11版本之后发布的dependency management system
从上述概念来说,二者是没有任何联系的,但是GOPATH的概念并不能体现出其在项目构建上的作用
这两个概念看似不相干,但实际上他们代表着先后两种项目构建模式:经典的GOPATH mode 和 目前的go Modules mode,这两个概念是两种设计模式的产物,并不能说二者毫无关联,因为在Go Modules模式下仍然会使用到GOPATH(go install会将可执行文件放置于$GOPATH/bin下)
之所以混乱,是因为其是一个历史发展的过程,而且后者模式并没有完全脱离前者,
经典的GOPATH mode
此模式下,项目结构如下图所示
目前的go Modules mode
Go Modules
想要理解Go Modules,需要理清Go project构建方式的发展历程.
- 在Go 1.11版本之前,代码分为两种情况,一是
import
语言内建的程序库(位于$GOROOT/pkg
下),另一种是import
第三方的程序库
对于前者,在任意目录下仅需要创建以下单文件,执行go run main.go
命令即可运行,go run
将代码进行编译并生成执行文件,而编译文件跟执行文件存在一个暂存文件夹内,当运行完此程序就会自动删除。 该指令可以想成类似解释的方式运行,而不需要做其他任何环境设定,即可运行。
// main.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
对于后者,同样的单文件执行go run main.go
命令,会出现以下错误.
// main.go
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.Run()
}
由错误信息可知,第三方包的搜索顺序是$GOROOT/src/
->$GOPATH/src/
,若两个路径下都未找到,则代码无法运行.
main.go:2:8: cannot find package "github.com/gin-gonic/gin" in any of:
/usr/local/go/src/github.com/gin-gonic/gin (from $GOROOT)
/root/go/src/github.com/gin-gonic/gin (from $GOPATH)
不难注意到,两个路径中都涉及到一个src
目录,实际上在Go 1.11版本之前的项目结构如下图所示,
- bin: 存放
go build
编译生成的可执行文件,go build <filename>
会在指定文件的当前目录生成可执行文件;go build <projectname>
会在当前目录生成$GOPATH/src/projectname
编译出的可执行文件;可通过-o
参数指定输出文件的路径,但源文件的根路径只能是$GOPATH/src
,无法指定其他路径 - pkg: 当项目过大时,
go build
的编译速度很慢, - src: 存放项目的源代码
在理解这3个目录的作用之前,首先需要理解一下
关于这3个目录的作用,需要首先理解2个命令,go build
和 go install
go build <filename>
: 在
go build <projectname>
: 在当前目录生成$GOPATH/src/projectname
编译出的可执行文件
go install <main包-filename>
:
go install <main包-filename>
:
- 在Go 1.11版本之前
至此虽然搞清了GOROOT和GOPATH的具体值,但是它们究竟起到何种作用仍然是不清晰的.起到干扰作用的
在后续的coding过程中,会很自然地发现一个问题
在,构建一个go project的方式为
参考
在传统gopath模式下,多项目的构建方式令人疑惑
在考虑传统模式下多项目的构建方式时,尝试在$GOPATH/src/project下创建2个文件,一个文件package写的非main,另一个文件package写的main,完全不对
然后不知道怎么就想到go文件里面写的package又可以和所在目录名称不同,这样对于包的理解就出现了疑惑,感觉有点混乱