リフレクションを使用したネストされた構造のフィールド アドレスの取得
このシナリオでは、ネストされた構造を走査して検査し、非構造体のアドレスを取得します。 -その中のポインターフィールド。リフレクションを使用すると、フィールドを反復処理する関数が作成できますが、埋め込まれた部分構造にある非ポインター フィールドのメモリ アドレスを取得するのが困難になります。
この問題を修正するには、valueField.Interface() が次のことを行うことに注意することが重要です。フィールド内に格納されている実際の値を返すため、期待される結果が得られません。これは、非ポインター型を操作する場合には無効です。
解決策は、InspectStructV 関数を変更して、代わりに Reflect.Value を受け取るようにすることです。インターフェース{}。これにより、リフレクション オブジェクトを直接操作し、フィールドのアドレスを取得できるようになります。さらに、構造体フィールドに対して InspectStructV を再帰的に呼び出すと、以前はインターフェイス値を保持していた valueField が、ネストされた構造体のリフレクション値を直接指すようになり、アドレスを正しく取得できるようになります。
修正されたコードは次のとおりです。スニペット:
<code class="go">func InspectStructV(val reflect.Value) { if val.Kind() == reflect.Interface && !val.IsNil() { elm := val.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { val = elm } } if val.Kind() == reflect.Ptr { val = val.Elem() } for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) typeField := val.Type().Field(i) address := "not-addressable" if valueField.Kind() == reflect.Interface && !valueField.IsNil() { elm := valueField.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { valueField = elm } } if valueField.Kind() == reflect.Ptr { valueField = valueField.Elem() } if valueField.CanAddr() { address = fmt.Sprintf("0x%X", valueField.Addr().Pointer()) } fmt.Printf("Field Name: %s,\t Field Value: %v,\t Address: %v\t, Field type: %v\t, Field kind: %v\n", typeField.Name, valueField.Interface(), address, typeField.Type, valueField.Kind()) if valueField.Kind() == reflect.Struct { InspectStructV(valueField) } } } func InspectStruct(v interface{}) { InspectStructV(reflect.ValueOf(v)) }</code>
これらの変更を行うことで、非ポインター フィールドがネストされた構造内に存在する場合でも、そのメモリ アドレスを正常に取得できるようになります。
以上がリフレクションを使用して入れ子構造のフィールド アドレスを取得するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。