01
介绍
在 Go 语言项目开发中,我们通常需要查看日志来调试程序,所以日志的快捷搜索和过滤就会至关重要。
因为 Go 标准库中的 log
,它不是结构化日志格式,使用上并不方便,所以在 Go 1.21.0 中,Go 标准库新增结构化日志记录包 log/slog
,它支持键值对格式。
本文我们介绍 log/slog
的使用方式。
log/slog
使用方式
log/slog
的默认 logger
使用的是 log
的默认 logger
,新增日志包 log/slog
和原始日志包 log
协同工作,使 log/slog
更易上手。
日志级别
log/slog
日志级别包括 Info
、Debug
、Warn
和 Error
,log/slog
为它们分别提供了函数。
示例代码:
func main() { log.Println("This is log") slog.Debug("This is Debug Level") slog.Info("This is Info Level") slog.Warn("This is Warn Level") slog.Error("This is Error Level") }
输出结果:
2023/10/06 11:18:04 This is log 2023/10/06 11:18:04 INFO This is Info Level 2023/10/06 11:18:04 WARN This is Warn Level 2023/10/06 11:18:04 ERROR This is Error Level
阅读上面这段代码,我们可以发现 log/slog
的输出结果和 log
的输出结果非常相似,只是在日志时间和日志消息之间多了日志级别。
因为 log/slog
的默认 logger
使用的是 log
的默认 logger
。
除了上述 4 个不同日志级别的函数之外,还有一个函数 log
,我们可以使用 log
函数替代上述 4 个函数。
示例代码:
func main() { slog.Log(context.Background(), -4, "This is Debug Level") slog.Log(context.Background(), 0, "This is Info Level") slog.Log(context.Background(), 4, "This is Warn Level") slog.Log(context.Background(), 8, "This is Error Level") }
输出结果:
2023/10/06 11:41:47 INFO This is Info Level 2023/10/06 11:41:47 WARN This is Warn Level 2023/10/06 11:41:47 ERROR This is Error Level
阅读上面这段代码,我们可以发现,log
函数通过参数定义日志级别,数字越大,级别越严重,并且不同级别之间,预留 4 个数字,我们可以定义其他日志级别。
log
函数与 4 个分别代表不同级别的函数之间,还有另外一个区别,它的第一参数是上下文,其实 4 个分别代表不同级别的函数也对应 4 个支持第一个参数是上下文的函数,分别是 InfoContext()
、DebugContext()
、WarnContext()
和 ErrorContext
。
细心的读者朋友们可能发现了,为什么输出结果没有 Debug
级别的日志输出?
因为 log/slog
的默认 logger 的默认日志级别是 Info,如果我们想要使用日志级别 Debug,可以新建 logger,并把默认日志级别设置为 Debug。
键值对
前面我们已经说过 log/slog
支持键值对格式,但是上述示例代码中并没有体现,接下来,我们以 Info
函数为例,介绍 log/slog
怎么输出键值对格式。
func main() { slog.Info("This is Info Level", "uid", 1001) }
输出结果:
2023/10/06 11:58:07 INFO This is Info Level uid=1001
阅读上面这段代码,我们发现 Info
函数中,在日志消息之后新增两个参数,分别是 uid
和 1001
,它们就是键值对的 key
和 value
。
Logger 修改输出日志格式
因为 log/slog
默认使用 log
的默认 logger
,所以输出格式就是我们上面看到的文本格式。
我们可以使用内置的 Handler NewTextHandler
和 NewJSONHandler
创建新的 Logger
,来输出新文本格式和 json
格式。
示例代码:
func main() { logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) logger.Info("This is a new text Info Level", "uid", 1002) jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) jsonLogger.Info("This is a json format Info Level", "uid", 1003) }
输出结果:
time=2023-10-06T12:19:21.676+08:00 level=INFO msg="This is a new text Info Level" uid=1002 {"time":"2023-10-06T12:19:21.676846+08:00","level":"INFO","msg":"This is a json format Info Level","uid":1003}
阅读上面这段代码,我们可以发现通过内置 Handler 创建新的 Logger
,输出新的日志格式,其中 NewTextHandler
输出的所有内容都是键值对格式,NewJSONHandler
输出一个 json
对象。
此外,我们还可以自定义 Handler,通过实现 slog.Handler
接口,生成特定的输出日志格式或者 wrap
另一个 Handler 来丰富其功能。
03
总结
本文我们介绍 log/slog
的使用方式,包括日志级别和输出日志格式。
限于篇幅,还有一些进阶用法没有介绍,比如 LogAttrs
函数,以及 NewTextHandler
和 NewJSONHandler
的方法。
感兴趣的读者朋友们,可以阅读标准库 log/slog[1] 文档了解更多。