Golang反射学习计划

Kind Name的区别

  1. Kind()返回的是基本类型,如果是类的话返回的基本类型是Struct
  2. Name()返回的是名称,当类型为基本类型的时候跟Kind的结果是一样的
func ReflectTest()  {

	type Person struct {
		Name string
		Age int	
		Gender int
		Desc string
	}

	p:=Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	reflectPerson:=reflect.TypeOf(p)
	fmt.Println("name is",reflectPerson.Name())
	fmt.Println("kind is",reflectPerson.Kind())

	number:=20.9
	reflectNumber:=reflect.TypeOf(number)
	fmt.Println("name is",reflectNumber.Name())
	fmt.Println("kind is",reflectNumber.Kind())
	
	// 获取值
	reflectNumberValue:=reflect.ValueOf(number)
	fmt.Println("value is",reflectNumberValue.Interface())
}

结果如下:
在这里插入图片描述

获取属性和值TypeOf ValueOf

在这里插入图片描述

  1. NumField可以获取属性的数量,然后可以通过Index去获取每个属性
  2. 对于ValueOf也是同样的操作,可以通过Interface()获取值
func ReflectTest()  {

	type Person struct {
		Name string
		Age int
		Gender int
		Desc string
	}

	p:=Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	reflectPerson:=reflect.TypeOf(p)
	fieldCount:=reflectPerson.NumField()
	for i:=0;i<fieldCount;i++{
		field:=reflectPerson.Field(i)
		reflectNumberValue:=reflect.ValueOf(p)
		fmt.Println(fmt.Sprintf("Name of field %d is %v",i,field.Name),"value is",reflectNumberValue.Field(i).Interface())
	}
}

在这里插入图片描述

获取方法

  1. 通过NumMethod()获取数量,在遍历
type Person struct {
	Name string `nameTag:"ShowName" anotherTag:"AnotherTag"`
	Age int		`ageTag:"SetAge"`
	Gender int
	Desc string
}

func(p* Person)ShowName(){
	fmt.Println("showName is ",p.Name)
}

func (p* Person)AnotherTag(param1 string,param2 string){
	fmt.Println("anotherTag param1 is",param1,"param2 is",param2)
}

func(p Person) SetAge(age int)  {
	p.Age = age
	fmt.Println("current age is",p.Age)
}

func ReflectTest()  {

	p:=Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	reflectPerson:=reflect.TypeOf(p)

	methodCount:=reflectPerson.NumMethod()
	for i:=0;i<methodCount;i++{
		method:=reflectPerson.Method(i)
		fmt.Println(fmt.Sprintf("Name of Method %d is %v",i,method.Name))
	}
}

结果如下:
在这里插入图片描述
可以发现有三个方法,但是只有一条输出,为什么呢(细心的小伙伴可能已经发现了获取到的方法是没有*号的方法)
稍微修改一下代码:

reflectPerson:=reflect.TypeOf(&p)   // 加上地址符号

结果如下:
在这里插入图片描述

反射调用方法

TypeOf中的调用

func ReflectTest()  {

	p:=&Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	reflectPerson:=reflect.TypeOf(p)

	method,ok:=reflectPerson.MethodByName("SetAge")
	if ok{
		params:=make([]reflect.Value,2)
		params[0] = reflect.ValueOf(p)
		params[1] = reflect.ValueOf(20)
		method.Func.Call(params)
	}
}

SetAge方法需要一个参数
也可以通过ValueOf进行方法调用:

func ReflectTest()  {

	p:=&Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	reflectPerson:=reflect.ValueOf(p)

	method:=reflectPerson.MethodByName("SetAge")
	params:=make([]reflect.Value,1)
	params[0] = reflect.ValueOf(20)
	method.Call(params)

	method=reflectPerson.MethodByName("ShowName")
	params=make([]reflect.Value,0)
	method.Call(params)

	method=reflectPerson.MethodByName("AnotherTag")
	params=make([]reflect.Value,2)
	params[0] = reflect.ValueOf("this is params 1")
	params[1] = reflect.ValueOf("this is params 2")
	method.Call(params)
}

