Return function pointer

2,336 views
Skip to first unread message

Erik Aigner

unread,
Oct 29, 2012, 7:31:57 PM10/29/12
to golan...@googlegroups.com
I want to return a function pointer from a method.

Example:

func (o *SomeStruct) dispatchCommand(cmd int) func() {
  // return a method of SomeStruct based on the input
  // I tried &o.SomeMethod, or o.SomeMethod - none of it worked
}

func (o *SomeStruct) someOtherMethod() {
  f := o.dispatchCommand(7)
  f()
}

How would I go about this in Go?
Is this possible?

Miki Tebeka

unread,
Oct 29, 2012, 7:39:31 PM10/29/12
to golan...@googlegroups.com
You can't currently (AFAIK), see here for previous discussion.
The best way is to create a closure and return it.

Erik Aigner

unread,
Oct 29, 2012, 7:41:49 PM10/29/12
to golan...@googlegroups.com
Thanks!

Jesse McNelis

unread,
Oct 29, 2012, 7:46:17 PM10/29/12
to Erik Aigner, golan...@googlegroups.com
On Tue, Oct 30, 2012 at 10:31 AM, Erik Aigner <aigne...@gmail.com> wrote:
> I want to return a function pointer from a method.
>
> Example:
>
> func (o *SomeStruct) dispatchCommand(cmd int) func() {
> // return a method of SomeStruct based on the input
> // I tried &o.SomeMethod, or o.SomeMethod - none of it worked
> }

You can do method expressions. eg.
f := SomeStruct.SomeMethod
http://golang.org/ref/spec#Method_expressions

But that just gives you the method as a function that takes the
receiver as it's first parameter.
If you want to wrap up the receiver along with the function you'll
need to make a closure.




--
=====================
http://jessta.id.au

tomwilde

unread,
Oct 30, 2012, 5:12:35 AM10/30/12
to golan...@googlegroups.com

Erik Aigner

unread,
Nov 5, 2012, 9:54:42 AM11/5/12
to golan...@googlegroups.com, gofa...@gmail.com
that assignment doesn't seem to work

     f = d.SayHello

it says "method ... is not an expression, must be called"

On Tuesday, October 30, 2012 2:20:55 AM UTC+1, gofa...@gmail.com wrote:
Would something like this work for you?

package main

import (
    "fmt"
)

type Dispatcher struct {
    SayHello func()
    SayGoodbye func()
}

func (d *Dispatcher) DispatchCommand(i int) func() {
    var f func()
    switch i {
        case 1:
            f = d.SayHello
        case 2:
            f = d.SayGoodbye
    }
    return f
}

func main() {
     d := Dispatcher{ SayHello: func() { fmt.Println("hello!") }, SayGoodbye: func() { fmt.Println("goodbye!") }}
     d.DispatchCommand(1)()
     d.DispatchCommand(2)()
}


Output:

hello!
goodbye!

Jan Mercl

unread,
Nov 5, 2012, 10:32:09 AM11/5/12
to Erik Aigner, golang-nuts, gofa...@gmail.com
On Mon, Nov 5, 2012 at 3:54 PM, Erik Aigner <aigne...@gmail.com> wrote:
> that assignment doesn't seem to work
>
> f = d.SayHello
>
> it says "method ... is not an expression, must be called"

It works here: http://play.golang.org/p/8zj3MYUH8C

-j

minux

unread,
Nov 5, 2012, 1:19:29 PM11/5/12
to Erik Aigner, golan...@googlegroups.com, gofa...@gmail.com
On Mon, Nov 5, 2012 at 10:54 PM, Erik Aigner <aigne...@gmail.com> wrote:
that assignment doesn't seem to work

     f = d.SayHello

it says "method ... is not an expression, must be called"

Francesc Campoy Flores

unread,
Nov 5, 2012, 1:36:04 PM11/5/12
to gofa...@gmail.com, golan...@googlegroups.com
You don't need reflection for this: 


Cheers,
Francesc

On Mon, Nov 5, 2012 at 10:12 AM, <gofa...@gmail.com> wrote:
from the compiler error you're reporting, it looks like you might have been doing / wanted to do something like this:

/*
  Code doesn't compile.
  Compiler is complaining about the statements
    return d.SayHello
    return d.SayGoodbye
  in method dispatchCommand
 
  method d.SayHello is not an expression, must be called
  method d.SayGoodbye is not an expression, must be called
*/

package main

import (
    "fmt"
)

type Dispatcher struct {
    SomeField int
}

func (d *Dispatcher) SayHello() {
    fmt.Println("hello!")
}

func (d *Dispatcher) SayGoodbye() {
    fmt.Println("goodbye!")
}

func (d *Dispatcher) dispatchCommand(cmd int) func() {
    switch cmd {
        case 1:
            return d.SayHello
        case 2:
            return d.SayGoodbye
    }

}

func (d *Dispatcher) someOtherMethod() {
    f := d.dispatchCommand(d.SomeField)
    f()
}


func main() {
    d1 := &Dispatcher{1}
    d1.someOtherMethod()

    d2 := &Dispatcher{2}
    d2.someOtherMethod()   
   
}

if you really want to go that route, you could use reflection.
see my example in:
http://play.golang.org/p/rd-iiSyuBW

as you can see, the reflection approach adds complexity to your code,
so it's not something i would recommend using unless i really have to.

evan chua-yap
--
 
 



--
--
Francesc

Reply all
Reply to author
Forward
0 new messages