第一章:Go 新框架爆发元年:技术演进与生态拐点
2024 年正成为 Go 语言生态的关键分水岭——不再是“是否需要新框架”的讨论,而是“如何在数十个高成熟度框架中精准选型”的实践纪元。这一拐点由三大动因共同驱动:Go 1.21+ 对泛型的深度优化释放了框架抽象能力;eBPF 与 WASM 运行时的标准化接入拓宽了服务边界;开发者对“零配置启动、可调试热重载、生产级可观测性内建”形成强共识。
框架范式迁移:从工具链到运行时
传统 Web 框架(如 Gin、Echo)聚焦 HTTP 层封装,而新一代框架(如 Fiber v3、Hertz v2、Zerolog-powered Zeroframe)将生命周期管理、依赖注入、中间件调度统一为可插拔运行时。例如,启用自动指标暴露仅需:
// 使用 Zeroframe 启用 Prometheus 集成(无需额外 exporter)
app := zeroframe.New(zeroframe.Config{
Metrics: zeroframe.MetricsConfig{
Enable: true,
Path: "/metrics", // 自动注册 /metrics 端点
PushGateway: "http://pushgateway:9091",
},
})
该配置在 app.Run() 启动时自动注入 Prometheus 注册器与 HTTP 处理器,避免手动调用 promhttp.Handler()。
生态协同新标准
框架不再孤立演进,而是与周边工具链形成契约化协作:
| 协作维度 | 旧范式 | 新范式 |
|---|---|---|
| 日志结构化 | 手动注入字段 | 框架内置 zerolog.Context 自动注入请求 ID、路径、延迟 |
| 错误追踪 | SDK 手动 wrap error | errors.Join() 兼容 OpenTelemetry SpanContext 透传 |
| 配置加载 | 多格式解析器自行实现 | 统一支持 .env + config.yaml + etcd 三级覆盖 |
开发者体验重构
热重载不再依赖第三方工具:air 已被 godev run --watch 原生替代,其通过 fsnotify 监听 .go 和模板文件变更,并智能区分 main.go(重启进程)与 handler/*.go(热替换函数),平均响应延迟
# 在模块根目录执行,自动识别 go.mod 并监听全部源码与模板
godev run --watch --port 8080
第二章:Fiber——极致性能驱动的轻量级 Web 框架
2.1 Fiber 的零分配路由引擎与中间件生命周期设计
Fiber 的路由引擎在启动时预构建静态 trie 树,所有路径匹配全程避免内存分配,包括参数提取与上下文复用。
零分配核心机制
- 路由注册阶段完成节点预分配,运行时仅指针跳转
ctx.Params复用底层[]byte切片,不触发make([]string, n)- 中间件链通过函数闭包组合,无
[]Middleware动态切片扩容
中间件生命周期控制
func authMiddleware() fiber.Handler {
return func(c *fiber.Ctx) error {
// 从复用池获取 token 解析器,非 new()
parser := getParserFromPool()
defer putParserBack(parser)
if err := parser.Validate(c.Get("Authorization")); err != nil {
return c.Status(fiber.StatusUnauthorized).SendString("401")
}
return c.Next() // 继续调用后续中间件
}
}
该中间件全程不分配新结构体:
c.Next()仅更新内部index指针;getParserFromPool()返回预初始化对象;defer绑定归还逻辑而非 GC 等待。
| 阶段 | 内存操作 | 示例 |
|---|---|---|
| 启动注册 | 一次性分配 trie 节点 | app.Get("/api/:id", h) |
| 请求进入 | 零堆分配路径匹配 | /api/123 → 直接索引 |
| 中间件执行 | 复用 ctx + 对象池 | getParserFromPool() |
graph TD
A[HTTP Request] --> B{Trie 路由匹配}
B --> C[复用 Context 实例]
C --> D[顺序执行中间件闭包]
D --> E[Handler 函数]
E --> F[返回前归还资源池]
2.2 基于 Fasthttp 的并发模型实践:百万级连接压测对比
Fasthttp 通过复用 bufio.Reader/Writer 和协程池规避 GC 压力,天然适配 C100K+ 场景。以下为关键优化实践:
核心配置调优
- 禁用默认日志(
fasthttp.RequestCtx.SetUserValue("log", nil)) - 自定义
Server.Concurrency限制 goroutine 泄漏 - 启用
Server.NoDefaultDate和NoDefaultContentType
高性能连接复用示例
// 使用预分配的 RequestCtx 池,避免 runtime.newobject 分配
var ctxPool sync.Pool
func getCtx() *fasthttp.RequestCtx {
if v := ctxPool.Get(); v != nil {
return v.(*fasthttp.RequestCtx)
}
return fasthttp.AcquireRequestCtx(&fasthttp.RequestCtx{})
}
func releaseCtx(ctx *fasthttp.RequestCtx) {
fasthttp.ReleaseRequestCtx(ctx) // 归还至 fasthttp 内部池
ctxPool.Put(ctx) // 双层池化:业务层 + fasthttp 底层
}
ctxPool减少跨请求上下文分配开销;Acquire/ReleaseRequestCtx触发底层内存复用,实测降低 37% GC pause。
| 压测指标 | net/http (默认) | Fasthttp (优化后) |
|---|---|---|
| 连接建立耗时 | 12.4 ms | 2.1 ms |
| 99% 延迟 | 86 ms | 14 ms |
| 内存占用/万连 | 1.8 GB | 420 MB |
连接生命周期管理
graph TD
A[客户端 SYN] --> B{Server.Accept}
B --> C[分配 reuseport socket]
C --> D[绑定预分配 ctx & conn]
D --> E[读取请求 → 复用 buffer]
E --> F[响应写入 → 零拷贝 sendfile]
F --> G[连接 Keep-Alive 或 Close]
2.3 类 Express 风格 API 开发实战:JWT 鉴权 + OpenAPI 3 自动生成
快速路由与中间件集成
使用 @koa/router 模拟 Express 风格链式路由,配合 koa-jwt 实现无状态鉴权:
const router = new Router();
router.get('/profile')
.use(jwt({ secret: process.env.JWT_SECRET }))
.use(async (ctx) => {
ctx.body = { user: ctx.state.user }; // 解析后的 payload 自动挂载
});
jwt()中间件自动校验Authorization: Bearer <token>,失败时返回401;ctx.state.user为解码后的 JWT payload,默认不验证exp(需显式传入{ algorithms: ['HS256'] }并启用key函数动态解析)。
OpenAPI 文档自动生成
通过 @asteas/koa-openapi 插件,基于 JSDoc 注释实时生成符合 OpenAPI 3.0 规范的 JSON Schema:
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
x-openapi-router-controller |
string | ✅ | 关联控制器路径 |
x-openapi-security |
array | ❌ | 指定鉴权方案(如 [{ bearerAuth: [] }]) |
鉴权流程可视化
graph TD
A[客户端请求] --> B{Header含Bearer Token?}
B -->|否| C[401 Unauthorized]
B -->|是| D[验证签名 & exp]
D -->|失败| C
D -->|成功| E[挂载user到ctx.state]
E --> F[执行业务逻辑]
2.4 生产就绪能力构建:Graceful Shutdown、Prometheus Metrics 集成
Graceful Shutdown 实现要点
Spring Boot 2.3+ 原生支持优雅停机,需启用配置:
server:
shutdown: graceful # 启用优雅关闭
spring:
lifecycle:
timeout-per-shutdown-phase: 30s # 最大等待时间
逻辑分析:
shutdown: graceful使 Tomcat 在收到SIGTERM后暂停接收新请求,但继续处理已入队的请求与异步任务(如@Async、CompletableFuture),超时后强制终止未完成任务。timeout-per-shutdown-phase控制各生命周期阶段(如SmartLifecyclebean 销毁)的最长等待时间。
Prometheus Metrics 集成
引入依赖并暴露端点:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
| 指标类型 | 示例指标名 | 用途 |
|---|---|---|
| Counter | http_server_requests_total |
请求总量计数 |
| Gauge | jvm_memory_used_bytes |
实时内存使用量(瞬时值) |
| Timer | http_server_requests_duration_seconds |
请求延迟分布(直方图) |
监控协同流程
graph TD
A[应用启动] --> B[自动注册MeterRegistry]
B --> C[暴露 /actuator/prometheus]
C --> D[Prometheus Server 定期抓取]
D --> E[Grafana 可视化告警]
2.5 Fiber 在边缘计算网关中的落地案例:低延迟 API 路由与 WebSocket 扩展
在某工业物联网边缘网关项目中,Fiber 作为轻量级 Go Web 框架,承担设备接入层的实时路由与长连接管理。
低延迟 HTTP 路由优化
app := fiber.New(fiber.Config{
DisableStartupMessage: true,
ReduceMemoryUsage: true, // 启用内存复用,降低 GC 压力
ServerHeader: "Edge-GW/1.0",
})
app.Get("/api/v1/metrics/:device_id", metricsHandler) // 零拷贝参数解析
ReduceMemoryUsage 启用后,Fiber 复用 []byte 缓冲池,实测 P99 延迟从 8.2ms 降至 3.1ms(ARM64 边缘节点)。
WebSocket 设备通道扩展
app.Get("/ws/:topic", websocket.New(func(c *websocket.Conn) {
deviceID := c.Params("topic") // 从 URL 提取设备标识
c.SetReadDeadline(time.Now().Add(30 * time.Second))
handleDeviceStream(c, deviceID)
}))
c.Params() 直接映射路径变量,避免正则匹配开销;结合心跳保活与消息优先级队列,支持单节点 2000+ 并发连接。
| 特性 | 默认值 | 边缘调优值 | 效果 |
|---|---|---|---|
| ReadBufferSize | 4KB | 8KB | 减少 TCP 分包次数 |
| WriteBufferSize | 4KB | 16KB | 提升批量上报吞吐 |
| IdleTimeout | 0 | 60s | 平衡资源与连接存活 |
graph TD A[客户端发起 /ws/DEV-001] –> B{Fiber 路由匹配} B –> C[提取 device_id = DEV-001] C –> D[绑定设备上下文至 Conn] D –> E[接入 MQTT 桥接模块] E –> F[双向透传传感器数据]
第三章:Echo v5——模块化重构后的企业级演进路径
3.1 v5 核心架构升级:Context 接口标准化与插件式中间件注册机制
v5 将 Context 抽象为统一接口,剥离运行时实现细节,支持 HTTP、gRPC、CLI 等多协议上下文共用同一契约。
Context 接口契约
type Context interface {
Value(key interface{}) interface{}
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
WithValue(key, val interface{}) Context // 不可变语义
}
该定义严格对齐 Go 标准库 context.Context,确保生态兼容;WithValue 返回新实例而非修改原对象,保障线程安全与可预测性。
插件式中间件注册流程
graph TD
A[Server.Start] --> B[LoadMiddlewarePlugins]
B --> C{Plugin manifest.json}
C --> D[Validate Interface Compliance]
D --> E[Register via MiddlewareRegistry.Add]
中间件注册表能力对比
| 特性 | v4(硬编码) | v5(插件式) |
|---|---|---|
| 注册时机 | 启动时静态绑定 | 运行时动态加载 |
| 插件热替换 | ❌ 不支持 | ✅ 支持 .so/.wasm |
| 上下文透传一致性 | 依赖框架约定 | 强制 Context 接口 |
3.2 实战:基于 Echo 的微服务 HTTP 网关开发(含 gRPC-Web 透传)
核心架构设计
网关采用分层路由策略:HTTP 路由转发至 REST 微服务,/grpcweb/* 路径统一交由 grpcweb.WrapHandler 处理,透传至后端 gRPC Server。
gRPC-Web 透传配置
// 启用 gRPC-Web 中间件,兼容浏览器 fetch 与 Unary/Streaming
grpcWeb := grpcweb.WrapServer(
grpcServer,
grpcweb.WithWebsockets(true),
grpcweb.WithCorsForRegisteredEndpointsOnly(false),
)
e.POST("/grpcweb/*", echo.WrapHandler(http.HandlerFunc(grpcWeb.ServeHTTP)))
WithWebsockets(true) 启用 WebSocket 流式支持;WithCorsForRegisteredEndpointsOnly(false) 允许跨域调用,适配前端直连场景。
路由能力对比
| 功能 | HTTP REST | gRPC-Web |
|---|---|---|
| 请求方式 | JSON/POST | Protobuf |
| 流式支持 | SSE/WS | 原生 Streaming |
| 前端兼容性 | 高 | 需 @improbable-eng/grpc-web |
graph TD
A[Browser] -->|gRPC-Web over HTTP/1.1| B(Echo Gateway)
B -->|Upgrade to gRPC| C[gRPC Server]
B -->|JSON Proxy| D[REST Service]
3.3 安全加固实践:自动 CSRF 防护、CSP 头注入与敏感头过滤策略
自动 CSRF 防护集成
现代 Web 框架(如 Express + csurf 或 Django 内置机制)可自动注入 _csrf 隐藏字段并校验请求头/体。关键在于同步 Token 生命周期:
// Express 中启用自动 CSRF 防护(v10+ 推荐使用 csurf 替代方案)
app.use(csrf({ cookie: true }));
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken(); // 注入模板上下文
next();
});
逻辑分析:csrf({ cookie: true }) 启用 HttpOnly Cookie 存储 Token,req.csrfToken() 生成并绑定至当前会话;需确保所有 POST/PUT/DELETE 表单含 <input type="hidden" name="_csrf" value="<%= csrfToken %>">。
CSP 与敏感头治理
| 头字段 | 推荐值 | 说明 |
|---|---|---|
Content-Security-Policy |
default-src 'self'; script-src 'self' 'unsafe-inline' |
阻断外域脚本,允许内联(开发期) |
X-Content-Type-Options |
nosniff |
防止 MIME 类型混淆 |
Server |
—(主动移除) | 消除指纹暴露 |
graph TD
A[HTTP 请求] --> B{是否为 POST/PUT/DELETE?}
B -->|是| C[校验 CSRF Token]
B -->|否| D[跳过 Token 校验]
C --> E[验证通过?]
E -->|否| F[返回 403]
E -->|是| G[继续路由处理]
第四章:Hertz——字节跳动开源的高性能 RPC/Web 框架
4.1 Hertz 底层 Netpoll I/O 多路复用与内存池优化原理剖析
Hertz 默认启用自研 netpoll 替代标准 net 库,基于 Linux epoll 实现无锁事件循环,避免 Goroutine 频繁调度开销。
内存池复用机制
- 请求头(
http.Header)与bufio.Reader/Writer实例均从sync.Pool获取 - 每次连接复用后自动
Reset(),规避 GC 压力 - 自定义
ByteSlicePool管理临时字节切片,最小分配粒度为 512B
// netpoll.Conn.Read() 中的内存复用逻辑
buf := byteSlicePool.Get().([]byte) // 从池中获取预分配缓冲区
n, err := syscall.Read(int(fd), buf) // 直接读入池化内存
// ... 处理后调用 byteSlicePool.Put(buf[:0])
byteSlicePool 使用 []byte 切片头复用底层数组,Put 时仅重置长度,零拷贝回收;Get 返回容量 ≥512 的可用块,避免 runtime.growslice。
epoll 事件分发流程
graph TD
A[epoll_wait] --> B{就绪 fd}
B --> C[Netpoll loop]
C --> D[无锁队列分发]
D --> E[Worker goroutine 处理]
| 优化维度 | 标准 net | Hertz netpoll |
|---|---|---|
| 连接建立开销 | ~12KB | ~3KB(池化复用) |
| 平均延迟 p99 | 86μs | 29μs |
4.2 替代 Gin 的迁移路线图:中间件兼容层、Gin 语法糖适配器实现
为平滑迁移至高性能替代框架(如 Fiber 或 Echo),需构建双层抽象:中间件兼容层屏蔽底层 http.Handler 差异,语法糖适配器复用 gin.Context 风格调用。
中间件桥接原理
通过封装 func(http.Handler) http.Handler 为 func(*gin.Context),实现 Gin 风格中间件零修改接入:
// GinMiddlewareAdapter 将 Gin 中间件转为标准 HTTP 中间件
func GinMiddlewareAdapter(ginMW gin.HandlerFunc) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c := &ginContextAdapter{w: w, r: r} // 模拟 gin.Context 行为
ginMW(c) // 执行原 Gin 中间件逻辑
if !c.Written() {
next.ServeHTTP(w, r)
}
})
}
}
c.Written() 判断是否已写响应,避免重复写入;ginContextAdapter 需实现 Abort()、JSON() 等关键方法。
语法糖适配器能力对比
| 功能 | Gin 原生 | 适配器支持 | 实现方式 |
|---|---|---|---|
c.JSON(200, v) |
✅ | ✅ | 封装 json.Marshal + header 设置 |
c.Param("id") |
✅ | ✅ | 解析 r.URL.Path 或路由变量 |
c.Bind() |
✅ | ⚠️(需反射) | 依赖结构体 tag 映射请求体 |
graph TD
A[Gin 应用] --> B[中间件兼容层]
B --> C[语法糖适配器]
C --> D[Fiber/Echo 路由引擎]
4.3 字节内部大规模落地实践:电商大促场景下的 QPS 提升与 GC 降低数据
在双十一大促压测中,字节电商业务通过 JVM 层面精细化调优 + 异步化重构 实现核心下单链路 QPS 提升 3.2 倍(12,800 → 41,100),Full GC 频次下降 96%(从平均 8.7 次/小时降至 0.3 次/小时)。
数据同步机制
采用 Canal + RocketMQ + 批量写入 Redis 的异步解耦方案,避免 DB 直连阻塞:
// 批量更新商品库存缓存(防击穿+减少序列化开销)
public void batchUpdateStock(List<StockUpdate> updates) {
Map<String, Long> pipelinedMap = updates.stream()
.collect(Collectors.toMap(
u -> "stock:" + u.getItemId(),
StockUpdate::getStock,
(a, b) -> a, // 冲突保留前者
LinkedHashMap::new
));
redisTemplate.opsForValue().multiSet(pipelinedMap); // 原子批量写入
}
✅ multiSet 减少网络往返;✅ LinkedHashMap 保序提升 pipeline 效率;✅ 冲突合并策略避免超卖误判。
关键指标对比
| 指标 | 优化前 | 优化后 | 变化 |
|---|---|---|---|
| P99 响应延迟 | 420 ms | 112 ms | ↓73% |
| Young GC 次数/分钟 | 24 | 5 | ↓79% |
| 堆外内存占用 | 1.8 GB | 0.6 GB | ↓67% |
graph TD
A[下单请求] --> B{同步校验库存}
B -->|通过| C[异步发MQ更新缓存]
C --> D[定时任务补偿DB一致性]
B -->|失败| E[快速熔断返回]
4.4 Hertz + Kitex 协同架构:统一传输层协议栈与跨语言服务治理集成
Hertz 作为高性能 Go HTTP 框架,与 Kitex(字节开源的 RPC 框架)通过共享 netpoll 底层 I/O 多路复用引擎实现协议栈复用,消除双栈冗余。
统一传输层抽象
- 共享
transport.Transporter接口,支持 HTTP/1.1、HTTP/2、Thrift 二进制多协议混跑 - 请求生命周期统一由
hertz/server中间件链 +kitex/server治理插件协同拦截
跨语言服务治理集成
// kitex_gen/user/userservice/server.go —— 自动注入 Hertz 兼容适配器
func NewServer(handler interface{}, opts ...server.Option) *server.Server {
opts = append(opts, server.WithTransHandler(hertz.NewTransHandler())) // 关键桥接
return server.NewServer(handler, opts...)
}
hertz.NewTransHandler()将 Kitex 的Message编解码流程映射至 Hertz 的context生命周期;WithTransHandler参数使 Kitex 服务可直挂载为 Hertz 子路由,无需反向代理。
| 能力 | Hertz 原生支持 | Kitex 注入扩展 | 协同效果 |
|---|---|---|---|
| TLS 双向认证 | ✅ | ✅ | 统一证书管理与校验链 |
| OpenTelemetry Trace | ✅ | ✅ | Span ID 全链路透传 |
| 限流熔断 | ❌ | ✅ | 通过 Kitex Middleware 注入 Hertz 中间件 |
graph TD
A[HTTP/2 Client] --> B[Hertz Router]
B --> C{Protocol Dispatch}
C -->|hertz://| D[Hertz Handler]
C -->|kitex://| E[Kitex TransHandler]
E --> F[Kitex Middleware Chain]
F --> G[Business Service]
第五章:第 3 个已被字节跳动内部全面替代 Gin 的框架深度解析
字节跳动自2021年起在核心微服务(如抖音Feed网关、TikTok广告实时竞价API集群)中逐步将 Gin 迁移至 Kratos(v2.4+),并于2023年Q3完成全量替换。该决策并非基于性能压测的单一指标,而是源于对可观测性、协议治理与云原生运维能力的系统性重构需求。
框架演进动因:从“能跑”到“可治”
Gin 在字节早期支撑了快速迭代,但其默认无中间件链路追踪、HTTP/1.1 单协议绑定、错误码分散定义等问题,在日均千亿级请求场景下暴露严重。Kratos 提供统一的 errors.Code 枚举体系与 tracing.WithSpan 自动注入机制,使某广告出价服务的故障平均定位时间从 17 分钟降至 92 秒。
核心能力对比:协议抽象层的实际价值
| 能力维度 | Gin(v1.9.1) | Kratos(v2.6.0) |
|---|---|---|
| 默认协议支持 | HTTP/1.1 | HTTP/1.1 + gRPC + HTTP/2 + OpenAPI 3.0 |
| 错误标准化 | c.JSON(500, map[string]any{...}) |
return errors.Newf(errors.CodeInternalServer, "db timeout") |
| 配置热加载 | 需手动监听 fsnotify | 原生集成 Apollo/Nacos,支持 config.Watch() 回调 |
生产级中间件链实战配置
某电商秒杀网关采用以下 Kratos 中间件组合,完整覆盖安全与稳定性需求:
srv := http.NewServer(
http.Address(":8080"),
http.Middleware(
recovery.Recovery(), // panic 捕获并上报 Sentry
rate.Limiter(rate.NewLimiter(1000, 500)), // 每秒1000 QPS,桶容量500
jwt.Auth(&jwt.Config{Key: []byte("secret")}), // JWT 解析注入 ctx
tracing.Server(), // 自动注入 X-B3-TraceId
),
)
流量染色与灰度发布流程
flowchart LR
A[客户端请求] --> B{Header 包含 x-deploy-env: canary?}
B -->|是| C[路由至 canary 实例组]
B -->|否| D[路由至 stable 实例组]
C --> E[执行 kratos.middleware.canary.Collector]
D --> F[执行 kratos.middleware.stable.Metrics]
E & F --> G[统一上报 Prometheus + Loki]
线上故障回滚机制
当 Kratos 的 grpc.Client 在跨机房调用中连续 3 次超时(阈值 200ms),自动触发熔断器切换至降级 HTTP 接口,并向 SRE 平台推送告警卡片,附带 kratos.traceid 与 kratos.spanid 链路标识。该机制在 2023 年双十一大促期间成功拦截 127 起潜在雪崩风险。
性能基准实测数据
在 32 核 64GB 容器环境下,使用 wrk 对 /user/profile 接口压测(100 并发,持续 60 秒):
- Gin:平均延迟 42.7ms,P99 118ms,错误率 0.02%
- Kratos(gRPC over HTTP/2):平均延迟 28.3ms,P99 76ms,错误率 0.00%
- Kratos(HTTP/1.1):平均延迟 31.5ms,P99 89ms,错误率 0.00%
内部工具链深度集成
Kratos CLI 已对接字节内部 DevOps 平台,执行 kratos new --template=internal-service 可自动生成含以下组件的项目骨架:
api/v1/user.pb.go(Protobuf 编译产物)internal/conf/app.yaml(Apollo 配置模板)scripts/deploy.sh(K8s Helm Chart 渲染脚本)test/benchmark_test.go(预置 go test -bench 参数)
迁移成本与收益量化
抖音推荐 API 团队耗时 6 周完成 Gin → Kratos 迁移,新增代码仅 1200 行(含中间件适配),但实现:
- 全链路日志检索效率提升 4.3 倍(Loki 查询响应
- gRPC 接口吞吐量提升 2.1 倍(相同硬件资源下)
- 新增协议扩展周期从 3 天缩短至 2 小时(基于 Protobuf IDL 自动生成)
生态兼容性策略
为降低历史 Gin 中间件迁移成本,字节开源了 kratos-gin-adapter 模块,允许直接复用 Gin 的 gin.HandlerFunc 类型中间件,例如:
import "github.com/go-kratos/kratos/v2/middleware/ginadapter"
// ...
http.Middleware(ginadapter.Wrap(myLegacyGinMiddleware)) 