Go 陷阱系列

陷阱一 interface问题

问题代码

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
package main

import "fmt"

//DetaildError ...
type DetaildError struct {
code int
message string
}

func (e DetaildError) Error() string {
return fmt.Sprintf("Error occured at (%d,%s)", e.code, e.message)
}

func handle(x int) *DetaildError {
if x != 1 {
return &DetaildError{code: 1000, message: "whoami?"}
}
return nil
}

func main() {
var err error
err = handle(0)
if err != nil {
fmt.Printf("I am Error 1 of %s\n", err)
}
err = handle(1)
if err != nil {
fmt.Printf("I am Error 2 of %s\n", err)
}
}

输出结果

1
2
I am Error 1 of Error occured at (1000,whoami?)
I am Error 2 of <nil>

原因

err 是一个接口,接口在Go中保存了两个值,一个是类型T,一个值V
只有当TV 同时nil时,接口才是nil
在Go中,接口是隐式实现,因此当我们用一个接口类型去接收一个nil结构体的时候,那么这个接口将不再是nil
此时的err值为(T=*DetaildError, V=nil),不满足接口为nil条件

解决办法

修正一:将var err Error 修改为接收Struct 而不是接口

1
var err *DetaildError

修正二:将handle方法的返回类型为interface

1
2
3
4
5
6
func handle(x int) error {
if x != 1 {
return &DetaildError{code: 1000, message: "whoami?"}
}
return nil
}

参考:

  • mp.weixin.qq.com/s/0bJOzNxoQhdVjFOunhmVKQ
-------------本文结束感谢您的阅读-------------