每日一库:slog 实现日志双写

Go 1.21 的 slog 提供结构化日志,相比传统 log 包更灵活,较 zap 更简洁。本文展示如何用 slog 实现日志双写,同时输出到文件和控制台,满足开发与生产需求。

为什么用 slog 和日志双写?

slog 支持键值对结构化日志,JSON 格式便于分析。双写兼顾开发调试(实时输出)和生产监控(持久保存),灵活可靠。

实现日志双写

以下是根据运行模式(开发/生产)配置日志的代码:

代码语言:go复制
package global

import (
	"io"
	"log/slog"
	"os"
)

// InitLogger 初始化日志,支持双写
func InitLogger(mode string) {
	var handler slog.Handler
	opts := &slog.HandlerOptions{AddSource: true}

	switch mode {
	case "production":
		// 生产:双写到文件和控制台
		if err := os.MkdirAll("log", os.ModePerm); err != nil {
			slog.Error("创建日志目录失败", "error", err)
			return
		}
		writer, err := os.OpenFile("log/server.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			slog.Error("打开日志文件失败", "error", err)
			return
		}
		opts.Level = slog.LevelInfo
		handler = slog.NewJSONHandler(io.MultiWriter(writer, os.Stdout), opts)
	case "development":
		// 开发:仅输出到控制台
		opts.Level = slog.LevelDebug
		handler = slog.NewTextHandler(os.Stdout, opts)
	default:
		panic("无效模式")
	}

	slog.SetDefault(slog.New(handler))
}

生产模式以 JSON 格式双写日志(文件+控制台),级别为 Info;开发模式以文本格式输出到控制台,级别为 Debug

使用方式

通过命令行参数(可用 flag 解析)指定模式:

代码语言:go复制
global.InitLogger("production")  // 双写到文件和控制台
global.InitLogger("development") // 仅输出到控制台

总结

slog 实现日志双写简单高效,灵活适配开发与生产环境。结构化日志和级别设置提升了应用的维护性与稳定性。