Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass method argument to function

Tags:

methods

go

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?

Here is a small example of what I would want:

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 thinks type Foo has a method called foo(), rather than replacing it with the passed in method name.

like image 754
dangeroushobo Avatar asked Aug 11 '16 13:08

dangeroushobo


People also ask

Can we pass a function as an argument to a function?

We cannot pass the function as an argument to another function. But we can pass the reference of a function as a parameter by using a function pointer.

How do you pass an argument to a function in Python?

Information can be passed into functions as arguments. Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just separate them with a comma.

How do you pass a method as an argument in Java?

We can't directly pass the whole method as an argument to another method. Instead, we can call the method from the argument of another method. // pass method2 as argument to method1 public void method1(method2()); Here, the returned value from method2() is assigned as an argument to method1() .


1 Answers

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 foo Foo bar := func(m func(f Foo)) {     m(foo) } 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.

like image 51
icza Avatar answered Oct 22 '22 23:10

icza