Golang初级项目中如何设计目录结构

11次阅读

go项目应将main.go放在cmd/子目录下,如cmd/userapi/main.go;internal/为访问边界,仅父级可导入;pkg/仅放明确复用的通用组件;测试文件与被测文件同目录。

Golang初级项目中如何设计目录结构

main.go 放哪?别塞进根目录

新手常把 main.go 直接丢在项目最外层,结果随着功能增加,根目录迅速满配置、工具脚本和测试文件。Go 官方推荐将入口文件放在 cmd/ 下,每个可执行程序一个子目录。比如项目叫 userapi,就建 cmd/userapi/main.go。这样既支持多命令(如 cmd/userapicmd/migrate),也避免 go build 时误编译非主包。

internal/ 不是摆设,是访问边界的硬约束

internal/ 目录下的包,只能被其父目录或祖先目录的代码导入——这是 Go 编译器强制的可见性规则。初级项目容易把所有业务逻辑塞进 pkg/ 或平铺在根下,导致后期模块耦合严重、无法安全重构。正确做法是:把核心业务逻辑(如用户认证、订单处理)放进 internal/userinternal/order;对外暴露的接口(如 http handler、gRPC service)则放在 pkg/ 或直接由 cmd/ 调用。这样即使未来要抽成独立库,也能快速识别哪些代码能拆、哪些必须保留。

config/ 和 pkg/ 怎么分?看是否会被外部复用

pkg/ 应只放**明确设计为被其他项目复用**的通用能力,比如自定义日志封装 pkg/logger、统一错误码 pkg/errno。而项目专用的配置加载逻辑(如从 YAML 解析数据库地址、自动 fallback 环境变量)必须放在 internal/configcmd/userapi/config.go。常见错误是把 pkg/config 做成万能加载器,结果每次加个新字段都要改签名、发版本。实际中,80% 的配置解析只需在启动时调一次 viper.Unmarshal(),根本不需要抽象成包。

test 相关文件不要单独建 test/ 目录

Go 的测试惯例是:单元测试文件与被测文件同目录,文件名以 _test.go 结尾,比如 internal/user/service.go 对应 internal/user/service_test.go。不建议建顶层 test/ 目录集中放测试——那样会导致导入路径混乱(例如要写 import "myproj/test/mocks"),且 ide 跳转、覆盖率统计都容易出错。集成测试若需独立数据或服务,可放在 internal/user/e2e_test.go,用 //go:build e2e 标签隔离。

立即学习go语言免费学习笔记(深入)”;

myproj/ ├── cmd/ │   └── userapi/ │       └── main.go ├── internal/ │   ├── config/          # 项目专用配置解析 │   ├── user/            # 用户领域逻辑(含 service_test.go) │   └── order/ ├── pkg/                 # 可被其他项目 import 的通用组件 │   └── logger/ ├── go.mod └── dockerfile

真正难的是坚持——比如新增一个“通知”功能,本能想建 pkg/notify,但得先问:这个通知逻辑会不会被另一个项目(比如后台任务系统)直接 import?如果答案是否定的,它就该进 internal/notify。目录结构不是一开始画完就结束的事,而是每次加代码时都要做的判断。

text=ZqhQzanResources