go语言反射获取属性值,go语言 反射

关于反射

在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

为吉林等地区用户提供了全套网页设计制作服务,及吉林网站建设行业解决方案。主营业务为成都做网站、网站设计、吉林网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

每种语言的反射模型都不同,并且有些语言根本不支持反射。Golang语言实现了反射,反射机制就是在运行时动态的调用对象的方法和属性,官方自带的reflect包就是反射相关的,只要包含这个包就可以使用。

多插一句,Golang的gRPC也是通过反射实现的。

在讲反射之前,先来看看Golang关于类型设计的一些原则

接下来要讲的反射,就是建立在类型之上的,Golang的指定类型的变量的类型是静态的(也就是指定int、string这些的变量,它的type是static type),在创建变量的时候就已经确定,反射主要与Golang的interface类型相关(它的type是concrete type),只有interface类型才有反射一说。

在Golang的实现中,每个interface变量都有一个对应pair,pair中记录了实际变量的值和类型:

value是实际变量值,type是实际变量的类型。一个interface{}类型的变量包含了2个指针,一个指针指向值的类型【对应concrete type】,另外一个指针指向实际的值【对应value】。

例如,创建类型为*os.File的变量,然后将其赋给一个接口变量r:

接口变量r的pair中将记录如下信息:(tty, *os.File),这个pair在接口变量的连续赋值过程中是不变的,将接口变量r赋给另一个接口变量w:

接口变量w的pair与r的pair相同,都是:(tty, *os.File),即使w是空接口类型,pair也是不变的。

interface及其pair的存在,是Golang中实现反射的前提,理解了pair,就更容易理解反射。反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。

既然反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。那么在Golang的reflect反射包中有什么样的方式可以让我们直接获取到变量内部的信息呢? 它提供了两种类型(或者说两个方法)让我们可以很容易的访问接口变量内容,分别是reflect.ValueOf() 和 reflect.TypeOf(),看看官方的解释

reflect.TypeOf()是获取pair中的type,reflect.ValueOf()获取pair中的value,示例如下:

当执行reflect.ValueOf(interface)之后,就得到了一个类型为”relfect.Value”变量,可以通过它本身的Interface()方法获得接口变量的真实内容,然后可以通过类型判断进行转换,转换为原有真实类型。不过,我们可能是已知原有类型,也有可能是未知原有类型,因此,下面分两种情况进行说明。

已知类型后转换为其对应的类型的做法如下,直接通过Interface方法然后强制转换,如下:

示例如下:

很多情况下,我们可能并不知道其具体类型,那么这个时候,该如何做呢?需要我们进行遍历探测其Filed来得知,示例如下:

通过运行结果可以得知获取未知类型的interface的具体变量及其类型的步骤为:

通过运行结果可以得知获取未知类型的interface的所属方法(函数)的步骤为:

reflect.Value是通过reflect.ValueOf(X)获得的,只有当X是指针的时候,才可以通过reflec.Value修改实际变量X的值,即:要修改反射类型的对象就一定要保证其值是“addressable”的。

示例如下:

这算是一个高级用法了,前面我们只说到对类型、变量的几种反射的用法,包括如何获取其值、其类型、如果重新设置新值。但是在工程应用中,另外一个常用并且属于高级的用法,就是通过reflect来进行方法【函数】的调用。比如我们要做框架工程的时候,需要可以随意扩展方法,或者说用户可以自定义方法,那么我们通过什么手段来扩展让用户能够自定义呢?关键点在于用户的自定义方法是未可知的,因此我们可以通过reflect来搞定

示例如下:

Golang的反射很慢,这个和它的API设计有关。在 java 里面,我们一般使用反射都是这样来弄的。

这个取得的反射对象类型是 java.lang.reflect.Field。它是可以复用的。只要传入不同的obj,就可以取得这个obj上对应的 field。

但是Golang的反射不是这样设计的:

这里取出来的 field 对象是 reflect.StructField 类型,但是它没有办法用来取得对应对象上的值。如果要取值,得用另外一套对object,而不是type的反射

