概述
其实标准库 log 包只有短短三百多行代码,非常适合拿来分析。
代码分析
首先,这是 log 包的一些引用的标准库,包括 fmt, io, os 等输出的包,也包括像 runtime 和 sync 这些控制并发的包。
1
2
3
4
5
6
7
8
|
import (
"fmt"
"io"
"os"
"runtime"
"sync"
"time"
)
|
The Fatal functions call os.Exit(1) after writing the log message.
根据注释提示,如果使用了 log.Fatal()
那么日志打印之后,就会直接调用 os.Exit(1)
然后进程就会退出。
The Panic functions call panic after writing the log message.
定义的几个常量。
1
2
3
4
5
6
7
8
9
|
const (
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
LstdFlags = Ldate | Ltime // initial values for the standard logger
)
|
Logger
结构体。
1
2
3
4
5
6
7
|
type Logger struct {
mu sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix to write at beginning of each line
flag int // properties
out io.Writer // destination for output
buf []byte // for accumulating text to write
}
|
Logger
的工厂方法。需要几个参数,包括 io.Writer
和 prefix
还有 flag
。
1
2
3
|
func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
|
SetOutput
是用来设置输出的目标地址,通过使用 Lock()
来控制锁的区域。
1
2
3
4
5
|
func (l *Logger) SetOutput(w io.Writer) {
l.mu.Lock()
defer l.mu.Unlock()
l.out = w
}
|
std
是一个可变的变量,初始化为下面的形式。
1
|
var std = New(os.Stderr, "", LstdFlags)
|
重点要讲一下 itoa
的原理。输入参数是一个指针类型的字节数组,和两个整数分别是 i
和 wid
。后者代表是是宽度。这个方法组要是将一个整数 i
转换成一个字符串,并且把结果直接追加到 buf
的尾部。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
func itoa(buf *[]byte, i int, wid int) {
// Assemble decimal in reverse order.
var b [20]byte
bp := len(b) - 1
for i >= 10 || wid > 1 {
wid--
q := i / 10
b[bp] = byte('0' + i - q*10)
bp--
i = q
}
// i < 10
b[bp] = byte('0' + i)
*buf = append(*buf, b[bp:]...)
}
|
其中核心方法是这个。如果输入 i
为11,且 wid
> 1,那么 q
为1,byte('0' + 11 -10)
,所以 b[bp]
就会被赋值为???。
1
2
3
4
5
6
7
|
for i >= 10 || wid > 1 {
wid--
q := i / 10
b[bp] = byte('0' + i - q*10)
bp--
i = q
}
|
参考资料
- log
警告
本文最后更新于 2022年10月19日,文中内容可能已过时,请谨慎参考。