结果如下:
在这里插入图片描述

反射修改值

func test(data interface{}){

	r:=reflect.ValueOf(data).Elem()
	nameField:=r.FieldByName("Name")
	nameField.SetString("Name")

	Age:=r.FieldByName("Age")
	Age.SetInt(100)

	Gender:=r.FieldByName("Gender")
	Gender.SetInt(1111)

	Desc:=r.FieldByName("Desc")
	Desc.SetString("Desc")
}

func main(){

	p:=Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	//getStructTagPoter(&p)
	//getStructTag(p)
	test(&p) // 需要传引用,不然无法修改
	fmt.Println(p)

}

结果:
在这里插入图片描述

反射获取Tag并根据tag调用函数

package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string `nameTag:"ShowName" anotherTag:"AnotherTag"`
	Age int		`ageTag:"SetAge"`
	Gender int
	Desc string
}

func(p* Person)ShowName(){
	fmt.Println("showName is ",p.Name)
}

func (p* Person)AnotherTag(param1 string,param2 string){
	fmt.Println("anotherTag param1 is",param1,"param2 is",param2)
}

func(p Person) SetAge(age int)  {
	p.Age = age
	fmt.Println("current age is",p.Age)
}
func main(){

	p:=Person{
		Name:   "Luna",
		Age:    30,
		Gender: 1,
		Desc:   "dahjdasdlaskdagdshjsad",
	}

	getStructTagPoter(&p)
	getStructTag(p)

}

// 非指针调用
func getStructTag(p Person){

	fields := reflect.TypeOf(p)

	for i:=0;i<fields.NumField();i++{
		field:=fields.Field(i)
		if field.Name=="Age" {
			methodName:=field.Tag.Get("ageTag")
			method:= reflect.ValueOf(p).MethodByName(methodName)
			v:=make([]reflect.Value,1)
			v[0] = reflect.ValueOf(20)
			method.Call(v)
		}
	}
}

// 指针函数的调用
func getStructTagPoter(p *Person){
	// 取指针元素的类型
	fields := reflect.TypeOf(p).Elem()
	// 显示反射类型对象的名称和种类
	fmt.Println("Elem:name is", fields.Name(), "kind is", fields.Kind())

	typePerson := reflect.TypeOf(p)
	fmt.Println("Name is",  typePerson.Name(),"Kind is", typePerson.Kind())

	typePerson = reflect.TypeOf(&p)
	fmt.Println("Name is",  typePerson.Name(),"Kind is", typePerson.Kind())

	for i:=0;i<fields.NumField();i++{
		field:=fields.Field(i)
		if field.Name == "Name"{
			methodName:=field.Tag.Get("nameTag")
			method,ok:= reflect.TypeOf(p).MethodByName(methodName)
			if ok{
				v := make([]reflect.Value, 1)
				v[0] = reflect.ValueOf(p)
				method.Func.Call(v)
			}

			method,ok= reflect.TypeOf(p).MethodByName(field.Tag.Get("anotherTag"))
			if ok{
				v := make([]reflect.Value, 3)
				v[0] = reflect.ValueOf(p)
				v[1] = reflect.ValueOf("this is param 1")
				v[2] = reflect.ValueOf("this is param 2")
				method.Func.Call(v)
			}
		}else if field.Name=="Age" {
			methodName:=field.Tag.Get("ageTag")
			method,_:= reflect.TypeOf(p).MethodByName(methodName)
			v:=make([]reflect.Value,2)
			v[0] = reflect.ValueOf(p)
			v[1] = reflect.ValueOf(20)
			method.Func.Call(v)
		}
	}
}

当传入指针的时候需要用Elem()获取真实的类型,否则kind得到的是ptr
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值