英文:
How to change method implementation in run-time using reflection?
问题
我有这个类型的实现:
type A struct{
name string
}
func (a A) getName() string {
return "My name is " + a.name
}
我如何使用反射更改该类型的getName()方法的实现?
例如,我想使用以下实现代替当前实现:
func newGetName() string {
return "test reflection"
}
英文:
I have this type implementation:
type A struct{
name string
}
func (a A) getName() string {
return "My name is " + a.name
}
How I can change implementation of method getName() for this type using reflection?
For example, I want use next implementation instead of current:
func newGetName() string {
return "test reflection"
}
答案1
得分: 11
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 " + foo.name
}
现在你可以调用A.getName()
,结果是"my name is hans"
。你可以正常使用方法表达式和许多其他特性,但是getName
是一个结构体成员,而不是A
的方法,所以请记住这一点。当你想要给getName
赋予新的含义时,将其赋值为其他内容:
foo.getName = func() string {
return "test reflection"
}
另一个特别适用的想法是,如果你事先知道getName
可能有哪些实现,可以向A
添加一个新的成员,表示getName
当前的实现,然后根据这个变量进行切换。
英文:
Go is a compiled language. As such, it's not possible to modify the implementation of things at runtime. What you can do is changing the place function pointers point to:
var getName func(string) = func(name string) {
return "my name is " + name
}
In order to make this work with a structure, you have to resort to a few tricks. First add getName
as a member to A
:
type A struct {
name string
getName func() string
}
Then we enclose a pointer to the structure as an implicit (i.e. closed over) parameter:
foo := &A{name: "Hans"}
foo.getName = func() string {
return "my name is " + name
}
Now you can call A.getName()
and the result is "my name is hans"
. You can use method expressions and many other features just fine, but getName
is a structure member and not a method of A
, so keep this in mind. When you want to give a new meaning to getName
, assign something different to it:
foo.getName = func() string {
return "test reflection"
}
Another idea that is especially applicable if you know in advance what implementations getName
could have is to add a new member to A
that says what implementation getName
currently has and then switch over this variable.
答案2
得分: 7
请注意,Go语言的惯用方式是不这样做,而是使用接口代替:
参考这个例子:
package main
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
英文:
Note the idiomatic Go is to not do that and use interface instead:
See this example:
package main
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())
}
Output:
My name is nameA
NEW: My name is nameA
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论