go语言学习-reflect反射理解和简单使用

1、golang中reflect说明:

本质上来说,反射就是一种检查接口变量的类型和值的机制。最基本的我们要知
reflect.Type和reflect.Value。可以通过reflect.TypeOf和reflect.ValueOf来得到接口变量的Type和Value,同样可以通过reflect.Value轻松得到reflect.Type。

2、golang中reflect的使用:

2.1 获取类型信息

golang通过reflect.TypeOf()获取对象的类型
2.2 获取值类型

golang中通过reflect.ValueOf()获取对象的值信息
通过Elem()获取对象的对应的值
######下面是对2.1和2.2的简单使用

package main

import (
	"fmt"
	"reflect"
)



func main(){


	var x float32 = 1.0

	v := reflect.ValueOf(x)
	fmt.Println("type:",v.Type())

	if v.CanSet(){
		fmt.Println("v can set ")
		v.SetFloat(1.6)
	}else {
		fmt.Println("v can not set")
	}

	p := reflect.ValueOf(&x)

	if p.CanSet(){
		fmt.Println("p can set ")
		p.SetFloat(1.6)
		v2 := p.Float()
		fmt.Println("p:",p," v2:",v2," x:",v)
	}else {
		fmt.Println("p can not set ")
		v2 := p.Elem()
		if v2.CanSet(){
			fmt.Println("v2 can set ")
			v2.SetFloat(1.6)
			fmt.Println("v2:",v2.Float()," x:",x)
			fmt.Println("v2地址:",v2.Addr()," x地址:",&x)
		}else{
			fmt.Println("v2 can not set")
		}
	}

}

######执行结果

x type is: float32
type: float32
v can not set
p can not set 
v2 can set 
v2: 1.600000023841858  x: 1.6
v2地址: 0xc042008100  x地址: 0xc042008100

2.3对自定义对象的反射

本质上和对基本类型的反射一样,只是多了使用Filed()函数诸葛访问成员,但是经过实测,reflect.valueof()参数必须是指针类型,否则调用Elem()方法相关的函数编译都会会报错。之前博主不知道是什么原因,但是通过查看Elem()函数的源码可以找到原因,下面是Elem()函数的源码:

func (v Value) Elem() Value {
	k := v.kind()
	switch k {
	case Interface:
		var eface interface{}
		if v.typ.NumMethod() == 0 {
			eface = *(*interface{})(v.ptr)
		} else {
			eface = (interface{})(*(*interface {
				M()
			})(v.ptr))
		}
		x := unpackEface(eface)
		if x.flag != 0 {
			x.flag |= v.flag & flagRO
		}
		return x
	case Ptr:
		ptr := v.ptr
		if v.flag&flagIndir != 0 {
			ptr = *(*unsafe.Pointer)(ptr)
		}
		// The returned value's address is v's value.
		if ptr == nil {
			return Value{}
		}
		tt := (*ptrType)(unsafe.Pointer(v.typ))
		typ := tt.elem
		fl := v.flag&flagRO | flagIndir | flagAddr
		fl |= flag(typ.Kind())
		return Value{typ, ptr, fl}
	}
	panic(&ValueError{"reflect.Value.Elem", v.kind()})
}

说明:

通过源码我们可以看出,Elem()函数只接受类型为Interface和ptr,接口和指针类型,当我们传入一个结构体对象是,不符合类型,所以就会报错。
######代码案例

package main

import (
	"reflect"
	"fmt"
)

type T struct {
	A int
	B string
}

func main(){

	t := &T{1,"test string"}

	//反射对象类型
	tType := reflect.TypeOf(t)
	fmt.Println("t type is ",tType)

	//反射对象的值信息
	tValue := reflect.ValueOf(t).Elem()
	fmt.Println("tValue value is ",tValue)

	tValueType := tValue.Type()
	for i:=0;i

######执行结果

t type is  *main.T
tValue value is  {1 test string}
0:A int = 1
1:B string = test string
欢迎关注问我团队公众号:

go语言学习-reflect反射理解和简单使用_第1张图片

你可能感兴趣的:(golang)