我在 go 中有一个深度嵌套的结构。它们是由 json 解组器构造的。
然而,这个结构中的相当多的字段是“omitifempty”,所以我用一个在不同地方可以有空的结构来结束操作。
示例(真实的嵌套更深,而且很大:400 行结构):
package main
import "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 语句将是一件痛苦的事情。
哦,速度是令人担忧的。
(在我看来)处理它的一种优雅的方法是将 getter 添加到用作指针的结构中。生成的 Go 代码也使用了这种“技术”protobuf https://developers.google.com/protocol-buffers/docs/gotutorial,并且它允许方法调用的自然链接,而不必担心由于nil
指针。
在你的例子中Bar
and Baz
结构体用作指针,因此请为它们配备吸气剂。重点是添加带有指针接收者的方法,首先必须检查接收者是否是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")
}
尝试一下去游乐场 https://play.golang.org/p/3pDCZYGmDqT.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)