Function pointer vs interface for callback?

1,701 views
Skip to first unread message

sh...@tigera.io

unread,
Oct 12, 2016, 8:28:32 AM10/12/16
to golang-nuts
Hi,

I've been writing some code where I have nodes in a processing graph that need to notify other nodes when something changes.  I'm using callbacks (rather than channels, say) because I want everything to be synchronous.  It seems like I've got a choice between

type Foo struct {
    Callback func(baz Biff) Boff
}

and

type callback interface {
    func(baz Biff) Boff
}

type Foo struct {
    Callback callback
}

to represent the callback reference.  Is there a convention (or a good argument) for when I should pick one or the other?  Seems like a function pointer is more universal (I don't even need an object to be a receiver) but maybe an interface is more idiomatic?

Thanks,

-Shaun


Ian Lance Taylor

unread,
Oct 12, 2016, 9:07:31 AM10/12/16
to sh...@tigera.io, golang-nuts
There are no hard and fast rules, but I think the func value is more
idiomatic. And if there aren't any other fields in Foo, I would write
it as

type Foo func(baz Biff) Boff

That said people do use interface values as well, as in go/parser.Visitor.

Ian

Jesse McNelis

unread,
Oct 12, 2016, 9:11:45 AM10/12/16
to sh...@tigera.io, golang-nuts
On Wed, Oct 12, 2016 at 11:05 PM, <sh...@tigera.io> wrote:
> Seems like a function
> pointer is more universal (I don't even need an object to be a receiver) but
> maybe an interface is more idiomatic?

An interesting pattern from the http pkg is that a function type can
also implement an interface.
https://golang.org/pkg/net/http/#HandlerFunc

Shaun Crampton

unread,
Oct 12, 2016, 2:33:47 PM10/12/16
to Jesse McNelis, golang-nuts
Thanks for the tips.

Chris Hines

unread,
Oct 13, 2016, 11:11:27 AM10/13/16
to golang-nuts, jes...@jessta.id.au
If you want to dig into this topic more. I gave a presentation on this topic at my local Go meetup earlier this year.


Some of the code examples will not run on the public go-talks app. The source material is at https://github.com/ChrisHines/talks/tree/master/non-orthogonal-choices-in-go.

If you just want my conclusion:

Informed choices for dynamic behavior:

Use interface values when:
  • Well known interfaces already exist, e.g. io.Reader
  • More than one behavior required
  • Typically stateful
  • Implementations non-trivial
Use function values when:
  • Only one behavior
  • Typically stateless
  • In-line implementations typical
Based on these guidelines and the outline of your code you've provided, I agree with Ian that a function value is the best fit for your case.

Chris
Reply all
Reply to author
Forward
0 new messages