首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在指针接收器上调用Elem()方法以进行结构反射的必要性

指针接收器是在Go语言中用于类型方法定义的一种特殊接收器。它可以使方法能够修改接收器指向的结构体实例的状态。在调用结构体的方法时,如果使用了指针接收器,那么该方法内部对结构体字段的修改将会影响到原始实例。而在调用非指针接收器的方法时,该方法内部对结构体字段的修改只会作用于方法内部的拷贝,不会影响原始实例。

结构反射是一种在运行时动态获取和操作结构体类型信息的能力。通过结构反射,我们可以在运行时检查结构体的字段、方法和标签等信息,并根据这些信息做出相应的操作。在Go语言中,可以使用reflect包来实现结构反射。

在指针接收器上调用Elem()方法是为了获取指针指向的结构体的值。当我们使用指针接收器调用方法时,反射会返回一个指向结构体的指针值,而不是结构体的值本身。为了获取结构体的值,我们可以使用Elem()方法来解引用指针,获取指针指向的结构体的值。

在一些特定的场景下,我们可能需要对结构体进行反射操作,例如根据结构体的字段名动态获取字段的值、修改结构体的字段值等。使用指针接收器并调用Elem()方法可以帮助我们获取到实际的结构体值,从而进行结构反射操作。

需要注意的是,使用指针接收器并调用Elem()方法可能会带来一些性能上的开销。因此,在性能敏感的场景下,我们应该谨慎使用结构反射,并考虑使用其他方式来满足需求。

总结起来,指针接收器上调用Elem()方法的必要性在于获取指针指向的结构体的值,以便进行结构反射操作。这样可以实现在运行时动态获取和修改结构体的字段值等操作。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Go 每日一库之 reflect

一个具体的例子就是fmt.Println()方法,可以打印出我们自定义的结构类型。 虽然,一般来说都不建议在代码中使用反射。...然后针对每个字段的Kind做相应的处理。 有些方法只有在原对象是某种特定类型时,才能调用。例如NumField()和Field()方法只有原对象是结构体时才能调用,否则会panic。...PkgPath string Type Type // 方法类型(即函数类型) Func Value // 方法值(以接收器作为第一个参数) Index int // 是结构体中的第几个方法...这需要以下方法: reflect.Value.MethodByName(name):获取结构体中定义的名为name的方法的reflect.Value对象,这个方法默认有接收器参数,即调用MethodByName...invokeMethod(m, "Add") invokeMethod(m, "Sub") invokeMethod(m, "Mul") invokeMethod(m, "Div") } 我们可以在结构体的反射值对象上使用

60620

深入理解 go 反射

因为这个值实际上被拷贝了一份,我们如果通过反射修改这个值,那么实际上是修改的这个拷贝的值,而不是原来的值。...也就是说,能调用 Elem 方法的反射对象,必须是一个指针或者一个接口。...在使用其他类型的 reflect.Value 来调用 Elem 方法的时候,会 panic: var a = 1 // panic: reflect: call of reflect.Value.Elem...的 Elem 方法 reflect.Type 的 Elem 方法的作用是获取数组、chan、map、指针、切片关联元素的类型信息,也就是说,对于 reflect.Type 来说, 能调用 Elem 方法的反射对象...type Type interface { // Align 返回该类型在内存中分配时,以字节数为单位的字节数 Align() int // FieldAlign 返回该类型在结构中作为字段使用时

