go build . 会编译当前目录所有 package main 的非测试文件,而 go build main.go 仅编译该文件及显式 import 的包,忽略同包其他文件,导致运行时出现 undefined 错误。

直接写 go build 能跑通,但一到发布、CI/CD 或跨平台分发就卡住。关键不是“能不能编译”,而是“哪个参数解决哪类问题”——比如 -o 是刚需,-race 只该调试时开,而 -a 多数时候反而拖慢构建。
go build . 和 go build main.go 的区别在哪
区别在于 Go 如何识别“一个包里有哪些文件”:
-
go build .(或go build ./)会加载当前目录下所有package main的非测试.go文件,不管有没有被显式 import -
go build main.go只编译这个文件 + 它显式import的包,同目录下的utils.go、handler.go全部被忽略 - 现象:运行时报
undefined: xxx,其实是函数定义在没被编译的文件里 - Windows cmd 下
go build *.go通常不展开通配符,Linux/macOS 也受 shell 配置影响,一律不推荐
GOOS/GOARCH 必须成对设置,且不能只设一次
交叉编译不是“设完环境变量再跑 build”,而是每个 go build 命令前都要带上目标平台变量:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 缺一不可:
GOOS=linux GOARCH=amd64 go build -o app-linux ./ - Windows 上用
set GOOS=linux && set GOARCH=amd64 && go build -o app.exe ./(CMD)或$env:GOOS="linux"; $env:GOARCH="amd64"; go build -o app.exe ./(PowerShell) -
GOOS=windows会自动加.exe后缀,其他平台不会;建议显式指定输出名,避免混淆 - 验证方式:
file app-linux-amd64应含ELF 64-bit LSB executable, x86-64;macOS 上file app-darwin-arm64应含Mach-O 64-bit executable arm64
CGO_ENABLED=0 是跨平台稳定的前提
只要用了 net、os/user、sqlite 等默认启用 cgo 的包,不关 CGO 就大概率失败:
立即学习“go语言免费学习笔记(深入)”;
- 典型报错:
exec: "gcc": executable file not found(Windows 编译 Linux)、not found(Linux 二进制在 Alpine 容器里运行失败) - 关掉后:
net回落到纯 Go 实现(稍慢但可靠),os/user只返回 UID/GID(可接受的 trade-off) - 必须每条命令都加:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o app-arm64 ./,不能只设一次环境变量再复用 - 搭配
-ldflags="-s -w"可减体积、去调试信息,适合发布版(但若用了//go:embed或需符号表,慎用-s)
最容易被忽略的是:每次换平台构建前,没清缓存就直接跑 go build,结果旧平台的 object 文件被复用,导致二进制行为异常。稳妥做法是加一句 go clean -cache -modcache 再构建。

















