是否可以在golang中创建一个包含具有接收器功能的地图?
我想完成以下
功能回调:
func (my *mystruct) doSometing(int parameter1){
// do something
}
func (my *mystruct) doAnotherThing(int parameter1){
// do something
}
包含指向函数的指针的地图
var lookupMap = map[string]func(int){
"action1" : doSomething,
"action2" : doAnotherThing
}
遗憾的是,这不起作用,因为回调函数绑定到接收器。 Go编译器说:
"undefined doSomething"
我的问题:
创建映射的语法是什么,其中值是绑定到特定接收器的函数?
像(伪代码):
var lookupMap = map[string]((*mystruct)func(int)){
}
任何帮助表示赞赏!
答案 0 :(得分:3)
您可以将Method values用于此目的。方法值是具有隐式接收器的函数值。引自Spec: Method values:
如果表达式
x
具有静态类型T
且M
位于类型T
的方法集中,则x.M
称为方法值。< / p>
因此,方法值的语法为x.M
,其中例如x
是类型的值,M
是方法的名称。这导致函数具有与没有接收器的方法相同的参数(和返回类型),因为接收器将与方法值一起保存并且是隐式的。
所以这意味着存储doSometing()
和doAnotherThing()
方法的方法值,函数类型只是func (int)
(没有接收者)。
这是一个有效的例子:
type mystruct struct {
name string
}
func (my *mystruct) doA(i int) {
fmt.Printf("[doA]: I'm %s, param is: %d\n", my.name, i)
}
func (my *mystruct) doB(i int) {
fmt.Printf("[doB]: I'm %s, param is: %d\n", my.name, i)
}
func main() {
my1 := &mystruct{"Bob"}
my2 := &mystruct{"Alice"}
lookupMap := map[string]func(int){
"action1": my1.doA,
"action2": my2.doB,
}
lookupMap["action1"](11)
lookupMap["action2"](22)
}
输出(在Go Playground上尝试):
[doA]: I'm Bob, param is: 11
[doB]: I'm Alice, param is: 22
如果您不希望接收器保存在字典中(在方法值中),您可以使用Method expressions。
不同之处在于,当您获得函数值时,不使用x.M
而是T.M
,这将导致函数值,函数类型具有相同的参数(并返回类型),但接收器类型也将在参数列表中,并在第一位。请参阅Spec: Method expressions的引用:
如果
M
位于T
类型的方法集中,T.M
是一个可调用为常规函数的函数,其参数与M
相同,前缀为附加参数,即方法的接收者。
因此,在您的情况下,要使用的函数类型将如下所示:func(*mystruct, int)
此外,由于不会保存接收器,因此在调用这些功能时必须提供它。
请参阅此工作示例(这是第一个示例的修改):
type mystruct struct {
name string
}
func (my *mystruct) doA(i int) {
fmt.Printf("[doA]: I'm %s, param is: %d\n", my.name, i)
}
func (my *mystruct) doB(i int) {
fmt.Printf("[doB]: I'm %s, param is: %d\n", my.name, i)
}
func main() {
lookupMap := map[string]func(*mystruct, int){
"action1": (*mystruct).doA,
"action2": (*mystruct).doB,
}
my1 := &mystruct{"Bob"}
my2 := &mystruct{"Alice"}
lookupMap["action1"](my1, 11)
lookupMap["action2"](my2, 22)
}
输出相同(在Go Playground上尝试):
[doA]: I'm Bob, param is: 11
[doB]: I'm Alice, param is: 22
见类似问题:
答案 1 :(得分:0)
类似于方法值,也可以使用闭包范围实现
package main
import (
"fmt"
)
type mystruct struct {
name string
}
func addCallbackToMap(lookupMap map[string]func(int), key string, my *mystruct) {
lookupMap[key] = func(i int) {
fmt.Printf("I'm %s, param is: %d\n", my.name, i)
}
}
func main() {
my1 := &mystruct{"Bob"}
my2 := &mystruct{"Alice"}
lookupMap := map[string]func(int){}
addCallbackToMap(lookupMap, "action1", my1)
addCallbackToMap(lookupMap, "action2", my2)
lookupMap["action1"](11)
lookupMap["action2"](22)
}
输出(在Go Playground上尝试):
I'm Bob, param is: 11
I'm Alice, param is: 22