go nil处理如何正确返回nil的error
作者:uccs
i == nil 会生效
对于下面这段代码,我们知道 i
实际上的值就是 nil
,所以 i == nil
会生效
func main() { var i *int = nil if i == nil { fmt.Println("i is nil") // i is nil } }
现在换一种写法,我们将 i
的类型改成 interface{}
,i == nil
依然会生效
func main() { var i interface{} = nil if i == nil { fmt.Println("i is nil") // i is nil } }
我们接着改造,将 i == nil
的逻辑封装成函数 IsNil
func IsNil(i interface{}) { if i == nil { fmt.Println("i is nil") } } func main() { var i *int = nil IsNil(i) }
IsNil 中的 i == nil 不生效
然后居然发现 IsNil
中的 i == nil
不生效了,为什么呢?
因为对于 interface{}
类型的值来说,如果要判断它是 nil
,必须同时满足 type T
和 value V
都是 nil
才行
可以用 reflect
中的 TypeOf
和 ValueOf
var i *int = nil fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // *int <nil> var i interface{} = nil fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // <nil> <invalid reflect.Value>
但是如果我们在函数中用 interface{}
作为参数的类型,表示并不代表参数就是 interface{}
类型,而是任意类型,调用时传入啥类型就是啥类型,如下代码
var i interface{} = 1 fmt.Println(reflect.TypeOf(i)) // int var j interface{} = "hello" fmt.Println(reflect.TypeOf(j)) // string var k interface{} = nil fmt.Println(reflect.TypeOf(k)) // nil
所以只有当我们传入类型的参数是 interface{}
类型时,且 value
为 nil
时,i == nil
才会生效
否则其他情况都不会生效
func main() { var i interface{} = nil IsNil(i) // i is nil } func IsNil(i interface{}) { if i == nil { fmt.Println("i is nil") } }
这个坑可能会出现在返回 error
的函数中,比如下面这段代码
在函数 SomeThing
中提前定义了 myError
,然后一系列的处理后,返回了 myError
业务逻辑
后面的业务逻辑需要判断 err
是否为 nil
type MyError struct{} func (me *MyError) Error() string { return "my error" } func SomeThing() error { var myError *MyError // 默认初始化为 nil // ... return myError } func main() { err := SomeThing() fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // *main.MyError <nil> if err != nil { // 虽然没有返回,这里会被执行,因为 err 的类型不是 nil fmt.Println(err) } }
从上面的代码我们看到,SomeThing
函数中定义的 myError
是 *MyError
类型,虽然返回了 nil
,但是 err
的类型不是 nil
,所以 err != nil
会生效,不符合预期
如果修改这个问题呢,当我们需要返回 nil
时,显示指明返回 nil
,如下代码:
type MyError struct{} func (me *MyError) Error() string { return "my error" } func SomeThing() error { var myError *MyError // 默认初始化为 nil // ... return nil } func main() { err := SomeThing() fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // <nil> <invalid reflect.Value> if err != nil { // 这段代码不会被执行 fmt.Println(err) } }
总结
需要返回 nil
时,要显示返回 nil
,不要用指针类型的零值
以上就是go nil处理如何正确返回nil的error的详细内容,更多关于go nil处理返回error的资料请关注脚本之家其它相关文章!