内容简介:参考文章:
参考文章:
Go语言实战笔记(二十四)| Go 反射 (推荐去看)
Go语言实战笔记(二十五)| Go Struct Tag (推荐去看)
Go语言中反射包的实现原理(The Laws of Reflection)
和 Java 语言一样,Go也实现运行时反射,这为我们提供一种可以在运行时操作任意类型对象的能力。Go是静态类型化的。每个变量都有一个静态类型,也就是说,在编译的时候变量的类型就被很精确地确定下来了,比如要么是int,或者是float32,或者是MyType类型,或者是[]byte等等。
1、第一反射定律(接口值到反射对象的反射)TypeOf和ValueOf
在 Go 的反射定义中,任何接口都会由两部分组成的,一个是接口的具体类型,一个是具体类型对应的值。比如 var i int = 3
,因为 interface{}
可以表示任何类型,所以变量 i
可以转为 interface{}
,所以可以把变量 i
当成一个接口,那么这个变量在Go反射中的表示就是 <Value,Type>
,其中Value为变量的值 3
,Type变量的为类型 int
。
reflect.Typeof获取具体的类型;reflect.Valueof获取接口的value。
type Myint int type User struct { name string age int } func main() { u := User{name:"lyd",age:24} var num Myint = 18 t := reflect.TypeOf(u) //main.User v := reflect.ValueOf(u) //{lyd 24} t_num := reflect.TypeOf(num) //main.Myint v_num := reflect.ValueOf(num) //18 } //还可以这样打印 fmt.Printf("%T\n",u) fmt.Printf("%v\n",u) v.Type() //main.User复制代码
2、将reflect.Value转原始类型(第二反射定律)
上面的例子我们可以通过 reflect.ValueOf
函数把任意类型的对象转为一个 reflect.Value
,给定一个reflect.Value,我们能用Interface方法把它恢复成一个接口值;
type Myint int type User struct { name string age int } func main() { u := User{name:"lyd",age:24} var num Myint = 18 v := reflect.ValueOf(u) v_num := reflect.ValueOf(num) y := v.Interface().(User) //fmt.Println可以处理interface{}, 所以可以直接 y_num := v_num.Interface() fmt.Println(y,y_num) //{lyd 24} 18 } 复制代码
3、修改反射对象的值(第三反射定律)
reflect.ValueOf
函数返回的是一份值的拷贝,所以前提是我们是传入要修改变量的地址。 其次需要我们调用 Elem
方法找到这个指针指向的值。
Value
为我们提供了 CanSet
方法可以帮助我们判断Value的settablity
一:反射对象不是settable的
func main() { var x float64 = 3.4 v := reflect.ValueOf(x) v.SetFloat(7.1) // Error: will panic. } 复制代码
func main() { var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("settability of v:", v.CanSet()) //settability of v: false } 复制代码
var x float64 = 3.4 p := reflect.ValueOf(&x) // Note: take the address of x.注意这里哦!我们把x地址传进去了! fmt.Println("type of p:", p.Type()) // type of p: *float64 fmt.Println("settability of p:", p.CanSet()) //settability of p: false 复制代码
反射对象p不是settable的,但是我们想要设置的不是p,而是(效果上来说)*p。为了得到p指向的东西,我们调用Value的Elem方法
二:总之,下面这样才是可以改变值的
func main() { x:=2 v:=reflect.ValueOf(&x) v.Elem().SetInt(100) fmt.Println(x) }复制代码
4、获取底层类型
type User struct { name string age int } func main() { u := User{name:"lyd",age:24} t := reflect.TypeOf(u) v := reflect.ValueOf(u) fmt.Println(t.Kind(),v.Kind()) //struct struct } 复制代码
5、遍历字段和方法
通过反射,我们可以获取一个结构体类型的字段,也可以获取一个类型的导出方法
type User struct { name string age int } func main() { u := User{name:"lyd",age:24} t := reflect.TypeOf(u) for i:=0;i<t.NumField();i++ { fmt.Println(t.Field(i).Name) } } //name //age复制代码
//方法 for i:=0;i<t.NumMethod() ;i++ { fmt.Println(t.Method(i).Name) }复制代码
6、动态调用方法
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP典型模块与项目实战大全
杨宇 / 清华大学出版社 / 2012-1 / 79.00元
《PHP典型模块与项目实战大全》以实战开发为原则,以PHP典型模块和项目开发为主线,通过12个高质量的PHP典型模块和6个PHP大型应用,向读者揭示了Web开发的整体结构,并详尽地介绍PHP开发与建站的技术要点。《PHP典型模块与项目实战大全》附带1张DVD,内容是作者为《PHP典型模块与项目实战大全》录制的全程多媒体语音教学视频及《PHP典型模块与项目实战大全》所涉及的源代码。《PHP典型模块与......一起来看看 《PHP典型模块与项目实战大全》 这本书的介绍吧!