Golang 错误处理最佳实践

Che Dan
9 min readDec 25, 2019

Golang有很多优点,这也是它如此流行的主要原因。但是Go 1 对错误处理的支持过于简单了,以至于日常开发中会有诸多不便利。

这些不足催生了一些开源解决方案。与此同时, Go 官方也在从语言和标准库层面作出改进。

本文将分析一些常见问题,对比各种解决方案,并展示了迄今为止(go 1.13)的最佳实践。

先说结论:建议使用 github.com/pkg/errors 进行错误处理。原因将在下面详细阐述

问题

Golang开发中经常需要检查返回的错误值并作相应处理。最简示例如下:

import (
"database/sql"
"fmt"
)

func foo() error {
return sql.ErrNoRows
}

func bar() error {
return foo()
}

func main() {
err := bar()
if err != nil {
fmt.Printf("got err, %+v\n", err)
}
}
//Outputs:
// got err, sql: no rows in result set

有时需要根据返回的error类型作不同处理,例如:

import (
"database/sql"
"fmt"
)

func foo() error {
return sql.ErrNoRows
}

func bar() error {
return foo()
}

func main() {
err := bar()
if err == sql.ErrNoRows {
fmt.Printf("data not found, %+v\n", err)
return
}
if err != nil {
// Unknown error
}
}
//Outputs:
// data not found, sql: no rows in result set

实践中经常需要为错误增加上下文信息后再返回,以方便调用者了解错误场景。例如 foo方法时常写成

func foo() error {
return fmt.Errorf("foo err, %v", sql.ErrNoRows)
}

但这时 err == sql.ErrNoRows 便不再成立。除此之外,上述写法都在返回错误时都丢掉了调用栈这个重要的诊断信息。我们需要更灵活、更通用的方式来应对此类问题。

解决方案

--

--