上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
10.2 模块
模块 (module)是包(packages)和其依赖项(dependency)的集合。
直接体现是 go.mod
文件,存储了模块路径、编译器版本,以及依赖项列表。
如此,模块是依赖管理方式,是发布和版本控制单元。
module = go.mod + package + subs...
- 模块路径(module path):在
go.mod
中声明的名称标识。 - 根目录(module root directory):包含
go.mod
文件的目录。 - 主模块(main module):执行
go
命令时,所在目录对应的模块。
初始化
模块对应一个包含 go.mod
的源码目录,所有不含 go.mod
的子目录都是其成员。
test/ | +-- go.mod (github.com/qyuhen/test) | +-- main.go | +-- mylib/ (github.com/qyuhen/test/mylib) | +-- add.go
$ cd test $ go mod init github.com/qyuhen/test go: creating new go.mod: module github.com/qyuhen/test
$ cd test/mylib $ go list -m # 向外查找 go.mod,主模块。 github.com/qyuhen/test
模块路径描述了线上存储位置,通过 go get
下载到本地缓存目录。
以 import
导入模块时,使用模块路径而非本地路径。
// go.mod module github.com/qyuhen/test // 模块路径 go 1.18 // 编译器最低版本号
// main.go package main import ( // "test/mylib" // ~~~~~~~~~~ package test/mylib is not in GOROOT "github.com/qyuhen/test/mylib" ) func main() { println(mylib.Add(1, 22)) }
如果子目录包含 go.mod
,那么它将是独立模块,不再属于当前模块。
$ cd test/mylib $ go mod init github.com/qyuhen/mylib go: creating new go.mod: module github.com/qyuhen/mylib $ cd .. $ go build no required module provides package github.com/qyuhen/test/mylib; to add it: go get github.com/qyuhen/test/mylib
依赖管理
命令 go get
添加、下载(更新)依赖项,其他操作可用 go mod
完成。
- 从
GOPROXY
下载源码到本地缓存GOMODCACHE
目录。 - 向
go.mod
、go.sum
添加依赖项和验证信息。 - 使用
go clean -modcache
清除缓存。(自动重新下载)
$ go get . # 分析源码,添加所有依赖。 $ go get example.com/my # 指定模块,下载最新版本。 $ go get example.com/my@v1.3.4 # 指定版本号。 $ go get example.com/my@lastet # 最新版本。 $ go get example.com/my@4cf76c2 # 伪版本号(commit hash) $ go get example.com/my@bufix # 分支(branch)
用 go mod
管理模块。
init
: 初始化模块,创建go.mod
文件。tidy
: 添加遗漏,移除不需要的依赖项。
edit
: 命令行方式编辑模块设置。
-fmt
:格式化go.mod
文件。-module
:模块路径。-go
:编译器版本。-require
,-droprequire
:添加直接或间接依赖项。-replace
,-dropreplace
:替换模块路径或版本。-exclude
,-dropexclude
:排除模块或版本。-retract
,-dropretract
:标识有问题需要忽略的版本。
$ go mod edit -require example.com/my@v1.3.4
版本标识
版本标识模块不可变快照。
- 以
v
开头,然后是语义版本(semantic version)。
- 不兼容(incompatible)更新,递增主要版本号。
- 添加功能的兼容更新,递增次要版本号。
- 优化和修复缺陷,不影响导出接口,递增补丁版本号。
- 正式发布前的预发行版本,添加
-pre
后缀。
- 使用
git tag
之类的功能标记语义化版本号。 - 如没有标记,则使用提交(commit)信息(time, ident)构成伪版本号。
v(major).(minor).(patch)-(pre|beta) 主要 次要 补丁 预发行或测试版
v1.2.3 v1.2.3-pre v1.5.0-beta v0.0.0-20191109021931-daa7c04131f5 --> go get example.com/my@daa7c041
查看所有版本。
$ go list -m -versions github.com/shirou/gopsutil v2.0.0+incompatible v2.16.10+incompatible v2.16.11+incompatible ... v2.21.11+incompatible v3.20.10+incompatible ... v3.21.11+incompatible
$ go list -m -versions all
更新依赖项。
$ go get -u example.com/my@v1.3 # minor or patch releases $ go get -u=patch example.com/my@v1.3.4 # patch release
可使用 >
、 >=
、 <
、 <=
操作符指定版本查询范围(module query)。
选择最接近条件的版本。例如:
>=1.0
选择1.0
,<1.0
选择0.9
,而不是0.8
。注意,命令行添加引号,否则显示版本错误。
$ go get "github.com/shirou/gopsutil@>v2.16.10"
兼容性规则
如新版和旧版有相同导入路径,则必须保证向后兼容(backwards compatible)。
主版本号出现在模块路径尾部,表示重大不兼容更新。
mod/v2
和mod/v1
不兼容。
v0
和v1
不需要使用版本后缀。
v0
本身就表示不稳定且不具有兼容性保证,v1
为默认版本。
另外,有预发行后缀也表示该版本不稳定,不受兼容性约束。
导入语句(import)须使用包含版本号( v2
)的全路径。
通常建议在原模块下建立 /v2/go.mod
模块(子目录)。
import github.com/qyuhen/test/v2
工作空间
以工作空间(workspace)解决多模块开发遇到的问题。
- 编译时,找不到未发布模块(非子包)。
- 只能以
replace
将模块路径替换为本地路径。 - 污染的
go.mod
意外提交到代码仓库。
app/ (workspace) | +-- go.work | +-- test/ (github.com/qyuhen/test) | | | +-- go.mod | | | +-- main.go | +-- mylib/ (github.com/qyuhen/mylib) | +-- go.mod | +-- add.go
$ go work init # 初始化工作空间。 $ go work use ./test ./mylib # 添加模块。
// go.work go 1.18 use ( ./mylib ./test )
导入(import)工作空间内其他模块,无需 require
指令。
// mylib/go.mod module github.com/qyuhen/mylib go 1.18
// test/go.mod module github.com/qyuhen/test go 1.18 // require github.com/qyuhen/mylib v0.0.1 // 不需要 !!!
// test/main.go package main import ( "github.com/qyuhen/mylib" ) func main() { println(mylib.Add(11, 22)) }
若必须添加 require
,编译时可关闭 GOPROXY
,阻止在线获取模块验证信息。
$ GOPROXY=off go build
模块还可放在空间目录外,或加入多个工作空间。
// go.work go 1.18 use ( ../mylib ./test )
环境变量
模块感知(module-aware)模式,相关环境变量说明。
GO111MODULE
:模块感知模式开关。(默认:on)GOMODCACHE
:模块缓存路径。GOPROXY
:模块代理服务列表。GOSUMDB
:模块数据安全校验数据库。GOPRIVATE
:私有模块路径,绕过 GOPROXY 直接获取。
GOPRIVATE=*.example.com
,以逗号分隔多个地址。
GOPRIVATE
是GONOPROXY
、GONOSUMDB
的默认值。
离线编译
打包含依赖在内的所有源码,进行离线编译。
$ go mod vendor # 将依赖复制到 ./vendor 目录下。 $ GOWORK=off go build -mod vendor # 禁用工作空间,以 vendor 方式编译。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论