Go Functions
Functions in Go bundle reusable logic behind a name, and Go's support for multiple return values makes them especially good at reporting both a result and an error.
Declaring a function
A function declaration starts with the func keyword, followed by a name, a parenthesized parameter list, an optional return type, and a body in braces. Each parameter must state its type, though consecutive parameters that share a type can list the type once at the end of the group.
A simple function with parameters
package main
import "fmt"
func greet(name string, times int) {
for i := 0; i < times; i++ {
fmt.Println("Hello,", name)
}
}
func main() {
greet("Maria", 2)
}Returning a value
To send a result back to the caller, a function declares a return type after its parameter list and uses the return keyword in its body. The returned value's type must match the declared return type exactly, since Go performs no implicit conversion between numeric types.
Function with a return value
package main
import "fmt"
func square(n int) int {
return n * n
}
func main() {
result := square(6)
fmt.Println("Result:", result)
}Multiple return values
Go functions can return more than one value, which is written as a comma-separated list of types in parentheses. This feature is used throughout the standard library to return a result alongside an error, avoiding the need for exceptions or out-parameters.
Multiple return values for a result and an error
package main
import (
"errors"
"fmt"
)
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("cannot divide by zero")
}
return a / b, nil
}
func main() {
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Result:", result)
}Named return values
Return values can be given names in the function signature, which pre-declares them as variables initialized to their zero value. A bare return statement then sends back whatever those named variables currently hold. Named returns can make short functions more self-documenting, but in longer functions they are best avoided since the values can be easy to lose track of.
- Parameters are always passed by value in Go — the function receives a copy, so reassigning a parameter inside the function does not affect the caller's variable.
- Slices, maps, and pointers still copy the value itself, but that value contains a reference to the same underlying data, so mutating their contents is visible to the caller.
- A function with no return type simply omits it after the parameter list.
- Variadic parameters, written as ...T, let a function accept a variable number of trailing arguments of type T.
Exercise: Go Functions
Can a Go function return more than one value?