简体   繁体   English

如何使用反射调用带有指针接收器的结构上的方法?

[英]How do you call a method on a struct with a pointer receiver using reflection?

I am working with reflection in Go and have some issues trying to call a method on a struct that has a pointer receiver.我正在使用 Go 中的反射,并且在尝试在具有指针接收器的结构上调用方法时遇到一些问题。 I have the following go code:我有以下 go 代码:

package main

import (
    "fmt"
    "reflect"
)

type Base struct {
    Name     string
    Greeting string
}

func (b *Base) SetGreeting() {
    b.Greeting = fmt.Sprintf("Hello %s\n", b.Name)
}

func main() {
    var pointer interface{}

    // create a new instance of base
    mybase := Base{
        Name: "reflect",
    }

    // create a pointer to the base
    pointer = &mybase

    s := reflect.ValueOf(pointer).Elem()

    // get the value of s which should be a pointer
    vv := reflect.ValueOf(s)
    switch vv.Kind() {
    case reflect.Struct:
        fmt.Println("struct")
    case reflect.Ptr:
        fmt.Println("pointer")
    }

    // output struct property
    fmt.Println(s.FieldByName("Name").String())

    // call the method using reflect
    sayHelloFunc := s.MethodByName("SetGreeting")

    if sayHelloFunc.IsValid() {
        sayHelloFunc.Call([]reflect.Value{})
    } else {
        fmt.Println("Unable to find method")
    }

    fmt.Println(s.FieldByName("Greeting").String())
}


The above is available at https://play.golang.org/p/V04m3LJlRia以上内容可在https://play.golang.org/p/V04m3LJlRia

If I change the method to use a value receiver then the method works, but I am not able to get the Greeting property.如果我将方法更改为使用值接收器,则该方法有效,但我无法获取Greeting属性。 If use the pointer receiver (as in the code) the method cannot be found but I can access the property.如果使用指针接收器(如代码中所示),则找不到该方法,但我可以访问该属性。

How can I do both?我怎样才能做到这两点?

Thanks to @Volker this is now working.感谢@Volker,这现在可以工作了。 The slightly modified code is:稍作修改的代码是:

package main

import (
    "fmt"
    "reflect"
)

type Base struct {
    Name     string
    Greeting string
}

func (b *Base) SetGreeting() {
    b.Greeting = fmt.Sprintf("Hello %s\n", b.Name)
}

func main() {
    var pointer interface{}

    // create a new instance of base
    mybase := Base{
        Name: "reflect",
    }

    // create a pointer to the base
    pointer = &mybase

    s := reflect.ValueOf(pointer)

    // get the value of s which should be a pointer
    vv := reflect.ValueOf(s)
    switch vv.Kind() {
    case reflect.Struct:
        fmt.Println("struct")
    case reflect.Ptr:
        fmt.Println("pointer")
    }

    // output struct property
    fmt.Println(s.Elem().FieldByName("Name").String())

    // call the method using reflect
    sayHelloFunc := s.MethodByName("SetGreeting")

    if sayHelloFunc.IsValid() {
        sayHelloFunc.Call([]reflect.Value{})
    } else {
        fmt.Println("Unable to find method")
    }

    fmt.Println(s.Elem().FieldByName("Greeting").String())
}

As can be seen s is no longer set as a pointer and the method can be called.可以看出s不再设置为指针,可以调用方法。

As I wanted to be able to call the properties on s I then make it a pointer using .Elem() and then I can use FieldByName .因为我希望能够调用s上的属性,所以我使用.Elem()将其设为指针,然后我可以使用FieldByName

Updated here https://play.golang.org/p/iiUrB961tUa在这里更新https://play.golang.org/p/iiUrB961tUa

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM