首页 > 其他分享 >浅谈go反射

浅谈go反射

时间:2023-10-24 13:11:05浏览次数:25  
标签:反射 浅谈 Elem Value reflect interface go 指针

基本概念
支持反射的语言可以在程序编译期将变量的反射信息,如字段名称、类型信息、结构体信息等整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取类型的反射信息,并且有能力修改它们。

Go语言提供了 reflect 包来访问程序的反射信息。

Refelct解析
Refelct包 定义了两个重要的类型 Type 和 Value,任意接口在反射中都可以理解为 由 reflect.Type 和 reflect.Value 两部分组成 。简单来说,go 的接口是由两部分组成的,一部分是类型信息,另一部分是数据信息
eg
var a=1
var b interface{}=a
对于 这个例子,b 的类型信息是 int,数据信息是 1,这两部分信息都是存储在 b 里面的。b 的内存结构如下:

而 b实际上是一个空接口,也就是说一个 interface{} 中实际上既包含了变量的类型信息,也包含了类型的数据

refelct.Type ,refelct.Value
如上所说,所有的接口都含有type 和value ,我们可以使用refelct包中的 typeof 和valueof将信息从接口中取出
var a = 1
t := reflect.TypeOf(a)

var b = "hello"
t1 := reflect.ValueOf(b)

反射定律
三条反射定律 :

  1. 反射可以将 interface 类型变量转换成反射对象。
  2. 反射可以将反射对象还原成 interface 对象。
  3. 如果要修改反射对象,那么反射对象必须是可设置的(CanSet)。

将 interface 类型变量转换成反射对象
我们可以通过 reflect.TypeOf 和 reflect.ValueOf 来获取到一个变量的反射类型和反射值。
var a = 1
typeOfA := reflect.TypeOf(a)
valueOfA := reflect.ValueOf(a)

将反射对象还原成 interface 对象。
我们可以通过 reflect.Value.Interface 来获取到反射对象的 interface 对象,也就是传递给 reflect.ValueOf 的那个变量本身。 不过返回值类型是 interface{},所以我们需要进行类型断言。
i := valueOfA.Interface()
fmt.Println(i.(int))

修改反射对象
通过 reflect.Value.CanSet 来判断一个反射对象是否是可设置的。如果是可设置的,我们就可以通过 reflect.Value.Set 来修改反射对象的值。

var x float64 = 3.4
v := reflect.ValueOf(&x)
fmt.Println("settability of v:", v.CanSet()) // false
fmt.Println("settability of v:", v.Elem().CanSet()) // true

那什么情况下一个反射对象是可设置的呢?前提是这个反射对象是一个指针,然后这个指针指向的是一个可设置的变量 .
在上面这个例子中,v.CanSet() 返回的是 false,而 v.Elem().CanSet() 返回的是 true。
在这里,v是一根指针,但是v.Elem()才是v这根指针指向的值。Elem方法是一个解引用的作用。对于这个指针本身,我们修改它是没有意义的,我们可以设想一下, 如果我们修改了指针变量(也就是修改了指针变量指向的地址),那会发生什么呢?那样我们的指针变量就不是指向 x 了, 而是指向了其他的变量,这样就不符合我们的预期了。所以 v.CanSet() 返回的是 false。
而 v.Elem().CanSet() 返回的是 true。这是因为 v.Elem() 才是 x 本身,通过 v.Elem() 修改 x 的值是没有问题的

Elem()
refelct.Value中的Elem
reflect.Value 的 Elem 方法的作用是获取指针指向的值,或者获取接口的动态值。
对于指针很好理解,其实作用类似解引用。而对于接口,还是要回到 interface 的结构本身,因为接口里包含了类型和数据本身,所以 Elem 方法就是获取接口的数据部分(也就是 iface 或 eface 中的 data 字段)。
refelct.Type中的Elem
reflect.Type 的 Elem 方法的作用是获取数组、chan、map、指针、切片关联元素的类型信息,也就是说,对于 reflect.Type 来说, 能调用 Elem 方法的反射对象,必须是数组、chan、map、指针、切片中的一种,其他类型的 reflect.Type 调用 Elem 方法会 panic。
t1 := reflect.TypeOf([3]int{1, 2, 3}) // 数组 [3]int
fmt.Println(t1.String()) // [3]int
fmt.Println(t1.Elem().String()) // int

