actions/setup-go 是唯一推荐的 Go 环境配置方式,必须在 actions/checkout@v4 之后执行以确保 go.mod 可见;需显式设置 GO111MODULE=on 和 GOPROXY;缓存 key 应基于 go.sum 哈希;交叉编译需声明 CGO_ENABLED、GOOS、GOARCH;建议添加 go mod verify 校验依赖完整性。

GitHub Actions 里跑 Go 项目,actions/setup-go 是唯一推荐的 Go 环境配置方式;手动安装或依赖系统自带 Go 版本会直接导致 go mod 行为不一致、cannot find module 报错,甚至测试通过但构建产物缺失。
必须把 actions/checkout@v4 放在 actions/setup-go@v5 之前
这是最常被颠倒的顺序。checkout 负责拉取代码并让 go.mod 和 go.sum 可见;setup-go 才能基于这些文件正确初始化模块环境。顺序反了,go test 或 go build 就会报 “no Go files in current directory” 或找不到依赖。
-
actions/checkout@v4默认检出到工作目录根(即仓库根),无需额外cd - 若项目实际模块在子目录(如
src/backend),改用working-directory参数,别在run里写cd src/backend - 不要用
actions/checkout@v3:v4 修复了 Windows runner 下符号链接和子模块权限问题
GO111MODULE=on 和 GOPROXY 必须显式设置
虽然 Go 1.16+ 默认启用 modules,但旧版 Ubuntu runner(如 ubuntu-20.04)仍可能 fallback 到 GOPATH 模式;且默认 GOPROXY 为空,国内拉包极易超时失败,错误信息却只显示 “module not found”,非常误导。
- 在
setup-go步骤后加一个env块或独立run步骤:GO111MODULE=on GOPROXY=https://goproxy.cn,direct - 避免用
https://proxy.golang.org(国内不稳定),https://goproxy.cn是更可靠的选择 - 如果项目含私有模块(如公司内网 GitLab),需在
GOPROXY后追加,https://gitlab.example.com/api/v4/groups/mygroup/-/packages/golang/proxy
缓存 ~/go/pkg/mod 时 key 必须基于 go.sum 哈希
只用 Go 版本或时间戳作 cache key,会导致缓存命中率极低——go.sum 才是模块依赖真实快照。key 不匹配,每次都会重下全部模块,CI 时间翻倍。
立即学习“go语言免费学习笔记(深入)”;
- 缓存路径固定为
~/go/pkg/mod(Linux/macOS),不是./vendor或$GOPATH/pkg/mod(后者在 Actions 中可能被重定向) - key 写成:
${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }},注意是双星号,覆盖多模块项目 - restore 缓存必须在
go mod download之前,save 必须在它之后;顺序错等于没缓存 - 不用
go mod download也行:只要后续有go test或go build,Go 会自动触发下载;手动加这步反而掩盖go.sum不一致问题
交叉编译和 cgo 需要提前声明环境变量
CI runner 是 Linux x86_64,但你要构建 Windows 二进制或启用 net 包的 DNS 解析,不设环境变量就会静默产出不可用文件,或者测试 panic。
- 静态编译 Linux 二进制(部署到 CentOS/RHEL):
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app . - 启用 cgo(如要用 SQLite、systemd 或某些 net 包功能):
CGO_ENABLED=1,且必须确保 runner 安装了对应头文件(apt-get install -y gcc libc6-dev) - 跨平台构建建议用
strategy: matrix,而不是在一个 job 里循环 set + build;matrix 天然隔离环境,避免变量污染 - 产物名带上平台标识,比如
app-${{ matrix.goos }}-${{ matrix.goarch }},否则多个 GOOS/GOARCH 构建会相互覆盖
真正容易被忽略的是 go mod verify —— 它不耗时,但能立刻发现 go.sum 被篡改或依赖被中间人劫持;建议在测试步骤前加一行 go mod verify,哪怕只是防止 CI 流水线被恶意 PR 绕过校验。


















