You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:06:34