go中无ddd框架,需靠目录结构、接口与包约束模拟领域边界;领域层仅含实体定义与纯业务逻辑,应用层编排事务,基础设施层实现仓储,值对象须封装并控制序列化,避免过度设计。

Go 里没有“DDD 框架”,只有分层和边界意识
Go 语言本身不提供 AggregateRoot、Repository 这类抽象,也没法靠注解或反射自动装配领域模型。所谓“Go 做 DDD”,本质是用目录结构、接口定义和包约束来模拟领域边界——不是语法支持,而是靠人守规矩。
常见错误是照搬 Java/C# 的分层命名(比如建 domain、application、infrastructure 包后,却把数据库查询逻辑直接写进 domain/entity.go),结果边界迅速塌方。
- 领域层(
domain/)只放struct定义、核心业务方法(不含 I/O)、以及纯函数式校验逻辑 - 应用层(
app/或usecase/)负责编排:调用领域对象 + 调用仓储接口 + 处理事务 - 基础设施层(
internal/infra/)实现仓储接口,例如UserRepo的 PostgreSQL 版本必须放在这里,不能出现在domain/ - 避免跨包直接引用:如果
app/依赖了internal/infra/,说明接口没抽好,或依赖方向反了
仓储接口怎么写才不踩坑
Repository 在 Go 里不是泛型魔法,而是明确的接口契约。很多人一上来就定义 Create(ctx, entity)、Update(ctx, entity),结果发现无法适配缓存、ES、甚至内存 mock——因为这些操作语义太重,且隐含了持久化细节。
真正可维护的仓储接口,应围绕“聚合根”生命周期设计,且只暴露查询能力;写操作交给应用层组合。
- 接口名用具体领域名词,如
UserRepository,而不是泛化的GenericRepo[T] - 方法只返回
error,不返回ctx或db——上下文由调用方传入,数据库连接由实现方持有 - 查询方法优先用 ID 或简单条件,如
FindByID(id string) (*User, error);避免Search(opts SearchOptions)这种模糊入口 - 不要在接口里塞
BeginTx、Commit——事务控制属于应用层职责,仓储只做单次原子操作
值对象和实体怎么区分才不影响序列化
Go 没有“值语义强制校验”机制,struct 默认就是值类型,但开发者常误把身份证号、金额等值对象当成普通字段塞进实体,导致修改时绕过不变性检查,或者 JSON 序列化时暴露内部状态。
典型症状:API 返回的 user.balance 是 float64,但业务要求精度为小数点后两位,且不允许负数——而你只在构造函数里校验了一次,后续被外部直接改了字段。
- 值对象必须封装字段,用小写字母开头(如
amount),只通过构造函数(如NewMoney(amount float64))创建 - 对外暴露只读方法,如
Amount() float64,而非导出字段 - 实现
json.Marshaler和json.Unmarshaler接口,确保序列化行为可控(比如Money输出字符串"12.50"而非浮点数) - 实体(
User、Order)的 ID 字段建议用自定义类型,如type UserID string,避免和普通string混用
为什么不用第三方 DDD 库反而更稳
Go 生态里确实有叫 ddd、go-ddd 的库,但它们多数只是提供模板目录或空接口,实际项目中反而增加认知负担:比如强制你继承某个 BaseEntity,结果为了兼容 ORM 又得加 tag,最终变成“既不像 DDD,也不像 Go”。
真实项目里,最常出问题的是“过度设计”——刚建完 domain/ 就急着加事件总线、CQRS 分离读写、Saga 协调分布式事务。其实 80% 的业务系统,只需要清晰的包边界 + 明确的错误返回 + 领域方法不碰 I/O。
- 先从一个聚合根开始:比如
Order,写全它的创建、支付、取消逻辑,再拆出OrderRepository接口 - 错误类型用自定义
error,如ErrOrderAlreadyPaid,别堆fmt.Errorf("order %s already paid") - 测试时,用内存实现替代数据库:写个
memOrderRepo满足接口即可,不用启动 PostgreSQL - 当团队开始自然地说“这个逻辑应该放在
domain/order里”,而不是“这个要走 service 层”,说明分层已生效
DDD 在 Go 里不是技术方案,是协作契约。最难的部分从来不是代码怎么写,而是所有人对“用户”“订单”“库存”的理解是否一致——而这个,没法靠 go mod tidy 解决。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











