go1.21中slog日志包用法入門
WHY
在日志處理上,我們從前使用的log包缺乏結(jié)構(gòu)化的輸出,導(dǎo)致信息呈現(xiàn)出來的樣子并非最適合人類閱讀,而slog是一種結(jié)構(gòu)化的日志,它可以用鍵值對(duì)的形式將我們需要的信息呈現(xiàn)出來,使得處理與分析日志變得更為容易。
HOW
1. 快速入門
package main
import (
"log/slog"
)
func main() {
slog.Info("my first slog msg", "greeting", "hello, slog")
slog.Error("my secod slog message", "greeting", "hello slog")
slog.Warn("my third message", "greeting", "hello slog")
}以上是三條最簡(jiǎn)單的slog語(yǔ)句,其結(jié)果是這樣的:
2023/09/10 21:51:03 INFO my first slog msg greeting="hello, slog"
2023/09/10 21:51:03 ERROR my secod slog message greeting="hello slog"
2023/09/10 21:51:03 WARN my third message greeting="hello slog"
這三行代碼中的第一個(gè)參數(shù)代表了log的message,我們可以看到,此時(shí)打印出來的日志信息是文本信息,那如何使得日志以非純文本(比如json)展現(xiàn)呢?
2. TextHandler和JSONHandler
當(dāng)我們想要日志以key-value格式呈現(xiàn)時(shí),我們可以用下面這種方式:
h := slog.NewTextHandler(os.Stderr, nil)
l := slog.New(h)
l.Info("greeting", "name", "xxx")最終結(jié)果:
time=2023-09-10T21:58:34.144+08:00 level=INFO msg=greeting name=xxx
當(dāng)我們想要日志以json格式呈現(xiàn)時(shí),我們可以使用下面這種方式:
h1 := slog.NewJSONHandler(os.Stderr, nil)
l1 := slog.New(h1)
l1.Info("greeting", "name", "xxx")最終結(jié)果:
{"time":"2023-09-10T22:00:04.687003+08:00","level":"INFO","msg":"greeting","name":"xxx"}
slog.NewJSONHandler函數(shù)和slog.NewTextHandler函數(shù)都會(huì)返回一個(gè)JsonHandler結(jié)構(gòu)體或是TextHandler的引用,這個(gè)結(jié)構(gòu)體會(huì)被slog.new函數(shù)接受,該函數(shù)返回一個(gè)Logger結(jié)構(gòu)體的引用,這個(gè)logger結(jié)構(gòu)體包含Handler接口,擁有一系列日志相關(guān)函數(shù),是我們最終打印日志的地方
func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {}
func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {}
func New(h Handler) *Logger {}
type Logger struct {
handler Handler // for structured logging
}
type Handler interface {}如此,我們實(shí)現(xiàn)了基本的日志結(jié)構(gòu)化輸出。
3.日志配置
我們通過對(duì)slog.HandlerOptions配置,可以實(shí)現(xiàn)例如 是否輸出日志來源 等設(shè)置;
s := &slog.HandlerOptions{
AddSource: true,
}
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, s)))
slog.Info("Test", "greeting", "hello, world")此處筆者將該s設(shè)置為default情況,這樣直接使用slog.info就可以用到之前的配置;
最終結(jié)果:
time=2023-09-10T22:11:04.432+08:00 level=INFO source="/Users/wurenyu/Library/Mobile Documents/com~apple~CloudDocs/Go_learn/basic/slog/t1.go:13" msg=Test greeting="hello, world"
可以看到,由于AddSource被設(shè)置為true,我們的輸出日志中多了source這一信息;
又由于NewTextHandler,所以日志是以鍵值對(duì)的形式輸出的。
再來看這一段代碼:
opts := slog.HandlerOptions{
AddSource: true,
Level: slog.LevelError,
}
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &opts)))
slog.Info("open file for reading", "name", "foo.txt", "path", "/home/tonybai/demo/foo.txt")
slog.Error("open file error", "err", os.ErrNotExist, "status", 2)在slog配置中將Level設(shè)置為了LevelError,如此,將只能使用slog.error這一級(jí)別;
最終輸出結(jié)果:
{"time":"2023-09-10T22:13:44.493714+08:00","level":"ERROR","source":{"function":"main.main","file":"/Users/wurenyu/Library/Mobile Documents/com~apple~CloudDocs/Go_learn/basic/slog/t1.go","line":16},"msg":"open file error","err":"file does not exist","status":2}
4. Group形式輸出日志
baseLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
groupedLogger := baseLogger.WithGroup("TTT")
// Log with the grouped logger
groupedLogger.Info("This log entry includes module information.", "test1", "answer1")
groupedLogger.Warn("This log entry also includes module information.", "test2", "answer2")上述代碼首先生成一個(gè)叫做baseLogger的logger,然后在這個(gè)logger上調(diào)用方法WithGroup,并傳入?yún)?shù)“TTT”,后面兩行分別輸出info和warn級(jí)別的日志;
最終結(jié)果如下:
{"time":"2023-09-10T22:23:28.527786+08:00","level":"INFO","msg":"This log entry includes module information.","TTT":{"test1":"answer1"}}
{"time":"2023-09-10T22:23:28.528019+08:00","level":"WARN","msg":"This log entry also includes module information.","TTT":{"test2":"answer2"}}
可以看到,在groupLogger后面加上的鍵值對(duì)都被加在了TTT后面;
不過值得關(guān)注的是,slog是支持給logger自定義字段的,給一個(gè)logger加上一個(gè)屬性之后,每次用這個(gè)logger輸出日志,都會(huì)輸出這個(gè)屬性對(duì)應(yīng)的鍵值對(duì),而這個(gè)信息不會(huì)被包含在WithGroup函數(shù)傳入的參數(shù)后面。
風(fēng)格
個(gè)人認(rèn)為一般不需要在msg中直接傳入代碼中的數(shù)據(jù),msg中應(yīng)該盡量直接使用constant常量,這樣更可控。
WHAT
以下是slog大致的架構(gòu):

