这篇文章主要介绍“什么是Go语言的反射机制”,在日常操作中,相信很多人在什么是Go语言的反射机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是Go语言的反射机制”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
成都创新互联公司,专注为中小企业提供官网建设、营销型网站制作、自适应网站建设、展示型网站设计制作、成都做网站等服务,帮助中小企业通过网站体现价值、有效益。帮助企业快速建站、解决网站建设与网站营销推广问题。
因为没有强类型语言的经验,反射这个概念,之前确实没怎么接触过。在维基百科上搜了一下,具体解释如下:
在计算机学中,反射式编程(英语:reflective programming)或反射(英语:reflection),是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。
go 中的反射也是这种作用,可以在程序运行期间,获取变量的类型与值的信息,然后进行访问或或者修改。go 语言中,内置了 reflect 包,用来获取一个变量的类型(type)与值(value),对应的方法分别为 reflect.TypeOf() 和 reflect.ValueOf()。
TypeOf 方法,会返回该变量的类型对象,类型对象下可以获取到变量的类型与种类。
import ( "fmt" "reflect" ) func main() { // 定义一个int类型的变量 var i int = 1 // 获取变量的类型对象 var typeOfNum = reflect.TypeOf(i) // 输出类型与种类 typeOfNumName = typeOfNum.Name() typeOfNumKind = typeOfNum.Kind() fmt.Printf("name: %s, kind: %s", typeOfNumName, typeOfNumKind) }
可以看到,此时的类型与种类都为 int。
类型表示定义变量的时候指定的类型,可以反映 type 关键字定义的类型,而种类是变量最终归属的类型。说起来可能比较苍白,我们直接上代码。
type num int // 定义一个num类型的变量 var i num = 1 var typeOfNum = reflect.TypeOf(i)
可以看到,此时的类型为 num,种类为 int。
对于一些引用类型的变量,比如切片、函数、结构体,kind 都能准确反映其底层的类型。
func printTypeOf(typeOf reflect.Type) { fmt.Printf("name: %s, kind: %s\n", typeOf.Name(), typeOf.Kind()) } type Person struct {} type IntSlice []int func main() { var a = IntSlice{} var b = Person{} printTypeOf(reflect.TypeOf(a)) printTypeOf(reflect.TypeOf(b)) }
而面对匿名结构体或者匿名函数,其类型值会返回为空。
func main() { var a = struct {}{} printTypeOf(reflect.TypeOf(a)) }
ValueOf 方法,可以获取一个变量的值。
var i = 3.1415926 var s = "欢迎关注我的公众号:『自然醒的笔记本』" fmt.Println(reflect.ValueOf(s)) fmt.Println(reflect.ValueOf(i))
通过反射的值对象,也能取到变量的种类,并且还能根据其种类,调用对应的方法获取变量的真实值。
var i = 100 var v = reflect.ValueOf(i) fmt.Println(v.Int()) // 如果值是 Int 类型,可以通过 Int 方法获取具体值 fmt.Println(v.Kind())
通过反射得到的值对象,可以对变量本身的值进行修改。首先,在获取反射值时,不能直接获取变量的反射值,而是要先取其指针的值对象。
var i = 100 var v = reflect.ValueOf(&i) // 取出变量i的指针的值对象 fmt.Println(v.Kind(), v)
取出指针的值对象之后,不能立即赋值,因为此时拿到的是变量的地址。
要赋值的话,需要先调用 Elem 方法,取出具体元素,然后进行赋值。
var i = 100 var v = reflect.ValueOf(&i) // 取出变量i的指针的值对象 var e = v.Elem() e.SetInt(500) // 修改元素值 fmt.Println(e.Kind(), i)
前面介绍过,通过反射可以得到变量的值,对于结构体来说,也是一样。
type Person struct { name string age int gender string address string } var p = Person{"Shenfq", 25, "男", "湖南长沙"} var v = reflect.ValueOf(p) fmt.Println(v.Kind(), v)
反射值对象还提供了一些方法,专门用来针对结构体成员的信息获取。
NumField() 可以获取结构体成员的具体数量。
var p = Person{"Shenfq", 25, "男", "湖南长沙"} var v = reflect.ValueOf(p) fmt.Println("Person 结构体成员数:", v.NumField())
Field() 可以获取结构体指定索引位置的成员的反射值。
var p = Person{"Shenfq", 25, "男", "湖南长沙"} var v = reflect.ValueOf(p) var num = v.NumField() for i :=0; i < num; i++ { var val = v.Field(i) fmt.Printf("Person[%d]: %s %v\n", i, val.Type(), val) }
FieldByName() 可以获取结构体指定成员名称的成员的反射值。
var p = Person{"Shenfq", 25, "男", "湖南长沙"} var v = reflect.ValueOf(p) var vOfName = v.FieldByName("name") fmt.Printf("Person[name]: %s %v\n", vOfName.Type(), vOfName)
到此,关于“什么是Go语言的反射机制”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!