CGO_ENABLED=0必须显式设置,否则交叉编译出的二进制默认动态链接libc,在Alpine等无C库环境会报错;仅设GOOS/GOARCH无效,且需配合go mod tidy确保依赖完整。

CGO_ENABLED=0 不设就打包失败
Ubuntu 上交叉编译出的二进制默认依赖 libc,一放到 Alpine 或无 C 库环境就报 no such file or directory 或直接 panic: runtime error: invalid memory address。这不是 Go 本身问题,而是链接时绑定了动态符号。
必须显式关闭 CGO:在 go build 前加 CGO_ENABLED=0,否则即使指定了 GOOS=linux GOARCH=amd64 也白搭。
- 只在构建阶段设,不影响开发时调试(如 sqlite 需要 CGO)
- 若代码里用了
cgo注释(比如// #include <sys/stat.h>),关掉后会编译失败,得先确认是否真需要 C 交互 - Docker 多阶段构建中,
builder阶段也要设,不然中间产物仍含动态链接
go.mod 未 tidy 就打包,运行时报 missing module
本地能跑不代表打包后能跑。常见现象是:本地 go run main.go 成功,但 go build 出的二进制在另一台机器上启动就报 failed to initialize module graph: cannot find module providing package。
根本原因是依赖没锁死或 vendor 没同步 —— go.mod 里可能有 replace 或 require 指向本地路径、未发布的分支,或者 go.sum 缺失校验和。
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 打包前务必执行
go mod tidy,它会自动补全缺失依赖、清理未用项、更新go.sum - CI/CD 中建议加
go list -m all检查模块树是否完整,避免隐式依赖漏掉 - 若用
vendor,得配go build -mod=vendor,且确保vendor/已由go mod vendor生成并提交
main 包混在库目录里,go build 找不到入口
错误提示通常是 no Go files in ... 或 cannot find package ".",但实际原因是:你把 package main 放进了 pkg/、internal/ 或其他非根目录下,而 go build 默认只认当前目录或显式指定路径下的 main 包。
Go 不靠文件名识别入口,只看 package main + func main() 组合,并且该组合必须位于可构建上下文中。
-
go build不带参数时,只构建当前目录下的main包;想构建子目录,得写go build ./cmd/myapp - 别在
pkg/目录下放main.go—— 这会让go list ./...报错,且 IDE 可能误判为库包 - 多命令项目(如 CLI 工具含多个二进制),每个应独立成
cmd/name/main.go,用go build ./cmd/...分别构建
文件权限没改,二进制丢在 Ubuntu 上不能直接执行
打包后复制到目标机器,./myapp 报 Permission denied。不是 SELinux 或 root 权限问题,就是最朴素的 Unix 权限位没开。
Go 编译器不负责设置可执行位,Linux 下默认生成的是 -rw-r--r-- 权限。
- 构建完立刻加
chmod +x ./myapp,别等部署时才发现 - CI 脚本里建议链式执行:
go build -o myapp . && chmod +x myapp - 如果用 Docker COPY,注意 COPY 默认保留源文件权限,但若源文件本身不可执行,镜像里也不会自动变可执行
CGO_ENABLED 和 go mod tidy 这两个开关——它们不报错,但会让二进制在“看似编译成功”的假象下,运行时当场崩溃。

