全文終。
以上就是go1.21中slog日志包用法入門的詳細(xì)內(nèi)容,更多關(guān)于go slog的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang?防緩存擊穿singleflight的實(shí)現(xiàn)
本文主要介紹了golang?防緩存擊穿singleflight的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Go語(yǔ)言與其他語(yǔ)言進(jìn)行交互的方式詳解
在當(dāng)今的軟件開發(fā)領(lǐng)域,多種編程語(yǔ)言常常需要協(xié)同工作,以充分利用各自的優(yōu)勢(shì)來構(gòu)建復(fù)雜的應(yīng)用系統(tǒng),Go 語(yǔ)言作為一門高效、簡(jiǎn)潔的編程語(yǔ)言,也經(jīng)常需要與其他語(yǔ)言進(jìn)行交互,接下來,我們將詳細(xì)探討 Go 語(yǔ)言如何與其他語(yǔ)言進(jìn)行交互,需要的朋友可以參考下2024-06-06
使用Golang的channel交叉打印兩個(gè)數(shù)組的操作
這篇文章主要介紹了使用Golang的channel交叉打印兩個(gè)數(shù)組的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04
Go語(yǔ)言中函數(shù)可變參數(shù)(Variadic Parameter)詳解
在Python中,在函數(shù)參數(shù)不確定數(shù)量的情況下,可以動(dòng)態(tài)在函數(shù)內(nèi)獲取參數(shù)。在Go語(yǔ)言中,也有類似的實(shí)現(xiàn)方式,本文就來為大家詳細(xì)講解一下2022-07-07
go語(yǔ)言題解LeetCode506相對(duì)名次示例詳解
這篇文章主要為大家介紹了go語(yǔ)言題解LeetCode506相對(duì)名次示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

