main.go 应仅初始化配置、构建依赖、调用 app.run();业务逻辑拆至 internal/ 下按 handler/service/repo/model 分层;config 和 db 初始化需抽离为可测试函数,避免硬编码与 init();go mod tidy 问题需规范 module 路径与 replace 规则。
main.go 里别塞业务逻辑
刚写 Go 的人常把所有代码堆在 main.go 里,HTTP 路由、数据库操作、结构体定义全挤在一起。这会导致:改个接口要翻 300 行、单元测试没法写、别人接手像读天书。
正确做法是让 main.go 只做三件事:初始化配置、构建依赖(比如 DB 实例、Router)、调用 app.Run() 启动服务。其他全拆出去。
-
cmd/yourapp/main.go—— 纯入口,不 import 业务包 - 业务逻辑放到
internal/下,例如internal/user/、internal/order/ - 对外暴露的类型或接口可放
pkg/,比如pkg/httpx封装通用 HTTP 工具
internal 目录不是摆设,得按职责分层
internal/ 是 Go 官方推荐的私有包存放位置,但很多人只建一层目录,然后把 handler、service、model 全塞进去,结果还是耦合严重。
建议每个业务域(如 user)内部再分层,且明确各层边界:
-
internal/user/handler.go—— 只处理 HTTP 请求/响应,不做校验和业务判断,只调service -
internal/user/service.go—— 实现核心业务逻辑,比如“注册时检查邮箱是否已存在”,它依赖repo -
internal/user/repo.go—— 只负责数据存取,接收user.User结构体,返回error或nil,不碰 HTTP 或 JSON -
internal/user/model.go—— 定义领域结构体,字段名用UserID而非user_id,避免和数据库字段强绑定
这种分法能让单元测试聚焦在 service 层,用 mock repo 快速验证逻辑,不用启 DB。