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()
的返回值。