测试嵌套结构中的nil值 [英] Test for nil values in nested stucts
问题描述
我在go中有一个深层嵌套的结构.这些是由json解组器构造的.
I have a deeply nested struct in go. These are constructed by a json unmarshaller.
但是,该结构中的某些字段都是'omitifempty'的,因此我以一个可以在各个位置带有nill的结构结束op.
Quite some fields in this struct are however 'omitifempty' so I end op with a struct that can have nills in various places.
示例(真正的东西嵌套得更深,很大:400行结构):
Example (the real thing is even deeper nested, and big: 400 lines of structs):
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")
}
}
问题是是否存在一种更通用的方法来测试参考树中的某个节点是否为nil?我需要获得很多不同的项目,而编写所有这些if语句将很痛苦. 哦,速度值得关注.
The question is if there is a more generic way to test if some node in the reference tree is nil? I need to get a lot of different items and it will be a pain to write all these if statements. Oh and speed is of concern.
推荐答案
一种处理它的优雅方法(我认为)是将getters添加到用作指针的结构中. protobuf 的生成的Go代码也使用了这种技术"它允许自然地链接方法调用,而不必担心由于nil
指针引起的运行时恐慌.
One elegant way (in my opinion) of handling it is to add getters to structs that are used as pointers. This "technique" is also used by the generated Go code of protobuf, and it allows natural chaining of method calls without having to worry about runtime panic due to nil
pointers.
在您的示例中,Bar
和Baz
结构用作指针,因此使用吸气剂武装它们.重点是使用指针接收器添加方法,首先必须检查接收器是否为nil
.如果是这样,则返回结果类型的零值.如果没有,请继续返回该结构的字段:
In your example the Bar
and Baz
structs are used as pointers, so arm them with getters. The focus is on adding methods with pointer receiver, and first it must be checked if the receiver is nil
. If so, return the zero value of the result type. If not, proceed to return the field of the struct:
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
作为指针参数).
The good thing about methods with pointer receivers is that you may call them with nil
receivers. It does not cause a runtime panic until you try to refer to their fields, which we don't, that's why we first check if the receiver is nil
(ultimately, receivers act as normal parameters–and it's never an error to pass nil
as a pointer argument).
具有上述吸气剂,将其简化使用,并且在以下任何示例中都不会发生运行时恐慌:
Having the above getters, use is simplified to this, and no runtime panic occurs in any of these examples:
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")
}
在游乐场上尝试.
这篇关于测试嵌套结构中的nil值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!