name: golang-enterprise-patterns description: 企业级Go架构模式,包括整洁架构、六边形架构、领域驱动设计(DDD)以及生产就绪的应用结构。 author: Joseph OBrien status: 未发布 updated: ‘2025-12-23’ version: 1.0.1 tag: 技能 type: 技能
Golang 企业级模式
本技能提供关于企业级Go应用程序架构、设计模式和生产就绪代码组织的指导。
何时使用此技能
- 设计具有复杂业务逻辑的新Go应用程序时
- 实施整洁架构或六边形架构时
- 应用领域驱动设计(DDD)原则时
- 组织大型Go代码库时
- 建立团队一致性模式时
整洁架构
分层结构
/cmd
/api - HTTP/gRPC入口点
/worker - 后台作业运行器
/internal
/domain - 业务实体和接口
/application - 用例和应用服务
/infrastructure
/persistence - 数据库实现
/messaging - 队列实现
/http - HTTP客户端实现
/interfaces
/api - HTTP处理器
/grpc - gRPC处理器
/pkg - 共享库(公共)
依赖规则
依赖关系仅向内流动:
接口 → 应用 → 领域
↓ ↓
基础设施(实现领域接口)
领域层
// domain/user.go
package domain
import "time"
type UserID string
type User struct {
ID UserID
Email 字符串
Name 字符串
CreatedAt 时间.时间
}
// UserRepository 定义用户持久化的契约
type UserRepository interface {
FindByID(ctx 上下文.上下文, id UserID) (*User, 错误)
FindByEmail(ctx 上下文.上下文, email 字符串) (*User, 错误)
Save(ctx 上下文.上下文, user *User) 错误
Delete(ctx 上下文.上下文, id UserID) 错误
}
// UserService 定义领域业务逻辑
type UserService interface {
Register(ctx 上下文.上下文, email, name 字符串) (*User, 错误)
Authenticate(ctx 上下文.上下文, email, password 字符串) (*User, 错误)
}
应用层
// application/user_service.go
package application
type UserServiceImpl struct {
repo 领域.UserRepository
hasher 密码哈希器
logger 日志记录器
}
func NewUserService(repo 领域.UserRepository, hasher 密码哈希器, logger 日志记录器) *UserServiceImpl {
return &UserServiceImpl{repo: repo, hasher: hasher, logger: logger}
}
func (s *UserServiceImpl) Register(ctx 上下文.上下文, email, name 字符串) (*领域.User, 错误) {
// 检查用户是否存在
existing, err := s.repo.FindByEmail(ctx, email)
if err != nil && !errors.Is(err, 领域.ErrNotFound) {
return nil, fmt.Errorf("检查现有用户: %w", err)
}
if existing != nil {
return nil, 领域.ErrUserAlreadyExists
}
user := &领域.User{
ID: 领域.UserID(uuid.New().String()),
Email: email,
Name: name,
CreatedAt: 时间.Now(),
}
if err := s.repo.Save(ctx, user); err != nil {
return nil, fmt.Errorf("保存用户: %w", err)
}
return user, nil
}
六边形架构(端口与适配器)
端口定义
// ports/primary.go - 驱动端口(输入)
package ports
type UserAPI interface {
CreateUser(ctx 上下文.上下文, req CreateUserRequest) (*UserResponse, 错误)
GetUser(ctx 上下文.上下文, id 字符串) (*UserResponse, 错误)
}
// ports/secondary.go - 被驱动端口(输出)
type UserStorage interface {
Save(ctx 上下文.上下文, user *领域.User) 错误
FindByID(ctx 上下文.上下文, id 字符串) (*领域.User, 错误)
}
type NotificationSender interface {
SendWelcomeEmail(ctx 上下文.上下文, user *领域.User) 错误
}
适配器实现
// adapters/postgres/user_repository.go
package postgres
type UserRepository struct {
db *sql.DB
}
func (r *UserRepository) Save(ctx 上下文.上下文, user *领域.User) 错误 {
query := `INSERT INTO users (id, email, name, created_at) VALUES ($1, $2, $3, $4)`
_, err := r.db.ExecContext(ctx, query, user.ID, user.Email, user.Name, user.CreatedAt)
return err
}
领域驱动设计(DDD)
聚合根
// domain/order/aggregate.go
package order
type Order struct {
id 订单ID
customerID 客户ID
items []订单项
status 订单状态
events []领域事件
}
func NewOrder(customerID 客户ID) *Order {
o := &Order{
id: 订单ID(uuid.New().String()),
customerID: customerID,
status: 状态待处理,
}
o.recordEvent(订单已创建{订单ID: o.id, 客户ID: customerID})
return o
}
func (o *Order) AddItem(productID 产品ID, quantity int, price 货币) 错误 {
if o.status != 状态待处理 {
return 错误订单不可修改
}
o.items = append(o.items, 订单项{
ProductID: productID,
Quantity: quantity,
Price: price,
})
return nil
}
func (o *Order) Submit() 错误 {
if len(o.items) == 0 {
return 错误空订单
}
o.status = 状态已提交
o.recordEvent(订单已提交{订单ID: o.id})
return nil
}
值对象
// domain/money.go
type Money struct {
amount int64 // 分
currency 字符串
}
func NewMoney(amount int64, currency 字符串) (Money, 错误) {
if amount < 0 {
return Money{}, 错误负金额
}
return Money{amount: amount, currency: currency}, nil
}
func (m Money) Add(other Money) (Money, 错误) {
if m.currency != other.currency {
return Money{}, 错误货币不匹配
}
return Money{amount: m.amount + other.amount, currency: m.currency}, nil
}
领域事件
// domain/events.go
type DomainEvent interface {
EventName() 字符串
OccurredAt() 时间.时间
}
type OrderCreated struct {
OrderID 订单ID
CustomerID 客户ID
occurredAt 时间.时间
}
func (e OrderCreated) EventName() 字符串 { return "order.created" }
func (e OrderCreated) OccurredAt() 时间.时间 { return e.occurredAt }
依赖注入
Wire风格DI
// wire.go
//+build wireinject
func InitializeApp(cfg *config.Config) (*App, 错误) {
wire.Build(
NewDatabase,
NewUserRepository,
NewUserService,
NewHTTPServer,
NewApp,
)
return nil, nil
}
手动DI(推荐用于简单性)
// main.go
func main() {
cfg := config.Load()
db := database.Connect(cfg.DatabaseURL)
userRepo := postgres.NewUserRepository(db)
orderRepo := postgres.NewOrderRepository(db)
userService := application.NewUserService(userRepo)
orderService := application.NewOrderService(orderRepo, userRepo)
handler := api.NewHandler(userService, orderService)
server := http.NewServer(cfg.Port, handler)
server.Run()
}
错误处理模式
自定义错误类型
// domain/errors.go
type Error struct {
Code 字符串
Message 字符串
Err 错误
}
func (e *Error) Error() 字符串 {
if e.Err != nil {
return fmt.Sprintf("%s: %s: %v", e.Code, e.Message, e.Err)
}
return fmt.Sprintf("%s: %s", e.Code, e.Message)
}
func (e *Error) Unwrap() 错误 { return e.Err }
var (
ErrNotFound = &Error{Code: "NOT_FOUND", Message: "资源未找到"}
ErrUserAlreadyExists = &Error{Code: "USER_EXISTS", Message: "用户已存在"}
ErrInvalidInput = &Error{Code: "INVALID_INPUT", Message: "无效输入"}
)
配置管理
// config/config.go
type Config struct {
Server 服务器配置
Database 数据库配置
Redis Redis配置
}
func Load() (*Config, 错误) {
cfg := &Config{}
cfg.Server.Port = getEnvInt("PORT", 8080)
cfg.Server.ReadTimeout = getEnvDuration("READ_TIMEOUT", 30*时间.Second)
cfg.Database.URL = mustGetEnv("DATABASE_URL")
cfg.Database.MaxConns = getEnvInt("DB_MAX_CONNS", 25)
return cfg, nil
}
最佳实践
- 保持领域纯净 - 领域层无框架依赖
- 接口隔离 - 小型、专注的接口
- 依赖倒置 - 依赖抽象,而非具体实现
- 显式依赖 - 通过构造函数传递依赖
- 快速失败 - 在边界处验证,信任内部代码
- 使非法状态不可表示 - 使用类型强制执行不变量