是不是所有的 if err != nil 的地方都应该输出错误日志?
打印过多的错误日志会导致日志文件变得冗长和难以阅读。
其次,重复的错误信息会增加冗余。
此外,每一层都打印错误日志,一旦错误信息设计不当,可能会导致上下文信息的丢失。
1、案例
假设我们有一个五层的Go函数调用栈,其中最底层的函数level4Function出现了一个错误
package main
import (
"fmt"
"log"
)
func main() {
if err := topFunction(); err != nil {
log.Printf("Error: %v", err)
}
}
func topFunction() error {
err := level1Function()
if err != nil {
log.Printf("topFunction: %v", err)
return err
}
return nil
}
func level1Function() error {
err := level2Function()
if err != nil {
log.Printf("level1Function: %v", err)
return err
}
return nil
}
func level2Function() error {
err := level3Function()
if err != nil {
log.Printf("level2Function: %v", err)
return err
}
return nil
}
func level3Function() error {
err := level4Function()
if err != nil {
log.Printf("level3Function: %v", err)
return err
}
return nil
}
func level4Function() error {
err := fmt.Errorf("出了问题")
if err != nil {
log.Printf("level4Function: %v", err)
return err
}
return nil
}
每个函数中都输出错误日志并返回错误值
当我们运行程序时,日志文件会出现重复的错误信息,并且上下文信息不易于进行链式追踪,因为每个函数只打印了特定错误的信息,而没有提供之前错误的上下文。
2. 实践技巧
应该只在最顶层的函数中输出错误日志,而在下层函数中返回错误值
package main
import (
"fmt"
"log"
)
func main() {
if err := topFunction(); err != nil {
log.Printf("Error: %v", err)
}
}
func topFunction() error {
err := level1Function()
if err != nil {
return fmt.Errorf("topFunction: %w", err)
}
return nil
}
func level1Function() error {
err := level2Function()
if err != nil {
return fmt.Errorf("level1Function: %w", err)
}
return nil
}
func level2Function() error {
err := level3Function()
if err != nil {
return fmt.Errorf("level2Function: %w", err)
}
return nil
}
func level3Function() error {
err := level4Function()
if err != nil {
return fmt.Errorf("level3Function: %w", err)
}
return nil
}
func level4Function() error {
err := fmt.Errorf("出现了问题")
if err != nil {
return fmt.Errorf("level4Function: %w", err)
}
return nil
}
3、总结
在编写Go代码时,请记住要么返回错误值,要么输出日志,不要两者都做。通过合理地处理错误,我们可以编写出更可靠、更易于调试的代码。