Ich möchte eine Methode erstellen, die eine Struktur als interface{}
nimmt und true
zurückgibt, wenn eines der Felder der bereitgestellten Struktur NULL sind.Rekursiv durch verschachtelte Strukturen gehen
Hier ist, was ich im Moment haben:
// 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
}
Und eine versagende 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)
}
Der Testcode ausführt, ohne in Panik zu geraten, aber nicht, weil die Methode false
zurückgibt, anstatt true
.
Das Problem, das ich habe, ist, dass ich nicht herausfinden kann, wie die verschachtelte Struktur zurück in den rekursiven Aufruf an ContainsNil
übergeben.
Wenn der rekursive Aufruf für die verschachtelte Struktur erfolgt, gibt die fieldIsExported
-Methode false
zurück, weil sie nicht den Wert empfängt, den ich erwarten würde, dass sie empfangen wird.
Ich erwarte fieldIsExported
, "SomeStruct" bei seinem ersten Aufruf zu empfangen, und "SomeString" beim zweiten (rekursiven) Aufruf zu erhalten. Der erste Anruf verläuft wie erwartet, aber beim zweiten Anruf erhält fieldIsExported
"typ", wenn ich erwarte, dass es "SomeString" empfängt.
Ich habe eine Menge Forschung über die Verwendung von reflects auf Strukturen gemacht, aber ich war noch nicht in der Lage, meinen Kopf dazu zu bringen. Ideen?
Referenzen:
- Pass by reference nested structures through reflection
- golang - reflection on embedded structs
- https://golang.org/pkg/reflect/
- gibt es jede Menge
Dies macht durchaus Sinn. Vielen Dank für die Hilfe! – Joe