Kind Name的区别
- Kind()返回的是基本类型,如果是类的话返回的基本类型是Struct
- 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
- NumField可以获取属性的数量,然后可以通过Index去获取每个属性
- 对于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())
}
}
获取方法
- 通过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