Skip to main content
Go supports pointers, allowing you to pass references to values and records within your program. Understanding the difference between passing by value and passing by reference is crucial for writing efficient Go code.

Pass by value vs pass by reference

Let’s compare two functions to understand how pointers work:
package main

import "fmt"

// zeroval has an int parameter, so arguments will be passed by value.
// zeroval will get a copy of ival distinct from the one in the calling function.
func zeroval(ival int) {
    ival = 0
}

// zeroptr has an *int parameter, meaning it takes an int pointer.
// The *iptr code dereferences the pointer from its memory address
// to the current value at that address.
func zeroptr(iptr *int) {
    *iptr = 0
}

func main() {
    i := 1
    fmt.Println("initial:", i)

    zeroval(i)
    fmt.Println("zeroval:", i)

    // The &i syntax gives the memory address of i, i.e. a pointer to i.
    zeroptr(&i)
    fmt.Println("zeroptr:", i)

    // Pointers can be printed too.
    fmt.Println("pointer:", &i)
}
Output:
initial: 1
zeroval: 1
zeroptr: 0
pointer: 0xc0000140b8

Key concepts

When you pass a variable to a function normally, Go creates a copy of that value. Changes made inside the function don’t affect the original variable.
func zeroval(ival int) {
    ival = 0  // Only changes the copy
}
When you pass a pointer, you’re passing the memory address of the variable. Changes made through the pointer affect the original variable.
func zeroptr(iptr *int) {
    *iptr = 0  // Changes the original value
}
  • & - Address-of operator: &i gives you a pointer to i
  • * - Dereference operator: *ptr accesses the value at the pointer
  • *int - Type declaration: a pointer to an int

Common use cases

Avoiding copies

Pass large structs by pointer to avoid copying all the data

Modifying values

Allow functions to modify their arguments

Sharing state

Multiple parts of your program can reference the same data

Nil values

Pointers can be nil, representing “no value”
Go is a garbage collected language. You can safely return a pointer to a local variable — it will only be cleaned up when there are no active references to it.

Best practices

  • Use pointers for large structs to avoid copying overhead
  • Use pointers when you need to modify the argument
  • Pass by value for simple types like int, bool, small structs
  • Be careful with nil pointers — dereferencing a nil pointer causes a panic

Structs

Learn about Go’s struct types

Methods

Methods with pointer receivers

Build docs developers (and LLMs) love