这里取出来的 fieldValue 类型是 reflect.Value,它是一个具体的值,而不是一个可复用的反射对象了,每次反射都需要malloc这个reflect.Value结构体,并且还涉及到GC。

Golang reflect慢主要有两个原因

上述详细说明了Golang的反射reflect的各种功能和用法,都附带有相应的示例,相信能够在工程应用中进行相应实践,总结一下就是:

如何通过反射来获取类的静态属性值

Field.get(null) 附上文档 public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException返回指定对象上此 Field 表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。

go语言的reflect(反射)

1、反射可以在运行时 动态获取变量的各种信息 ,比如变量的类型、类别;

2、如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法);

3、通过反射,可以修改 变量的值 ,可以调用关联的方法;

4、使用反射,需要import " reflect ".

5、示意图:

1、不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射。

例如以下这种桥接模式:

示例第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数。

1、reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型。

2、reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型。

3、变量、interface{}和reflect.Value是可以互相转换的,这点在实际开发中,会经常使用到。

1、reflect.Value.Kind,获取变量的 类别(Kind) ,返回的是一个 常量 。在go语言文档中:

示例如下所示:

输出如下:

Kind的范畴要比Type大。比如有Student和Consumer两个结构体,他们的 Type 分别是 Student 和 Consumer ,但是它们的 Kind 都是 struct 。

2、Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的。

3、通过反射可以在让 变量 在 interface{} 和 Reflect.Value 之间相互转换,这点在前面画过示意图。

4、使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么久应该使用reflect.Value(x).Int(),而不能使用其它的,否则报panic。

如果是x是float类型的话,也是要用reflect.Value(x).Float()。但是如果是struct类型的话,由于type并不确定,所以没有相应的方法,只能 断言。

5、通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()方法。

输出num=20,即成功使用反射来修改传进来变量的值。

6、reflect.Value.Elem()应该如何理解?

go语言中的反射

import (

"fmt"

"reflect"

)

func reflecType(x interface{}){

v := reflect.TypeOf(x)

fmt.Println("type:%v\n", v)

fmt.Println("type name:%v , rtpe kind:%v \n", v.getName(), v.getType())

}

type Cat struct{}

//通过反射设置变量的值

func reflectSetValue1(x interface{}){

v := reflect.ValueOf(x)

if v.Kind() == reflect.Int64{

v.SetInt(200) //修改的是副本, reflect 包会引发panic

}

}

//通过反射设置变量的值

func reflectSetValue2(x interface{}){

v := reflect.ValueOf(x)

//反射中使用Elem()获取指针对应的值

if v.Elem().Kind() == reflect.Int64{

v.Elem().SetInt(200)

}

}

func main(){

var a float32 = 3.14

reflectType(a) //type name:float32 type kind:float32

var b int64 = 100

reflectType(b) // type name :int64 type kind :int64

var c = Cat{}

reflectType(c) // type name :Cat type kind :struct

reflectSetValue1(b)

fmt.Println(b) //依然为100

reflectSetValue2(b)

}

反射怎么获取类属性类型

反射可以获取到属性类型,Field类里面有个方法,getType()就是获取属性类型的。。。

下面是个示例代码。。。

public

static

void

main(String

args[])

{

People

peo

=

new

People();

Class

cla

=

People.class;

try

{

Field[]

fields

=

cla.getFields();

for(Field

field:fields){

Class

c

=

field.getType();

if(c==String.class){

field.set(peo,

"EMPTY");

}else

if(c==Integer.class){

field.set(peo,

0);

}

}

}

catch

(SecurityException

e)

{

//

TODO

Auto-generated

catch

block

e.printStackTrace();

}catch

(IllegalArgumentException

e)

{

//

TODO

Auto-generated

catch

block

e.printStackTrace();

}

catch

(IllegalAccessException

e)

{

//

TODO

Auto-generated

catch

block

e.printStackTrace();

}

}

主要就是用Class

c

=

field.getType();

这个来获取类型。。。。

希望能帮到你。。。仍有问题可以Hi我。。。或者直接追问。。。


文章名称:go语言反射获取属性值,go语言 反射
分享路径:http://azwzsj.com/article/hddidp.html