What is the difference between value types and reference-like types in Go?

5 minintermediategovalue-typespointersfundamentals

Quick Answer

Structs and arrays are value types: assigning one variable to another, or passing one to a function, copies the entire value. Slices, maps, channels, and functions are reference-like: their variable is a small header (or pointer) referencing shared underlying data, so copying the header doesn't copy the underlying data. This means func modify(s []int) can mutate the caller's underlying array through indices, but func modify(arr [5]int) only ever modifies its own local copy. Pointers (*T) let you opt any value type into reference-like behavior explicitly, which is exactly why Go methods often take a pointer receiver when they need to mutate the receiver.

Detailed Answer

Getting this distinction wrong is the single most common source of "why didn't my change show up" bugs in Go.

Value types copy on assignment

type Point struct{ X, Y int }

p1 := Point{1, 2}
p2 := p1        // full copy
p2.X = 99
fmt.Println(p1.X) // still 1 — p1 was never touched
func modify(arr [3]int) {
    arr[0] = 99   // modifies the local copy only
}
a := [3]int{1, 2, 3}
modify(a)
fmt.Println(a)   // [1 2 3] — unchanged

Reference-like types share underlying data

func modify(s []int) {
    s[0] = 99   // writes through to the shared backing array
}
sl := []int{1, 2, 3}
modify(sl)
fmt.Println(sl)  // [99 2 3] — changed

Table of behavior

TypeCopy behavior on assignment/pass
struct, arrayFull copy of all fields/elements
slice, map, channelHeader/reference copied; underlying data shared
pointerAddress copied; both variables point to the same value
function valueReference to the function; safe to copy and pass around

Opting a struct into reference-like behavior

func modify(p *Point) {
    p.X = 99   // dereferences and writes through the pointer
}
pt := Point{1, 2}
modify(&pt)
fmt.Println(pt.X)  // 99

This is exactly why a method meant to mutate its receiver needs a pointer receiver — a value receiver method only ever sees a copy.

Related Resources