应该用cmd目录放主程序,这是官方推荐做法;cmd下每个子目录对应一个独立二进制,main.go仅含启动逻辑,业务代码须下沉至internal/或pkg/,二者按可见性严格区分。

Go项目该不该用cmd目录放主程序
应该,而且这是官方推荐做法。把main函数放在cmd/子目录下(如cmd/myapp),能清晰区分可执行入口和可复用库代码。否则所有main.go散落在根目录,随着命令增多会迅速失控——比如你后续加个myapp-admin或myapp-migrate,不靠目录隔离就只剩复制粘贴和命名混乱。
实操建议:
-
cmd/下每个子目录对应一个独立二进制,且只包含main.go和极少量启动逻辑 - 业务逻辑必须下沉到
internal/或pkg/,cmd/里禁止写数据库操作、HTTP路由注册等 - 避免
cmd/main.go这种扁平结构——Go工具链会把它识别为包main,但无法支持多命令构建
internal/和pkg/到底怎么分
按可见性划分:internal/里的代码只能被本项目导入,pkg/则设计为可被外部项目引用。这不是风格偏好,而是Go编译器的硬性规则——任何路径含/internal/的包,若被非其父目录的项目导入,go build直接报错use of internal package not allowed。
常见误用场景:
立即学习“go语言免费学习笔记(深入)”;
- 把通用工具函数(如
uuid.New()封装)放在internal/utils,结果其他项目想复用却导不进去 → 应移至pkg/utils - 把领域核心类型(如
Order结构体、OrderService接口)放在pkg/domain,但实际只供本项目使用 → 反而该进internal/domain,避免过早承诺API稳定性 -
internal/下嵌套过深(如internal/handler/http/v1) → Go不需要Java式分层,扁平化更利于查找,优先用internal/handler+ 清晰命名(http_handler.go,grpc_handler.go)
测试文件和mock要不要单独建test/目录
不要。Go测试惯例是把xxx_test.go和被测文件放在同一目录,且命名严格匹配(service.go对应service_test.go)。额外建test/目录会导致go test ./...漏掉测试,IDE也无法自动关联跳转。
mock处理原则:
- 单元测试需要mock时,优先用接口+匿名结构体(
struct{ DoSomething func() }),而非生成mock文件 - 必须用gomock或wire等工具生成mock时,把生成的
mock_xxx.go放在对应包的internal/xxx/mock下(如internal/payment/mock),而非顶层test/mock - 集成测试(如调用真实DB或HTTP服务)可单独放
integration/目录,但需在go.mod中用//go:build integration标注,避免日常go test误执行
Go Modules初始化后go.mod路径写错怎么办
模块路径(module声明)必须与代码实际可导入路径一致,否则其他项目go get会失败。典型错误是本地开发时写成module myapp,但仓库地址其实是github.com/username/myapp——别人go get github.com/username/myapp后,Go会去查github.com/username/myapp/go.mod里的module值,发现是myapp,于是报错cannot find module providing package。
修复步骤:
- 运行
go mod edit -module github.com/username/myapp(确保和GitHub路径完全一致,含大小写) - 检查所有
import语句是否已更新,尤其internal/包的导入路径(旧路径import "myapp/internal/config"要改成import "github.com/username/myapp/internal/config") - 执行
go mod tidy重新解析依赖,再跑一遍go build ./...确认无编译错误
模块路径一旦发布就不可更改,所以初始化时就要想清楚域名和组织名——别用localhost或test占位,那只是给自己埋雷。










