golang 这段代码 checkError 为什么会触发 panic ?
package main
import (
"fmt"
)
type Error struct {
errCode uint8
}
func (e *Error) Error() string {
switch e.errCode {
case 1:
return "file not found"
case 2:
return "time out"
case 3:
return "permission denied"
default:
return "unknown error"
}
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
func main() {
var e *Error
checkError(e)
}
checkError 传参 err 是 nil,为什么也会进入到 panic ?
题主还是不明白nil,我用你的例子来给你介绍一下。
首先你在main函数里的
这里的e是一个Error类型的指针,而指针的自动初始化为nil,在这里e的确是nil没有错,
e==nil
。但是当你把e传入进checkError函数时,发生了变化,因为接受的形参是个error接口类型,所以形参err是一个接口值,而一个接口值实际上是包含了实际值和动态类型两个部分的。
err这个接口值大概是这样的(nil,*Error),这里后面的部分*Error表示它的动态类型。
你把err和外面的e做比较时,因为接口类型会断言,所以会相等,
err==e
。但是你把err和nil做比较时,nil实际上是(nil,nil)这种,比较结果自然是false
err!=nil
你把nil用显示类型转换一下,变成了(nil,*Error)后就和err相同了,
err==(*Error)(nil)
总而言之,就是你把一个拥有实际类型的指针传给了接口,那么这个接口值永远不可能是nil。
golang这个设计是因为接口值持有的类型必须是动态的。