Kratos项目目录结构强制要求/cmd、/internal、/pkg三目录共存:/cmd为唯一合法启动入口且决定二进制名;/internal按biz/data/service三层单向依赖保障可测性与DI;/pkg为对外稳定公共库,三者缺一将导致kratos run失败或编译报错。

Kratos项目目录结构不是可选项,而是编译器和工具链强制依赖的契约——缺了/cmd、/internal、/pkg任意一个,kratos run会失败,go build可能因internal可见性规则报错。
为什么/cmd必须存在且只放main.go
Go 编译器从 Go 1.4 起就硬性规定:internal 包只能被同一模块下、路径中不包含 /internal/ 的包导入。而 /cmd 是唯一能合法 import /internal 和 /api 的地方。
-
/cmd/demo/main.go是整个服务的启动入口,它负责初始化 logger、config、wire 注入容器、注册 HTTP/gRPC server —— 这些逻辑一旦挪进/internal/service,就会导致循环 import 或构建失败 - 每个子目录名(如
/cmd/user)直接决定生成的二进制文件名(user),make build或kratos build依赖这个命名约定 - 若把业务代码塞进
/cmd,后续无法用wire自动生成依赖图,ent generate也找不到data层的实体定义位置
/internal/biz、/internal/data、/internal/service 三层不能合并
这三层不是“风格偏好”,而是 wire 依赖注入、单元测试隔离、接口抽象导出的物理前提。
-
/internal/biz只含领域模型(如Userstruct)和核心逻辑(如UserUsecase.Create()),不 import 任何框架或 transport 层代码 -
/internal/data实现数据访问,必须通过 interface(如UserRepo)被biz依赖;若与biz同包,Go 的包级可见性会让mock失效,go test无法替换真实 DB 调用 -
/internal/service是 transport 层适配器,它 importapi/xxx/v1和/internal/biz,但绝不能 import/internal/data—— 否则 service 层会直连 DB,破坏分层,也无法被独立打包为 RPC client SDK
/api 目录只存 .proto,生成代码严禁手动修改
make api 命令会调用 buf 或 protoc 把 /api/user/v1/user.proto 编译成 api/user/v1/user_http.pb.go 和 api/user/v1/user_grpc.pb.go,这些是契约快照,不是源码。
- HTTP 映射必须用
option (google.api.http)在.proto中声明,不能在service层用http.HandleFunc补充路由 —— 否则swagger.json不会更新,OpenAPI 文档和实际行为脱节 - 生成的
*_pb.go文件要 gitignore 掉(标准模板已配置),否则多人协作时 protobuf 版本/插件差异会导致大量无意义 diff - 若需自定义 HTTP 编解码(如 form 表单),应在
transport/http初始化时传入http.WithEncoder(),而不是改生成代码
/pkg 和 /internal/pkg 的边界经常被搞反
/pkg 是对外的、语义稳定的、带版本号的公共库;/internal/pkg 是项目内复用的私有工具,两者生命周期和发布方式完全不同。
-
/pkg/redis应该有完整 go.mod、README、单元测试,支持go get github.com/yourorg/yourproject/pkg/redis@v1.2.0,且 API 一旦发布就不能破坏兼容性 -
/internal/pkg/zaplog可以随意重构、删减,甚至被/internal/biz直接 copy-paste,因为它只服务于当前项目,不承诺向后兼容 - 把本该放
/internal/pkg的代码误放/pkg,会导致其他团队升级困难(例如你改了个日志字段名,下游所有import /pkg/log的服务都得跟着改)
最常被忽略的一点:目录结构本身是 Kratos 工具链的输入信号。kratos proto client 查找 /api,wire gen 扫描 /internal 下的 biz/data/service,go list ./... 依赖 /cmd 存在才能识别主模块 —— 它们不是“建议”,是硬编码路径。


















