DDD::repo.go

repo.go 里面写的都是接口

ChatGPT said:

💯 完全正确!你抓到了 DDD 和 Kratos 架构的一个核心原则。

是的------repo.go(或 repository.go) 文件里写的就是接口(interface) ,不写具体实现。

下面我来系统讲清楚:为什么要这么做、repo 接口应该长什么样、它和 data 层是怎样配合的。


🧩 一、repo.go 是干嘛的?

在 DDD(领域驱动设计)中,仓储(Repository)是领域层的一部分,用来:

把领域对象(Entity / Aggregate)从持久化介质中取出或保存进去,

并屏蔽数据库等基础设施的细节。

也就是说:

  • 领域层(domain) 只定义仓储接口(描述"要干什么");
  • 数据层(data) 来实现这些接口(描述"怎么干")。

📦 二、典型的 repo.go 示例

假设我们在 internal/domain/order/ 下有一个 repo.go

scss 复制代码
package order

import "context"

// Repository 是订单仓储接口
type Repository interface {
	// 保存订单
	Save(ctx context.Context, order *Order) error

	// 根据ID获取订单
	FindByID(ctx context.Context, id OrderID) (*Order, error)

	// 获取用户的所有订单
	ListByUserID(ctx context.Context, userID string) ([]*Order, error)

	// 删除订单
	Delete(ctx context.Context, id OrderID) error
}

特点:

  • 只定义接口(不关心怎么实现);
  • ✅ 入参/出参都是领域对象(Order, OrderID);
  • ✅ 不暴露数据库类型(如 gorm.Modelsql.DB);
  • ✅ 语义贴近领域(Save、FindByID、ListByUserID)。

🏗️ 三、为什么接口放在领域层?

👉 这是 依赖倒置原则(Dependency Inversion Principle) 的体现:

职责 依赖方向
usecase 调用仓储做业务逻辑 依赖 domain.Repository 接口
domain 定义领域模型 + 仓储接口 不依赖下层
data 实现仓储接口 依赖 domain.Repository 定义

也就是说:

kotlin 复制代码
usecase ───→ domain (interface)
             ↑
             └── data (implementation)

这样:

  • usecase 只知道接口,不知道数据库;
  • data 层只管实现接口,替换实现不会影响上层逻辑;
  • 业务层和数据层完全解耦。

⚙️ 四、对应的 data 层实现

internal/data/order_repo.go

go 复制代码
package data

import (
	"context"
	"ddd-kratos/internal/domain/order"
)

type orderRepo struct {
	data *Data // Data 持有数据库、缓存等实例
}

// NewOrderRepo 是仓储的构造函数
func NewOrderRepo(data *Data) order.Repository {
	return &orderRepo{data: data}
}

func (r *orderRepo) Save(ctx context.Context, o *order.Order) error {
	return r.data.db.WithContext(ctx).Save(o).Error
}

func (r *orderRepo) FindByID(ctx context.Context, id order.OrderID) (*order.Order, error) {
	var entity order.Order
	if err := r.data.db.WithContext(ctx).First(&entity, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &entity, nil
}

func (r *orderRepo) ListByUserID(ctx context.Context, userID string) ([]*order.Order, error) {
	var list []*order.Order
	err := r.data.db.WithContext(ctx).Where("user_id = ?", userID).Find(&list).Error
	return list, err
}

func (r *orderRepo) Delete(ctx context.Context, id order.OrderID) error {
	return r.data.db.WithContext(ctx).Delete(&order.Order{}, "id = ?", id).Error
}

🧠 五、这样分层的好处

优点 说明
解耦 业务逻辑不依赖数据库实现
🧪 可测试 usecase 层可以用 mock repository 测试
🔄 可替换 想从 MySQL 换成 MongoDB,只需改 data 层
🧱 结构清晰 domain 纯业务,data 纯实现

✅ 总结一句话

repo.go 写的是 仓储接口 ,位于 domain 层;

它定义了"要提供什么数据访问能力",而不管"怎么实现";

具体的实现放在 data 层,用数据库或其他方式实现这些接口。

相关推荐
维构lbs智能定位3 分钟前
融合定位室内外系统:从核心架构、技术原理到部署实施流程等详解(四)
大数据·架构·融合定位室内外系统
我有一棵树3 分钟前
淘宝 npm 镜像与 CDN 加速链路解析:不只是 Registry,更是分层静态加速架构
前端·架构·npm
逐云者1236 分钟前
构建高效任务中心:CDC 数据同步的工程实践与架构权衡
人工智能·架构·大模型·数据中心·cdc·任务中心·大数据同步
维构lbs智能定位6 分钟前
室内外融合定位系统从核心架构、技术原理到部署实施流程等详解(三)
架构·室内外融合定位系统
国科安芯1 小时前
商业卫星载荷FPGA转RISC-V架构MCU方案经济性评估
单片机·嵌入式硬件·fpga开发·架构·安全威胁分析·risc-v
San30.1 小时前
从面向对象 CSS 到原子化架构:Tailwind CSS 与 React 性能优化实践
css·react.js·架构
酌沧2 小时前
编程智能体Cline的核心架构
架构·状态模式
‿hhh3 小时前
微服务智慧交通管理平台 - 项目实现(结合Qoder搭建)
java·人工智能·机器学习·微服务·架构·需求分析·规格说明书
Henry Zhu1234 小时前
计算机硬件组成详解:从基础原理到现代架构(下)
架构
未知原色15 小时前
web worker使用总结(包含多个worker)
前端·javascript·react.js·架构·node.js