over-golang/01-基础语法/15-反射-2-应用.md
2021-07-02 18:11:59 +08:00

3.2 KiB
Raw Permalink Blame History

一 反射的使用

1.1 反射操作简单数据类型

	var num int64 = 100

	// 设置值:指针传递
	ptrValue := reflect.ValueOf(&num)
	newValue := ptrValue.Elem()                         // Elem()用于获取原始值的反射对象
	fmt.Println("type", newValue.Type())				// int64
	fmt.Println(" can set", newValue.CanSet())		// true
	newValue.SetInt(200)

	// 获取值:值传递
	rValue := reflect.ValueOf(num)
	fmt.Println(rValue.Int())					// 方式一200
	fmt.Println(rValue.Interface().(int64))		// 方式二200

1.2 反射进行类型推断

	type user struct {
		Name string
		Age int
	}

	u := &user{
		Name: "Ruyue",
		Age:  100,
	}

	fmt.Println(reflect.TypeOf(u))			// *main.user
	fmt.Println(reflect.TypeOf(*u))			// main.user
	fmt.Println(reflect.TypeOf(*u).Name())	// user
	fmt.Println(reflect.TypeOf(*u).Kind())	// struct

1.3 反射操作指针

	type user struct {
		Name string
		Age int
	}

	u := &user{
		Name: "Ruyue",
		Age:  100,
	}

	typeOfUser = reflect.TypeOf(u).Elem()
	fmt.Println("element name: ", typeOfUser.Name())		// user
	fmt.Println("element kind: ", typeOfUser.Kind())		// struct

1.4 反射操作结构体

反射可以获取结构体的详细信息:

	type user struct {
		Name string
		Age  int `json:"age" id:"100"` // 结构体标签
	}

	s := user{
		Name: "zs",
		Age:  1,
	}

	typeOfUser := reflect.TypeOf(s)

	// 字段用法
	for i := 0; i < typeOfUser.NumField(); i++ {        // NumField 当前结构体有多少个字段
		fieldType := typeOfUser.Field(i)                // 获取每个字段
		fmt.Println(fieldType.Name, fieldType.Tag)
	}
	if userAge, ok := typeOfUser.FieldByName("Age"); ok {
		fmt.Println(userAge)						// {Age  int json:"age" id:"100" 16 [1] false}
	}

	// 方法用法
	for i := 0; i < typeOfUser.NumMethod(); i++ {
		fieldType := typeOfUser.Method(i)                // 获取每个字段
		fmt.Println(fieldType.Name)
	}

二 反射调用函数与方法

2.1 使用反射调用函数

如果反射值对象(reflect.Value)中值的类型为函数时,可以通过 reflect.Value调用该 函数。使用反射调用函数时,需要将参数使用反射值对象的切片 口reflect.Value 构造后传入 Call()方法中 调用完成时,函数的返回值通过 []reflect.Value 返回 。

func add(name string, age int) {
	fmt.Printf("name is %s, age is %d \n", name, age)
}

func main() {
	funcValue := reflect.ValueOf(add)
	params := []reflect.Value{reflect.ValueOf("lisi"), reflect.ValueOf(20)}

	reList := funcValue.Call(params)
	fmt.Println(reList)			// 函数返回值
}

2.2 反射调用方法

方法的调用是需要接收者的:

package main

import (
	"fmt"
	"reflect"
)

type user struct {
	Name string
	Age int
}
func (u *user) ShowName() {
	fmt.Println(u.Name)
}

func (u *user) AddAge(addNum int) {
	fmt.Println("age add result:", u.Age + addNum)
}

func main() {

	u := &user{"lisi", 20}
	v := reflect.ValueOf(u)

	// 调用无参方法
	methodV := v.MethodByName("ShowName")
	methodV.Call(nil)		// 或者传递一个空切片也可

	// 调用有参方法
	methodV2 := v.MethodByName("AddAge")
	args := []reflect.Value{reflect.ValueOf(30)}	//
	methodV2.Call(args)
}