1. 构建过程中遇到错误记录
1.1. unrecognized relocation (0x2a) in section `.text'
在 go 编译过程中遇到
|
|
2. 常见 go 命令行相关命令
2.1. 交叉编译
|
|
2.2. go build 涉及点
Go Path 相关:
GOPATH
: 包含 Go 源码的 path 路径,Unix 通过:
分割多个路径,Win 通过;
分割src/
: 源码pkg/
: 安装 objects,期内每个 OS 和 Arch 有其 subdir,模式pkg/GOOS_GOARCH
,接着跟着包名路径bin/
: 编译文件存储路径
|
|
2.3. 构建约束
参考: https://tkstorm.com/gopl-book/ch10/ch10-07.html
|
|
3. go module 管理
3.1. 模块感知
模块感知模式下,该go命令使用go.mod文件来查找版本化依赖项,通常从模块缓存中加载包,如果模块丢失,则下载模块。
模块感知模式下,GOPATH
无意义了,但仍然存储下载的依赖放在GOPATH/pkg/mod
下,并且安装到GOPATH/bin
(当GOBIN
未设置时候)
- 在
GOPATH
模式下,该go命令忽略模块,它在vendor
目录中GOPATH
查找并查找依赖项。 Go 1.16
开始,默认情况下启用模块感知模式,无论 go.mod文件是否存在- 模块感知模式可以与控制GO111MODULE环境变量,它可以被设置为on,off,或auto
GO111MODULE=off
,则该go命令将忽略go.mod文件并以GOPATH模式运行GO111MODULE=on 或 未设置
,go即使没有go.mod文件存在,该命令也会以模块感知模式运行GO111MODULE=auto
,在Go 1.15
及更低版本中,这是默认行为- 如果go.mod文件存在于当前目录或任何父目录中,则以模块感知模式运行
- 如果
go mod
子命令和go install
会一个以模块感知模式运行,即使没有go.mod文件存在
3.1.1. 所有加载包相关信息的均为模块感知的
|
|
3.1.2. go get
用途: go get
命令更新主模块go.mod文件中的模块依赖关系,然后构建和安装命令行中列出的包
|
|
两个不同版本中需要一个模块(在命令行参数中明确指定或满足升级和降级),go get
将报告错误。在go get
选择了一组新版本后,它会检查任何新选择的模块版本或任何提供命令行中命名的包的模块是否已被收回或弃用,在Go 1.18
中,go get
更专注于管理go.mod. 该-d
标志已弃用,默认即始终启用
3.1.3. go install
Go 1.15
及更低版本不支持使用go install
用途: go install
命令构建并安装由命令行上的路径命名的包。可执行文件(main包)安装到GOBIN的环境变量,其默认值为$GOPATH/bin
或者$HOME/go/bin
,可执行文件在$GOROOT
安装在$GOROOT/bin
或$GOTOOLDIR
代替$GOBIN
,不可执行的包被构建和缓存但不安装
|
|
3.1.4. go list -m
|
|
3.2. go.mod 范例
|
|
3.3. 模块版本号
模块版本号的含义,模块版本号的每一部分来表示版本的稳定性和向后兼容性:
- 开发中:
v0.x.x
,表示模块仍处于开发阶段且不稳定,没有向后兼容保证 - 主版本:
v1.x.x
,主版本有重大更新,不保证向后 API 兼容 - 次版本:
vx.4.x
, 主版本无大改动,但有功能变化,保证后项兼容和稳定性 - 修订版:
vx.x.1
, 不影响模块公共 API,保证后项兼容和稳定 - 预发版:
vx.x.x-beta.2
,预发布历程碑,如 alpha 或 beta,不提供稳定性保证
3.4. Go Proxy 包下载逻辑
假设该 go 命令正在寻找提供 package 的模块golang.org/x/net/html
假定配置的 GoProxy 设置: https://corp.example.com,https://proxy.golang.org
https://corp.example.com/(并行):
- 索取最新版本 golang.org/x/net/html
- 索取最新版本 golang.org/x/net
- 索取最新版本 golang.org/x
- 索取最新版本 golang.org
https://proxy.golang.org/,如果所有请求
https://corp.example.com/
都以404
或410
失败:- 索取最新版本 golang.org/x/net/html
- 索取最新版本 golang.org/x/net
- 索取最新版本 golang.org/x
- 索取最新版本 golang.org
找到合适的模块后,该 go 命令将使用新模块的路径和版本将新需求添加 到主模块的go.mod
文件中,将在相同的版本中使用相同的模块。如果解析的包不是由主模块中的包导入的,新的需求会有 // indirect
注释。
3.5. 最小版本选择(MVS)
MVS 在依赖的有向图上运行,用 go.mod 指定,每个顶点代表一个模块版本,每条边代表最低要求版本,使用 require 指令指定,replace、exclude 修改图形;
通过go list -m all
检测构建列表
3.5.1. 最小版本选择 Case
MVS 返回一个包含粗体版本的构建列表:A 1.2、B 1.2、C 1.4 和 D 1.2。请注意,可以使用更高版本的 B 和 D,但 MVS 不会选择它们,因为不需要它们。
3.5.2. 替换 -replace
其中 C 1.4 已被 R 替换。R 依赖于 D 1.3 而不是 D 1.2,因此 MVS 返回包含 A 1.2、B 1.2、C 1.4(替换为 R)和 D 1.3 的构建列表
3.5.3. 排除 - exclude
C 1.3 已被排除。MVS 的行为就像 A 1.2 需要 C 1.4(下一个更高版本)而不是 C 1.3。
3.5.4. 升级 - go get -u
模块B可能从1.2升级到1.3,C可能从1.3升级到1.4,D可能从1.2升级到1.3。升级(和降级)可能会添加或删除间接依赖项。在这种情况下,E 1.1 和 F 1.1 出现在升级后的构建列表中,因为 B 1.3 需要 E 1.1。为了保留升级,该go命令会更新go.mod. 它将对 B 的要求更改为 1.3 版。它还将添加对 C 1.4 和 D 1.3 的要求和// indirect注释,因为否则不会选择这些版本。
3.5.5. 降级
假设发现 C 1.4 有问题,所以我们降级到 C 1.3。C 1.4 从模块图中删除。B 1.2 也被删除,因为它需要 C 1.4 或更高。主模块对B的要求改为1.1
3.6. go.mod 文件
参考:
每个 go module 都有一个 go.mod 文件定义,描述了模块的属性,包括对其他模块和 Go 版本的依赖关系,模块属性包括:
- 模块名: 描述当前模块的路径,和模块版本唯一标识一个唯一的模块,通常能够被
go tool
下载,如果模块版本 v2 或更后,则尾部加上版本号,如/v2
:module example.com/mymodule/v2
- Go 版本: 说明当前模块需要的最低 Go 版本,
go 1.14
表示最小版本是go 1.14
- 模块路径: 用于 go 工具从下载位置,如代码仓库,和版本号结合一起当做唯一标识符
- 模块依赖: 当前模块所依赖其他模块的最低版本列表
- 模块替代: 用另一个模块版本或本地路径替代 require 的模块,或者排除指定版本依赖的模块
- 模块 go.mod 文件初始化:
go mod init example/mymodule
- 常用命令:
go get
go mod tidy
go mod edit
3.6.1. 模块名
|
|
3.6.2. 依赖 - require
|
|
3.6.3. 替换 - replace
replace 指令在以下情况下很有用:
- 正在开发一个新模块,其代码尚未在存储库中,但想使用本地版本对客户端进行测试
- 已经确定了依赖项的问题,克隆了依赖项的存储库,并正在使用本地存储库测试修复程序
一些 replace 的示例:
|
|
3.6.4. 排除 - exclude
可以使用它来排除具有无效校验和的模块版本,通过 go 命令: go mod edit -exclude=example.com/theirmodule@v1.3.0
|
|
3.6.5. 回收 - retract
当一个版本发布过早或发布后发现一个严重的问题指令非常有用
|
|
3.7. 管理依赖
3.8. 帮助命令
|
|
3.9. 开发与发布Go Module
参考:
3.9.1. 发布Module
- 进入到模块根目录
go mod tidy
,移除无效依赖go test ./...
- 对项目进行用新版本 tag 打包:
|
|
- 发布到远程仓库
|
|
- 通过
go list
验证模块可用
|
|
- 在其他项目通过
go get
获取指定版本
|
|