Pointers
Prerequisites: Structs
A pointer holds the memory address of a value. Pointers let a function change a variable that belongs to its caller, and avoid copying large structs.
Syntax
x := 5
p := &x // & takes the address: p has type *int
fmt.Println(*p) // * dereferences: reads the value at the address
*p = 10 // writes through the pointer — x is now 10
q := new(int) // allocates a zero int and returns its address
var r *int // a pointer's zero value is nil (points nowhere)
Example
package main
import "fmt"
type Player struct {
Name string
Score int
}
func double(n *int) {
*n *= 2
}
func addPoints(p *Player, points int) {
p.Score += points // same as (*p).Score
}
func main() {
x := 5
p := &x
fmt.Println(*p)
*p = 10
fmt.Println(x)
double(&x)
fmt.Println(x)
counter := new(int)
*counter++
fmt.Println(*counter)
var missing *int
fmt.Println(missing == nil)
player := Player{Name: "Ada", Score: 10}
addPoints(&player, 5)
fmt.Println(player.Score)
hero := &Player{Name: "Hero"} // pointer to a new struct
hero.Score = 99
fmt.Printf("%+v\n", *hero)
}
Expected output
5
10
20
1
true
15
{Name:Hero Score:99}
Things that make Go pointers simpler than C pointers:
- No pointer arithmetic — you can't do
p + 1to move to the next address, which removes a whole class of memory bugs. - Automatic dereferencing for struct fields —
p.Scoreworks on a*Playerwithout writing(*p).Score. - Garbage collected — it's safe to return a pointer to a local variable from a function; Go keeps the value alive as long as something points to it.
Printing a pointer itself (fmt.Println(p)) shows an address such
as 0xc000012345, which differs from run to run.
Common mistakes
- Dereferencing a
nilpointer. This compiles but crashes:panic: runtime error: invalid memory address or nil pointer dereference. Checkif p != nilwhen a pointer might be empty. - Mixing up the two uses of
*: in a type (*int) it means "pointer to"; in an expression (*p) it means "the value pointed to". - Using pointers everywhere "for speed". Small values such as
ints and small structs are cheap to copy; use a pointer when you need to share or modify.
Practice
Write swap(a, b *int) that exchanges the values of two int
variables. Call it on x := 1 and y := 2 and print them.
Show solution
package main
import "fmt"
func swap(a, b *int) {
*a, *b = *b, *a
}
func main() {
x, y := 1, 2
swap(&x, &y)
fmt.Println(x, y) // 2 1
}