Pass method argument to function

后端 未结 2 1952
礼貌的吻别
礼貌的吻别 2020-11-29 05:52

I\'m curious if this is possible in Go. I have a type with multiple methods. Is it possible to have a function which takes a method argument and then call it for the type?

相关标签:
2条回答
  • 2020-11-29 06:37

    Yes, it's possible. You have 2 (3) options:

    Spec: Method expressions

    The expression Foo.A yields a function equivalent to A but with an explicit receiver as its first argument; it has signature func(f Foo).

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

    Here the method receiver is explicit. You only pass the method name (with the type it belongs to) to bar(), and when calling it, you have to pass the actual receiver: m(f).

    Output as expected (try it on the Go Playground):

    A
    B
    C
    

    Spec: Method values

    If f is a value of type Foo, the expression f.A yields a function value of type func() with implicit receiver value f.

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

    Note that here the method receiver is implicit, it is saved with the function value passed to bar(), and so it is called without explicitly specifying it: m().

    Output is the same (try it on the Go Playground).

    (For completeness: reflection)

    Inferior to previous solutions (both in performance and in "safeness"), but you could pass the name of the method as a string value, and then use the reflect package to call the method by that name. It could look like this:

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

    Try this on the Go Playground.

    0 讨论(0)
  • 2020-11-29 06:44

    You could also use the “method values” option listed by @icza with different receivers.

    package main
    
    import "fmt"
    
    type Foo int
    type Goo int
    
    func (f Foo) A() { fmt.Println("A") }
    func (f Foo) B() { fmt.Println("B") }
    func (g Goo) A() { fmt.Println("A") }
    
    func main() {
        //Method values with receiver f
        var f Foo
        bar2 := func(m func()) { m() }
        bar2(f.A) //A
        bar2(f.B) //B
        //Method values with receivers f and g
        var g Goo
        bar2(f.A) //A
        bar2(g.A) //A
    }
    
    0 讨论(0)
提交回复
热议问题