Go: 标准库 slog

2026-05-191 引用

以 `Record` 为事件模型、以 `Attr` 为结构化数据、以 `Handler` 为策略和副作用边界的日志处理系统

结构化日志包,记录由 time、level、message 和 key-value 属性组成。

核心架构:Logger 描述事件 -> Record 承载事件 -> Handler 处理事件

go
type Logger struct{}
 
func New(h Handler) *Logger {}
 
// 暴露 Debug/Info/Warn/Error 等方法,每条调用生成日志记录
func (l *Logger) Debug(msg string, args ...any)
func (l *Logger) Error(msg string, args ...any)
func (l *Logger) Info(msg string, args ...any)
func (l *Logger) Warn(msg string, args ...any)
 
// ...
 
// Handler:接收 Record 决定输出方式
type Handler interface {
	Enabled(context.Context, Level) bool
 
	Handle(context.Context, Record) error
 
	WithAttrs(attrs []Attr) Handler
	WithGroup(name string) Handler
}
 
// 内置 TextHandler(key=value)和 JSONHandler(行分隔 JSON)
type TextHandler struct{}
type JSONHandler struct{}
 
type Record struct {
	Time    time.Time
	Message string
	Level   Level
	// ...
}

如何使用 Logger

SetDefault 让顶层函数和 log 包都走自定义 handle

go
func SetDefault(l *Logger) {}
func Default() *Logger     {}

最佳实践

  • 显式注入 Logger
    • 不使用全局 Logger,将 Logger 作为依赖传入,使测试、库代码和多环境配置更可控
  • 字段使用 Attr
    • 优先使用 slog.Attr,避免松散的 key-value 参数;字段类型更明确,也更安全
    • 为业务字段封装 helper,统一构造 slog.Attr
  • 稳定上下文使用 With
    • 使用 Logger.With 预先绑定公共属性
  • 层次结构使用 Group
    • 使用 slog.Group 表达复杂对象和领域结构
  • 类型投影使用 LogValuer
    • 使用 LogValuer 定义类型的日志表示
  • 调用链使用 Context
    • 优先使用 Context 版本 API,传入 ctx,便于 Handler 提取 trace 等调用链信息
  • 使用 sloglint 强制规则
    • 使用 sloglint 自动检查并约束日志规范
  1. https://go.dev/blog/slog
  2. https://go.dev/wiki/Resources-for-slog

评论