是否可以在不丢失行号前缀的情况下包装log.Logger函数?

Hub*_*bro 8 logging callstack go

使用该log.Lshortfile标志时,记录器会在所有日志行前加上记录器函数调用的文件名和行号,例如:

myfile.go:14: Hello, world!

如果我像这样包装日志函数,例如:

func info(pattern string, args ...interface{}) {
    myLogger.Printf(pattern + "\n", args...)
}
Run Code Online (Sandbox Code Playgroud)

此函数发出的每一行都将以Printf调用的行号为前缀.这是预期的,但是期望的行为是每行都以要info调用的行的行号为前缀.

它有什么办法吗?

icz*_*cza 9

方法log.Logger调用的Logger.Output()方法将消息发送到相应的输出.Logger.Output()允许你传递calldepth(要跳过的帧数).

不幸的是,log.Logger包含calldepth"有线"的方法,因此您无法提供跳过包装函数框架的偏移量.

但更好的选择是Logger.Output()从你的包装器调用它,所以你不必自己打扰帧和行.另请注意,您不需要附加换行符"\n",因为log.Logger如果要记录的消息不以换行符结尾,则类型已经这样做.

所以更好,更短的选择:

var myLogger = log.New(os.Stdout, "[my]", log.Lshortfile)

func info(pattern string, args ...interface{}) {
    myLogger.Output(2, fmt.Sprintf(pattern, args...))
}
Run Code Online (Sandbox Code Playgroud)

测试它:

func main() {
    log.SetFlags(log.Lshortfile)
    log.Println("hello")
    info("world")
}
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

main.go:11: hello
[my]main.go:12: world
Run Code Online (Sandbox Code Playgroud)

如您所见,info()打印正确的行号(+1与上一行打印的行号相比log.Println()).

  • 这就是我在说的:D很棒的答案 (2认同)