Golang日志中出现错误怎么办
Go开发中日志与错误处理需关注细节:标准库log便于定位,但丢失类型信息;推荐用fmt.Errorf的%w包装错误以便追溯;第三方库如logrus支持结构化输出。错误处理策略包括记录并继续、返回错误和终止程序,需根据业务场景组合使用。
在Go开发中,日志和错误处理几乎是每天都要打交道的事情。很多新手往往习惯写一个log.Println(err)就完事了,但实际项目中,错误怎么记、记到什么粒度、是否要包装上下文,这些细节直接影响问题排查的效率。今天就顺着思路,把常见的几种做法梳理一遍。

先从最基础的说起。标准库的log包提供了开箱即用的日志功能,自带时间戳、文件名和行号,很适合快速定位问题。
import ("log")
func main() {
err := someFunction()
if err != nil {
log.Printf("Error in someFunction: %v", err)
}
}
但直接打印字符串有个缺陷——丢失了错误的类型和上下文。这时可以用errors包创建带描述的error,或者用fmt.Errorf做更灵活的格式化。比如下面这样,既能保留原始错误,又能附加说明信息:
import ("errors")
func someFunction() error {
return errors.New("something went wrong")
}
// 或者用fmt.Errorf包装
func someFunction() error {
return fmt.Errorf("something went wrong: %w", someOtherError)
}
说到包装错误,%w这个动词是Go 1.13引入的,它能让上层调用者通过errors.Is或errors.As逐层解包,追溯根源。这是目前生产环境最推荐的做法。
如果项目对日志的要求更高——比如需要结构化JSON输出、按级别过滤、或者与ELK等日志系统对接,那第三方库就是更好的选择。业内用得比较多的有logrus和zap,前者上手简单,后者性能极佳。以logrus为例,配合Fields可以很方便地添加结构化字段:
import ("github.com/sirupsen/logrus")
func main() {
logrus.SetFormatter(&logrus.JSONFormatter{})
err := someFunction()
if err != nil {
logrus.WithFields(logrus.Fields{"error": err}).Error("Error in someFunction")
}
}
日志工具只是手段,真正重要的是错误处理策略。根据错误的严重程度,常见的做法可以归纳为三类:
- 记录并继续——适用于非关键错误,比如解析一条用户输入失败,不影响主流程,记下来就好。
- 返回错误——这是函数设计的常规做法,让上层调用者根据上下文决定怎么处理,保持职责分离。
- 终止程序——当发生系统级故障(如无法连接数据库、配置文件缺失)时,再往下跑已经没有意义,直接
log.Fatal或panic。
func main() {
err := someFunction()
if err != nil {
log.Fatalf("Error in someFunction: %v", err)
}
}
当然,实际项目中往往需要组合使用这几种策略。举个例子:一个HTTP服务中,某个请求处理过程中调用RPC失败,你可能先记录错误日志,然后把这个error包装后返回给中间件,由中间件决定是返回500还是重试。这里没有银弹,关键是根据业务场景定好边界。


































