$GOPATH 配置¶
当你在非默认 $GOPATH
目录下存放Go代码,使用 我的vim配置 这样支持GO的编辑器编辑时,会出现类似以下错误提示:
could not import github.com/xxx/yyy (cannot find package "github.com/xxx/yyy" in any of ...
这是因为在 Go 1.11之前,所有项目都在 $GOPATH
下创建,这样Go编译器就会搜索到依赖并构建Go应用程序。这里 $GOPATH
包含了源代码和二进制程序:
$GOPATH/src
- 所有源代码$GOPATH/pkg
- Go内部使用的运行自身的包$GOPATH/bin
- 包含执行程序
Go Modules¶
从 Go 1.11之后,Go Modules可以在 $GOPATH
之外创建项目,并且导入包管理
在没有Go Modules之前的缺点:
没有Go Modules情况下,就会被迫把所有项目存放到单一的目录
$GOPATH
不支持Go packages版本,不允许在
package.json
指定Go package的特定版本,也就是不能使用相同包的不同版本所有扩展包被存放在一个 vender 目录并推送到服务器
Go Module提供了:
模块是相关 Go 包的集合,它们作为一个单元一起进行版本控制。
模块记录精确的依赖需求并创建可重现的构建。
操作¶
这里我是在学习 「Go in Action」的案例代码:
package main
import (
"log"
"os"
_ "github.com/goinaction/code/chapter2/sample/matchers"
"github.com/goinaction/code/chapter2/sample/search"
)
// init is called prior to main.
func init() {
// Change the device for logging to stdout.
log.SetOutput(os.Stdout)
}
// main is the entry point for the program.
func main() {
// Perform the search for the specified term.
search.Run("president")
}
执行以下命令按照
github.com/{your_username}/{repo_name}
来创建一个go.mod
文件:go mod init github.com/huataihuang/etudes
提示信息:
go: creating new go.mod: module github.com/huataihuang/etudes
go: to add module requirements and sums:
go mod tidy
此时会在当前目录下生成一个 go.mod
文件内容如下:
module github.com/huataihuang/etudes
go 1.18
执行:
go build
提示信息:
main.go:7:2: no required module provides package github.com/goinaction/code/chapter2/sample/matchers; to add it:
go get github.com/goinaction/code/chapter2/sample/matchers
main.go:8:2: no required module provides package github.com/goinaction/code/chapter2/sample/search; to add it:
go get github.com/goinaction/code/chapter2/sample/search
该怎么解决呢?
go mod tidy
也即是前面go mod init
初始化仓库的命令返回的提示,这个命令会帮助移除不需要的依赖,go build
只会更新依赖但不会触碰不需要的依赖。tidy
会帮助你做清理:go mod tidy
执行了上述命令后,提示信息:
go: finding module for package github.com/goinaction/code/chapter2/sample/search
go: finding module for package github.com/goinaction/code/chapter2/sample/matchers
go: downloading github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb
go: found github.com/goinaction/code/chapter2/sample/matchers in github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb
go: found github.com/goinaction/code/chapter2/sample/search in github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb
此时会看到当前目录下多了一个 go.sum
内容是:
github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb h1:xpDeYJF7P9jgczf4KjRQOoqPrrKs56vqMBiWOXnSoQM=
github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb/go.mod h1:3NRM3Fi26eZwRU/33Y0fH7YaVlo6EDQUAE2CBQ/snQ0=
而且 go.mod
内容最后添加了一行:
require github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb
此时完整的 go.mod
内容如下:
module github.com/huataihuang/etudes
go 1.18
require github.com/goinaction/code v0.0.0-20171020164608-49fc99e6affb
到这个步骤时,已经完成了非 $GOPATH 目录下项目的部署准备
,也即是此时再次执行 build
将不会报错:
go build
Go将在当前项目目录下进行编译,并生成执行文件 etudes
(也就是前面我们指定的项目名字repo_name github.com/{your_username}/{repo_name}
)
注意,执行了 go mod tidy
命令之后,go会下载好依赖包并配置完module,所以此时在我前文说的 vim
编辑Go代码时候,不会再报错提示无法加载 could not import github.com/xxx/yyy (cannot find package "github.com/xxx/yyy" in any of ...
如果还有
vendor
目录,则对应运行:go mod vendor
和 go mod tidy
类似,会自动下载所有依赖,并存放到项目目录的 /vendor
目录,解决依赖
总结¶
Go 1.11 之前,所有项目都必须存放在
$GOPATH
目录下Go 1.11 之后,项目可以存放在其他目录目录下,但是需要初始化项目module
go mod init github.com/{your_username}/{repo_name} go mod tidy go mod vendor
此时Go会在当前项目目录下下载依赖package,并配置好 go.mod
和 go.sum
指向对应依赖package
接下来就可以按正常流程执行程序编译:
go build