go mod init 是创建新模块的唯一标准入口,必须在空目录或仅含源码文件的目录中执行,模块路径需为全局唯一可解析的导入前缀(如 github.com/username/project),不可随意填写;它不下载依赖,仅生成基础 go.mod,后续 go build 或 go mod tidy 才触发依赖分析与填充。

Go 1.11 引入模块(module)后,go mod init 是创建新模块的唯一标准入口,不是可选步骤,而是构建可复现依赖的前提。跳过它或随意填写模块名,后续 go build、go test 都可能静默降级为 GOPATH 模式,导致依赖解析异常。
模块路径必须是全局唯一且可解析的
模块路径(即 go mod init 后跟的参数)本质是导入路径前缀,不是项目名也不是文件夹名。它应反映代码未来被他人 import 时的真实路径。
- 推荐用托管地址:例如 GitHub 仓库
github.com/username/project,即使本地未 push 也应如此设定 - 避免使用
example.com或myproject这类无意义占位符——它们会导致go get失败,且无法被其他模块正确引用 - 若项目不对外公开,仍建议用私有域名(如
git.internal.company/project),并配合GOINSECURE或私有代理配置
初始化时当前目录必须为空或仅含源码文件
go mod init 会扫描当前目录下所有 .go 文件,自动推导依赖并写入 go.mod。如果目录里混有旧的 Gopkg.lock、vendor/ 或已编译二进制,不会报错,但可能漏掉间接依赖或误判主模块路径。
- 执行前先清理:运行
rm -rf vendor/ Gopkg.lock go.sum(如有) - 确保
go.mod不存在,否则go mod init会直接报错go.mod already exists - 如果已有
go.mod但想重置,需先删除再重新 init,不能靠覆盖
go mod init 不会自动下载依赖,但会影响后续行为
执行 go mod init example.com/foo 只生成最简 go.mod,内容类似:
module example.com/foo go 1.21
此时运行 go build 才会触发依赖分析,并自动生成 go.sum 和填充 require 条目。常见误解是认为 init 会拉取包——它不会。
- 如果项目已 import 第三方包(如
"golang.org/x/sync/errgroup"),首次go build会失败并提示 “missing go.sum entry”,这是正常流程 - 想预加载所有依赖?用
go mod tidy,而不是反复调用 init - 模块 Go 版本由
go mod init自动设为当前go version输出的主版本(如 go1.21),不可手动指定小版本
子模块或内部工具库要单独 init,不能共享父目录 go.mod
一个文件夹下只能有一个 go.mod。若你在 cmd/app/ 和 internal/pkg/ 分别运行 go mod init,Go 会把后者识别为独立模块——但实际它们属于同一代码库,这种拆分会导致版本不一致、测试失败、replace 难以维护。
- 正确做法:只在仓库根目录运行一次
go mod init github.com/user/repo - 子目录通过相对 import 路径引用,例如
github.com/user/repo/internal/pkg - 只有当你明确要发布独立可导入的库(如
github.com/user/repo/v2)时,才在子目录新建模块并 init
最容易被忽略的是模块路径和实际 Git 仓库地址的对齐。CI 构建、Go Proxy 缓存、甚至 go list -m all 的输出,都依赖这个路径的真实性。随便写个名字,短期能跑,长期会让协作和升级变成黑洞。










