Skip to content

Deeper in Functions

Variables of Type Function

Functions in Go are values. The function type is composed of the func keyword followed by the parameters and return values, creating the function signature. Functions with the same number and types of parameters and return values meet the function signature. The default zero value for a function variable is nil.

Using Func Type Variables

run command
$ go run src/function/value_func.go
TEST1 A PARAM:  CALLING funcSignature
RESULT:  10
TEST2 b PARAM:  CALLING AGAIN funcSignature
RESULT:  200
package main

import "fmt"

func test1(a string) int {
    fmt.Println("TEST1 A PARAM: ", a)
    return 10
}

func test2(b string) int {
    fmt.Println("TEST2 b PARAM: ", b)
    return 200
}

func main() {
    var funcSignature func(string) int
    funcSignature = test1

    result := funcSignature("CALLING funcSignature")
    fmt.Println("RESULT: ", result)

    funcSignature = test2
    result = funcSignature("CALLING AGAIN funcSignature")
    fmt.Println("RESULT: ", result)
}

Function Type Declarations

The type keyword can be used to define a function type, just like is used to create a struct. Any function that meets the defined function signature type can be considered as a variable of that type.

Creating a Function Type
package main

func main() {
    type FuncType func(int, int) int
    var mapFunc = map[string]FuncType{}
}

Anonymous Functions

Go supports anonymous functions, which can be assigned to variables or passed as arguments to other functions. Inner functions are anonymous, they don't have a name.

You can call an anonymous function immediately after the creation. This is common in two situations: defer statements and creating goroutines.

Creating and Calling Two Anonymous Functions

run command
$ go run src/function/anonymous.go
Result1:  6
Result1:  7
Result1:  8
Result2:  20
package main

import "fmt"

func main() {
    add := func(a, b int) int {
        return a + b
    }

    result1 := add(2, 4)
    fmt.Println("Result1: ", result1)
    result1 = add(3, 4)
    fmt.Println("Result1: ", result1)
    result1 = add(4, 4)
    fmt.Println("Result1: ", result1)

    result2 := func(a, b int) int {
        return a + b
    }(10, 10)
    fmt.Println("Result2: ", result2)
}

Closures

Closures are functions declared inside function. This is a computer science term that means that closures can access and modify variables declared in the outer function. They can capture and use variables from their surrounding scope.

Shadow Variable

Using := instead of = inside the closure creates a new variable inside the function scope.

Closures allow to limit of a function's scope. When a function is called from only one other function, an inner function can be used, reducing declarations at the package level. Repeated code logic within a function can be encapsulated into a closure.

Closures Example

run command
$ go run src/function/closures.go
Inner Function -> closure1:  10
closure1 ENDING:  30

Inner Function -> closure2:  10
Inner Function SHADOW DATA -> closure2:  30
closure2 ENDING:  10
package main

import "fmt"

func closure1() {
    data := 10
    func() {
        fmt.Println("Inner Function -> closure1: ", data)
        data = 30
    }()
    fmt.Println("closure1 ENDING: ", data)
}

func closure2() {
    data := 10
    func() {
        fmt.Println("Inner Function -> closure2: ", data)
        data := 30
        fmt.Println("Inner Function SHADOW DATA -> closure2: ", data)
    }()
    fmt.Println("closure2 ENDING: ", data)
}

func main() {
    closure1()
    fmt.Println()
    closure2()
}