Written by

on August 7, 2015

A cool golang interface trick

While working on juju, I noticed a curious code snippet:

var ( stepPrepare = executorStep{"preparing", Operation.Prepare} stepExecute = executorStep{"executing", Operation.Execute} stepCommit = executorStep{"committing", Operation.Commit} )

where Operation is an interface:

type Operation interface { Prepare(state State) (*State, error) Execute(state State) (*State, error) Commit(state State) (*State, error) }

Surely, storing a method of an interface definition as a variable makes no sense. But then again, what is the type of an interface method? Let’s check:

package main import "fmt" type A interface { Run(param string) string } func main() { fmt.Printf("%T", A.Run) }

The output is

func(main.A, string) string Program exited.

We can see that the method is actually a function taking the receiver as its first parameter. Can we use it as a first class citizen? Let’s see:

package main import "fmt" type A interface { RunA(param string) string RunB(param string) string } type impl struct {} func (impl) RunA(param string) string { return "ran A: " + param } func (impl) RunB(param string) string { return "ran B: " + param } func execute(on A, runner func(A, string)string) string { return runner(on, "hey!") } func main() { fmt.Println(execute(impl{}, A.RunA)) fmt.Println(execute(impl{}, A.RunB)) }

And the output we get:

ran A: hey! ran B: hey! Program exited.

Neat! So we can actually specify which method to run on an interface implementation without bulky switches and constants!