本质上来说,反射就是一种检查接口变量的类型和值的机制。最基本的我们要知
reflect.Type和reflect.Value。可以通过reflect.TypeOf和reflect.ValueOf来得到接口变量的Type和Value,同样可以通过reflect.Value轻松得到reflect.Type。
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
本质上和对基本类型的反射一样,只是多了使用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