Go语言中反射的正确使用
介绍
反射是元数据编程的一种形式,指的是程序获得本身结构的一种能力。不同语言的反射模型实现不一样,本文中的反射,仅仅指的是Go语言中的反射模型。
反射有两个问题,在使用前需要三思:
- 大量的使用反射会损失一定性能
- Clearisbetterthanclever.Reflectionisneverclear.
Go的类型设计上有一些基本原则,理解这些基本原则会有助于你理解反射的本质:
- 变量包括<type,value>两部分。理解这一点你就知道为什么nil!=nil了。
- type包括statictype和concretetype.简单来说statictype是你在编码是看见的类型,concretetype是runtime系统看见的类型。
- 类型断言能否成功,取决于变量的concretetype,而不是statictype.因此,一个reader变量如果它的concretetype也实现了write方法的话,它也可以被类型断言为writer.
- Go中的反射依靠interface{}作为桥梁,因此遵循原则3.例如,反射包.Kind方法返回的是concretetype,而不是statictype.
多说无用,下面来看示例代码
packagemain
import(
"fmt"
"reflect"
)
typeTstruct{
Aint
Bstring
}
funcmain(){
t:=T{23,"skidoo"}
tt:=reflect.TypeOf(t)
fmt.Printf("ttype:%v\n",tt)
ttp:=reflect.TypeOf(&t)
fmt.Printf("ttype:%v\n",ttp)
//要设置t的值,需要传入t的地址,而不是t的拷贝。
//reflect.ValueOf(&t)只是一个地址的值,不是settable,通过.Elem()解引用获取t本身的reflect.Value
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())
}
}
//输出结果
//ttype:main.T
//ttype:*main.T
//0:Aint=23
//1:Bstring=skidoo
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。