Functions

beginner go functions

A function is a named block of code that takes some inputs, does work, and gives back a result. Nothing new there.

But Go functions have a few twists that show up in almost every interview. Let’s go through them.

The basics

We declare a function with func, list the parameters with their types, and put the return type after the parentheses.

// takes two ints, returns an int
func add(a int, b int) int {
	return a + b
}

// if params share a type, we can write it once
func multiply(a, b int) int {
	return a * b
}

Multiple return values (the idiomatic part)

Here’s the first thing that surprises people coming from other languages: a Go function can return more than one value. This is everywhere in Go.

func divmod(a, b int) (int, int) {
	return a / b, a % b // return both quotient and remainder
}

func main() {
	q, r := divmod(17, 5) // q = 3, r = 2
	fmt.Println(q, r)
}

The most famous use of this is returning a result and an error together. This is the Go pattern — we’ll see it constantly.

import "strconv"

func main() {
	// strconv.Atoi returns (the number, an error)
	value, err := strconv.Atoi("42")
	if err != nil {
		// something went wrong, handle it
		fmt.Println("bad input")
		return
	}
	fmt.Println(value) // 42
}

Think of value, err := as Go’s polite way of saying “here’s your answer, and here’s whether it worked.” We’ll cover error handling deeply later — for now just know this shape.

Named return values

We can give the return values names. When we do, a bare return automatically sends back whatever those named variables currently hold.

// x and y are pre-declared and start at their zero values
func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return // "naked" return — sends back x and y automatically
}

This is handy for short functions, but don’t overuse it — in long functions it makes the code harder to follow.

Variadic parameters

A variadic function accepts any number of arguments of the same type. We mark it with ... before the type.

In simple language, ...int means “zero or more ints, please.”

func sum(nums ...int) int {
	total := 0
	for _, n := range nums { // nums behaves like a slice here
		total += n
	}
	return total
}

func main() {
	fmt.Println(sum(1, 2, 3))    // 6
	fmt.Println(sum())           // 0 — zero args is fine
	nums := []int{4, 5, 6}
	fmt.Println(sum(nums...))    // spread a slice with ...
}

fmt.Println itself is variadic — that’s why we can pass it any number of things.

Functions as first-class values

In Go, functions are just values. We can store them in variables, pass them as arguments, and return them from other functions. This is what “first-class” means.

func apply(nums []int, op func(int) int) []int {
	result := make([]int, len(nums))
	for i, n := range nums {
		result[i] = op(n) // call the passed-in function
	}
	return result
}

func main() {
	double := func(x int) int { return x * 2 } // function stored in a variable
	fmt.Println(apply([]int{1, 2, 3}, double))  // [2 4 6]
}

Closures

A closure is a function that “remembers” variables from the scope where it was created — even after that scope has finished running.

Think of it like a backpack: the inner function carries around the variables it needs.

func counter() func() int {
	count := 0          // this lives on inside the returned function
	return func() int {
		count++         // each call remembers and updates count
		return count
	}
}

func main() {
	next := counter()
	fmt.Println(next()) // 1
	fmt.Println(next()) // 2
	fmt.Println(next()) // 3 — count persists between calls
}

Each call to counter() makes a fresh, independent count. Closures are great for generators, callbacks, and keeping a little private state.

Interview soundbite

Go functions can return multiple values, which powers the idiomatic value, err := error pattern. They support named returns, variadic parameters with ..., and they’re first-class — we can pass them around as values. Closures take this further: an inner function captures and remembers variables from its surrounding scope, like carrying them in a backpack.