结论:应采用接口抽象、协议适配器和统一容器三件套架构;service 接口与传输协议解耦,统一调用如 usersvc.getuser,参数返回值为纯 go struct,错误统一用 apperror 映射各协议状态码,新增协议只需添加 adapter,监听与关闭由 app 容器统一调度,注册器负责语义转换而非路由硬编码。

直接上结论:别拼凑协议栈,用接口抽象 + 协议适配器 + 统一容器三件套,才能真正复用业务逻辑、避免生命周期混乱。
Service 接口必须与传输协议解耦
业务逻辑不能感知自己是被 HTTP 还是 gRPC 调用。所有协议最终都要调用同一组方法,比如 UserSvc.GetUser(ctx, req),参数和返回值只能是纯 Go struct,不含 http.Header、grpc.RequestInfo 等协议相关字段。
- 错误处理也得统一:定义
AppError类型,含Code(业务码)、HTTPStatus、GRPCCode,由适配器按需映射 - 禁止在 service 层做 JSON 序列化、status code 设置、中间件拦截——这些是协议层的事
- 新增 WebSocket 或 MQTT 支持时,只需加 adapter,完全不动
UserSvc实现
每个协议写一个薄 adapter,只负责“翻译”
adapter 层不是业务逻辑,而是胶水:解析请求 → 调用 service → 格式化响应。它不决策、不判断,只转译。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
-
HTTP adapter:用net/http或chi提取 body/query/header → 构造 domain struct;写响应时自动设http.StatusOK或http.StatusBadRequest,注入traceID到ctx -
gRPC adapter:实现pb.UserServiceServer接口,把pb.GetUserRequest转成UserSvc.GetUser所需的 struct;错误用status.Errorf(codes.InvalidArgument, ...)统一封装 -
WebSocket adapter:用github.com/gorilla/websocket读消息,按"type": "get_user"字段路由到对应 service 方法,结果以 JSON 推回 client
App 容器统一管理监听器启停顺序
多个协议监听器(HTTP、gRPC、MQTT)不能各自 ListenAndServe,否则信号中断时无法保证优雅关闭顺序。
- 每个监听器实现
Listener接口:Addr()、Protocol()、ListenAndServe()、Shutdown(context.Context) -
App.Run()并发启动所有监听器,用sync.WaitGroup等待;收到os.Interrupt后,按反向顺序调用Shutdown() - 关键细节:
gRPC.GracefulStop()必须等http.Server.Shutdown()完成后再执行,否则可能丢请求 - 配置驱动开关:YAML 中
http: { enabled: true, port: 8080 },运行时决定启用哪些协议
Registrar 注册器必须隔离路由与实现
注册器不是路由表,而是协议语义转换器。它要把同一组业务逻辑,适配到不同协议的注册模型里。
- HTTP 注册器暴露
HandleHTTP(path string, h http.Handler),内部自动包装http.HandlerFunc,处理 JSON 解析/序列化/错误码 - gRPC 注册器暴露
HandleGRPC(serviceDesc *grpc.ServiceDesc, impl interface{}),内部调用pb.RegisterUserServiceServer(grpcServer, &userServer{svc: service}) - 绝对不要在 service 实现里硬编码
http.ListenAndServe或grpc.Serve——这些必须交给App统一调度 - 注册器持有具体协议对象(
*grpc.Server、http.ServeMux),但对外只暴露语义一致的注册方法
最容易被忽略的是上下文传递和错误映射的一致性:同一个 ctx 要贯穿 HTTP/gRPC/WS 全链路,同一个 AppError 要在各协议中正确转成 400 / InvalidArgument / 1002。这比支持多少种协议更关键。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










