是否可以在不丢失行号前缀的情况下包装 log.Logger 函数?
Is it possible to wrap log.Logger functions without losing the line number prefix?
当使用log.Lshortfile
标志时,记录器在所有日志行前加上记录器函数调用的文件名和行号,例如:
myfile.go:14: Hello, world!
如果我像这样包装日志函数,例如:
func info(pattern string, args ...interface{}) {
myLogger.Printf(pattern + "\n", args...)
}
此函数发出的每一行都将以 Printf
调用的行号作为前缀。这是预期的,但期望的行为是每一行都以调用 info
的行的行号为前缀。
有什么办法解决吗?
我打算将此作为我当前的解决方法包括在问题中,但我认为这是一个有效的答案。我希望有人能告诉我一个我错过的记录器配置选项,它可以让我调整记录器在调用 runtime.Caller
.
时使用的深度
解决方法是删除 log.Lshortfile
标志并手动实施行为:
func info(format string, args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
prefix := fmt.Sprintf("%v:%v: ", path.Base(file), line)
if logger != nil {
logger.Printf(prefix+format+"\n", args...)
}
}
方法log.Logger
call the Logger.Output()
方法将消息发送到适当的输出。 Logger.Output()
允许您传递 calldepth
(要跳过的帧数)。
不幸的是 log.Logger
的方法包含 calldepth
"wired in",因此您无法提供偏移量来跳过包装函数的帧。
但更好的替代方法是从包装器中调用此 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...))
}
正在测试:
func main() {
log.SetFlags(log.Lshortfile)
log.Println("hello")
info("world")
}
输出(在 Go Playground 上尝试):
main.go:11: hello
[my]main.go:12: world
如您所见,info()
打印了正确的行号(与上一行 log.Println()
打印的行号相比 +1)。
当使用log.Lshortfile
标志时,记录器在所有日志行前加上记录器函数调用的文件名和行号,例如:
myfile.go:14: Hello, world!
如果我像这样包装日志函数,例如:
func info(pattern string, args ...interface{}) {
myLogger.Printf(pattern + "\n", args...)
}
此函数发出的每一行都将以 Printf
调用的行号作为前缀。这是预期的,但期望的行为是每一行都以调用 info
的行的行号为前缀。
有什么办法解决吗?
我打算将此作为我当前的解决方法包括在问题中,但我认为这是一个有效的答案。我希望有人能告诉我一个我错过的记录器配置选项,它可以让我调整记录器在调用 runtime.Caller
.
解决方法是删除 log.Lshortfile
标志并手动实施行为:
func info(format string, args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
prefix := fmt.Sprintf("%v:%v: ", path.Base(file), line)
if logger != nil {
logger.Printf(prefix+format+"\n", args...)
}
}
方法log.Logger
call the Logger.Output()
方法将消息发送到适当的输出。 Logger.Output()
允许您传递 calldepth
(要跳过的帧数)。
不幸的是 log.Logger
的方法包含 calldepth
"wired in",因此您无法提供偏移量来跳过包装函数的帧。
但更好的替代方法是从包装器中调用此 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...))
}
正在测试:
func main() {
log.SetFlags(log.Lshortfile)
log.Println("hello")
info("world")
}
输出(在 Go Playground 上尝试):
main.go:11: hello
[my]main.go:12: world
如您所见,info()
打印了正确的行号(与上一行 log.Println()
打印的行号相比 +1)。