将结构方法作为参数传递
Passing a struct method as an argument
我不确定我是否试图超出 Go 允许的限制,但这是上下文:
我有一个名为 Map
的类型,其中包含大量有用的成员函数,例如 Interpolate
、Add
和 Clear
。我还有一个结构类型 Layered
,它包含几个 Map
s.
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
的任何成员函数作为参数,然后在其包含的所有 Map
上调用它。大致如下:
func (l Layered) MapCall(callMe func(Map)) {
for _, m := range l.data {
callMe(m)
}
}
这部分有效,但仅适用于 Map
的不带附加参数的成员函数,例如 Clear
。是否完全可以接受 Map
的 any 成员函数作为参数(连同它的 ...interface{}
形式的潜在参数),然后调用Layered
中所有成员 Map
的函数及其正确的参数?像这样的东西,例如:
func (l Layered) MapCall(callMe func(Map, ...interface{}), params ...interface{}) {
for _, m := range l.data {
callMe(m, params...)
}
}
与尝试使用界面相比,您可能想要更多的功能。
我将使用您的 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
我不确定我是否试图超出 Go 允许的限制,但这是上下文:
我有一个名为 Map
的类型,其中包含大量有用的成员函数,例如 Interpolate
、Add
和 Clear
。我还有一个结构类型 Layered
,它包含几个 Map
s.
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
的任何成员函数作为参数,然后在其包含的所有 Map
上调用它。大致如下:
func (l Layered) MapCall(callMe func(Map)) {
for _, m := range l.data {
callMe(m)
}
}
这部分有效,但仅适用于 Map
的不带附加参数的成员函数,例如 Clear
。是否完全可以接受 Map
的 any 成员函数作为参数(连同它的 ...interface{}
形式的潜在参数),然后调用Layered
中所有成员 Map
的函数及其正确的参数?像这样的东西,例如:
func (l Layered) MapCall(callMe func(Map, ...interface{}), params ...interface{}) {
for _, m := range l.data {
callMe(m, params...)
}
}
与尝试使用界面相比,您可能想要更多的功能。
我将使用您的 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