必须显式设置goos和goarch,否则ci构建的二进制在linux服务器上会报cannot execute binary file;正确命令为goos=linux goarch=amd64 go build -ldflags="-s -w" -o app-linux-amd64 ./cmd/service。

go build 在 CI 中必须指定 GOOS 和 GOARCH
本地开发时 go build 默认生成当前系统平台的二进制,但 CI 环境(通常是 Linux x86_64)和目标部署环境(如生产服务器、K8s Pod)往往不一致。直接用默认构建会出错或无法运行。
- 生产服务几乎都部署在
linux/amd64或linux/arm64,CI 中必须显式设置:GOOS=linux GOARCH=amd64 go build -o bin/app ./cmd/main.go - 若需多平台支持(如同时发布 macOS 和 Windows 客户端),可用矩阵策略,但每个 job 都要单独设
GOOS和GOARCH - 忽略这点会导致:本地能跑,CI 构建成功但部署后
exec format error—— 这是容器启动失败最常见原因之一
go mod download 必须在测试前完成且建议缓存
CI 每次拉新代码后,go mod download 会从公网拉依赖,慢且不稳定。不提前执行或未缓存,后续 go test 或 go build 可能因网络超时失败。
- GitHub Actions 中应放在
setup-go后、test前,用run: go mod download - 务必启用模块缓存:在 workflow 中添加
actions/cache@v4缓存~/.cache/go-build和$GOMODCACHE(即$(go env GOMODCACHE)) - 不缓存时,100+ 依赖的项目单次
go mod download可能耗时 40 秒以上;缓存后通常压到 2 秒内
测试阶段必须加 -race 且覆盖 main 包以外的路径
go test 默认只跑当前目录,CI 中若只写 go test ./... 会漏掉 internal/ 或 pkg/ 下的关键逻辑,导致线上竞态问题暴露不出来。
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
- 正确写法是:
go test -v -race ./...(三个点表示递归所有子包) -
-race开销较大,但 CI 是唯一能稳定复现并发 bug 的环节,不能为提速关闭 - 常见错误:写成
go test -v ./—— 这只测根目录,internal/service根本不执行 - 如果项目有集成测试或 e2e 测试,需额外指定
-tags=integration并确保环境变量就位
ldflags 注入版本信息必须与 git commit 绑定
二进制里没版本号,出问题时根本没法定位是哪次提交编译的。硬编码版本或靠 CI 变量拼接容易错位,必须从 Git 获取真实 commit ID。
- 推荐命令:
go build -ldflags="-X 'main.Version=$(git rev-parse --short HEAD)'" -o bin/app ./cmd/main.go - 确保
main.Version在代码中声明为var Version string,否则链接失败报undefined: main.Version - GitHub Actions 中
git默认 shallow clone,需加步骤:steps: - uses: actions/checkout@v4 with: fetch-depth: 0,否则git rev-parse失败 - 别用
GITHUB_SHA替代git rev-parse:PR 场景下它指向 merge commit,不是实际变更的 commit
CI 中构建准备真正难的不是写对命令,而是让每条命令在不同触发场景(push、PR、tag)下行为一致,且不因 shallow clone、缓存污染、环境变量缺失而静默失败。这些细节不验证,流水线看似绿了,实则埋着交付雷。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










