# 模块四层模式 每个业务模块内部采用四层结构:**Domain → Application → Infrastructure → Interfaces**。 ## 四层结构 ``` ┌─────────────────────────────────────┐ │ Interfaces │ ← HTTP Handler, 路由注册 ├─────────────────────────────────────┤ │ Application │ ← 业务逻辑编排 ├─────────────────────────────────────┤ │ Infrastructure │ ← GORM Model, Redis 实现 ├─────────────────────────────────────┤ │ Domain │ ← 实体, 值对象, 接口定义 └─────────────────────────────────────┘ ``` ## 依赖方向 **从上到下依赖,Domain 在最底层,不依赖任何外部包。** | 层 | 职责 | 可以依赖 | 禁止依赖 | |---|---|---|---| | Interfaces | HTTP 入口 | Application, Domain | Infrastructure | | Application | 业务编排 | Domain | Infrastructure, Interfaces | | Infrastructure | 数据持久化 | Domain | Application, Interfaces | | Domain | 业务核心 | 标准库 | 所有外部包 | ## Domain 层 定义业务的核心概念和契约: ```go // domain/entity.go type User struct { ID uint Email string Username string Password string TenantID string } // domain/repository.go — 定义接口,不定义实现 type UserRepository interface { Create(ctx context.Context, user *User) error FindByEmail(ctx context.Context, email string) (*User, error) } ``` Domain 层**零外部依赖**,只使用 Go 标准库。这使得业务逻辑可以独立于框架和数据库进行单元测试。 ## Application 层 编排业务流程,调用 Domain 层定义的接口: ```go // application/service.go type Service struct { repo domain.UserRepository hasher domain.PasswordHasher jwt domain.TokenManager } func (s *Service) Register(ctx context.Context, req domain.RegisterRequest) (*domain.TokenPair, error) { // 1. 验证邮箱唯一性 // 2. 密码哈希 // 3. 创建用户 // 4. 生成 JWT // 5. 返回 Token } ``` Application 层不知道数据是怎么存的(GORM?Redis?),它只依赖 Domain 层定义的接口。 ## Infrastructure 层 提供 Domain 层接口的具体实现: ```go // infrastructure/repository.go type GormUserRepository struct { db *gorm.DB } func (r *GormUserRepository) Create(ctx context.Context, user *domain.User) error { // GORM 实现 } ``` Infrastructure 层实现 Domain 层定义的接口,但 Domain 层不知道 Infrastructure 的存在。 ## Interfaces 层 HTTP 入口,负责请求解析和响应: ```go // interfaces/handler.go func (h *Handler) Register(c *gin.Context) { var req domain.RegisterRequest c.ShouldBindJSON(&req) tokens, err := h.svc.Register(c.Request.Context(), req) response.Success(c, tokens) } ``` ## 好处 1. **可测试**:Domain 层可以脱离数据库进行单元测试 2. **可替换**:换数据库只需写新的 Infrastructure 实现 3. **边界清晰**:每层职责明确,新人容易理解 4. **防止腐败**:Gin 的 `c *gin.Context` 不会渗透到业务逻辑中