猿问

如何使用 reflect 和 interface{} 在 Golang 中实现带有参数的方法的

我正在将一些代码从C++移植到golang。我对golang中的OOP和多态性做了一些研究,都建议使用接口和嵌入来实现多态性。我有一个示例代码,如下所示


type Worker interface {

    Show()

    Inc()

}


type WorkerA struct {

    x int

    Worker // embed all methods in interface

}


type WorkerB struct {

    WorkerA // embed WorkerA to have all methods

}


func (a *WorkerA) Inc() {

    a.x++

}


func (a WorkerA) Show() {

    fmt.Println("A:", a.x)

}


func (b WorkerB) Show() {

    fmt.Println("B:", b.x)

}


func main() {

    list := make([]Worker, 10)

    for n:=0; n<len(list); n++ {

        if n%2==0 {

            list[n] = &WorkerA{}

        } else {

            list[n] = &WorkerB{WorkerA{}}

        }

    }

    list[0].Inc()

    list[1].Inc()

    list[1].Inc()

    list[2].Inc()

    list[2].Inc()

    list[2].Inc()

    list[0].Show()

    list[1].Show()

    list[2].Show()

在接口数组的帮助下,我可以在两个 Worker 之间调用相应的方法和 'WorkerBAddx'''ShowWorkerA. Now I would like to add a third method call which add the


func (a *WorkerA) Add(b WorkerA) {

    a.x += b.x

}

我发现调用以下内容会导致错误之前是持有接口而不是结构list


list[0].Add(list[2])

我在网上查找一些想法,看看可能有助于解决问题,这是我写的reflect


func callMethodParam(p interface{}, q interface{}) {

    o := reflect.ValueOf(p)

    m := reflect.ValueOf(q)

    args:=[]reflect.Value{reflect.ValueOf(m)}

    o.MethodByName("Add").Call(args)

}


callMethodParam(list[0], list[2])

但这似乎也行不通。任何想法如何使它工作?谢谢。


慕姐8265434
浏览 77回答 1
1回答

慕的地8271018

你问题的标题听起来像是一个XY问题,但幸运的是,我们知道X,是吗?此外,代码无法像示例中显示的那样工作,因为代码被声明为 切片并且没有方法。list[0].Add(list[2])listWorkerWorkerAdd但让我们假装它确实如此。鉴于 的实现需要访问 一个 字段,您可以更改签名以接受提供 的接口,并实现该接口:Add(b WorkerA)WorkerAxxWorkerAtype XProvider interface {&nbsp; &nbsp; X() int}func (a *WorkerA) X() int {&nbsp; &nbsp; return a.x}func (a *WorkerA) Add(b XProvider) {&nbsp; &nbsp; a.x += b.X()}然后在调用之前,使用类型断言来确保(其中包含的类型)的特定实例也实现:a.AddWorkerXProviderif xp, ok := list[2].(XProvider); ok {&nbsp; &nbsp; list[0].Add(xp)}这是一个更新的游乐场
随时随地看视频慕课网APP

相关分类

Go
我要回答