Go反射机制Reflect

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

内容简介:参考文章:

参考文章:

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


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

查看所有标签

猜你喜欢:

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

深入浅出程序设计(中文版)

深入浅出程序设计(中文版)

Paul Barry、David Griffiths / 蒋雁翔、童健 / 东南大学出版社 / 2012-1 / 98.00元

《深入浅出程序设计(中文版)》介绍了编写计算机程序的核心概念:变量、判断、循环、函数与对象——无论运用哪种编程语言,都能在动态且多用途的python语言中使用具体示例和练习来运用并巩固这些概念。学习基本的工具来开始编写你感兴趣的程序,而不是其他人认为你应该使用的通用软件,并对软件能做什么(不能做什么)有一个更好的了解。当你完成这些,你就拥有了必要的基础去使用任何一种你需要或想要学习的语言或软件项目......一起来看看 《深入浅出程序设计(中文版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具