关于go:go里边一个让新手误解让老炮犯错的小知识点

问题:在一个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带来的便当了。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理