go mod tidy 慢的主因是触发远程校验和下载,国内未配代理时sum.golang.org TLS握手常卡5–10秒;应设GOPROXY=https://goproxy.cn,direct并酌情配GOSUMDB=off(开发环境)或sum.golang.google.cn(生产)。

go mod tidy 为什么每次都在下载依赖
不是 go mod tidy 本身慢,而是它触发了模块校验和远程拉取——尤其在国内没配代理时,sum.golang.org TLS 握手常卡 5–10 秒,且每改一次 go.mod 就重来一遍。
- 确认是否真在下载:执行
go mod tidy -v,看输出里有没有大量go: downloading - 国内必须设代理:
GOPROXY=https://goproxy.cn,direct(不是https://goproxy.io,后者已停服) - 禁用校验可跳过 sum 检查:
GOSUMDB=off(仅开发环境,CI 中慎用) - 如果项目用了
replace指向本地路径,go mod tidy会反复扫描该目录,建议改用go mod edit -replace静态写入,避免运行时解析
vendor 目录到底要不要用
go build -mod=vendor 能彻底绕过网络,但代价是维护成本和缓存失效风险——$GOCACHE 对 vendor 内包的复用率极低,且 go mod vendor 本身不智能,会把未使用的间接依赖也拖进来。
- 适合场景:CI 构建、离线环境、或依赖频繁变更且无法信任 proxy 的团队
- 不适合场景:日常开发——改一行代码后
go build -mod=vendor仍要全量扫描 vendor/ 下所有 .go 文件 - 替代方案更轻量:
go mod download提前拉好依赖,再配合-mod=readonly,既保网络隔离又不丢$GOCACHE增量能力 - 若坚持用 vendor,请搭配
go mod vendor -o vendor并 git commit vendor/,否则go build可能漏包
go list 怎么精准定位变更包
大型项目里,90% 的修改只影响 2–3 个包,但 go build ./... 默认扫全树。用 go list 结合 git 可锁定真实影响范围,跳过无关包编译。
- 基础命令:
git status --porcelain | grep '\.go$' | xargs dirname | sort -u | xargs go list -f '{{.ImportPath}}' - 注意过滤 vendor 路径:
... | grep -v '^vendor/',否则可能误把第三方包当主模块包 - 输出含
main包时,要显式加上其依赖项:go list -deps -f '{{.ImportPath}}' ./cmd/myapp - CI 中可固化为脚本:
go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' all | grep -v 'vendor\|golang.org',排除标准库和 vendor
交叉编译时缓存为何完全不生效
GOOS=linux go build 和 GOOS=darwin go build 使用的是不同子缓存目录,这本身没问题;但一旦混用 CGO_ENABLED=0 和 CGO_ENABLED=1,哪怕其他参数全一样,$GOCACHE 也完全不共享——因为 cgo 开关会改变底层 C 编译器调用链和符号生成逻辑。
立即学习“go语言免费学习笔记(深入)”;
- 检查当前缓存命中率:
go env GOCACHE后执行du -sh $(go env GOCACHE)/* | sort -hr | head -5,看是否有大量小目录堆积 - CI 中固定 cgo 状态:
CGO_ENABLED=0 GOOS=linux go build -trimpath -mod=readonly -o app - 开发机若需同时支持 cgo/non-cgo,建议分目录构建,比如
build/linux-cgo/和build/linux-static/,避免缓存污染 - 别信 “缓存自动适配”——Go 不会合并不同 cgo 设置下的产物,这是设计使然,不是 bug
缓存目录 $GOCACHE 看似透明,但它对路径、cgo、embed、甚至 git 工作区状态都敏感;最常被忽略的是:你改完代码跑 go run main.go,它根本不用 $GOCACHE,而用临时目录编译——这种“伪快感”会掩盖真实瓶颈。


















