Go: 标准库 slog
以 `Record` 为事件模型、以 `Attr` 为结构化数据、以 `Handler` 为策略和副作用边界的日志处理系统
结构化日志包,记录由 time、level、message 和 key-value 属性组成。
核心架构:Logger 描述事件 -> Record 承载事件 -> Handler 处理事件
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
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 等调用链信息
- 优先使用 Context 版本 API,传入
- 使用 sloglint 强制规则
- 使用
sloglint自动检查并约束日志规范
- 使用
评论