一尘不染

将方法参数传递给函数

go

我很好奇Go中是否有可能。我有多种方法的类型。是否可以有一个函数,该函数需要一个方法参数,然后将其称为类型?

这是我想要的一个小例子:

package main

import (
    "fmt"
)

type Foo int

func (f Foo) A() {
    fmt.Println("A")
}
func (f Foo) B() {
    fmt.Println("B")
}
func (f Foo) C() {
    fmt.Println("C")
}

func main() {
    var f Foo
    bar := func(foo func()) {
        f.foo()
    }
    bar(A)
    bar(B)
    bar(C)
}

Go认为type Foo有一个称为的方法foo(),而不是用传入的方法名称替换它。


阅读 259

收藏
2020-07-02

共1个答案

一尘不染

是的,有可能。您有2(3)个选项:

规范:方法表达式

该表达式Foo.A产生的功能A与第一个参数等效,但具有一个显式接收器。它有签名func(f Foo)

var f Foo
bar := func(m func(f Foo)) {
    m(f)
}
bar(Foo.A)
bar(Foo.B)
bar(Foo.C)

在这里,方法接收器是显式的。您只需将方法名称(具有它所属的类型)传递给bar(),并且在调用它时,您必须传递实际的接收者:m(f)

预期的输出(在Go Playground上尝试):

A
B
C

规格:方法值

如果f是type的值Foo,则表达式会f.A产生func()具有隐式接收者值的type的函数值f

var f Foo
bar := func(m func()) {
    m()
}
bar(f.A)
bar(f.B)
bar(f.C)

请注意,这里的方法接收器是隐含的,它被保存与传递给函数的值bar(),所以它被称为没有明确指定它:m()

输出是相同的(在Go Playground上尝试)。

(出于完整性考虑:反射

不如以前的解决方案(在性能和“安全性”上都不错),但是您可以将方法的名称作为string值传递,然后使用该reflect包使用该名称来调用方法。它可能看起来像这样:

var f Foo
bar := func(name string) {
    reflect.ValueOf(f).MethodByName(name).Call(nil)
}
bar("A")
bar("B")
bar("C")

Go Playground上尝试一下。

2020-07-02