這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
目錄
-
- 反射 reflection
- 使用反射
- 訪問結構中的匿名欄位
- 動態修改屬性的值
- 動態調用方法
摘要
使用反射,匿名欄位,動態修改屬性,動態調用方法
反射 reflection
使用反射
前提
使用反射之前必須引用包 reflect
定義一個結構及方法
import "reflect"type User struct { Id int Name string Age int}func (u User) say() { fmt.Println("hello")}u := User{Id: 1, Name: "Peter", Age: 20}
反射所有欄位及方法
reflect.TypeOf(o)
用於獲得類型原型
reflect.ValueOf(o)
用於獲得值
注意要想訪問欄位的值則欄位應為 public
,要想調用方法則方法應為 public
func info(o interface{}) { //獲得參數類型的原型 t := reflect.TypeOf(o) fmt.Println("t", t) //t main.User fmt.Println("t.Name()", t.Name()) //t.Name() User fmt.Println("t.NumField()", t.NumField()) //t.NumField() 3 v := reflect.ValueOf(o) fmt.Println("v", v) //v <main.User Value> //檢測類型 if k := t.Kind(); k != reflect.Struct { return } //輸出屬性 for i := 0; i < t.NumField(); i++ { f := t.Field(i) //此時的 Field 必須為public val := v.Field(i).Interface() fmt.Println(f.Name, f.Type, val) //--> outputs //Id int 1 //Name string Peter //Age int 20 } fmt.Println() //輸出方法 for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) fmt.Println(m.Name, m.Type) //-->outputs //say func(main.User) }}info(u)
訪問結構中的匿名欄位
type Manager struct { User title string}//typem := Manager{title: "Manager", User: User{Id: 2, Name: "Jane", Age: 22}}t := reflect.TypeOf(m)f := t.FieldByIndex([]int{0, 1})fmt.Println("f", f.Name, f.Type) //f Name string//valuev := reflect.ValueOf(m)val := v.FieldByIndex([]int{0, 1}).Interface()fmt.Println("val", val) //val Jane
使用 reflect.FieldByIndex()
方法,該方法的參數為 slice
,以上第一個位置的 “0” 表示 Manager 的0號屬性(User),1表示 User 的1號屬性(Name)
動態修改屬性的值
func set(o interface{}) { v := reflect.ValueOf(o) ////判斷是否為指標類型且可寫 if k := v.Kind(); k != reflect.Ptr || !v.Elem().CanSet() { fmt.Println("invalid type") return } v = v.Elem() f := v.FieldByName("Name") //判斷指定屬性是否存在 if !f.IsValid() { fmt.Println("invalid name") return } if f.Kind() == reflect.String { f.SetString("a") }}u := User{Id: 1, Name: "Peter", Age: 20}fmt.Println("u.Name", u.Name) //u.Name Peterset(&u)fmt.Println("u.Name", u.Name) //u.Name aset(u)
注意以上是通過傳入指標來實現動態修改的
動態調用方法
注意調用方法時該方法應為 public
func (u User) Hello(name string) { fmt.Println("hello ", name, " my name is ", u.Name)}u := User{Id: 1, Name: "Peter", Age: 20}v = reflect.ValueOf(u)mn := v.MethodByName("Hello")args := []reflect.Value{reflect.ValueOf("Andy")}mn.Call(args)fmt.Println("u.Name", u.Name) //hello Andy my name is a