Go log/slog 怎么给同一请求追加分组字段
来源:17golang原创
时间:2026-09-10 10:30:21 272浏览 收藏
同一请求通常会打印“开始处理”“调用下游”“返回结果”几条日志。如果每次都重复传入 request_id、method 和 path,字段很快会散落在各处。Go 的 log/slog 更适合先用 WithGroup("request") 建立分组,再用 Logger.With 追加一次公共属性:它返回一个新的 logger,不会改掉原来的全局 logger,后续该请求的日志都能复用这份字段。
WithGroup("request")为后续属性建立稳定的 request 命名空间。With适合把同一请求的公共字段绑定到派生 logger,业务日志只写当前事件。- TextHandler 会显示
request.request_id,JSONHandler 会输出嵌套的request对象;单条日志才优先考虑slog.Group。
先为请求创建一个独立的 slog logger
不要把请求字段写进全局 logger,也不要期待 context.Context 会自动替你注入属性。context 可以沿着调用链传递取消信号和请求上下文,但字段是否进入日志,仍要显式交给 slog。
package main
import (
"context"
"log/slog"
"net/http"
"os"
)
func handleRequest(ctx context.Context, base *slog.Logger, r *http.Request) {
// 派生 logger 只服务当前请求,避免公共 logger 被请求字段污染。
requestLogger := base.WithGroup("request").With(
slog.String("request_id", "req-7f31"),
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
)
// Context 仍然要显式传入;With 绑定的字段会自动出现在这条日志里。
requestLogger.InfoContext(ctx, "request started")
requestLogger.InfoContext(ctx, "downstream call finished", "status", http.StatusOK)
}
func main() {
// JSONHandler 适合交给日志采集系统继续按字段查询。
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
req, _ := http.NewRequest(http.MethodGet, "https://example.test/items", nil)
handleRequest(context.Background(), logger, req)
}
这里的关键是“每个请求一个派生 logger”。requestLogger 包含的三个字段会跟随两次日志调用出现,而原始 base 仍然可以给启动日志或其他请求使用。字段名放在 request 组内,也给后续的 user、downstream 等子系统留出了清晰空间。
WithGroup 和 With 到底改变了什么
WithGroup 负责命名空间,With 负责把属性绑定到 logger。两者都返回新的 *slog.Logger,可以继续链式调用;它们不是修改已有 logger 的 setter。若一个子系统也记录 id,可以继续使用自己的组,避免同名键混在同一层。
| 写法 | 适合场景 | 字段范围 |
|---|---|---|
base.With("service", "api") | 所有后续日志的公共字段 | 当前派生 logger |
base.WithGroup("request").With(...) | 同一请求的多条日志 | request 组及其子字段 |
slog.Group("request", ...) | 只有一条日志需要成组字段 | 当前这一条 Record |
如果请求处理函数还会调用多个下层函数,把 requestLogger 作为参数传下去通常比重复传字段更稳。若下层模块也需要自己的命名空间,可以写成 requestLogger.WithGroup("storage");它会把该模块后续的属性限定在 request.storage 下面。

同一组字段在文本和 JSON 中长什么样
分组的逻辑结构不会因为 Handler 改变,但展示方式会改变。TextHandler 通常用点号限定属性名,便于在一行文本中区分作用域;JSONHandler 会把组表现为对象,更适合日志系统按 request.request_id 这样的路径检索。
// 使用 TextHandler 时,字段会以限定键出现在一行文本中。
textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil))
textLogger.WithGroup("request").With(
slog.String("request_id", "req-7f31"),
).Info("text event")
// 只对这一条日志分组时,slog.Group 不需要创建派生 logger。
jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
jsonLogger.Info("one event", slog.Group("request",
slog.String("request_id", "req-7f31"),
slog.Int("status", http.StatusOK),
))
选择时可以记住一个简单边界:一条日志的结构用 slog.Group,一个请求生命周期的结构用 WithGroup 加 With。不要为了让输出“看起来像 JSON”而手工拼字符串,那会失去字段类型和后续处理能力。

上线前检查字段作用域和敏感信息
- 请求 logger 是否在请求入口派生,而不是修改全局 logger。
- 公共字段是否确实对整个请求都有效;只对单条事件有效的值不要绑定得过早。
- 是否用
InfoContext、LogContext或LogAttrs显式传入可用的 context。 - 公共字段中不要放访问令牌、Cookie、密码或未经处理的个人敏感数据。
常见问题
WithGroup 会把字段写入原来的 logger 吗?
不会。它返回一个带分组状态的新 logger,原 logger 保持不变,因此可以把派生 logger 限定在当前请求或当前子系统。
为什么 context 里有 request_id,slog 仍然没有输出?
slog 不会自动读取任意 context 键。要么用 With 把字段绑定到派生 logger,要么在调用点显式传入属性;context 主要仍承担请求上下文传递职责。
WithGroup 和 slog.Group 应该怎么选?
同一请求有多条日志时用 WithGroup 加 With;只有一条记录需要嵌套字段时用 slog.Group,这样作用域更小。
官方参考:https://pkg.go.dev/log/slog、https://go.dev/blog/slog。真正接入日志平台时,再按平台的字段路径规则确认 request.request_id 是否被正确索引。
-
119 收藏
-
Golang · Go教程 | 43分钟前 | 错误处理 · 静态资源 · Go教程 · io/fs · embed.FS · Go ReadFile errors.Is errors.As embed.FS io/fs211 收藏
-
194 收藏
-
249 收藏
-
328 收藏
-
257 收藏
-
334 收藏
-
130 收藏
-
428 收藏
-
Golang · Go教程 | 7小时前 | 并发 · Context · 资源管理 · Go教程 · 超时取消 · Go 资源清理 context取消 context.AfterFunc stop函数375 收藏
-
361 收藏
-
Golang · Go教程 | 7小时前 | Context · 并发控制 · Go教程 · Cause · Err · Go 上下文取消 context.Cause 取消原因 context.Err382 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习