在进行Go语言编程中,我们会看见诸如if err == nil {}或者if err != nil {}之类的判断,这跟go语言的错误处理哲学(计划失败而非成功 / 及早失败)有关;大多数情况下,我们对一个err是否是nil进行判断是很直白的,无需考虑很多,但是如果对于interface的情况来说,处理的时候稍有点难度,多了许多要留意的地方。
看个重要的例子
package main import ( "bytes" "fmt" "io" ) //check的参数类型是io.Writer,是一个interface,所以只要某个类型的变量具有了Write方法 //也就等同于实现了Writer这个接口 //Writer的源码定义如下 //type Writer interface { // Write(p []byte) (n int, err error) //} func check(w io.Writer) { if w != nil { fmt.Println("w不是nil") } fmt.Printf("w是 %+v\n",w) } func main() { var b *bytes.Buffer //默认值是nil //bytes包里面的Buffer是一个struct,它具有Write方法,也就实现了io.Writer接口 //从而可以作为参数 //func (b *Buffer) Write(p []byte) (n int, err error) check(b) fmt.Printf("b的值是%+v\n",b) }大家可以先猜一下输出结果是什么?
......
w不是nil w是 <nil> b的值是<nil>不知道你猜对了没?但是对于新手来说,这一点确实有点困惑,w怎么一会儿是nil,一会儿又不是呢?其实这个奇怪的现象跟go语言中interface的内部结构有关, interface内部由一个类型T和一个值V构成,其中V是一个具体类型(int, struct, pointer,string…)的值,比如int类型的10或者string类型的“wdy”
PS: 前天我发了一篇名为《如何理解Go语言的空接口interface{}》,对interface内部不懂的同学请看回头翻一下那篇文章
阅读下面代码的前提【知识储备-源码】
//我们知道error是一个类型,同时在go语言的源码定义中,error也是一个interface type error interface { Error() string } //所以任意一个类型拥有了方法 func (any <any Type>) Error() string {}就是实现了error这个interface //比如: type some struct{} func (s *some) Error() string { return "some" } //这个代码段说明*some这个类型实现了error这个interface package main import( "fmt" ) type someError struct{} //类型定义 //*someError这个类型通过定义Error()函数实现了error这个接口 func (se *someError) Error() string { return "wdy" } func check(e error) { if e != nil { fmt.Println("e 不是nil") }else{ fmt.Println("e 是 nil") } fmt.Printf("e的值是%+v\n",e) } func main() { //情况1 var e error = nil check(e) fmt.Println() //情况2 var se *someError = nil check(se) }同样请猜一下输出结果:
......
e 是 nil e的值是<nil> e 不是nil e的值是wdy记得实操一遍哦,自己在Go playground上面动手,尝试自己写一个例子。 【weixin-公-众-号:go学习】