从源码学习 Go 标准库(二):log(1)

165 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情

前言

本系列文章将以源码和文档为依据,梳理标准库的内容,拓展对标准库的认识,并进一步探索标准库的使用方法。

第二章,我们来看一看 log 包。Go 语言内置了 log 包,它可以帮助我们实现一些简单的日志服务。

备注:本系列文章使用的是 go 1.19 源码:

github.com/golang/go/t…

log

github.com/golang/go/b…

常量与类型

按照惯例,我们先来看看 log 包里都定义了哪些常量与类型。

首先,是 flag 标志:

  • 这些标志用于定义记录器生成的每条日志的前缀文本

  • 使用 | 将不同的标志组合在一起

  • 除了 Lmsgprefix 以外,没有其他标志控制前缀出现的顺序或者打印的格式

  • 只有设置 Llongfile 或 Lshortfile 时,前缀后面会跟着一个冒号

const (
	Ldate         = 1 << iota     // 本地时区的日期: 2009/01/23
	Ltime                         // 本地时区的时间: 01:23:23
	Lmicroseconds                 // 微秒精度: 01:23:23.123123. 覆盖 Ltime
	Llongfile                     // 完整路径和行号: /a/b/c/d.go:23
	Lshortfile                    // 文件名和行号: d.go:23. 覆盖 Llongfile
	LUTC                          // 如果设置了 Ldate 或 Ltime, 使用 UTC 而不是本地时区
	Lmsgprefix                    // 将前缀从行首移到消息前
	LstdFlags     = Ldate | Ltime // 默认值
)

然后是,记录器结构体 Logger:

type Logger struct {
	mu        sync.Mutex
	prefix    string
	flag      int
	out       io.Writer
	buf       []byte
	isDiscard int32
}

其中

  • 互斥锁用于保证写入操作的原子性

  • buf 用于存储写入的文字

  • isDiscard 原子布尔值:判断 out 是否等于 io.Discard

变量与导出函数

log 包里默认创建一个标准记录器,将日志打印到标准错误中。

var std = New(os.Stderr, "", LstdFlags)

所有直接调用的导出函数都是通过这个默认的记录器来进行相应操作。

记录器设置:

  • SetFlags:设置标志

  • SetOutput:设置输出目标,需实现满足 io.Writer 接口

  • SetPrefix:设置前缀

log.SetPrefix("<prefix>")
log.Println("这是一条日志")  // <prefix>2022/08/26 23:06:29 这是一条日志

打印方法一共有 3x3=9 种,它们分别是:

PrintPrintfPrintln
FatalFatalfFatalln
PanicPanicfPanicln

它们的不同在于,Fatal 系列会在打印日志后,调用 os.Exit(1) 退出程序;Panic 系列会在打印日志后,调用 panic(s) 进入恐慌。

总结

本篇文章,我们分析了 log 包的常量、类型与函数,了解了 log 的基本使用。log 包的功能十分有限,我们在实际开发中可以根据需求选择一些第三方的日志库。在下一章中,会介绍一些第三方日志库的使用方法。

最后,如果本篇文章对您有所帮助,希望您可以 点赞、收藏、评论,感谢支持 ✧(≖ ◡ ≖✿