为了账号安全,请及时绑定邮箱和手机立即绑定

测试嵌套结构中的 nil 值

测试嵌套结构中的 nil 值

Go
函数式编程 2021-09-13 14:42:44
我在 go 中有一个深度嵌套的结构。这些是由 json 解组器构建的。然而,这个结构中的相当多的字段是“省略空的”,所以我以一个可以在不同地方有 nill 的结构结束 op。示例(真实的嵌套更深,而且很大:400 行结构):package mainimport "fmt"type Foo struct {    Foo string    Bar *Bar}type Bar struct {    Bar string    Baz *Baz}type Baz struct {    Baz string}func main() {    f1 := Foo{Foo: "f1"}    f2 := Foo{Foo: "f2", Bar: &Bar{Bar: "br2"}}    f3 := Foo{Foo: "f3", Bar: &Bar{Bar: "br3", Baz: &Baz{Baz: "bz3"}}}    fmt.Println(f3.Bar.Baz.Baz) //-> bz3    fmt.Println(f2.Bar.Baz.Baz) //-> panic: runtime error: invalid memory address or nil pointer dereference    fmt.Println(f1.Bar.Baz.Baz) //-> panic: runtime error: invalid memory address or nil pointer dereference        //so far so good, but    //is there a more generic way to do this kind of testing?    if f2.Bar != nil && f2.Bar.Baz != nil {        fmt.Println(f2.Bar.Baz.Baz)    } else {        fmt.Println("something nil")    }}问题是是否有更通用的方法来测试参考树中的某个节点是否为零?我需要获得很多不同的项目,编写所有这些 if 语句会很痛苦。哦,速度令人担忧。
查看完整描述

2 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

处理它的一种优雅方式(在我看来)是将 getter 添加到用作指针的结构中。这种“技术”也被protobuf生成的 Go 代码使用,它允许方法调用的自然链接,而不必担心由于nil指针导致的运行时恐慌。


在您的示例中,Bar和Baz结构用作指针,因此用 getter 武装它们。重点是添加带有指针接收器的方法,首先必须检查接收器是否为nil。如果是,则返回结果类型的零值。如果没有,继续返回结构的字段:


func (b *Bar) GetBaz() *Baz {

    if b == nil {

        return nil

    }

    return b.Baz

}


func (b *Baz) GetBaz() string {

    if b == nil {

        return ""

    }

    return b.Baz

}

带有指针接收器的方法的好处是你可以用nil接收器调用它们。它不会导致运行时恐慌,直到您尝试引用它们的字段,而我们不会,这就是为什么我们首先检查接收器是否是nil(最终,接收器充当正常参数 -nil作为指针传递永远不会出错争论)。


有了上面的 getter,使用被简化为这样,并且在任何这些示例中都不会发生运行时恐慌:


fmt.Println(f3.Bar.GetBaz().GetBaz()) // naturally no panic

fmt.Println(f2.Bar.GetBaz().GetBaz()) // No panic

fmt.Println(f1.Bar.GetBaz().GetBaz()) // No panic


if baz := f2.Bar.GetBaz(); baz != nil {

    fmt.Println(baz.GetBaz())

} else {

    fmt.Println("something nil")

}

在Go Playground上试一试。


查看完整回答
反对 回复 2021-09-13
  • 2 回答
  • 0 关注
  • 170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信