Enterprise Patterns 在 Golang:使用 Repository Pattern 解耦你的代码
Source: Dev.to
引言:耦合问题
当我们阅读 Martin Fowler 的 Patterns of Enterprise Application Architecture 时,常常会想到旧的 Java 单体系统。然而,在微服务时代,这些模式比以往任何时候都更为重要。
在 Go 应用中,一个常见的错误是把 SQL 查询(SELECT * FROM …)直接写在 HTTP 控制器或业务逻辑里。这会导致代码难以测试,也难以迁移。
今天我们将实现 Repository Pattern(仓储模式)。该模式在领域层(你的业务逻辑)和数据映射层(数据库)之间创建一个抽象层,使得应用能够在不破坏业务核心的前提下演进。

场景
设想一个企业员工管理系统。我们需要创建员工并保存它。我们并不关心数据是保存在 Postgres、MySQL 还是内存中;业务逻辑不应该知道这些细节。
Go 语言实现
实体(领域)
// domain/employee.go
package domain
type Employee struct {
ID string
Name string
Role string
Salary float64
}
仓储接口
// domain/repository.go
package domain
// EmployeeRepository define el contrato para acceder a los datos
type EmployeeRepository interface {
Save(employee *Employee) error
FindByID(id string) (*Employee, error)
}
服务层(业务逻辑)
// service/employee_service.go
package service
import (
"errors"
"enterprise-patterns/domain"
)
type EmployeeService struct {
repo domain.EmployeeRepository
}
func NewEmployeeService(repo domain.EmployeeRepository) *EmployeeService {
return &EmployeeService{repo: repo}
}
func (s *EmployeeService) RegisterEmployee(id, name, role string) error {
if name == "" {
return errors.New("el nombre no puede estar vacío")
}
// Regla empresarial: solo los gerentes pueden tener bonos iniciales (simulado aquí)
emp := &domain.Employee{
ID: id,
Name: name,
Role: role,
}
return s.repo.Save(emp)
}
具体实现(基础设施)
// infrastructure/memory_repo.go
package infrastructure
import (
"errors"
"enterprise-patterns/domain"
)
type InMemoryEmployeeRepo struct {
store map[string]*domain.Employee
}
func NewInMemoryRepo() *InMemoryEmployeeRepo {
return &InMemoryEmployeeRepo{
store: make(map[string]*domain.Employee),
}
}
func (r *InMemoryEmployeeRepo) Save(employee *domain.Employee) error {
if _, exists := r.store[employee.ID]; exists {
return errors.New("el empleado ya existe")
}
r.store[employee.ID] = employee
return nil
}
func (r *InMemoryEmployeeRepo) FindByID(id string) (*domain.Employee, error) {
if emp, ok := r.store[id]; ok {
return emp, nil
}
return nil, errors.New("empleado no encontrado")
}
在 main.go 中使用
// main.go
package main
import (
"fmt"
"enterprise-patterns/infrastructure"
"enterprise-patterns/service"
)
func main() {
// 1. 创建具体实现(基础设施)
repo := infrastructure.NewInMemoryRepo()
// 2. 将仓储注入服务层(领域)
empService := service.NewEmployeeService(repo)
// 3. 执行业务逻辑
err := empService.RegisterEmployee("001", "Carlos Dev", "Senior Engineer")
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Empleado registrado exitosamente usando Repository Pattern!")
}
}
结论
通过使用 Repository Pattern,我们让 EmployeeService 完全不依赖于具体的数据库实现。如果明天想把内存实现换成 MongoDB,只需要在 infrastructure 目录下新增一个实现文件,而业务逻辑代码无需任何修改。这就是稳健的企业级架构。