您好,登錄后才能下訂單哦!
//反射 練習
//獲取字段的類型信息,方法信息, 屬性信息
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (user User) Hello(){
fmt.Println("hello world")
}
func main() {
user := User{Id:2, Name:"xiaoqiang",Age:30}
info(user)
}
//定義一個方法
//此方法接收的是一個空接口
//這樣的話,其實是任何類型都可以接收了
func info(o interface{}) {
//獲取o的類型
t := reflect.TypeOf(o)
fmt.Println("Type:\t", t.Name())
//取出類型后,需要對類型進行校驗,
//查看是否是規定的類型
if k :=t.Kind(); k != reflect.Struct {
//如果不是規定的Struct類型的話,就需要進行
//異常處理
fmt.Println("輸入參數的類型不匹配!")
return
}
//獲取o的屬性
v := reflect.ValueOf(o)
fmt.Println("Fields:\n")
//開始遍歷,輸出字段
for i := 0; i < t.NumField(); i++ {
//獲取屬性下標
f := t.Field(i)
val := v.Field(i).Interface()
//輸出屬性的名稱,類型,對應的值
fmt.Printf("%6s:%v = %v\n", f.Name, f.Type, val)
}
//開始獲取 方法的基本信息
for i:=0; i<t.NumMethod(); i++ {
m := t.Method(i)
fmt.Printf("%6s:%v\n", m.Name, m.Type)
}
}
//反射 是如何處理 匿名字段的?
package main
import (
"reflect"
"fmt"
)
type Stu struct {
Id int
Name string
Age int
}
type Man struct {
//這里你要注意一下,你創建的屬性,是有順序的,是有下標的
//如Stu 下標 就是0, title下標就是1
// Stu 就是匿名屬性
Stu
title string
}
func main() {
//注意,對匿名字段進行初始化時的方式,其實本質上跟其他屬性是一樣的
m := Man{Stu:Stu{Id:2,Name:"Jack",Age:19}, title:"Manager"}
t := reflect.TypeOf(m)
//取匿名字段的方式
//FieldByIndex 方法,傳入的是一個切片slice類型
//第1個0,表示,匿名字段在Man中的下標位置
//第2個0,表示,你要取匿名字段中哪個屬性的下標
fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0})) //取的是id
fmt.Printf("%#v\n", t.FieldByIndex([]int{0,1})) //取的是Name
fmt.Printf("%#v\n", t.FieldByIndex([]int{0,2})) //取的是Age
}
//如果通過反射,對基本類型進行修改
package main
import (
"reflect"
"fmt"
)
func main() {
//下面測試,對基本類型的修改 操作
x := 456
//傳遞的參數是 地址
v := reflect.ValueOf(&x)
//Elem方法,是取出元素值來,然后通過setint方法,進行重新設置
v.Elem().SetInt(789)
fmt.Println(x)
}
//如果通過反射,對復雜類型進行修改
package main
import (
"reflect"
"fmt"
)
type Teac struct {
Id int
Name string
Age int
}
func main() {
teac := Teac{Id:5,Name:"Ant-man",Age:23}
fmt.Println("teac:\t", teac)
//傳遞的是 地址哦
Set(&teac)
fmt.Println("teac:\t", teac)
}
func Set(o interface{}) {
v := reflect.ValueOf(o)
if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {
fmt.Printf("xxx")
return
}else{
v = v.Elem()
}
// 通過FieldByName 這個方法,直接輸入 名稱,來獲取
f := v.FieldByName("Name")
//校驗,是否取到Name屬性的值
if !f.IsValid() {
fmt.Printf("BAD")
return
}
//然后,再校驗,類型是否匹配
if f.Kind() == reflect.String {
f.SetString("Iron Man")
}
}
//通過反射,進行方法的調用,相當于動態調用了
package main
import (
"fmt"
"reflect"
)
type Teacher struct {
Id int
Name string
Age int
}
//通過receiver將Show方法,跟Teacher類型,進行綁定
func (teacher Teacher)Show(name string) {
fmt.Println("hello, ", name, ", my name is ", teacher.Name)
}
//注意======目前沒有發現====如何通過====反射===來獲取=====私有方法
func (teacher Teacher)info(){
fmt.Println("=====")
}
func main() {
teacher := Teacher{Id:34, Name:"Thor",Age:34}
teacher.Show("Hawkeye")
//下面通過反射,調用show方法
v := reflect.ValueOf(teacher)
//獲取show方法
m := v.MethodByName("Show")
//校驗一下,是否獲取到show方法呢
if !m.IsValid() {
fmt.Printf("=======沒有獲取到制定的方法====")
return
}
//參數必須是切片類型
//reflect.Value{} 這里面,可以設定多個參數類型
//目前,我們這里只有一個string類型的參數
//
args := []reflect.Value{reflect.ValueOf("Hulk")}
m.Call(args)
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。