golang reflect
本文内容纲要:
-golangreflect
-接口值到反射对象
-反射对象到接口值
-修改反射对象
-获取结构体标签
-interface{}到函数反射
golangreflect
go语言中reflect反射机制。详细原文:地址
接口值到反射对象
packagemain
import(
"fmt"
"reflect"
)
funcmain(){
varxint=1
fmt.Println("type:",reflect.TypeOf(x))
}
type:int
TypeOf
函数的定义如下,参数为接口类型,返回值为类型
funcTypeOf(iinterface{})Type
ValueOf
函数的定义如下,参数为接口类型,返回值为Value
varxint=1
fmt.Println("value:",reflect.ValueOf(x))
value:<intValue>
可以通过Kind
函数来检查类型,
fmt.Println("Kind:",reflect.ValueOf(x).Kind())
fmt.Println("KindisInt?",reflect.ValueOf(x).Kind()==reflect.int)
Kind:int
KindisInt?true
反射对象到接口值
通过Interface
函数可以实现反射对象到接口值的转换,
func(vValue)Interface()interface{}
//Interface以interface{}返回v的值
y:=v.Interface().(float64)
fmt.Println(y)
修改反射对象
修改反射对象的前提条件是其值必须是可设置的
varxfloat64=3.4
v:=reflect.ValueOf(x)
v.SetFloat(7.3)//Error:panic
为了避免这个问题,需要使用CanSet
函数来检查该值的设置性,
varxfloat64=3.4
v:=reflect.ValueOf(x)
fmt.Println("settabilityofv:",v.CanSet())
settabilityofv:false
那么如何才能设置该值呢?
这里需要考虑一个常见的问题,参数传递
,传值还是传引用或地址?
在上面的例子中,我们使用的是reflect.ValueOf(x)
,这是一个值传递,传递的是x的值的一个副本,不是x本身,因此更新副本中的值是不允许的。如果使用reflect.ValueOf(&x)
来替换刚才的值传递,就可以实现值的修改。
varxfloat64=3.4
p:=reflect.ValueOf(&x)//获取x的地址
fmt.Println("settabilityofp:",p.CanSet())
v:=p.Elem()
fmt.Println("settabilityofv:",v.CanSet())
v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)
settabilityofp:false
settabilityofv:true
7.1
7.1
获取结构体标签
首先介绍如何遍历结构体字段内容,
假设结构体如下,
typeTstruct{
Aint
Bstring
}
t:=T{12,"skidoo"}
从而,通过反射来遍历所有的字段内容
s:=reflect.ValueOf(&t).Elem()
typeOfT:=s.Type()
fori:=0;i<s.NumField();i++{
f:=s.Field(i)
fmt.Printf("%d%s%s=%v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface())
}
0Aint=23
1Bstring=skidoo
接下来,如何获取结构体的标签内容?
funcmain(){
typeSstruct{
Fstring`species:"gopher"color:"blue"`
}
s:=S{}
st:=reflect.TypeOf(s)
field:=st.Field(0)
fmt.Println(field.Tag.Get("color"),field.Tag.Get("species"))
}
interface{}到函数反射
一般情况下,为了存储多个函数值,一般采用map
来存储。其中key为函数名称,而value为相应的处理函数。
在这里需要定义好函数类型,但是函数的参数以及返回类型就需要是统一的,如下
packagemain
import"fmt"
funcsay(textstring){
fmt.Println(text)
}
funcmain(){
varfuncMap=make(map[string]func(string))
funcMap["say"]=say
funcMap["say"]("hello")
}
如果希望map
可以存储任意类型的函数(参数不同,返回值不同),那么就需要用interface{}而不是func(param...)来定义value。
packagemain
import"fmt"
funcsay(textstring){
fmt.Println(text)
}
funcmain(){
varfuncMap=make(map[string]interface{})
funcMap["say"]=say
funcMap["say"]("hello")
}
cannotcallnon-functionfuncMap["say"](typeinterface{})
直接调用会报错,提示不能调用interface{}类型的函数。
这时,需要利用reflect
把函数从interface转换到函数来使用,
packagemain
import(
"fmt"
"reflect"
)
funcsay(textstring){
fmt.Println(text)
}
funcCall(mmap[string]interface{},namestring,params...interface{})(result[]reflect.Value){
f:=reflect.ValueOf(m[name])
in:=make([]reflect.Value,len(params))
fork,param:=rangeparams{
in[k]=reflect.ValueOf(param)
}
result=f.Call(in)
return
}
funcmain(){
varfuncMap=make(map[string]interface{})
funcMap["say"]=say
Call(funcMap,"say","hello")
本文内容总结:golangreflect,接口值到反射对象,反射对象到接口值,修改反射对象,获取结构体标签,interface{}到函数反射,
原文链接:https://www.cnblogs.com/coder2012/p/4881854.html