模块 2 · 第 5 课(共 5)课程中的10/50~12 min
模块课程(5/5)
错误:“if err != nil”模式
在 Go 中,错误是值,而不是异常。一个函数可以 失败返回错误作为最后一个值,调用者检查它 明确地。它是明确的、可预测的、易于测试的——价格是 更冗长一点。
error 接口
error 是语言内置的一个小接口:
Go
type error interface {
Error() string
}任何实现 Error() string 的类型都是 error。
基本模式
Go
v, err := operazione()
if err != nil {
// gestisci o propaga
return err
}
// usa v您将看到这一点数千次:这是每个人的惯用代码 容易出错的电话。不要对重复感到内疚——这是一个功能,而不是 一个错误。
构建错误:errors.New 和 fmt.Errorf
Go
import (
"errors"
"fmt"
)
err1 := errors.New("file mancante")
err2 := fmt.Errorf("apertura %q fallita: permesso negato", path)当您想在消息中包含变量时,fmt.Errorf 是完美的选择。
用 %w 包装
要传播错误添加上下文而不丢失原始内容:
Go
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("config: %w", err)
}%w “包装”原始错误,稍后可以使用
errors.Is (哨兵相等)或 errors.As (对于具体类型):
Go
if errors.Is(err, os.ErrNotExist) {
// file inesistente, gestione speciale
}哨兵错误
这些是作为变量导出的错误,用于与 errors.Is 进行比较:
Go
var ErrNotFound = errors.New("non trovato")
func find(id int) (Item, error) {
// ...
return Item{}, ErrNotFound
}
// chiamante:
if errors.Is(err, ErrNotFound) { ... }panic 和 recover (预览)
panic 存在于 Go 中,但保留用于 不可恢复 错误(例如 bug、
违反了不变量),不适用于正常控制流。我们将更深入地
具有 defer/recover 的函数模块。现在:不要在适当的地方使用它
if err != nil 模式的。
尝试一下
锻炼#go.m2.l5.e1
尝试:0加载中...
处理来自 strconv.Atoi 的错误:如果 err != nil,则打印并返回;否则打印n。
正在加载编辑器...
显示提示
规范模式:检查 `err != nil`,记录/返回,然后使用 `n`。
3 次尝试后可用的解决方案
锻炼#go.m2.l5.e2
尝试:0加载中...
实现 safeDiv:如果 b == 0 返回 0 和错误。New('divisione per Zero');否则 a/b 和 nil。
正在加载编辑器...
显示提示
在除法之前检查 `b == 0` 以避免运行时恐慌。
3 次尝试后可用的解决方案
Quiz#go.m2.l5.e3
准备好Go 中处理错误的惯用模式是什么?
Go
v, err := f()
// poi?回顾
error是一个具有一种方法Error() string的接口。- 规范模式:
v, err := f(); if err != nil { return err }。 - 使用
errors.New(msg)或fmt.Errorf("ctx: %w", err)构建错误。 - 使用
%w进行包装,并使用errors.Is/errors.As检查链条。 panic仅适用于不可恢复的错误,不适用于正常控制流。