Go Clean Architecture 的第一道红线是 cmd 必须极简cmd/api/main.go 仅解析 flag、调用 app.Run()、返回 error配置加载、DB 初始化、路由注册等全下沉至 internal/app禁止在 cmd 中 import infrastructure 或 repository。cmd 目录里只放 main.go别的都算越界Go Clean Architecture 的第一道红线就是cmd 必须极简——它不是启动脚本集合更不是配置加载中心。你塞进去的每一行初始化代码都在给单元测试埋雷。cmd/api/main.go 只做三件事解析 flag、调用 app.Run()、返回 error其余全甩给 internal/app禁止在 cmd 里 import internal/infrastructure 或 internal/repository否则依赖箭头就反了domain 层反而被 infra 拖着走常见错误现象go test ./... 报错 “cannot load config: no such file”根源是 main.go 里硬编码了 viper.ReadInConfig()导致测试时绕不开文件系统正确做法把配置加载、DB 连接池创建、HTTP 路由注册全部下沉到 app.NewApp()main.go 仅负责“启动”这个动作domain 层不能出现 sql.NullString 或 time.Time领域模型一旦带上数据库或框架类型就等于给业务逻辑焊死了持久化方式——这不是设计是自缚手脚。domain/user.go 中的时间字段必须是 CreatedAt string 或 type CreatedAt time.Time自定义类型不直接用标准库 type转换逻辑交给 internal/adapter空值语义统一用 Go 原生指针*string、*int64而不是 sql.NullString后者绑死了 database/sql 的 Scan/Value 方法mock 仓库时根本没法构造合法实例ORM tag如 gorm:column:name只能出现在 internal/adapter/repository 的映射结构体里绝不出现在 domain 层使用场景写单元测试时你要用内存仓库模拟用户创建如果 domain 结构体含 sql.NullString连 json.Unmarshal 都会失败——因为它的内部字段不可导出go mod tidy 后 go.sum 疯涨先查是不是误引了重型 SDKgo.sum 膨胀本身不危险但若里面混进 google.golang.org/grpc/cmd/protoc-gen-go-grpc 或 golang.org/x/tools说明 build 流程已把开发期工具打进生产依赖。 Mokker AI AI产品图添加背景