Golang log 源码阅读

来看看Go标准库里的log,怎么实现的,首先我们来看一个例子:

package main

import (
	"log"
)

func main() {
	log.Printf("hello %s", "world")
	log.Panicf("this")
}

运行一下:

$ go build && ./test
2020/04/28 22:24:25 hello world
2020/04/28 22:24:25 this
panic: this

goroutine 1 [running]:
log.Panicf(0x4cc48d, 0x4, 0x0, 0x0, 0x0)
	/snap/go/5646/src/log/log.go:358 +0xc0
main.main()
	/home/jiajun/Code/test/main.go:9 +0xa0

我们从 log.Printf 来看看咋实现的:

func Printf(format string, v ...interface{}) {
	std.Output(2, fmt.Sprintf(format, v...))
}

我们跟进 Output

func (l *Logger) Output(calldepth int, s string) error {
	now := time.Now() // get this early.
	var file string
	var line int
	l.mu.Lock()
	defer l.mu.Unlock()
	if l.flag&(Lshortfile|Llongfile) != 0 {
		// Release lock while getting caller info - it's expensive.
		l.mu.Unlock()
		var ok bool
		_, file, line, ok = runtime.Caller(calldepth)
		if !ok {
			file = "???"
			line = 0
		}
		l.mu.Lock()
	}
	l.buf = l.buf[:0]
	l.formatHeader(&l.buf, now, file, line)
	l.buf = append(l.buf, s...)
	if len(s) == 0 || s[len(s)-1] != '\n' {
		l.buf = append(l.buf, '\n')
	}
	_, err := l.out.Write(l.buf)
	return err
}

可以看到里面的实现,就是往 l.buf 里写入,然后呢,往 l.out 写出,下面的代码可以看到,标准库里其实就是往 os.Stderr 写:

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

func New(out io.Writer, prefix string, flag int) *Logger {
	return &Logger{out: out, prefix: prefix, flag: flag}
}

type Logger struct {
	mu     sync.Mutex // ensures atomic writes; protects the following fields
	prefix string     // prefix on each line to identify the logger (but see Lmsgprefix)
	flag   int        // properties
	out    io.Writer  // destination for output
	buf    []byte     // for accumulating text to write
}

最后我们来看一下 Panicf,其实很简单,就是输出log,然后来一个 panic

func Panicf(format string, v ...interface{}) {
	s := fmt.Sprintf(format, v...)
	std.Output(2, s)
	panic(s)
}

更多文章
  • 提取kindle笔记
  • 一个Golang gRPC握手错误的坑
  • Golang(Go语言)爬虫框架colly简明教程及源码阅读与分析
  • 选择合适的技术栈
  • Golang的template(模板引擎)简明教程
  • 毕业三年,一路走来
  • 代码的坏味道
  • 消息分帧(字符串设计或协议设计)的两种形式
  • C, Go, Python的错误处理和异常机制杂谈
  • 好的命名是最好的文档
  • 读《系统之美:决策者的系统思考》
  • Linux高分屏支持
  • GCC默认的头文件搜索路径
  • 读《远见-如何规划职业生涯3大阶段》
  • 后端工程师学前端(五): SASS