微服务打散需靠抽象分层而非目录拆分,核心是接口契约、concrete type承载业务能力、wire收敛依赖、module按部署单元划分,并确保可单元测试。

大型微服务打散不是靠“拆包”或“建新目录”,而是靠抽象分层把耦合逻辑从代码里抽出来、封住边界、再按职责隔离——否则只会得到一堆更难维护的“微型单体”。
用接口定义契约,而不是用目录结构假装分层
很多人以为把 handler、service、repo 按文件夹切开就完成了分层,结果发现 service 层还在直接调 sql.DB、handler 里塞了校验逻辑、model 被到处 import 修改。真正的分层起点是接口:
- 所有跨层调用必须通过 interface,比如
UserRepository接口,而非具体实现*pgRepo - service 层只依赖 interface,不 import 任何 db 或 http 包;repository 层不碰 request/context,只处理数据存取
- model 层只含结构定义和 JSON tag,禁止加方法、验证逻辑或外部依赖
- 一旦某层开始
import另一层的具体实现(如 service 直接 new 一个 repo),分层就失效了
把“业务能力”落到 concrete type,而不是堆 function
Go 不是 Java,不能靠 interface+abstract class 模拟领域模型。真正能承载业务边界的,是 concrete type + method 组合:
- 比如“下单”是一个完整能力,就该有
type OrderService struct{ ... },它内部聚合InventoryClient、PricingEngine等接口,而不是散落在几十个CalculateXxx()函数里 - 每个 concrete type 对应一个限界上下文(Bounded Context),它的方法只读写自己拥有的数据,不越界操作其他服务的 state
- 避免出现
func ProcessOrderWithInventoryAndPayment(...)这种长命名函数——它暴露了强耦合,应该被拆成orderService.Create()+ 事件驱动通知 inventory/payment
依赖注入必须在编译期收敛,别等 runtime 才发现环形引用
手动 new 一堆依赖看似简单,但随着模块增多,main.go 会变成上帝对象,且无法静态检查循环依赖:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 用
wire工具生成注入器:定义func InitializeApp() (*App, error),wire 自动分析 provider 链并报错 - 所有 provider 必须返回 interface,例如
func NewUserRepo(db *sql.DB) UserRepository,而非具体类型 - 禁止在 provider 里做 heavy init(如连接 DB、加载配置),这些该由上层控制生命周期;provider 只负责组装
- 如果
wire build报circular dependency,说明两个模块本就不该共存于同一服务内,得重新划界
module 划分以 deploy unit 为准,不是以代码量为标准
一个 go.mod 文件代表一个可独立构建、测试、部署的单元。别为了“看起来小”而过度切分:
- 如果 user-service 和 auth-service 总是一起发布、共享数据库 schema、共用一套配置,那它们本质是一个 deploy unit,硬拆只会增加 gRPC 调用和事务协调成本
- 真正该拆的是那些变更频率差异大的部分:比如风控规则频繁迭代,但用户基础信息稳定——那就把
risk-engine单独成 module,用 event 与 user-service 解耦 - 每个 module 的
go.mod只 require 它真正依赖的外部库,禁止replace全局路径来绕过版本约束 - internal 目录不是摆设:所有不对外暴露的实现(如 mock、testutil、私有中间件)必须放
internal/下,否则会被其他 module 无意 import
最常被忽略的点是:分层之后,每个 concrete type 的 method 是否还能在不启动 HTTP server、不连 DB 的情况下被单元测试覆盖?如果不能,说明抽象还没到位——接口没封住依赖,或者业务逻辑仍和 transport 绑定。这不是代码量问题,是契约是否干净的问题。

















