Dapatkan Penunjuk kepada Nilai Menggunakan Refleksi
Refleksi memainkan peranan penting dalam introspeksi dan pengendalian data yang dinamik dalam Go. Walau bagaimanapun, ia memberikan cabaran apabila menyasarkan medan bukan penunjuk untuk mendapatkan semula alamat. Artikel ini menumpukan pada menangani isu ini dan menyediakan penyelesaian untuk mendapatkan alamat medan bukan penuding dalam struktur bersarang menggunakan pantulan.
Pertimbangkan kod contoh berikut:
<code class="go">type Z struct { Id int } type V struct { Id int F Z } type T struct { Id int F V }</code>
Di sini, T ialah struktur bersarang dengan F sebagai medan jenis V, yang seterusnya mempunyai medan lain F jenis Z. Matlamatnya adalah untuk mendapatkan semula alamat medan Id dalam struktur Z.
Menggunakan refleksi, kami boleh berulang melalui medan dan mengakses nilainya. Walau bagaimanapun, kod di bawah menunjukkan cara mengendalikan medan bukan penuding dan mendapatkan semula alamatnya:
<code class="go">package main import ( "fmt" "reflect" ) func InspectStructV(val reflect.Value) { // Handle interface types if val.Kind() == reflect.Interface && !val.IsNil() { elm := val.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { val = elm } } // Dereference pointers if val.Kind() == reflect.Ptr { val = val.Elem() } // Iterate over fields for i := 0; i < val.NumField(); i++ { valueField := val.Field(i) typeField := val.Type().Field(i) address := "not-addressable" // Handle nested interfaces if valueField.Kind() == reflect.Interface && !valueField.IsNil() { elm := valueField.Elem() if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr { valueField = elm } } // Dereference embedded pointers if valueField.Kind() == reflect.Ptr { valueField = valueField.Elem() } // Retrieve address if possible if valueField.CanAddr() { address = fmt.Sprintf("0x%X", valueField.Addr().Pointer()) } // Print field details 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()) // Recurse for nested structures if valueField.Kind() == reflect.Struct { InspectStructV(valueField) } } } func InspectStruct(v interface{}) { InspectStructV(reflect.ValueOf(v)) } func main() { t := new(T) t.Id = 1 t.F = *new(V) t.F.Id = 2 t.F.F = *new(Z) t.F.F.Id = 3 InspectStruct(t) }</code>
Dengan menghantar refleksi.Nilai terus dan bukannya antara muka{} dan menafikan penuding bersarang, kod ini memastikan bahawa alamat medan Id dalam struktur Z bersarang boleh diambil semula.
Sampel output di bawah menunjukkan kejayaan mendapatkan semula alamat untuk medan Id walaupun kedalamannya dalam struktur bersarang:
Field Name: Id, Field Value: 1, Address: 0x40c1080088, Field type: int, Field kind: int Field Name: F, Field Value: {2 {3}}, Address: 0x40c108008c, Field type: main.V, Field kind: struct Field Name: Id, Field Value: 2, Address: 0x40c1080090, Field type: int, Field kind: int Field Name: F, Field Value: {3}, Address: 0x40c1080098, Field type: main.Z, Field kind: struct Field Name: Id, Field Value: 3, Address: 0x40c10800a0, Field type: int, Field kind: int
Atas ialah kandungan terperinci Bagaimana untuk Mendapatkan Alamat Medan Bukan Penunjuk dalam Struktur Nested Go Menggunakan Refleksi?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!