我希望构建一个方法,该方法以结构体的interface{}
形式接收输入,并在提供的结构体字段中有任何一个为nil
时返回true
。
以下是我目前拥有的:
// ContainsNil returns true if any fields within the supplied structure are nil.
//
// If the supplied object is not a struct, the method will panic.
// Nested structs are inspected recursively.
// Maps and slices are not inspected deeply. This may change.
func ContainsNil(obj interface{}) bool {
if obj == nil {
return true
}
s := reflect.Indirect(reflect.ValueOf(obj))
for i := 0; i < s.NumField(); i++ {
f := s.Type().Field(i)
field := s.Field(i)
if fieldIsExported(f) { // Exported-check must be evaluated first to avoid panic.
if field.Kind() == reflect.Struct {
if ContainsNil(field.Addr()) {
return true
}
} else {
if field.IsNil() {
return true
}
if field.Interface() == nil {
return true
}
}
}
}
return false
}
func fieldIsExported(field reflect.StructField) bool {
log.Println(field.Name)
return field.Name[0] >= 65 == true && field.Name[0] <= 90 == true
}
还有一个失败的测试:
func Test_ContainsNil_NilNestedValue_ReturnsTrue(t *testing.T) {
someNestedStruct := &c.SomeNestedStruct{
SomeStruct: c.SomeStruct{
SomeString: nil,
},
}
result := util.ContainsNil(someNestedStruct)
assert.True(t, result)
}
测试代码执行时没有出现panic,但失败了,因为该方法返回的是
false
而不是true
。我遇到的问题是,我无法弄清楚如何正确地将嵌套结构传递回递归调用
ContainsNil
。当对嵌套结构进行递归调用时,
fieldIsExported
方法返回false
,因为它未收到我期望的值。我期望
fieldIsExported
在第一次调用时接收到"SomeStruct",在第二次(递归)调用时接收到"SomeString"。第一个调用按预期进行,但在第二个调用中,fieldIsExported
接收到"typ",而我希望它接收到"SomeString"。我已经做了大量关于在结构体上使用反射的研究,但我还没有能够理解这个问题。有什么想法吗?
参考资料: