Reflect反射
尚硅谷Golang課

reflect反射

func reflectTest01(b interface{}) {
	//通過反射獲取傳入的各種訊息
	//先拿reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println("rType=", rType)

	rVal := reflect.ValueOf(b)
	fmt.Println("rVal=", rVal)
	// n1:=10+rVal //rVal他看起來是int但其實是type reflect.Value
	n1 := 10 + rVal.Int() //用.Int()轉換後就可以了
	// n3 := rVal.Float()//像這樣也不行的,一定要確認類型
	fmt.Println("n1=", n1)
	// fmt.Println("n3=", n3)

	//把rVal轉回interface{}
	iV := rVal.Interface()
	n2 := iV.(int)
	fmt.Println("n2=", n2)
}

func reflectTest02(b interface{}) {
	//通過反射獲取傳入的各種訊息
	//先拿reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println("rType=", rType)

	rVal := reflect.ValueOf(b)
	fmt.Println("rVal=", rVal)

	//把rVal轉回interface{}
	iV := rVal.Interface()
	//斷言回來
	n2, ok := iV.(Student)
	if !ok {
		fmt.Println("從interface{}轉換回Student失敗")
	}
	fmt.Println("n2=", n2)
	fmt.Println("n2.Name=", n2.Name)

	//獲取變量對應的kind,可以從Type也能從val拿。
	//比如這個type是包名.Student,kind是stuct,可以說定義上kind包含type
	fmt.Println("kind=", rType.Kind())
	fmt.Println("kind=", rVal.Kind())

}

type Student struct {
	Name string
	Age  int
}

func main() {
	var num int = 100
	reflectTest01(num)
	fmt.Println("===============================")
	stu := Student{
		Name: "tom",
		Age:  20,
	}
	reflectTest02(stu)

}

修改變量

func reflect01(b interface{}) {
	rVal := reflect.ValueOf(b)
	fmt.Println("rVal=", rVal)
	rType := reflect.TypeOf(b)
	fmt.Println("rType=", rType)

	iV := rVal.Interface()
	vNew, ok := iV.(float64)
	if ok {
		fmt.Println("轉換成功 vNew=", vNew)
	} else {
		fmt.Println("err")
	}
}
func main() {
	var v float64 = 1.2
	reflect01(v)

	// var str string = "tom"  //錯誤示範
	// fs := reflect.ValueOf(str)
	// fs.SetString("jack")
	// fmt.Println(str)

	var str string = "tom"
	fs := reflect.ValueOf(&str)
	fs.Elem().SetString("jack")
	fmt.Println(str)
}

實踐

type Monster struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Score float64
}

//方法打印m值
func (m Monster) Print() {
	fmt.Println(m)
}

//方法 求2和
func (m Monster) GetSum(n1, n2 int) int {
	return n1 + n2
}

//方法 接收4值給Monster
func (m Monster) Set(n string, a int, s float64) {
	m.Name = n
	m.Age = a
	m.Score = s
}

//反射實例
func TestStruct(a interface{}) {
	typ := reflect.TypeOf(a)
	val := reflect.ValueOf(a)
	kd := val.Kind()
	if kd != reflect.Struct {
		fmt.Println("傳入的不是結構體")
		return
	}
	//獲取該結構有幾字段
	num := val.NumField()
	fmt.Println("struct有幾個字段=", num)

	//遍歷所有字段
	for i := 0; i < num; i++ {
		fmt.Printf("Field%d 值為%v\n", i, val.Field(i))
		//獲取struct標籤
		tagVal := typ.Field(i).Tag.Get("json")
		if tagVal != "" {
			fmt.Printf("Field%d tag為%v\n", i, tagVal)
		}
	}
	//獲取結構體有幾個方法
	numOfMethod := val.NumMethod()
	fmt.Println("方法有", numOfMethod)
	//調用第[]個方法且call調用他(傳入參數值)
	//但他這個是方法的首字(asc碼)當排序的 我們的方法是G P S開頭 (1)=第2個
	val.Method(1).Call(nil)
	//試著調用getsum 他call傳入的是要[]reflect.Value
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(20))
	res := val.MethodByName("GetSum").Call(params)
	fmt.Println("res=", res[0].Int())
}

func main() {

	var a Monster = Monster{
		Name:  "牛梅王",
		Age:   500,
		Score: 87,
	}
	TestStruct(a)

}

上次修改於 2021-08-01

此篇文章的評論功能已經停用。