如何使用反射在运行时更改方法实现?

问题描述 投票:3回答:2

我有这种类型的实现:

type A struct{
  name string
}

func (a A) getName() string {
  return "My name is " + a.name 
}

如何使用反射更改此类型的方法getName()的实现?例如,我想使用下一个实现而不是当前:

func newGetName() string {
  return "test reflection"
} 
reflection go
2个回答
5
投票

Go是一种编译语言。因此,无法在运行时修改事物的实现。你可以做的是改变位置函数指针指向:

var getName func(string) = func(name string) {
    return "my name is " + name
}

为了使这个结构工作,你必须采取一些技巧。首先将getName添加为A的成员:

type A struct {
    name string
    getName func() string
}

然后我们将一个指向结构的指针作为隐式(即封闭)参数包含在内:

foo := &A{name: "Hans"}
foo.getName = func() string {
    return "my name is " + name
}

现在你可以打电话给A.getName(),结果是"my name is hans"。你可以使用方法表达式和许多其他功能,但getName是一个结构成员,而不是A的方法,所以请记住这一点。当你想给getName赋予一个新的含义时,给它分配一些不同的东西:

foo.getName = func() string {
    return "test reflection"
}

如果你事先知道getName可能具有什么实现,那么另一个特别适用的想法是向A添加一个新成员,该成员说明getName当前具有什么实现,然后切换这个变量。


5
投票

请注意,惯用Go不是这样做而是使用interface代替:

this example

包主

import "fmt"

type Aer interface {
    getName() string
}

type A struct {
    name string
}

func (a A) getName() string {
    return "My name is " + a.name
}

type testA struct {
    a A
}

func (ta testA) getName() string {
    return "NEW: My name is " + ta.a.name
}
func main() {
    a := A{name: "nameA"}
    fmt.Println(a.getName())
    ta := testA{a: a}
    fmt.Println(ta.getName())
}

输出:

My name is nameA
NEW: My name is nameA
© www.soinside.com 2019 - 2024. All rights reserved.