Go反射机制Reflect

栏目: Go · 发布时间: 6年前

内容简介:参考文章:

参考文章:

Go语言实战笔记(二十四)| Go 反射 (推荐去看)

Go语言实战笔记(二十五)| Go Struct Tag (推荐去看)

Go语言中反射包的实现原理(The Laws of Reflection)

GCTT 出品』Go 反射机制介绍

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、动态调用方法

Go反射机制Reflect


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Kotlin实战

Kotlin实战

【美】Dmitry Jemerov(德米特里·詹莫瑞福)、【美】 Svetlana Isakova(斯维特拉娜·伊凡诺沃) / 覃宇、罗丽、李思阳、蒋扬海 / 电子工业出版社 / 2017-8 / 89.00

《Kotlin 实战》将从语言的基本特性开始,逐渐覆盖其更多的高级特性,尤其注重讲解如何将 Koltin 集成到已有 Java 工程实践及其背后的原理。本书分为两个部分。第一部分讲解如何开始使用 Kotlin 现有的库和API,包括基本语法、扩展函数和扩展属性、数据类和伴生对象、lambda 表达式,以及数据类型系统(着重讲解了可空性和集合的概念)。第二部分教你如何使用 Kotlin 构建自己的 ......一起来看看 《Kotlin实战》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具