Basic

Functions

Define reusable blocks of code that return values.

What you will see

Hello, Ada Hello, Alan

About 2 min of reading

Try It

Go functions take inputs and send a result back. Arguments are copied in, so changes inside never leak to the caller. You will write a small calculation, return more than one value, and name your returns for clarity.

1

I define a function that takes two ints and returns one. Calling add(3, 4) runs the body, and I print the returned total to confirm the value came back.

package main import "fmt" func add(a, b int) int { return a + b } func main() { result := add(3, 4) fmt.Println(result) }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
7
Parameters are passed by value, so the copies inside add cannot change the callers' variables.
2

I return a value and an error together. On success the error is nil, so I print both pieces and see the result with a nil error.

package main import ( "errors" "fmt" ) func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("divide by zero") } return a / b, nil } func main() { result, err := divide(10, 2) fmt.Println(result, err) }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
5
Go has no exceptions; the error is a value. Always check err before trusting the result that comes back with it.
3

I pass a string in and send a new string back. Calling greet with a name builds the text, and I print the whole greeting.

package main import "fmt" func greet(name string) string { return "Hello, " + name } func main() { fmt.Println(greet("Ada")) }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Hello, Ada
Functions declared here return copies of their inputs, so mutating a parameter leaves the caller untouched.
4

I name the return values so the function can return with no arguments. split(47) fills ten and one, and I print both from main.

package main import "fmt" func split(num int) (ten, one int) { ten = num / 10 one = num % 10 return } func main() { t, o := split(47) fmt.Println(t, o) }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
4 7
Named return values are self-documenting but rarely used with real logic; keep the style for simple, well-understood functions.
5

I call the same function twice to confirm the pattern scales. Two different names produce two different greetings, printed one after the other.

package main import "fmt" func greet(name string) string { return "Hello, " + name } func main() { a := greet("Ada") b := greet("Alan") fmt.Println(a) fmt.Println(b) }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Hello, Ada Hello, Alan
Because arguments are copies, calling greet again does not remember earlier calls. Each call is independent.

Data Flow

Arguments flow into a function; a return value flows back to the caller.
1 Caller passes arguments to the function
↓
2 Parameters receive copies of the values
↓
3 The body computes and returns a value
↓
4 The caller receives the return and continues
Why this works
Parameters and results

Functions declare their inputs and outputs:

func greet(name string) string {
    return "Hello, " + name
}

Parameters flow in one way; results flow back. Go is call-by-value: functions receive copies, so mutating a parameter does not change the caller's variable.

Error handling pattern

The (value, error) idiom is everywhere in Go:

result, err := doThing()
if err != nil {
    fmt.Println("failed:", err)
    return
}
// use result

Functions return nil for the error when they succeed. Callers decide what to do with it instead of catching exceptions.

Examples

A simple function

Defining functions

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

result := add(3, 4)   // 7

func add(a int, b int) int takes two ints and returns one. Parameters without type changes share the type: a int, b int can be a, b int.

Why it works: the return statement sends a value back to the caller and ends the function.

Multiple return values

Returning more than one thing

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("divide by zero")
    }
    return a / b, nil
}

result, err := divide(10, 2)

Go functions can return multiple values. The common pattern is (value, error): check err before trusting the result.

Why it works: errors are explicit values, not exceptions that skip the stack.

Named return values

Self-documenting returns

func split(num int) (ten, one int) {
    ten = num / 10
    one = num % 10
    return  // returns named values
}

Naming the return values lets you return with no arguments. It is a nice self-documenting trick for functions with several outputs.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Loops and Iteration
Previous Lesson
Loops and Iteration
Next Lesson
Slices and Arrays
Slices and Arrays →