12310
  • golang源码分析:encodingjson(1)

    encodeStatePool.Put(e) return buf, nil } 首先初始化了编码状态机,然后进行序列化,默认是进行html转义的,将序列化结果append到输出buf上,最后用...,检查它是否实现了类型接收器的序列化方法,其中marshalerType marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()...然后检查是否实现了指针接受器的序列化方法,接着检查非指针类型接收器和指针类型接收器的文本序列化方法 textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler...)(nil)).Elem() 如果类型实现了上述序列化方法,就会按照类型自己定义的序列化方法来序列化,否则就用系统默认的序列化方法来序列化。...,介绍完毕,我们可以看到,虽然尽量使用了缓存的方法,来提升复用和减少反射操作,但是,对象和序列化方法的对应关系,还是在运行时通过反射的方式建立来写入sync.Map的,这里有两个比较低效的操作,map的写入和反射建立类型与序列化方法对应关系

    33020

    Go语言——反射

    Go语言中使用反射可以在编译时不知道类型的情况下更新变量,在运行时查看值、调用方法以及直接对他们的布局进行操作。...Elem 方法能够对指针进行“解引用”,然后将结果存储到反射 Value 类型对象 v 中: func main() { var x float64 = 3.4 p :=...v := p.Elem() // 获取指针&x指向的变量x,等同于*(&x),但是在反射中不可以那么写,有一个专门的方法Elem()获取指针指向的变量 v.SetFloat(7.1) fmt.Println...下面的例子将会对各种方式的空指针进行 IsNil() 和 IsValid() 的返回值判定检测。 同时对结构体成员及方法查找 map 键值对的返回值进行 IsValid() 判定,参考下面的代码。...struct 的字段进行注入,参数为指向底层类型为结构体的指针。

    1.5K30

    深入理解Golang的reflect原理

    b 的内存结构如下:图片在上图中,b 的类型实际上是 eface,它是一个空接口,在src/runtime/runtime2.go 中,它的定义如下:type eface struct { _type...:", v.Elem().CanSet()) // true}可设置要求:反射对象是一个指针这个指针指向的是一个可设置的变量原因:如果这个值只是一个普通的变量,这个值实际上被拷贝了一份。...能调用 Elem 方法的反射对象,必须是数组、chan、map、指针、切片中的一种,其他类型的 reflect.Type 调用 Elem 方法会 panic。...// Type 是 Go 类型的表示。//// 并非所有方法都适用于所有类型。// 在调用 kind 具体方法之前,先使用 Kind 方法找出类型的种类。...type Type interface { // Align 返回该类型在内存中分配时,以字节数为单位的字节数 Align() int // FieldAlign 返回该类型在结构中作为字段使用时

    74971

    Go通关16:运行时反射,深度解析!

    ,所以需要调用 Elem 方法找到这个指针指向的值,这样才能修改 要修改一个变量的值,关键点:传递指针(可寻址),通过 Elem 方法获取指向的值,才可以保证值可以被修改,reflect.Value 为我们提供了...Age int } 步骤总结: 传递一个 struct 结构体的指针,获取对应的 reflect.Value; 通过 Elem 方法获取指针指向的值; 通过 Field 方法获取要修改的字段; 通过...如果要修改 struct 结构体字段值的话,该字段需要是可导出的,而不是私有的,也就是该字段的首字母为大写。 记得使用 Elem 方法获得指针指向的值,这样才能调用 Set 系列方法进行修改。...Struct Tag struct tag 是一个添加在 struct 字段上的标记,使用它进行辅助。要想获得字段上的 tag,就要先反射获得对应的字段,可以通过 Field 方法做到。...Go 语言的作者在博客上总结了反射的三大定律: ❝ 任何接口值 interface{} 都可以反射出反射对象,也就是 reflect.Value 和 reflect.Type,通过函数 reflect.ValueOf

    40930

    Golang反射-上篇

    1、反射的定义 It’s a great source of confusion ~ (引用自官方博客) 反射是指在运行时动态的访问和修改任意类型对象的结构和成员,在go语言中提供reflect...更新变量 运行时查看值 调用方法 对他们的布局进行操作 使用反射的两个经典场景 你编写的这个函数,还不知道传给你的类型具体是什么,可能是还没约定好,也可能是传入的类型很多 希望通过用户的输入来决定调用哪个函数...(根据字符串调用方法),动态执行函数 2、反射的基础数据类型 3、Type reflect.Type是一个接口类型,用于获取变量类型相关的信息,可通过reflect.TypeOf函数获取某个变量的类型信息...reflect.Value提供了Elem()方法,可以获得指针向指向的value package main import ( "reflect" "fmt" ) func main() {...()函数把Value转为interface{},再从interface{}强制类型转换,转为原始数据类型 //或者在Value上直接调用Int()、String()等一步到位 fmt.Printf("origin

    84910

    Go 反射机制详解及实例 【Go语言圣经笔记】

    其实map的key的类型并不局限于formatAtom能完美处理的类型;数组、结构体和接口都可以作为map的key。) 指针:Elem方法返回指针指向的变量,依然是reflect.Value类型。...然后是在Value上调用Interface()方法,也就是返回一个interface{},里面包含指向变量的指针。3....Value.Elem()可以对接口或者指针调用。如果对接口调用,返回接口包含的值;如果对指针调用,则返回指针指向的值。如果对非接口也非指针的类型调用,则会产生panic。...每次Method(i)方法调用都返回一个reflect.Value以表示对应的值(§6.4),也就是一个方法绑定的的接收者。...在每个有风险的操作前进行额外的类型检查。

    1.3K20

    Go 面向对象编程篇(八):空接口、反射和泛型

    ) 执行这段代码,打印结果是: dog type: animal.Dog 如果你想要获取 dog 值的结构体信息,并且动态调用其成员方法,使用反射的话需要先获取对应的 reflect.Value 类型值...: // 返回的是 dog 指针对应的 reflect.Value 类型值 dogValue := reflect.ValueOf(&dog).Elem() 当然,Dog 类中不包含指针方法的话...我们可以通过反射获取变量的所有未知结构信息,以结构体为例(基本类型只有类型和值,更加简单),包括其属性、成员方法的名称和类型,值和可见性,还可以动态修改属性值以及调用成员方法。...不过这种灵活是有代价的,因为所有这些解析工作都是在运行时而非编译期间进行,所以势必对程序性能带来负面影响,而且可以看到,反射代码的可读性和可维护性比起正常调用差很多,最后,反射代码出错不能在构建时被捕获...四、空结构体 另外,有的时候你可能会看到空的结构体类型定义: struct{} 表示没有任何属性和成员方法的空结构体,该类型的实例值只有一个,那就是 struct{}{},这个值在 Go 程序中永远只会存一份

    96310

    学习使用Go的反射

    使用反射时要注意的一件事:反射包中的所有内容都假定你知道自己在做什么,并且如果使用不正确,许多函数和方法调用都会引起 panic。...例如,如果你在 reflect.Type上调用与当前类型不同的类型关联的方法,您的代码将会 panic。...如果变量是结构体,则可以使用反射来获取结构体中的字段数,并从每个字段上获取 reflect.StructField结构体。...这将返回一个指针值,然后可以像上面那样使用 Elem().Set()对其进行修改。 最后,你可以通过调用 Interface()方法从 reflect.Value回到普通变量值。...由于Go没有泛型,因此变量的原始类型会丢失;该方法返回类型为 interface{}的值。如果创建了一个指针以便可以修改该值,则需要使用 Elem().Interface()解引用反射的指针。

    1.1K10

    Golang反射-下篇

    1、判断类型interface.Type 2、自定义struct的反射 3、结构体标签和反射 4、反射调用函数 5、反射调用方法 6、反射创建值 6.1 反射创建struct 6.2 反射创建slice...最后通过Name和Type获取方法的类型和值 注意点 用于对未知类型进行遍历探测其Field,抽象成一个函数 go语言里面struct成员变量小写,在反射的时候直接panic() 结构体方法名小写是不会...panic的,反射值也不会被查看到 指针方法是不能被反射查看到的 package main import ( "fmt" "reflect" ) type Person struct { Name...()在定义的时候它是指针的方法 bmiMethod := valueUser.MethodByName("BMI") //MethodByName()通过Name返回类的成员变量 resultValue...(float32) fmt.Printf("bmi=%.2f\n", result) //Think()在定义的时候用的不是指针,valueUser可以用指针也可以不用指针 thinkMethod :

    90940

    上篇:Go的反射基础

    什么是反射反射的机制是在运行时可以获取到其变量的类型和值,且可以在运行时对其变量类型和值进行检查,可以对其值进行修改。...这种机制,其实在编写业务代码时是比较少用到的,那么在框架中,使用的反射的机制是比较常见,如web框架、Orm框架,实现通用性的目的。...,再调用它的Kind()方法可以将返回的结果用来进行类型的判断package mainimport ("fmt""reflect")func main() {fmt.Println("公众号搜索:不背锅运维...通过Elem()方法获取变量的指针所指向的对象注意,先传入变量的地址给ValueOf方法,然后调用Elem()方法获取该变量的指针所指向的对象package mainimport ("fmt""reflect...")func main() {fmt.Println("公众号搜索:不背锅运维")a := 100.89// ValueOf传入的是地址,调用Elem()方法可以获取变量的指针指向的对象PaValue

    18400

    经过99次失败后, 我总结了几点 Golang 反射的经验(附源码)

    ) 指向指针的指针对象 如果需要通过 *main.Person 的 反射指针对象 p 需要获取真实对象类型 main.Person ,可以使用 p.Elem() 方法。...结构体方法调用 https://github.com/tangx-labs/golang-reflect-demo/blob/master/method_call_test.go#L31 调用结构体的方法...使用 mv.Call(...In) 调用方法。 需要额外注意的是: 方法的 接收者 是有 指针 (s *student) 和 结构体 (s student) 之分的。...在反射对象中 指针接收者 的方法是不能被 结构体接收者 调用。..., 可以是 **指针对象** 也可以是 **结构体对象** // 如果是指针对象的方法, **结构体对象** 是不能调用起方法的 rv := reflect.ValueOf(stu) prv :=

    44920

    (四十五)golang--反射

    反射基本介绍: (1)反射可以在运行时动态获取变量的各种信息,比如变量的类型、类别; (2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段、方法); (3)通过反射,可以修改变量的值,可以调用关联的方法...; (5)通过反射来修改变量,注意当使用SetXxx方法来设置需要通过对指针类型来完成,这样才能改变传入变量的值,同时需要使用到reflect.Value.Elem()方法;即rVal.Elem().SetInt...(20) 具体实践; 使用反射来遍历结构体的字段,并调用结构体的方法,并获取结构体标签的值。...has %d methods\n", numOfMethod) //获取第二个方法,函数的顺序是按首字母的ACSII进行排序的,所以这里第二个方法是Print rval.Elem()....,必须传入的是地址,并且在反射中使用.Elem().SetXxx() ?

    34520

    Goalng下的反射模块reflect学习使用

    ,即pointer-interface 通过反射可以"动态" 调用方法 常用的类型、函数和方法 1//返回动态类型i的类型,如果i是一个空结构体类型,TypeOf将返回nil 2func TypeOf.../返回反射结构体的Value的类型.如果v为零值,IsValid将返回false 104func (v Value) Kind() Kind 105//判断value是否为有效值,通常用在判断某个字段是否在反射体的...如果是指针类型的话,我们需要使用reflect.Struct字段进行判断接口类型的Kind()方法 1if k := t.Kind();k !...使用反射的相关知识进行方法的动态调用 1$ cat method-reflect.go 2package main 3import ( 4 "fmt" 5 "reflect"..."),reflect.ValueOf(5256)} 31 fmt.Println("通过反射动态调用方法:") 32 //使用Value的Call(in []Value)方法进行方法的动态调用

    83430

    golang中的反射

    在得到p变量的地址值类型之后先调用Elem()返回地址指针指向的值的Value封装。然后通过Set方法进行修改赋值。...因此在反射中使用反射包提供refelct.TypeOf和refelct.ValueOf方法获得接口对象的类型,值和方法等。...10 这里: 调用 reflect.ValueOf 函数获取变量指针; 调用 reflect.Value.Elem 方法获取指针指向的变量; 调用 reflect.Value.SetInt 方法更新变量的值...: 由于 Go 语言的函数调用都是值传递的,所以我们只能先获取指针对应的 reflect.Value,再通过 reflect.Value.Elem 方法迂回的方式得到可以被设置的变量,我们通过如下所示的代码理解这个过程...请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知类型的分类。调用该分类不支持的方法会导致运行时的panic。

    1.2K30

    大量实例详解Go反射机制原理与应用

    这些能让开发者攫取到编程元素深层信息或者进行深度操作的接口就叫反射,在Go和Java都有提供,运用好反射功能可以开发出功能强大的程序,但是反射由于涉及到编译原理,因此比较抽象,在此我们用丰富的例子来说清楚...,在GO中,任何变量定义后会根据其类型初始化为0,所以结构体的每个字段初始化成了相应类型的nil,由于string对应的”nil”是空字符串,因此打印时没有输出任何内容。...同时我们还能看到,reflect.Value对象也支持Field接口,它得到各个字段对应的reflect.Value对象,然后通过Kind接口返回信息来判断字段的基础类型,根据基础类型调用不同方法来获得对应数据...*int,指针对应的值就是变量在内存中的地址,通过Elem调用获得了指针指向元素的类型和数值,要注意如果元素的类型存在“过渡”属性,那么调用Elem就会导致panic,接下来我们看看切片的解析: import...返回的是指针类型对象对应的reflect.Value,由于它具有“过渡”属性,因此我们可以调用Elem获得指针指向对象的reflect.Value对象,然后调用相应的Set接口来设置对象的数值,如果对象类型是

    45120

    Golang的反射reflect深入理解和示例

    如果要修改 struct 结构体字段值的话,该字段需要是可导出的,而不是私有的,也就是该字段的首字母为大写。记得使用 Elem 方法获得指针指向的值,这样才能调用 Set 系列方法进行修改。...reflect.Value.Elem() 表示获取原始值对应的反射对象,只有原始对象才能修改,当前反射对象是不能修改的也就是说如果要修改反射类型对象,其值必须是“addressable”【对应的要传入的是指针...,同时要通过Elem方法获取原始值对应的反射对象】struct 或者 struct 的嵌套都是一样的判断处理方式通过reflect.ValueOf来进行方法的调用这算是一个高级用法了,前面我们只说到对类型...但是在工程应用中,另外一个常用并且属于高级的用法,就是通过reflect来进行方法【函数】的调用。...settable,即 pointer-interface通过反射可以“动态”调用方法因为Golang本身不支持模板,因此在以往需要使用模板的场景下往往就需要使用反射(reflect)来实现参考The

    55622

    《快学 Go 语言》第 14 课 —— 反射

    在接口小节我们提到接口类型包含两个指针,一个指向类型,一个指向值,上面两个方法的作用就是将接口变量进行解剖分离出类型和值。 ?...图片 Value 这个结构体虽然很简单,但是附着在 Value 上的方法非常之多,主要是用来方便用户读写 ptr 字段指向的数据内存。...Value // 将接口变量装成数组,一个是类型指针,一个是数据指针 func (v Value) InterfaceData() [2]uintptr // 根据名称获取结构体的方法进行调用...reflect.ValueOf(&s) // 要拿出指针指向的元素进行修改 v.Elem().SetInt(43) fmt.Println(s) } ------- 43 可以看到变量...s 的值确实被修改成功了,不过这个例子修改的是指针指向的值而不是修改指针变量本身,如果不使用 Elem() 方法进行修改也会抛出一样的异常。

    42430

    Go 译文之如何使用反射

    举个例子,你在 int 类型上调用 struct 结构体类型上才用的方法,你的代码就会产生 panic。我们时刻要记住,什么类型有有什么方法可以使用,从而避免产生 panic。...如果一个变量是指针、映射、切片、管道、或者数组类型,那么这个变量的类型就可以调用方法 varType.Elem()。...如果想更新值,记住要通过指针,而且在设置时,要先取消引用,通过 refPtrVal.Elem().Set(newRefVal) 更新其中的值,传递给 Set 的参数也必须要是 reflect.Value...如果想创建一个新的变量,可以通过 reflect.New(varType) 实现,传递的参数是 reflect.Type 类型,该方法将会返回一个指针,如前面介绍的那样,你可以通过使用 Elem().Set...虽然运行时可以通过反射创建新的函数,但无法用反射创建新的方法,这也就意味着你不能在运行时用反射实现一个接口,用反射创建的结构体使用起来很支离破碎。

    44730
    领券