跟我學 Go:記錄

Go 標準程式庫提供能從 Go 程式輸出記錄的直觀工具,可使用 log 套件進行自由格式輸出,以及使用 log/slog 套件進行結構化輸出。

package main
import (
    "bytes"
    "fmt"
    "log"
    "os"
    "log/slog"
)
func main() {

只要從 log 套件呼叫函式,例如 Println,就會使用 標準 記錄器,它已預先設定為將合理的記錄輸出到 os.StderrFatal*Panic* 等其他方式會在記錄後退出程式。

    log.Println("standard logger")

記錄器可以使用 標記 設定其輸出格式。預設情況下,標準記錄器會設定 log.Ldatelog.Ltime 標記,且這些標記會收集在 log.LstdFlags 中。例如,我們可以變更其標記,以微秒精確度發出時間。

    log.SetFlags(log.LstdFlags | log.Lmicroseconds)
    log.Println("with micro")

它還支援自 呼叫 log 函式的檔案名稱和行輸出。

    log.SetFlags(log.LstdFlags | log.Lshortfile)
    log.Println("with file/line")

建立自訂記錄器並傳遞出去非常有用。建立新的記錄器時,我們可以設定 字首,以其輸出與其他記錄器區分開來。

    mylog := log.New(os.Stdout, "my:", log.LstdFlags)
    mylog.Println("from mylog")

我們可以使用 SetPrefix 方法設定現有記錄器的字首 (包含標準記錄器)。

    mylog.SetPrefix("ohmy:")
    mylog.Println("from mylog")

記錄器可以有自訂輸出目標;任何 io.Writer 都可使用。

    var buf bytes.Buffer
    buflog := log.New(&buf, "buf:", log.LstdFlags)

此呼叫會將記錄輸出寫入 buf

    buflog.Println("hello")

這實際上會在標準輸出上顯示它。

    fmt.Print("from buflog:", buf.String())

slog 套件提供 結構化 記錄輸出。例如,直接以 JSON 格式記錄。

    jsonHandler := slog.NewJSONHandler(os.Stderr, nil)
    myslog := slog.New(jsonHandler)
    myslog.Info("hi there")

除了訊息之外, slog 輸出可以包含任意數量的 key=value 對。

    myslog.Info("hello again", "key", "val", "age", 25)
}

範例輸出;發出的日期和時間會依據範例執行時間而定。

$ go run logging.go
2023/08/22 10:45:16 standard logger
2023/08/22 10:45:16.904141 with micro
2023/08/22 10:45:16 logging.go:40: with file/line
my:2023/08/22 10:45:16 from mylog
ohmy:2023/08/22 10:45:16 from mylog
from buflog:buf:2023/08/22 10:45:16 hello

這些會為了網站上的呈現而包覆起來;實際上,它們會在單一列中發出。

{"time":"2023-08-22T10:45:16.904166391-07:00",
 "level":"INFO","msg":"hi there"}
{"time":"2023-08-22T10:45:16.904178985-07:00",
    "level":"INFO","msg":"hello again",
    "key":"val","age":25}

下一個範例:HTTP Client