簡體   English   中英

如何使用反射調用帶有指針接收器的結構上的方法?

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

我正在使用 Go 中的反射,並且在嘗試在具有指針接收器的結構上調用方法時遇到一些問題。 我有以下 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())
}


以上內容可在https://play.golang.org/p/V04m3LJlRia

如果我將方法更改為使用值接收器,則該方法有效,但我無法獲取Greeting屬性。 如果使用指針接收器(如代碼中所示),則找不到該方法,但我可以訪問該屬性。

我怎樣才能做到這兩點?

感謝@Volker,這現在可以工作了。 稍作修改的代碼是:

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())
}

可以看出s不再設置為指針,可以調用方法。

因為我希望能夠調用s上的屬性,所以我使用.Elem()將其設為指針,然后我可以使用FieldByName

在這里更新https://play.golang.org/p/iiUrB961tUa

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM