272

In Java I can do something like

derp(new Runnable { public void run () { /* run this sometime later */ } }) 

and "run" the code in the method later. It's a pain to handle (anonymous inner class), but it can be done.

Does Go have something that can facilitate a function/callback being passed in as a parameter?

2
  • 8
    Nit/clarification for readers: In Java, "functions" are not passable (actually, all "functions" in Java are more aptly called Methods). Runnable (and anonymous inner classes that derive from that) are just that: a type from which objects are instantiated that subscribed to the required interface .. Commented Sep 29, 2012 at 18:50
  • 3
    (Six years later...) Java does now have a way to pass methods (e.g. containingObject::instanceMethodName): docs.oracle.com/javase/tutorial/java/javaOO/… Commented Dec 6, 2018 at 17:10

8 Answers 8

358

Yes, consider some of these examples:

package main import "fmt" // convert types take an int and return a string value. type convert func(int) string // value implements convert, returning x as string. func value(x int) string { return fmt.Sprintf("%v", x) } // quote123 passes 123 to convert func and returns quoted string. func quote123(fn convert) string { return fmt.Sprintf("%q", fn(123)) } func main() { var result string result = value(123) fmt.Println(result) // Output: 123 result = quote123(value) fmt.Println(result) // Output: "123" result = quote123(func(x int) string { return fmt.Sprintf("%b", x) }) fmt.Println(result) // Output: "1111011" foo := func(x int) string { return "foo" } result = quote123(foo) fmt.Println(result) // Output: "foo" _ = convert(foo) // confirm foo satisfies convert at runtime // fails due to argument type // _ = convert(func(x float64) string { return "" }) } 

Play: http://play.golang.org/p/XNMtrDUDS0

Tour: https://tour.golang.org/moretypes/25 (Function Closures)

Sign up to request clarification or add additional context in comments.

5 Comments

Is it possible to pass a parameter to a function which itself is also a parameter? In the above examples, the things getting printed were hard coded: Printing 123. Can any changes being made so that we can print something else rather than 123 ? Without declaring global variables.
If I understand your question correctly, I think you're looking for a func that returns a func, see here where I replace a hardcoded "quote123" function with a "quote" function that achieves the same result after you pass it some input: play.golang.org/p/52ahWAI2xsG
Mind blowing example of closures in golang! It covers almost all cases. Include one more function that returns a function and you are done.
I just note that type is not mandatory, you can declare the func parameter type directly: func quote123(fn func(int)string) string.
Hate this! Very confusing, too much of brain pressure reading this :D
69

You can pass function as parameter to a Go function. Here is an example of passing function as parameter to another Go function:

package main import "fmt" type fn func(int) func myfn1(i int) { fmt.Printf("\ni is %v", i) } func myfn2(i int) { fmt.Printf("\ni is %v", i) } func test(f fn, val int) { f(val) } func main() { test(myfn1, 123) test(myfn2, 321) } 

You can try this out at: https://play.golang.org/p/9mAOUWGp0k

4 Comments

Thank you! This was a really clear example of how to best use this idea! I have recreated it using an lookup table of structs that store info, including a pointer to the function you wish to execute. Perfect for this!
This should have been the answer IMO.
Perfect. Simple and clean to understand. Sometimes i feel decorator makes thing not necessarily complex. You decorate a function it returns the decorated function and then you call it with parameters. Sometimes complicates my brain.
Don´t forget that you can also specify the return value (if required): type fn func(int) string and then: myString := f(val)
28

Here is the sample "Map" implementation in Go. Hope this helps!!

func square(num int) int { return num * num } func mapper(f func(int) int, alist []int) []int { var a = make([]int, len(alist), len(alist)) for index, val := range alist { a[index] = f(val) } return a } func main() { alist := []int{4, 5, 6, 7} result := mapper(square, alist) fmt.Println(result) } 

Comments

14

This is the simplest way I can come with.

package main import "fmt" func main() { g := greeting getFunc(g) } func getFunc(f func()) { f() } func greeting() { fmt.Println("Hello") } 

Comments

7

Here is a simple example:

 package main import "fmt" func plusTwo() (func(v int) (int)) { return func(v int) (int) { return v+2 } } func plusX(x int) (func(v int) (int)) { return func(v int) (int) { return v+x } } func main() { p := plusTwo() fmt.Printf("3+2: %d\n", p(3)) px := plusX(3) fmt.Printf("3+3: %d\n", px(3)) } 

1 Comment

that's returning a function not passing a function
3

You can also pass the function of a struct, like:

 package main // define struct type Apple struct {} // return apple's color func (Apple) GetColor() string { return "Red" } func main () { // instantiate myApple := Apple{} // put the func in a variable theFunc := myApple.GetColor // execute the variable as a function color := theFunc() print(color) } 

output will be "Red", check on the playground

Comments

2

I hope the below example will provide more clarity.

package main type EmployeeManager struct{ category string city string calculateSalary func() int64 } func NewEmployeeManager() (*EmployeeManager,error){ return &EmployeeManager{ category : "MANAGEMENT", city : "NY", calculateSalary: func() int64 { var calculatedSalary int64 // some formula return calculatedSalary }, },nil } func (self *EmployeeManager) emWithSalaryCalculation(){ self.calculateSalary = func() int64 { var calculatedSalary int64 // some new formula return calculatedSalary } } func updateEmployeeInfo(em EmployeeManager){ // Some code } func processEmployee(){ updateEmployeeInfo(struct { category string city string calculateSalary func() int64 }{category: "", city: "", calculateSalary: func() int64 { var calculatedSalary int64 // some new formula return calculatedSalary }}) } 

Comments

-4

Yes Go does accept first-class functions.

See the article "First Class Functions in Go" for useful links.

3 Comments

Please expand on this response some; include an example, link to reference (e.g. actual reference), etc.
actually there is 0 information on that page, only link to stupid example by source code.
This is not useful info, it only adds noise to the answers above. It would be better if we can remove it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.