问题:在一个nil变量上调用函数,会发生什么?
一般会认为panic。为了不发生panic,每次调用方法前,都要判断变量是否为nil。这么做虽然没错,但终究使代码看起来不那么优雅。
那么一定会panic吗?
让我们来做个实验
type PlanConfig struct {
No int64
}
func (p *PlanConfig) IsEmpty() bool {
if p == nil {
fmt.Println("hello")
return false
}
return reflect.ValueOf(*p).IsZero()
}
var p *PlanConfig
fmt.Println(p)
fmt.Println(p.IsEmpty())
该代码会输出
<nil>
hello
false
可以看到,新声明的指针类型变量p,是nil,但是并不妨碍他调用IsEmpty()方法。
如果强制赋nil呢,还会执行吗?
type PlanConfig struct {
No int64
}
func (p *PlanConfig) IsEmpty() bool {
if p == nil {
fmt.Println("hello")
return false
}
return reflect.ValueOf(*p).IsZero()
}
var p *PlanConfig
fmt.Println(p)
p = nil
fmt.Println(p.IsEmpty())
依然输出
<nil>
hello
false
是不是很顽强。
再模拟一下我们实际代码中的用法,比如从一个函数获取某个变量,但是返回值nil,然后用这个变量调用方法
type PlanConfig struct {
No int64
}
func (p *PlanConfig) IsEmpty() bool {
if p == nil {
fmt.Println("hello")
return false
}
return reflect.ValueOf(*p).IsZero()
}
func getPlan() *PlanConfig {
return nil
}
p := getPlan()
fmt.Println(p.IsEmpty())
输出
hello
false
这样我们只需要在方法的入口处判断一次即可,而不用每次调用方法前,都判断变量是否为nil了。
我们再看看,程序会崩的情况。
type PlanConfig struct {
No int64
}
func (p *PlanConfig) IsEmpty() bool {
if p == nil {
fmt.Println("hello")
return false
}
return reflect.ValueOf(*p).IsZero()
}
p := nil
fmt.Println(p.IsEmpty())
ide直接会飘红。执行代码也会抛出错误
use of untyped nil
再看这种
type PlanConfig struct {
No int64
}
func (p *PlanConfig) IsEmpty() bool {
return reflect.ValueOf(*p).IsZero()
}
func getPlan() *PlanConfig {
return nil
}
p := getPlan()
fmt.Println(p.IsEmpty())
这一次,我们在方法 IsEmpty()入口处去掉 nil判断,结果确实会发生panic。
结论:
用指针作为方法接收者的时候,只要我们在函数入口处做是否为nil的判断,那么就可以尽情去享受go带来的便利了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。