Rumah > Artikel > pembangunan bahagian belakang > Bagaimanakah Saya Boleh Menggunakan Kaedah Secara Dinamik pada Antara Muka dalam Go, Mengendalikan Kedua-dua Penerima Nilai dan Penunjuk?
Sistem templat sangat bergantung pada pakej reflect dalam Go. Apabila bekerja dengan pakej ini, seseorang mungkin menghadapi kesukaran dalam menggunakan kaedah secara dinamik pada antara muka. Isu ini menjadi jelas apabila jenis data disimpan sebagai antara muka{}.
Memahami dinamik penggunaan kaedah untuk antara muka adalah penting. Terdapat empat senario yang perlu dipertimbangkan:
Refleksi boleh membantu menentukan nilai data asas antara muka. Dengan maklumat ini, seseorang boleh menjana jenis data ganti dan membezakan antara nilai dan kaedah penerima penuding.
Untuk menyelesaikan isu ini, adalah perlu untuk mencipta kedua-dua nilai dan perwakilan penunjuk daripada data:
value := reflect.ValueOf(data) if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() // acquire value referenced by pointer } else { ptr = reflect.New(reflect.TypeOf(i)) // create new pointer temp := ptr.Elem() // create variable to value of pointer temp.Set(value) // set value of variable to our passed in value }
Dengan kedua-dua jenis data tersedia, menyemak kehadiran kaedah menjadi mudah:
var finalMethod reflect.Value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].String() }
Dengan menerima pendekatan ini, ia menjadi mungkin untuk menggunakan mana-mana kaedah secara dinamik secara berkesan, tidak kira sama ada ia ditakrifkan sebagai penerima nilai atau penunjuk.
package main import ( "fmt" "reflect" ) type Test struct { Start string } // value receiver func (t Test) Finish() string { return t.Start + "finish" } // pointer receiver func (t *Test) Another() string { return t.Start + "another" } func CallMethod(i interface{}, methodName string) interface{} { var ptr reflect.Value var value reflect.Value var finalMethod reflect.Value value = reflect.ValueOf(i) // if we start with a pointer, we need to get value pointed to // if we start with a value, we need to get a pointer to that value if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() } else { ptr = reflect.New(reflect.TypeOf(i)) temp := ptr.Elem() temp.Set(value) } // check for method on value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].Interface() } // return or panic, method not found of either type return "" } func main() { i := Test{Start: "start"} j := Test{Start: "start2"} fmt.Println(CallMethod(i, "Finish")) fmt.Println(CallMethod(&i, "Finish")) fmt.Println(CallMethod(i, "Another")) fmt.Println(CallMethod(&i, "Another")) fmt.Println(CallMethod(j, "Finish")) fmt.Println(CallMethod(&j, "Finish")) fmt.Println(CallMethod(j, "Another")) fmt.Println(CallMethod(&j, "Another")) }
Output:
startfinish startfinish <nil> startanother startfinish startfinish <nil> startanother
Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Menggunakan Kaedah Secara Dinamik pada Antara Muka dalam Go, Mengendalikan Kedua-dua Penerima Nilai dan Penunjuk?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!