需要注意的是,如果我们要获取 map 类型 key 的类型信息,需要使用 Key 方法,而不是 Elem 方法。
m := make(map[string]string)
t1 := reflect.TypeOf(m)
fmt.Println(t1.Key().String()) // string

标签:反射,浅谈,Elem,Value,reflect,interface,go,指针
From: https://www.cnblogs.com/shashark/p/17784584.html

相关文章

  • Django+celery+eventlet+flower+redis异步任务创建及查询实现
    1.环境版本:Django3.2.12celery5.3.4eventlet0.33.3flower2.0.1redis3.5.3项目名称:new_project2.celery配置(settings.py)#celery#django-celery配置的部分#Broker配置,使用Redis作......
  • 注解与反射
    注解与反射笔记整理于@bilibili遇见狂神说注解(Annotation)什么是注解可被程序读取的注释注解的格式@Override@Deprecated内置注解//在java.lang.Override中定义,表示重写@Override//在java.lang.Deprecated中定义,表示已过时@Deprecated//镇压警告@SuppressWarn......
  • javascript: Sorting Algorithms
      /***fileSort.js*ide:vscodeJavaScriptSortingAlgorithms*插件:IntelliSense,JSDoc,CodeLens,DebuggerforChrome,静态代码检查:ESLint,JSHint,FlowLangugaeSupport,StandardJS-JavaScriptStandardStyle,koroFileHeader(文件头注释),测试插件:Mochasideba......
  • go并发的取消操作
    Go的并发模式:使用Context进行资源管理原创 lincyang lincyang新自媒体 2023-10-2310:00 发表于河北收录于合集#GO进阶16个大家好!我是[lincyang]。今天我们要一起探讨Go语言中的一个核心话题:使用Context进行资源管理。什么是Context?Context,即上下文,是Go语言中用于......
  • 在goland上部署环境用于区块链开发
    1.下载ubantu虚拟环境,使用Linux。(直接在goland中的plugin搜索下载)2.在plugin中搜索Remotedevelopmentconnector下载,用于远程开发3.在terminal中使用ubantu,下载NVM用于管理Node.js版本的工具curl-o-https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh|bas......
  • javascript: Sorting Algorithms
     /***fileSort.js*ide:vscodeJavaScriptSortingAlgorithms*插件:IntelliSense,JSDoc,CodeLens,DebuggerforChrome,静态代码检查:ESLint,JSHint,FlowLangugaeSupport,StandardJS-JavaScriptStandardStyle,koroFileHeader(文件头注释),测试插件:Mochasidebar,M......
  • go-ethereum-master/core/vm/stack.go 源码阅读
    //Copyright2014Thego-ethereumAuthors//Thisfileispartofthego-ethereumlibrary.////Thego-ethereumlibraryisfreesoftware:youcanredistributeitand/ormodify//itunderthetermsoftheGNULesserGeneralPublicLicenseaspublishedby......
  • Oracle10gOCP042题库121166题共168题
    121.Youwanttocreateanewoptimizeddatabaseforyourtransactionalproductionenvironmenttobeusedbyafinancialapplication.Whilecreatingthedatabase,youwanttheOraclesoftwaretotakecareofallbasicsettingstooptimizethedatabasep......
  • Oracle10gOCP042题库130题共168题
    声明:对于答案的相关的说明,是个人对Oracle的理解。1.Becauseofapoweroutage,instancefailurehasoccurred.Fromwhatpointintheredologdoesrecoverybeginandwheredoesitend?A.CurrentredologandinactiveredologB.Checkpointpositiontoendofr......
  • Oracle10gOCP042题库3170题共168题
    31.WhichtwostatementsaretrueregardingthedatabaseinARCHIVELOGmode?(Choosetwo.) A)Youhavetoshutdownthedatabasetoperformthebackups. B)Archivinginformationiswrittentothedatafilesandredologfiles. C)Youcanperformcomp......