|
| 1 | +# About |
| 2 | + |
| 3 | +In Go, functions are first-class values. This means that you can do with functions the same things you can do with all other values - assign functions to variables, pass them as arguments to other functions or even return functions from other functions. |
| 4 | + |
| 5 | +Below we are creating two functions, `engGreeting` and `espGreeting` and we are assigning them to the variable `greeting`: |
| 6 | + |
| 7 | +```go |
| 8 | +import "fmt" |
| 9 | + |
| 10 | +func engGreeting(name string) string { |
| 11 | + return fmt.Sprintf("Hello %s, nice to meet you!", name) |
| 12 | +} |
| 13 | + |
| 14 | +func espGreeting(name string) string { |
| 15 | + return fmt.Sprintf("¡Hola %s, mucho gusto!", name) |
| 16 | +} |
| 17 | + |
| 18 | +greeting := engGreeting // greeting is a variable of type func(string) string |
| 19 | +fmt.Println(greeting("Alice")) // Hello Alice, nice to meet you! |
| 20 | + |
| 21 | +greeting = espGreeting |
| 22 | +fmt.Println(greeting("Alice")) // ¡Hola Alice, mucho gusto! |
| 23 | +``` |
| 24 | + |
| 25 | +Function values provide an opportunity to parametrize functions not only with data but with behavior too. |
| 26 | +In the following example, we are passing behaviour to the `dialog` function via the `greetingFunc` parameter: |
| 27 | + |
| 28 | +```go |
| 29 | +func dialog(name string, greetingFunc func(string) string) { |
| 30 | + fmt.Println(greetingFunc(name)) |
| 31 | + fmt.Println("I'm a dialog bot.") |
| 32 | +} |
| 33 | + |
| 34 | +func espGreeting(name string) string { |
| 35 | + return fmt.Sprintf("¡Hola %s, mucho gusto!", name) |
| 36 | +} |
| 37 | + |
| 38 | +greeting := engGreeting |
| 39 | +dialog("Alice", greeting) |
| 40 | +// Output: |
| 41 | +// ¡Hola Alice, mucho gusto! |
| 42 | +// I'm a dialog bot. |
| 43 | +``` |
| 44 | + |
| 45 | +The value of an uninitialized variable of function type is `nil`. |
| 46 | +Therefore, calling a `nil` function value causes a panic. |
| 47 | + |
| 48 | +```go |
| 49 | +var dutchGreeting func(string) string |
| 50 | +dutchGreeting("Alice") // panic: call of nil function |
| 51 | +``` |
| 52 | + |
| 53 | +Function values can be compared with `nil`. This can be useful to avoid unnecessary program panics. |
| 54 | + |
| 55 | +```go |
| 56 | +var dutchGreeting func(string) string |
| 57 | +if dutchGreeting != nil { |
| 58 | + dutchGreeting("Alice") // safe to call dutchGreeting |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +## Function types |
| 63 | + |
| 64 | +Using function values is possible thanks to the function types in Go. A function type denotes the set of all functions with the same sequence of parameter types and the same sequence of result types. User-defined types can be declared on top of function types. For instance, the `dialog` function from the previous examples can be updated as following: |
| 65 | + |
| 66 | +```go |
| 67 | +type greetingFunc func(string) string |
| 68 | + |
| 69 | +func dialog(name string, f greetingFunc) { |
| 70 | + fmt.Println(f(name)) |
| 71 | + fmt.Println("I'm a dialog bot.") |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +## Anonymous functions |
| 76 | + |
| 77 | +Another powerful tool that is available thanks to first-class functions support is anonymous functions. Anonymous functions are defined at their point of use, without a name following the `func` keyword. Such functions have access to the variables of the enclosing function. |
| 78 | + |
| 79 | +For example: |
| 80 | + |
| 81 | +```go |
| 82 | +func fib() func() int { |
| 83 | + var n1, n2 int |
| 84 | + |
| 85 | + return func() int { |
| 86 | + if n1 == 0 && n2 == 0 { |
| 87 | + n1 = 1 |
| 88 | + } else { |
| 89 | + n1, n2 = n2, n1 + n2 |
| 90 | + } |
| 91 | + return n2 |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +next := fib() |
| 96 | +for i := 0; i < N; i++ { |
| 97 | + fmt.Printf("F%d\t= %4d\n", i, next()) |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +A call to `fib` initializes the variables `n1` and `n2` and returns an anonymous function that, in turn, changes the values of these variables each time the function is called. Nth calls of the anonymous function return the Nth number of the Fibonacci sequence starting from 0. The anonymous inner function has access to the local variables (`n1` and `n2`) of the enclosing function `fib`. This is a great way to have function values keep state between calls. We say that the anonymous function is a closure of the variables `n1` and `n2`. [Closures][closure] are widely used in programming and you might see other languages supporting them. |
| 102 | + |
| 103 | +[closure]: https://en.wikipedia.org/wiki/Closure_(computer_programming) |
0 commit comments