跳到主要内容

反射-2-应用

一 反射的使用

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)
}