Pointers

Go · Essentials · 10 min

Pointers decide whether a function sees a copy or the original, and they are central to methods.

A pointer holds the address of a value. &x takes the address of x, giving a *int if x is an int; *p reads or writes the value it points to. The zero value of a pointer is nil, and dereferencing nil panics.

Since Go passes everything by value, a function that must modify its argument takes a pointer:

func reset(n *int) { *n = 0 }
reset(&count)

For structs, Go saves you the explicit dereference: if p is a *User, p.Name means (*p).Name. &User{Name: "Ann"} creates a struct and returns its address in one step, and new(T) allocates a zero T and returns *T.

It is completely safe to return a pointer to a local variable — the compiler notices the value outlives the function and allocates it on the heap. There's no manual memory management; the garbage collector frees values when nothing points to them.

Go has no pointer arithmetic (outside the unsafe package), which removes a whole class of memory bugs.

When to use a pointer:

  • The callee must modify the value.
  • The struct is large and copying it on every call would be wasteful.
  • You need to represent "no value" with nil.

Slices, maps, channels and functions already refer to shared data, so you rarely need a pointer to them. For small structs that are not modified, passing by value is simpler and often just as fast.

Example

package main

import "fmt"

type Account struct {
	Owner   string
	Balance int
}

func deposit(a *Account, amount int) {
	a.Balance += amount // same as (*a).Balance
}

func newAccount(owner string) *Account {
	return &Account{Owner: owner} // safe: escapes to the heap
}

func main() {
	acc := newAccount("ann")
	deposit(acc, 50)
	fmt.Println(acc.Balance) // 50

	n := 10
	p := &n
	*p = 20
	fmt.Println(n) // 20
}

Remember

  • &x takes an address, *p follows it; zero value is nil
  • Pass a pointer when the callee must modify the value
  • Returning a pointer to a local is safe; the GC manages memory

Watch out for

  • Dereferencing a nil pointer (e.g. a field of a struct you never initialised).

Check yourself

  1. `func f(u User) { u.Name = "x" }` is called as `f(user)`. What happens to `user.Name`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: go.dev/tour/moretypes/1