Golang: Pattern: Error Handling with Err()

21st December 2020 at 4:00pm
Golang: Pattern

Go 的博客中有一篇 Errors are values 提到了一种错误处理的 pattern。代码示例如下:

好的例子:

scanner := bufio.NewScanner(input)
for scanner.Scan() {
    token := scanner.Text()
    // process token
}
if err := scanner.Err(); err != nil {
    // process the error
}

差的例子:

scanner := bufio.NewScanner(input)
for {
    token, err := scanner.Scan()
    if err != nil {
        return err // or maybe break
    }
    // process token
}

即是说,对于处理流式数据的接口,没有必要在每次处理一块数据时去判断错误,因为一旦出现错误,整个处理就结束了;而应该在整套处理结束后(不管是因为数据全部处理完了,还是中途出了错),再去判断有无错误发生。

反例

可惜的是,因为需求不同,database/sql 中的接口没有遵循这种模式:

for rows.Next() {
    err := rows.Scan(&id, &name)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(id, name)
}

虽然有 rows.Err() 函数,但是它是用于在不遍历数据的情况下获得错误信息的。如果要遍历数据,仍然需要判断每次 rows.Scan() 的返回值。