構造体を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)
}
テストコードは、慌てずに実行されますが、この方法はfalse
ではなくtrue
を返すために失敗します。
問題は、ContainsNil
への再帰呼び出しにネストされた構造体を正しく渡す方法がわかりません。
ネストされた構造体に対して再帰呼び出しが行われると、fieldIsExported
メソッドは、受信すると予想される値を受信していないため、false
を返します。
fieldIsExported
は、最初の呼び出しで "SomeStruct"を受け取り、2番目(再帰的)呼び出しで "SomeString"を受け取ると期待しています。最初の呼び出しは期待どおりに行われますが、2番目の呼び出しではfieldIsExported
は "typString"を受け取ると予想されますが、 "typ"を受け取ります。
私は、構造体に反映使用についての研究の束をやったが、私はまだこのまわりで私の頭を取得することができていません。アイデア?
参考文献:
- Pass by reference nested structures through reflection
- golang - reflection on embedded structs
- https://golang.org/pkg/reflect/
- ロトの
これは完璧な意味があります。助けてくれてありがとう! – Joe