Как вы вызываете метод структуры с получателем указателя с помощью отражения? - PullRequest
0 голосов
/ 06 августа 2020

Я работаю с отражением в 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. Если использовать приемник указателя (как в коде), метод не может быть найден, но я могу получить доступ к свойству.

Как я могу сделать и то, и другое?

1 Ответ

0 голосов
/ 06 августа 2020

Благодаря @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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...