1、經過反射獲取類型信息
在 Go 程序中,使用 reflect.TypeOf() 函數能夠得到任意值的類型對象(reflect.Type),程序經過類型對象能夠訪問任意值的類型信息。json
package main import ( "fmt" "reflect" ) func test1() { var a int t := reflect.TypeOf(a) fmt.Printf("name:%v kind:%v\n", t.Name(), t.Kind()) // name:int kind:int } func test2() { type User struct {} user := User{} t := reflect.TypeOf(user) fmt.Printf("name:%v kind:%v\n", t.Name(), t.Kind()) // name:User kind:struct } func main() { test1() test2() }
2、經過反射獲取指針指向的元素類型
package main import ( "fmt" "reflect" ) func main() { // 聲明一個空結構體 type User struct {} // 建立User的實例 user := &User{} // 獲取結構體實例的反射類型對象 t := reflect.TypeOf(user) // 顯示反射類型對象的名稱和種類 fmt.Printf("name:'%v' kind:'%v'\n", t.Name(), t.Kind()) // name:'' kind:'ptr' // 獲取指針類型的元素類型 e := t.Elem() // 顯示指針變量指向元素的類型名稱和種類 fmt.Printf("name:'%v' kind:'%v'\n", e.Name(), e.Kind()) // name:'User' kind:'struct' }
3、經過反射獲取結構體的成員類型
任意值經過 reflect.TypeOf() 得到反射對象信息後,若是它的類型是結構體,能夠經過反射值對象(reflect.Type)的 NumField() 和 Field() 方法得到結構體成員的詳細信息。app
package main import ( "fmt" "reflect" ) type User struct { Name string `json:"username"` Age int Salary float64 } func main() { user := User{"pd", 18, 9999.99} tf := reflect.TypeOf(user) // 遍歷結構體全部成員 for i := 0; i < tf.NumField(); i++ { // 獲取每一個成員的結構體字段類型 fieldType := tf.Field(i) fmt.Printf("name:'%v' tag:'%v'\n", fieldType.Name, fieldType.Tag) // name:'Name' tag:'json:"username"' // name:'Age' tag:'' // name:'Salary' tag:'' } // 經過字段名, 找到字段類型信息 userType, ok := tf.FieldByName("Name") if ok { // 從tag中取出須要的tag fmt.Println(userType.Tag.Get("json")) // username } }
4、經過反射獲取值信息
package main import ( "fmt" "reflect" ) func main() { // 聲明整型變量a並賦初值 var a int a = 666 // 獲取變量a的反射值對象 vf := reflect.ValueOf(a) // 將vf反射值對象以Interface{}類型取出, 經過類型斷言轉換爲int類型 r1 := vf.Interface().(int) // 將vf反射值對象以int64類型取出 r2 := vf.Int() // 強制類型轉換爲int類型 r3 := int(r2) fmt.Printf("r1值:%v r1類型:%T\n", r1, r1) // r1值:666 r1類型:int fmt.Printf("r2值:%v r2類型:%T\n", r2, r2) // r2值:666 r2類型:int64 fmt.Printf("r3值:%v r3類型:%T\n", r3, r3) // r3值:666 r3類型:int }
5、經過反射訪問結構體成員的值
package main import ( "fmt" "reflect" ) type User struct { Name string Age int Salary float64 } func main() { user := User{"pd", 18, 9999.99} vf := reflect.ValueOf(user) // 獲取字段數量 fmt.Printf("NumField:%v\n", vf.NumField()) // NumField:3 // 獲取索引爲2的字段 field := vf.Field(2) fmt.Println(field.Type()) // float64 // 根據名字查找字段 fbn := vf.FieldByName("Name") fmt.Println(fbn.Type()) // string // 根據索引查找字段 fbi := vf.FieldByIndex([]int{1}) fmt.Println(fbi.Type()) // int }
6、判斷反射值的空和有效性
package main import ( "fmt" "reflect" ) func main() { // *int的空指針 var a *int fmt.Println(reflect.ValueOf(a).IsNil()) // true // nil值 fmt.Println(reflect.ValueOf(nil).IsValid()) // false // 實例化一個結構體 s := struct{}{} // 嘗試從結構體中查找一個不存在的字段 fmt.Println(reflect.ValueOf(s).FieldByName("").IsValid()) // false // 嘗試從結構體中查找一個不存在的方法 fmt.Println(reflect.ValueOf(s).MethodByName("").IsValid()) // false }
7、經過反射修改變量的值
package main import ( "fmt" "reflect" ) func main() { // 聲明整型變量a並賦初值 var a int var b string a = 100 b = "哈哈哈" // 獲取變量a、b的反射值對象(a、b的地址) vfa := reflect.ValueOf(&a) vfb := reflect.ValueOf(&b) // 取出a、b地址的元素(值) vfae := vfa.Elem() vfbe := vfb.Elem() // 修改a、b的值 vfae.SetInt(200) vfbe.SetString("嘻嘻嘻") // 打印a、b的值 fmt.Println(a, b) // 200 嘻嘻嘻 }
package main import ( "fmt" "reflect" ) type User struct { Name string Age int } func main() { user := User{"pd", 18} vf := reflect.ValueOf(&user) // 取出User實例地址的元素 vfe := vf.Elem() // 獲取Name字段的值 name := vfe.FieldByName("Name") // 修改此實例(對象)對應字段的值 name.SetString("佩奇") fmt.Println(user) // {佩奇 18} }
8、經過類型信息建立實例
package main import ( "fmt" "reflect" ) func main() { var a int // 取變量a的反射類型對象 tf := reflect.TypeOf(a) // 根據反射類型對象建立這個類型的實例值,值以 reflect.Value 類型返回 obj := reflect.New(tf) // 輸出類型和種類 fmt.Printf("type:%v kind:%v\n", obj.Type(), obj.Kind()) // type:*int kind:ptr }
9、經過反射調用函數、方法
package main import ( "fmt" "reflect" ) // add函數 func add(a, b int) int { return a + b } func main() { // 將函數包裝爲反射值對象 vf := reflect.ValueOf(add) // 構造函數參數, 傳入兩個整型值 paramList := []reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)} // 反射調用函數 retList := vf.Call(paramList) // 獲取第一個返回值, 取整數值 fmt.Println(retList[0].Int()) // 30 }
package main import ( "fmt" "reflect" ) type User struct { Name string } func (u *User) Hello(name string) { fmt.Printf("%s對%s打了一個招呼...\n", u.Name, name) // pd對佩奇打了一個招呼... } func main() { user := User{"pd"} vf := reflect.ValueOf(&user) method := vf.MethodByName("Hello") // 方式1 // args := []reflect.Value{reflect.ValueOf("佩奇")} // 方式2 var args []reflect.Value args = append(args, reflect.ValueOf("佩奇")) // 調用方法 method.Call(args) }