golang reflect实例

在实际的项目中,我们接收一个struct,要判断struct内部的字段、值、类型,reflect的数据结构体由

reflect.Type和reflect.Value两部分组成,并且reflect包提供了reflect.TypeOf和reflect.ValueOf两个函数来获取任意对象的Value和Type。

reflect.TypeOf()方法

任意值通过reflect.TypeOf()获得反射对象信息后,如果它的类型是结构体,可以通过反射值对象(reflect.Type)的NumField()和Field()方法获得结构体成员的详细信息。

在这里插入图片描述
eg:NumField()和Field()

    typ:=reflect.TypeOf(x)
    v:=reflect.ValueOf(x)
    for i:=0;i<v.Elem().NumField();i++{
		field := typ.Elem().Field(i) //字段的数据类型
        fmt.Printf("&&&& typeof 反射:%v\n",field)
        fmt.Printf("&&&& typeof 反射:%v\n",field.Name)

		value := v.Elem().Field(i) //字段的数据值
&&&& typeof 反射:{Name  string json:"name" 0 [0] false}
&&&& typeof 反射:{Age  int json:"age" 16 [1] false}
&&&& typeof 反射:Name
&&&& typeof 反射:Age

这样通过对NumField()循环就可以拿到struct内部的字段名字field.Name

reflect.ValueOf()方法

reflect.ValueOf()返回的是reflect.Value类型,其中包含了原始值的值信息。reflect.Value与原始值之间可以互相转换。

reflect.Value类型提供的获取原始值的方法如下:

在这里插入图片描述

eg:

func reflectValue(x interface{}) {
	v := reflect.ValueOf(x)
	k := v.Kind()
	switch k {
	case reflect.Int64:
		// v.Int()从反射中获取整型的原始值,然后通过int64()强制类型转换
		fmt.Printf("type is int64, value is %d\n", int64(v.Int()))
	case reflect.Float32:
		// v.Float()从反射中获取浮点型的原始值,然后通过float32()强制类型转换
		fmt.Printf("type is float32, value is %f\n", float32(v.Float()))
	case reflect.Float64:
		// v.Float()从反射中获取浮点型的原始值,然后通过float64()强制类型转换
		fmt.Printf("type is float64, value is %f\n", float64(v.Float()))
	}
}
func main() {
	var a float32 = 3.14
	var b int64 = 100
	reflectValue(a) // type is float32, value is 3.140000
	reflectValue(b) // type is int64, value is 100
	// 将int类型的原始值转换为reflect.Value类型
	c := reflect.ValueOf(10)
	fmt.Printf("type c :%T\n", c) // type c :reflect.Value
}

E l e m ( ) 方 法 在 传 指 针 的 时 候 可 以 获 取 到 指 针 的 值 \color{#A0A}{Elem()方法在传指针的时候可以获取到指针的值} Elem()
\color{#A0A}{}


type struct1 struct{
    Name string `json:"name"`
    Age int `json:"age"`
}


func get_value(x interface{}){
    传参是穿指针
    typ:=reflect.TypeOf(x)
    v:=reflect.ValueOf(x)
    for i:=0;i<v.Elem().NumField();i++{
		field := typ.Elem().Field(i) //字段的数据类型
		value := v.Elem().Field(i) //字段的数据值
        switch value.Kind() {
        case reflect.String:
            fmt.Printf("反射出来的key是 %v ,反射出来的值是:%v   类型是:%v\n",field.Name,value.String(),value.Kind())
            value.SetString("charlie & bennie")
            fmt.Printf("反射出来的key是 %v ,反射出来的值是:%v   类型是:%v\n",field.Name,value.String(),value.Kind())

        case reflect.Int:
            fmt.Printf("反射出来的key是 %v ,反射出来的值是:%v   类型是:%v\n",field.Name,value,value.Kind())
            value.SetInt(88)
            fmt.Printf("反射出来的key是 %v ,反射出来的值是:%v   类型是:%v\n",field.Name,value,value.Kind())

        default:
            fmt.Printf("useless type!\n")
    }
    }
}

func main(){
    var mystruct1 struct1
    mystruct1.Name="charlie"
    mystruct1.Age=23
    一定要传地址
    一定要传地址
    一定要传地址
	get_value(&mystruct1)

反射出来的key是 Name ,反射出来的值是:bennie   类型名字是:string
反射出来的key是 Name ,反射出来的值是:charlie & bennie   类型名字是:string
{Age  int json:"age" 16 [1] false} 23
反射出来的key是 Age ,反射出来的值是:23   类型名字是:int
反射出来的key是 Age ,反射出来的值是:88   类型名字是:int
package test
 
import (
    "fmt"
    "reflect"
)
 
type Person struct {
    Name   string
    Age    int
    Gender string//所有field首字母都要大写,否则反射时会报错
}
func (p Person)Refpersion() reflect.Value{
	t := reflect.TypeOf(p)
    v := reflect.ValueOf(p)
    fmt.Println(t, v) //main.Person {John 30 male}
    return v
}
func Myreftest(){
	reftest()
	p := Person{"John", 30, "male"}
	p.Refpersion()
	p.struceelem()
    p.Structmethod()
    DoFiledAndMethod(p)

}
如果知道类型可以强制转换,interfacce().(type)
func reftest() {
    var num int = 100
    t := reflect.TypeOf(num)
	v := reflect.ValueOf(&num)
    ptr := reflect.ValueOf(&num)
    fmt.Println(t.Name())//int
    fmt.Println(t, v,ptr) //int 0xc420090030 0xc420090030
    atype := v.Interface().(*int)//如果知道类型可以强制转换
    fmt.Println(*atype) //100
 
}

func (p *Person)struceelem(){
	v := reflect.ValueOf(p).Elem()
 
    //p(v)的属性数量
    count := v.NumField()
    for i := 0; i < count; i++ {
        fmt.Println(v.Type().Field(i).Name) //属性名
        fmt.Println(v.Field(i).Type())      //属性类型
        fmt.Println(v.Field(i))             //属性值
    }
    //  打印结果:
    //  Name string John
    //  Age  int    99
    // gender string male
 
    //修改第一个属性的值
    v.Field(0).SetString("Jane")
 
    //修改Age属性的值
    v.FieldByName("Age").SetInt(88)
    fmt.Println(v) //{Jane 88 male}
    fmt.Println(p) //{Jane 88 male}
}

func (p Person)Structmethod(){
	v := reflect.ValueOf(&p).Elem()
    //方法数量
    count := v.NumMethod()
    for i := 0; i < count; i++ {//只有方法传值和首字母大写的可以能反射
        fmt.Println(v.Type().Method(i).Name, v.Method(i).Type())
	}
	
	params := make([]reflect.Value, 0)
    v.Method(0).Call(params) //调用SetAge方法
    fmt.Printf("call: %s",v) //&{John 50}
    fmt.Println(p) //&{John 50}
 
    res := v.MethodByName("Refpersion").Call(nil)
    fmt.Println(&res) //Name:John, Age:50
}

func DoFiledAndMethod(input interface{}) {

	getType := reflect.TypeOf(input)
	fmt.Println("get Type is :", getType.Name())

	getValue := reflect.ValueOf(input)
	fmt.Println("88  get all Fields is:", getValue)

	// 获取interface{}字段
	// 1. 先获取interface的reflect.Type,然后通过NumField进行遍历
	// 2. 再通过reflect.Type的Field获取其Field
	// 3. 最后通过Field的Interface()得到对应的value
	for i := 0; i < getType.NumField(); i++ {//NumField()返回结构体的field的count,即有几个字段,然后循坏获取type和value
		field := getType.Field(i)
		value := getValue.Field(i).Interface()
		fmt.Printf("97    %s: %v = %v\n", field.Name, field.Type, value)
	}

	// 获取方法
	// 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历
	for i := 0; i < getType.NumMethod(); i++ {
		m := getType.Method(i)
        fmt.Printf("104  %s: %v\n", m.Name, m.Type)
        params := make([]reflect.Value, 0)
        getValue.Method(i).Call(params) 
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值