Go log包使用

本文深入探讨了Go语言内置的日志包,包括如何创建和使用Logger对象,以及如何自定义日志格式和输出。通过示例展示了如何设置日志输出位置、前缀和标志位,以及如何获取调用者信息。此外,还讲解了如何根据业务需求创建多个自定义的Logger实例,例如Info、Warning和Error日志,并将其输出到不同的目的地。
摘要由CSDN通过智能技术生成


日志包提供了方便的携带多样化信息的输出,比如日期、调用者行号等,为我们找bug或者分析问题提供了强有力的工具

基本使用

日志的输入输出都基于log.Logger对象,通过New方法进行创建

func New(out io.Writer, prefix string, flag int) *Logger

// eg.
l := log.New(os.Stderr, "", Ldate | Ltime | Lshortfile)

out指定输出位置(比如标准流、文件),prefix指定每行输出日志的前缀字符串,为了区分业务日志和第三方库输出的日志,flag通过将标志位进行位或操作来指定每行日志携带的信息,其中可选的位有

const (
	Ldate         = 1 << iota     // 日期
	Ltime                         // 时间
	Lmicroseconds                 // 毫秒
	Llongfile                     // 文件绝对路径和行号
	Lshortfile                    // 文件名和行号
	LUTC                          // 如果同时使用了Ldate或者Ltime,使用UTC
  Lmsgprefix                    // prefix将紧跟在用户输出内容的头部,而不是日志的行首
	LstdFlags     = Ldate | Ltime // Go提供的标准抬头信息
)

以上三个参数也可以分别通过公有方法来单独进行设置

log包内已经定义了一个名为stdLogger,通过包名直接调用Logger的方法时其实就是对std对象进行操作

func Println(v ...any) {
	if atomic.LoadInt32(&std.isDiscard) != 0 {
		return
	}
	std.Output(2, fmt.Sprintln(v...)) // 对std进行调用
}

其中所有的日志输出方法如PrintlnFatalf都是通过调用Output方法来输出,因此最重要的是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) // 获取Println、Fatalf等调用时的所在文件和行数
		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) // 输出到指定的output中
	return err
}

其中获取调用者的runtime.Caller中传入的calldepth作用如下

0表示*Logger.Output中调用runtime.Caller的源代码文件和行号
1表示log.Println中调用*Logger.Output的源代码文件和行号
2表示main中调用log.Println的源代码文件和行号

因此PrintlnFatalf等方法调用Output传入的calldepth总是2

定制Logger

在实际的业务中通常不会使用默认的std来输出日志,而是通过New创建新的Logger实现自定义格式的日志输出

var (
	Info *log.Logger
	Warning *log.Logger
	Error * log.Logger
)

func init(){
	errFile,err:=os.OpenFile("errors.log",os.O_CREATE|os.O_WRONLY|os.O_APPEND,0666)
	if err!=nil{
		log.Fatalln("打开日志文件失败:",err)
	}

	Info = log.New(os.Stdout,"Info:",log.LstdFlags | log.Lshortfile)
	Warning = log.New(os.Stdout,"Warning:",log.LstdFlags | log.Lshortfile)
	Error = log.New(io.MultiWriter(os.Stderr,errFile), "Error:", log.LstdFlags | log.Lshortfile)
}

func main() {
	Info.Println("普通信息")
	Warning.Println("警告信息")
	Error.Println("错误信息")
}

其中io.MultiWriter封装多个Writer,很简单,进行Write操作时只是循环遍历传入的Writer并调用各自的Write输出同样的数据

参考链接:https://www.flysnow.org/2017/05/06/go-in-action-go-log

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值