errors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
errors.Is() 使用场景总结
✅ 可以使用的情况
1. 直接返回预定义错误实例 // 定义
var ErrNotFound = errors.New("not found")
// 返回
func GetUser(id string) error {
return ErrNotFound // ✅ 直接返回同一个实例
}
// 判断
if errors.Is(err, ErrNotFound) { // ✅ 返回 true
2. 通过 fmt.Errorf 包装的错误链
// 定义
var ErrNotFound = errors.New("not found")
// 返回(Go 1.13+ 支持 %w)
func GetUser(id string) error {
err := ErrNotFound
return fmt.Errorf("get user failed: %w", err) // ✅ 使用 %w 包装
}
// 判断
if errors.Is(err, ErrNotFound) { // ✅ 返回 true(会解包查找)
3. 多层包装
var ErrNotFound = errors.New("not found")
func layer1() error {
return fmt.Errorf("layer1: %w", ErrNotFound)
}
func layer2() error {
return fmt.Errorf("layer2: %w", layer1())
}
// 判断
if errors.Is(err, ErrNotFound) { // ✅ 即使包装多层也能找到
❌ 不能使用的情况
1. 使用 errors.New() 创建新实例(你的代码中的情况)
var ErrNotFound = errors.New("not found")
func GetUser(id string) error {
return errors.New("not found") // ❌ 创建了新的错误实例
}
// 判断
if errors.Is(err, ErrNotFound) { // ❌ 返回 false(不是同一个实例)
2. 使用 fmt.Errorf 但不带 %w
var ErrNotFound = errors.New("not found")
func GetUser(id string) error {
return fmt.Errorf("get user failed: %v", ErrNotFound) // ❌ 使用 %v
}
// 判断
if errors.Is(err, ErrNotFound) { // ❌ 返回 false(%v 不会保留错误链)
3. 代理请求模式(你的代码中的情况)
// 从你看到的 ks.go 第 138 行
if rv.Code != 0 {
return "", errors.New(rv.Message) // ❌ 创建了新实例
}