go mod init 必须在 gopath/src 外执行,因 go111module=auto 时若目录在 gopath/src 内会退回到 gopath 模式,忽略 go.mod;建议项目放 ~/projects/myproj 等路径,并用 go mod init github.com/username/repo 规范模块名。

go mod init 为什么必须在 GOPATH/src 外执行
因为 GO111MODULE=auto(默认值)下,只要当前目录或任意父目录在 GOPATH/src 内,Go 就会退回到旧的 GOPATH 模式,忽略 go.mod —— 即使你手动创建了它也没用。
常见错误现象:执行 go mod init myproj 后,go build 仍报 no required module provides package xxx,或者 IDE 中 import 一直标红。
- 确认路径:用
go env GOPATH查出 GOPATH,确保项目不在$GOPATH/src下(比如放在~/projects/myproj更安全) - 强制启用:临时设
GO111MODULE=on可绕过路径判断,但治标不治本,建议直接迁出 GOPATH - 模块名别乱写:
go mod init github.com/username/repo比go mod init myproj更利于后续 import 路径一致
go mod tidy 为什么会自动加依赖又删依赖
go mod tidy 不是“智能猜测”,而是严格按当前代码中实际出现的 import 语句做双向同步:缺的补上,没用的剔除。它不看注释、不看未引用的 vendor、也不管你心里想用哪个版本。
容易踩的坑:
- 有未提交的 .go 文件含新 import?
tidy会立刻拉进来——删掉测试文件再跑一次 - 依赖里间接引入了你不想要的模块(比如某库用了
golang.org/x/net),tidy也会记进go.mod,这是正常行为 - 执行后发现
go.sum变了但没动go.mod?说明只是校验哈希更新,没增删依赖
go get 和 go mod edit 的分工边界在哪
go get 是日常依赖变更的主力命令;go mod edit 是“最后手段”——它绕过 Go 的版本解析逻辑,直接改文件,风险高。
使用场景对比:
- 升级主依赖到 v1.12.0:
go get github.com/sirupsen/logrus@v1.12.0(推荐,会自动处理兼容性) - 替换私有 fork:
go mod edit -replace github.com/old/lib=github.com/your/fork@main(必须配go mod tidy生效) - 手动删 require 行?别手改
go.mod—— 改完大概率触发go build报错,因为缓存和go.sum对不上
go mod vendor 后为什么还要加 -mod=vendor
go mod vendor 只是把依赖复制到 vendor/ 目录,Go 默认构建时仍优先读 go.mod 并从远程或本地缓存加载——vendor 目录此时形同虚设。
真正启用 vendor 的唯一方式是显式指定:
- 构建时:
go build -mod=vendor - 测试时:
go test -mod=vendor - CI/CD 环境没网络?漏写
-mod=vendor就会卡在go: downloading ... -
vendor/modules.txt是自动生成的,别提交它;但vendor/整个目录建议提交 Git,否则离线构建失效
最常被忽略的一点:go.sum 的哈希校验只对 go mod download 或 go build(非 vendor 模式)生效;一旦用了 -mod=vendor,Go 就完全跳过校验——所以 vendor 目录本身必须可信且受控。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











