252

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?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Saad
  • 26,316
  • 15
  • 48
  • 69
  • 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 .. –  Sep 29 '12 at 18:50
  • 2
    (Six years later...) Java does now have a way to pass methods (e.g. `containingObject::instanceMethodName`): https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html – vazor Dec 06 '18 at 17:10

8 Answers8

334

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)

dskinner
  • 10,527
  • 3
  • 34
  • 43
  • 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. – Satyajit Das Jan 24 '19 at 13:45
  • 1
    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: https://play.golang.org/p/52ahWAI2xsG – dskinner Apr 02 '19 at 06:13
  • Mind blowing example of closures in golang! It covers almost all cases. Include one more function that returns a function and you are done. – mchar Feb 07 '21 at 19:39
  • 1
    I just note that `type` is not mandatory, you can declare the func parameter type directly: `func quote123(fn func(int)string) string`. – Ferran Maylinch Oct 18 '21 at 10:14
  • Hate this! Very confusing, too much of brain pressure reading this :D – Alok Kumar Singh Dec 19 '21 at 08:54
62

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

SeattleOrBayArea
  • 2,808
  • 6
  • 26
  • 38
  • 2
    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! – James O'Toole Oct 31 '16 at 05:16
  • This should have been the answer IMO. – Mr H Dec 13 '21 at 23:45
  • 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. – Alok Kumar Singh Dec 19 '21 at 08:54
  • Don´t forget that you can also specify the return value (if required): `type fn func(int) string` and then: `myString := f(val)` – Edenshaw Feb 24 '23 at 14:03
27

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)

}
robus gauli
  • 381
  • 4
  • 2
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))
    }
foamdino
  • 360
  • 2
  • 5
6

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")
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Tushar Ghige
  • 121
  • 1
  • 5
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
    }})
}
dan
  • 1,198
  • 8
  • 25
CodeAdocate
  • 149
  • 1
  • 4
1

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

Amin Shojaei
  • 5,451
  • 2
  • 38
  • 46
-3

Yes Go does accept first-class functions.

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

AbdulFattah Popoola
  • 949
  • 2
  • 13
  • 22
  • 4
    Please expand on this response some; include an example, link to reference (e.g. actual reference), etc. –  Sep 29 '12 at 18:58
  • 3
    actually there is 0 information on that page, only link to stupid example by source code. – OZ_ Feb 20 '15 at 11:10