package main
import "fmt"
type Person struct {
fname string
lname string
age int
address string
}
func (p *Person) GetName() string {
return p.fname + " " + p.lname
}
func (p *Person) GetAge() int {
return p.age
}
func (p *Person) GetAddress() string {
return p.address
}
type IPerson interface {
GetName() string
GetAge() int
GetAddress() string
}
func PrintPerson(p IPerson) {
if p == nil {
fmt.Println("Person is nil")
return
}
fmt.Println("Name: ", p.GetName())
}
type Group struct {
person IPerson
}
func (g *Group) Print() {
if g.person == nil {
fmt.Println("Person is nil")
return
}
fmt.Println("Name: ", g.person.GetName())
}
func NewGroup(p *Person) *Group {
return &Group{
person: p,
}
}
func main() {
m := &Person{
fname: "John",
lname: "Doe",
age: 22,
address: "International Seas",
}
g1 := NewGroup(m)
g2 := NewGroup(nil)
g1.Print()
g2.Print()
}
考虑上面的代码。即使没有检查,它也会在
panic: runtime error: invalid memory address or nil pointer dereference
处抛出 fmt.Println("Name: ", g.person.GetName())
。
如果我对
NewGroup
进行零签入 p
并返回
&Group{
person: nil,
}
一切正常。
这里有什么区别?为什么接口类型对于 nil 检查的行为不同?除了 NewGroup 中的 nil 检查之外,处理此问题的惯用方法是什么?
我的期望是,自打印对象输出以来,当传递 nil 对象时,nil 检查将起作用
<nil>
。
value := reflect.ValueOf(g.person)
log.Println("value is ", value, value.IsNil())