I want to build a method that takes a struct as an interface{}
and returns true
if any of the supplied struct's fields are nil.
Here's what I have at the moment:
// 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
}
And a failing test:
func Test_ContainsNil_NilNestedValue_ReturnsTrue(t *testing.T) {
someNestedStruct := &c.SomeNestedStruct{
SomeStruct: c.SomeStruct{
SomeString: nil,
},
}
result := util.ContainsNil(someNestedStruct)
assert.True(t, result)
}
The test code executes without panicking, but fails because the method returns false
rather than true
.
The issue I'm having is that I can't figure out how to properly pass the nested struct back into the recursive call to ContainsNil
.
When recursive call is made for the nested structure, the fieldIsExported
method returns false
because it's not receiving the value that I would expect it to be receiving.
I expect fieldIsExported
to receive "SomeStruct" on its first call, and receive "SomeString" on the second (recursive) call. The first call goes as expected, but on the second call, fieldIsExported
receives "typ", when I would expect it to receive "SomeString".
I've done a bunch of research about using reflect on structs, but I haven't been able to get my head around this yet. Ideas?
References:
- Pass by reference nested structures through reflection
- golang - reflection on embedded structs
- http://ift.tt/1s8oWkD
- Lot's of googling
Aucun commentaire:
Enregistrer un commentaire