首页 > 解决方案 > 将结构方法作为参数传递

问题描述

我不确定我是否试图超出 Go 允许的限制,但这里是上下文:我Map使用大量有用的成员函数调用类型,例如Interpolate,AddClear. 我还有一个 struct 类型,Layered它包含几个Maps。

type Map [][]float64

func (m Map) Interpolate(min, max float64) { ... }
func (m Map) Add(val float64) { ... }
func (m Map) Clear() { ... }

type Layered struct {
    data []Map
}

我想添加一个成员函数,Layered它接受任何成员函数Map作为参数,然后在其包含的所有Maps 上调用它。类似于以下内容:

func (l Layered) MapCall(callMe func(Map)) {
    for _, m := range l.data {
        callMe(m)
    }
}

这部分有效,但仅适用于不带额外参数的成员函数Map,例如Clear. 是否有可能接受任何成员函数Map作为参数(以及其形式的潜在参数...interface{}),然后Map在 a 中的所有成员上调用具有正确参数的函数Layered?像这样的东西,例如:

func (l Layered) MapCall(callMe func(Map, ...interface{}), params ...interface{}) {
    for _, m := range l.data {
        callMe(m, params...)
    }
}

标签: goreflection

解决方案


您可能希望比尝试使用接口更具功能性。

Interpolate我将使用您的方法提供一个示例。

您可以首先定义一个用于生成操作的辅助函数:

func InterpolateOp(min, max float64) func(Map) {
    return func(m Map) {
        m.Interpolate(min, max)
    }
}

另一个更适合您的MapCall功能的名称是MapInterpolate.

然后,在使用MapCall或创建操作列表时,您可以使用之前使用的相同类型,即func(Map)

var l Layered
...
l.MapCall(InterpolateOp(2, 4))

该解决方案的关键在于将数据绑定到组成函数的闭包上,从而解决了最初的问题:没有足够的数据来调用相应的函数。

在您的情况下,如果有很多方法不值得这样做,那么您可能会考虑代码生成,因为它是重复且容易的。这超出了这个问题的范围。

另见:https ://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions


推荐阅读