跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Clean Architecture在Go网络协议层架构落地

协议层应置于adapters或interface adapters层,HTTP/gRPC/WebSocket等协议处理代码(路由、绑定、响应)不得进入usecase或domain;DTO与domain实体须显式单向转换,时间字段用Clock接口抽象,JSON/protobuf/db tag严禁出现在domain中。 Go 里 Clean Architecture 落地到网络协议层(如 HTTP、gRPC、WebSocket),关键不是“加一层 adapter”,而是让协议细节彻底不出现在 domain 和 usecase 中——否则协议变更(比如从 HTTP 换成 gRPC)就会牵动业务逻辑。 protocol 层该放在哪一层? 协议处理代码(路由注册、中间件、request binding、response writing)必须属于
adapters
或
interfaces
层,不能进
usecase
,更不能进
domain
。常见错误是把
http.HandlerFunc
直接写在 usecase 包里,或让 usecase 接收
*http.Request
。 正确做法:在
adapters/http
下写 controller,它只做三件事:解析请求 → 调用 usecase → 格式化响应 controller 构造函数接收 usecase 接口(如
CreateUserUsecase
),不 import 任何 infra 包 HTTP-specific 错误码(如
http.StatusConflict
)只出现在 controller 层,usecase 返回的错误必须是 domain 定义的错误类型(如
ErrEmailAlreadyExists
) gRPC 的
.proto
生成代码建议放在
adapters/grpc/pb
,服务实现(
UnimplementedUserServiceServer
)放在
adapters/grpc
,同样只调用 usecase 如何避免 protocol 层污染 domain 实体? 最常踩的坑是把协议相关字段塞进 domain struct,比如加
CreatedAt time.Time
或
UpdatedAt *time.Time
,或者用
json:"id"
tag 绑定 HTTP 序列化逻辑。 domain 实体字段只能用基础类型(
string
,
int64
)、自定义枚举、或 domain 内定义的值对象(如
type Email string
) 时间字段应抽象为接口传入:定义
Clock
接口,在 controller 层 new 一个
realClock{}
注入 usecase,再注入 domain 实体方法 JSON tag 必须剥离:domain struct 不写任何
json:
、
protobuf:
或
db:
tag;DTO(如
user_http_response
)才负责序列化适配 DTO 和 domain 实体之间转换必须显式、单向:controller 层用
mapToDomain()
和
mapToResponse()
,不复用 struct,不嵌套指针引用 WebSocket / MQTT 等长连接协议怎么适配? 这类协议本质仍是输入/输出适配器,但生命周期和调用模型不同——不能按 HTTP 那样“一次请求一次 usecase 调用”。核心原则不变:协议状态管理归 adapter,业务动作仍走 usecase。 在
adapters/ws
中启动连接管理器(
ConnectionManager
),它持有
UserSession
状态,但不碰业务规则 收到消息后,提取 payload → 构造 input DTO → 调用对应 usecase(如
wsUC.HandleChatMessage(input)
) usecase 执行完返回 domain event(如
MessageSentEvent
),adapter 再决定推送给谁、是否广播、是否存档 切忌在 usecase 里调用
conn.WriteMessage()
或持有
*websocket.Conn
—— 这等于把 transport 细节拖进业务层 协议层最容易被忽略的复杂点,是错误传播路径。HTTP 返回 400 是因为参数校验失败,gRPC 返回
InvalidArgument
是同一语义,但它们不该由 usecase 判断;应该由 adapter 做初步校验(如 JSON 解析失败、必填字段缺失),再把 clean input 交给 usecase,让 usecase 只专注领域规则校验(如“余额不足”)。混淆这两类错误,会直接破坏 Clean Architecture 的边界感。

相关文章