如何在Go语言不同包中使用自定义slog处理器NewSlogHandler?
使用slog自定义处理器在多包中实现结构化日志
我是Go语言新手,正在进行POC开发,希望用slog实现结构化日志。已经在logger包编写了logger.go文件,想了解如何在main、database等其他不同包中使用自定义日志处理器NewSlogHandler。
原代码问题说明
你最初编写的SlogHandler结构体及方法设计存在不合理之处:将NewSlogHandler定义为结构体方法,且每次调用都会创建新的Logger实例并覆盖全局默认Logger,这会导致日志初始化逻辑冗余,甚至引发不必要的资源开销。更推荐使用你提供的可用代码版本,它采用全局初始化的方式,更符合slog的使用规范。
优化后的logger包代码
package logger import ( "log/slog" "os" "runtime" "time" ) func NewSlogHandler() slog.Logger { hostname, err := os.Hostname() if err != nil { hostname = "" slog.Error("could not get hostname") } logHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelDebug, AddSource: true, ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { if a.Key == slog.TimeKey { a.Key = "UTCTime" a.Value = slog.TimeValue(time.Now().UTC()) } return a }, }).WithAttrs([]slog.Attr{ slog.Group("app_details", slog.Int("pid", os.Getpid()), slog.String("hostname", hostname), slog.String("go_version", runtime.Version()), ), }) logger := slog.New(logHandler) slog.SetDefault(logger) return *logger }
在其他包中使用的步骤
1. 在main包中初始化日志处理器
程序启动时,先调用logger.NewSlogHandler()完成全局默认Logger的初始化,后续所有包即可直接使用slog的全局日志方法。
package main import ( "log/slog" "your-project/logger" // 替换为你的项目实际路径 ) func main() { // 初始化自定义日志处理器,仅需调用一次 logger.NewSlogHandler() // 直接使用slog全局方法输出日志 slog.Info("应用启动完成", slog.String("env", "development")) slog.Debug("加载配置文件", slog.String("path", "./config.yaml")) }
2. 在database等其他业务包中使用
无需再次初始化,直接调用slog.Info()、slog.Error()等方法即可,日志会自动使用自定义处理器输出结构化JSON格式,并携带app_details等全局属性。
package database import "log/slog" func ConnectDB() { slog.Info("尝试连接数据库", slog.String("db_type", "postgres")) // 模拟连接失败场景 err := someDBConnectFunc() if err != nil { slog.Error("数据库连接失败", slog.String("error_msg", err.Error())) } }
额外说明
- 全局初始化仅需一次:务必在main函数启动阶段调用
NewSlogHandler(),避免在多个包中重复调用,防止默认Logger被多次覆盖。 - 局部自定义Logger:如果某个业务模块需要额外的专属字段,可以基于全局默认Logger创建子Logger:
// 在database包中创建带模块标识的子Logger dbLogger := slog.With(slog.String("module", "database")) dbLogger.Info("执行SQL查询", slog.String("sql", "SELECT * FROM users"))
内容的提问来源于stack exchange,提问作者Ranjeet
相关产品推荐
相关产品推荐

