【问题标题】:Syntax for Map with Callback to functions which have a receiver带有回调函数的 Map 的语法,该函数具有接收器
【发布时间】:2019-05-08 12:36:46
【问题描述】:

是否可以在 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)){
}

任何帮助表示赞赏!

【问题讨论】:

标签: dictionary go


【解决方案1】:

使用方法值

您可以为此目的使用Method values。方法值是具有隐式接收器的函数值。引用Spec: Method values:

如果表达式x具有静态类型T,并且MT类型的方法集中,则x.M称为方法值。

所以方法值的语法是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)

另外,由于receiver不会被保存,所以调用这些函数时必须提供。

查看这个工作示例(这是对第一个示例的修改):

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

查看类似问题:

golang - pass method to function

golang function alias on method receiver

【讨论】:

  • 太棒了!感谢您的全面回答!方法表达式完成了这项工作
【解决方案2】:

类似于方法值,这也可以通过闭包范围来实现

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

【讨论】:

    猜你喜欢
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多