Logging

Logging->日志 #

// Go标准库提供了直观的工具用于从Go程序输出日志
// 使用 [log](https://pkg.go.dev/log) 包进行自由格式输出
// 使用 [log/slog](https://pkg.go.dev/log/slog) 包进行结构化输出。

package main

import (
	"bytes"
	"fmt"
	"log"
	"os"

	"log/slog"
)

func main() {

	// 只需调用 `log` 包中的 `Println` 等函数即可使用 _标准_ logger。
	// 它已经预先配置为将日志输出到 `os.Stderr`。
	// 像 `Fatal*` 或 `Panic*` 这样的附加方法将在记录日志后退出程序。
	log.Println("standard logger")

	// 日志记录器可以使用 _flags_ 进行配置,以设置它们的输出格式。
	// 默认情况下,标准记录器已设置了 `log.Ldate` 和 `log.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")

	// 除了 `msg` 之外,`slog` 输出还可以包含任意数量的键值对。
	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}