闲社服务运行正常AI智能体自动化平台
g

Go中间件

技能标识:go-middleware

Idiomatic Go HTTP middleware patterns with context propagation, structured logging via slog, centralized error handling, and panic recovery. Use when writing middleware, adding request tracing, or implementing cross-cutting concerns.

作者:admin | 来源记录:ClawHub
登记来源
ClawHub
版本
V 2.3.0
检测标记
后台标记通过
免费
免费获取
0
收藏
来源与检测标记为平台登记信息,并不代表已展示可复核的检测报告。使用前请核对版本、依赖和所需权限,建议先在隔离环境中运行。
概述
安装方式
版本历史

Go中间件

Go HTTP中间件

快速参考

主题参考
上下文键、请求ID、用户元数据references/context-propagation.md
slog设置、日志中间件、子日志器
references/structured-logging.md | | AppHandler模式、领域错误、恢复 | references/error-handling-middleware.md |

中间件签名

所有中间件遵循标准的func(http.Handler) http.Handler模式。这是Go HTTP服务器中横切关注点的可组合构建块。

go
// 标准中间件签名
func RequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get(X-Request-ID)
if id == {
id = uuid.New().String()
}
ctx := context.WithValue(r.Context(), requestIDKey, id)
w.Header().Set(X-Request-ID, id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}

// 类型安全的上下文键
type contextKey string
const requestIDKey contextKey = request_id

func RequestIDFromContext(ctx context.Context) string {
id, _ := ctx.Value(requestIDKey).(string)
return id
}

关键点:

  • - 接受http.Handler,返回http.Handler——始终如此
  • 调用next.ServeHTTP(w, r)将控制权传递给下一个处理器
  • 可在调用前(预处理)或调用后(后处理)工作,或两者兼有
  • 使用r.WithContext(ctx)向下游传播新的上下文值

上下文传播

使用context.WithValue存储跨API边界的请求范围数据(请求ID、认证用户、租户ID)。始终使用类型化键以避免冲突。

go
type contextKey string

const (
requestIDKey contextKey = request_id
userKey contextKey = user
)

提供类型化的辅助函数用于提取:

go
func RequestIDFromContext(ctx context.Context) string {
id, _ := ctx.Value(requestIDKey).(string)
return id
}

参见references/context-propagation.md了解用户元数据模式、下游传播和超时设置。

结构化日志

在中间件中使用slog(标准库,Go 1.21+)进行结构化日志记录。包装http.ResponseWriter以捕获状态码。

go
func Logger(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &statusWriter{ResponseWriter: w, status: http.StatusOK}

next.ServeHTTP(wrapped, r)

logger.Info(请求完成,
method, r.Method,
path, r.URL.Path,
status, wrapped.status,
duration_ms, time.Since(start).Milliseconds(),
request_id, RequestIDFromContext(r.Context()),
)
})
}
}

参见references/structured-logging.md了解JSON/文本处理器设置、日志级别和子日志器。

集中式错误处理

定义一个返回error的自定义处理器类型,这样处理器就不需要自己编写错误响应:

go
type AppHandler func(w http.ResponseWriter, r *http.Request) error

func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
handleError(w, r, err)
}
}

在单个handleError函数中将领域错误映射到HTTP状态码。切勿向客户端泄露内部错误详情。

参见references/error-handling-middleware.md了解完整的AppError、errors.As和JSON响应模式。

恢复中间件

捕获恐慌以防止单个错误请求导致服务器崩溃:

go
func Recovery(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
slog.Error(已恢复恐慌,
panic, rec,
stack, string(debug.Stack()),
request_id, RequestIDFromContext(r.Context()),
)
writeJSON(w, 500, map[string]string{error: 内部服务器错误})
}
}()
next.ServeHTTP(w, r)
})
}

恢复必须是最外层的中间件,这样它才能捕获所有内部中间件和处理器的恐慌。详情参见references/error-handling-middleware.md。

中间件链排序

应用中间件时最外层优先。链中的第一个中间件包装所有其他中间件。

go
// 嵌套风格(最外层优先)
handler := Recovery(
RequestID(
Logger(
Auth(
router,
),
),
),
)

// 或使用链辅助函数
func Chain(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
for i := len(middleware) - 1; i >= 0; i-- {
h = middlewarei
}
return h
}

handler := Chain(router, Recovery, RequestID, Logger(slog.Default()), Auth)

推荐顺序

  1. 1. 恢复——最外层;捕获所有内部中间件的恐慌
  2. 请求ID——尽早分配,以便所有后续中间件可以引用它
  3. 日志——记录完成的请求及其ID和状态
  4. 认证——在日志之后,以便记录失败的认证尝试
  5. 应用特定中间件——速率限制、CORS等

反模式

使用字符串或整数作为上下文键

go // 错误:与其他包冲突 ctx = context.WithValue(ctx, user, user)

// 正确:未导出的类型化键
type contextKey string
const userKey contextKey = user
ctx = context.WithValue(ctx, userKey, user)

在调用next之前写入响应

go // 错误:先写入响应然后继续链 func Bad(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) // 太早了! next.ServeHTTP(w, r) }) }

忘记调用next.ServeHTTP

go // 错误:吞掉了请求 func Bad(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(收到请求) // 忘记调用 next.ServeHTTP(w, r) }) }

在上下文中存储大对象

上下文值应该是小的、请求范围的元数据(ID、令牌、用户结构体)。切勿存储数据库连接、文件句柄或大型负载。

使用context.WithValue传递函数参数

如果函数需要某个值来完成工作,应将其作为显式参数传递。上下文用于跨API传递的横切元数据,而不是用于避免函数签名。

恢复中间件位置错误

如果恢复不是最外层的中间件,外层中间件中的恐慌将导致服务器崩溃。始终首先应用恢复。

标签

skill ai

通过对话安装

以下为平台配置的接入选项,并非逐项实测通过。能否安装取决于客户端支持、技能来源和运行环境:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 go-middleware-1776089649 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 go-middleware-1776089649 技能

通过命令行安装

skillhub install go-middleware-1776089649

下载

⬇ 下载 go-middleware v2.3.0(免费)

文件大小: 11.04 KB | 发布时间: 2026-4-14 12:44

v2.3.0 最新 2026-4-14 12:44
- Added a comprehensive SKILL.md with detailed documentation and best practices for Go HTTP middleware.
- Covers context propagation, structured logging with slog, centralized error handling, and recovery middleware.
- Provides code samples, recommended middleware chain order, and anti-patterns to avoid.
- Includes quick references to more in-depth documentation for each major topic.
返回顶部