To export a function it should start with a capital letter, see Go exported name.

Each function has its signature that describes its type and consists of:

Multiple return values

Function can return multiple values, e.g.:

func nextInt(b []byte, i int) (int, int) {
    for ; i < len(b) && !isDigit(b[i]); i++ {
    }
    x := 0
    for ; i < len(b) && isDigit(b[i]); i++ {
        x = x*10 + int(b[i]) - '0'
    }
    return x, i
}

Named return parameters

Go’s return values may be named. These names should be used to document the meaning of the return values.

func nextInt(b []byte, pos int) (value, nextPos int) {

They are treated as variables defined at the top of the function.

Parentheses are required.

Named returned values are initialized with their zero values.

In case you need to name some of the returned values, use _ for the rest to remain nameless.

Naked/blank return

A return statement without arguments returns the named return values. This is known as a “naked” return. But it’s recommended that it should be used only in short functions because they harm readability in longer functions.

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

Omit the type

When two or more consecutive named function parameters share a type, you can omit the type from all but the last. So x int, y int can be shortened to x, y int:

func add(x, y int) int {
	return x + y
}

Variadic input parameters

func addTo(base int, vals ...int) []int {
    ...
}
 
addTo(3, 2, 4, 6, 8)

The vals will be a slice of int values.

When calling with a slice, ... should be specified after the variable/slice literal:

addTo(3, a...)
addTo(3, []int{1, 2, 3, 4, 5}...)

First-class citizens

Functions can be passed around as arguments or return values.

package main
 
import (
	"fmt"
	"math"
)
 
func compute(fn func(float64, float64) float64) float64 {
	return fn(3, 4)
}
 
func main() {
	hypot := func(x, y float64) float64 {
		return math.Sqrt(x*x + y*y)
	}
	fmt.Println(hypot(5, 12))
 
	fmt.Println(compute(hypot))
	fmt.Println(compute(math.Pow))
}

Function type declaration

Can be defined with type keyword:

type opFuncType func(int,int) int
var opMap = map[string]opFuncType {
    ...
}

Function closures

A closure is a function value that references variables from outside its body.

For example, the adder function returns a closure. Each closure is bound to its own sum variable.

package main
 
import "fmt"
 
func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}
 
func main() {
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ {
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	}
}

Methods

Nested/anonymous functions

Useful when we want to reduce the scope of the function.

To do that, function need to be assigned to a variable.

func main() {
    i := 42
 
    fn := func() {
      fmt.Println(i)
    }
 
    fn()
    i = 12
    fn()
}

Ignore returned values

To ignore some of the returned values, use _:

result, remainder = div_and_remainder(4,2)
result, _ = div_and_remainder(5,2)

References