之前对 Golang 的包管理机制没有很清晰的认识,今天来详细分析一下,其实 Golang 的包管理方式分为以下两种:
go mod 包管理
方式:项目可以放到任意位置,目录下需要有 go.mod 文件。gopath 包管理
方式:必须将项目放在$GOPATH/src
下。
下面我们从 GO111MODULE 的三种模式来分析一下什么时候采用哪种包管理模式,以及两种包管理模式具体有什么区别。
一、GO111MODULE 的三种模式
- auto 模式:如果当前项目中存在 go.mod 文件那么就是用 go mod 包管理模式,否则就使用 gopath 模式(后者的前提是项目必须在
$GOPATH/src
目录下) - on 模式:均采用 go mod 包管理模式
- off 模式:均采用 gopath 包管理模式(项目必须在
$GOPATH/src
目录下)
二、go mod 和 gopath 包管理模式的区别
- gopath 模式:项目必须放在
$GOPATH/src
目录下,在 import 导包时会自动加上$GOPATH/src
的前缀,拼成的路径即为需要导的包的位置。 - go mod 模式:我们在当前项目文件夹执行
go mod init test
命令,那么 test 就是 module name,也就表示当前项目的绝对路径引用。
举例项目结构如下:
- demo
- pkg
- cmd
- main.go
- model
在 main.go 中想调用 pkg 包下逻辑:
- gopath 模式:
import("demo/pkg")
- go mod 模式:在 demo 项目文件夹下执行
go mod init test
命令后,import("test/pkg")
,其中 test 也可以指定为其他。
注意:以上两张方式当使用到 go-sdk 中包时,比如 fmt 等,都需要去 goroot/src
路径下寻找。
三、get、install、build、run 命令
- go run:专门用来运行命令源码文件的命令,一般用来运行单个文件
- go build: 主要是用于测试编译。编译某个包或者项目,在当前目录下生成可执行文件
- go install: 编译并安装代码包或者源码文件的。
- go get: 用于从远程代码仓库上下载代码包并更新 mod 文件。
go get
命令,会将依赖下载至指定目录并写入 mod 文件(gopath 包管理方式指定目录为$GOPATH/src
,而go mod 包管理的方式指定目录为gopath/pkg
)
go install
命令会将项目编译并安装,.a
文件放入 pkg 目录下,.exe
文件放入 bin 目录下,如果项目很大,每次编译都要花很长时间,则建议使用 go install 来编译,充分利用它对依赖包的缓存功能,因为会将非主包放入 pkg 目录下缓存起来。
注意:Go 1.17 之后对 go get
和 go install
两个命令进行了更新,其中 go get
命令不再有编译包的功能,后续只有添加,更新,移除 mod 文件中的依赖项的功能。而编译安装等功能由 go install
命令替代。
四、包之前的相互引用
主要一点:项目执行 go mod init moduleName
后,该项目放到任何位置,moduleName 都是该项目一级路径在当前环境下的绝对路径的引用。
- go mod tidy:解析项目文件,并找到所使用的包。生成 go.sum 文件,其中保存了所使用包的版本。
- go mod edit -replace:替换依赖项的导入路径,可以替换成具体路径或包名的方式。
注意:同个目录下 .go 文件的包名必须一致,但目录名和包名允许不一致,导包方式有所区分 import(diff "moduleName/pkg")
,其中 pkg 是目录名,一般导包时默认为包名。但如果包名和目录名不一致需要在前面指出真实包名。