Intermediate · Pointers, interfaces and errors · topic 16 of 46 · 35 min
Pointers without fear
Explanation
What a pointer is
Every variable lives somewhere in memory, at an address. A pointer is a variable whose value is such an address. The type *int means "pointer to an int". Two operators do all the work: & (address of) and * (the value at).
x := 10
p := &x // p holds the address of x; its type is *int
fmt.Println(*p) // 10: read through the pointer
*p = 25 // change x through the pointer
fmt.Println(x) // 25
fmt.Println(p) // something like 0xc000012345 (an address)Why use pointers?
- To let a function change the caller's variable. Go passes arguments as copies, so without a pointer the function only changes its copy.
- To avoid copying a large struct every time it is passed or returned.
- To share one value between several parts of the program, for example one *Config or one *sql.DB.
- To say "no value": a nil pointer can mean "not set", different from a zero value. For example *int can tell "0 runs" from "not played yet".
func addBonus(marks *int, bonus int) {
*marks += bonus
}
func main() {
m := 80
addBonus(&m, 5)
fmt.Println(m) // 85
}nil pointers
The zero value of a pointer is nil: it points nowhere. Following a nil pointer crashes the program with "invalid memory address or nil pointer dereference". This is the most common Go crash. Check for nil when a pointer may be empty.
var p *int
fmt.Println(p == nil) // true
// fmt.Println(*p) // panic: runtime error: invalid memory address or nil pointer dereference
if p != nil {
fmt.Println(*p)
}new, and returning pointers to local variables
n := new(int) // allocates an int set to 0, returns *int
*n = 7
func newCounter() *int {
c := 0
return &c // perfectly safe in Go
}In practice you rarely call new. For structs, &Student{Name: "Asha"} is the common way to get a pointer to a new value.
What Go does NOT allow
- No pointer arithmetic: you cannot write p++ to move to the next address (except with the unsafe package, which normal code never needs).
- No manual free(): the garbage collector frees memory once no pointer refers to it.
- No dangling pointers to freed memory in normal Go code.
Pointers and slices, maps and channels
Slices, maps and channels already contain internal pointers to their data, so you almost never need *[]int or *map[string]int. Pass them as they are. (A function that appends to a slice should return the new slice, as you learned in module 3.)
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Pointers without fear · 1/7
A pointer holds the address of a value, not the value itself.
Prefer a video by a teacher? Find free videos on “golang pointers explained for beginners & and *” on YouTube ↗
In real life: Optional fields in a cricket score API
A cricket scoring API sends a player's strike rate. Before the player faces a ball, the strike rate does not exist yet, which is different from a strike rate of 0. Using *float64 lets the code store nil for "not batted yet". When this struct is turned into JSON, nil becomes null, so the app can show "-" instead of a misleading 0.0.
package main
import "fmt"
type Batter struct {
Name string
StrikeRate *float64 // nil = has not batted yet
}
func show(b Batter) {
if b.StrikeRate == nil {
fmt.Println(b.Name, "SR: -")
return
}
fmt.Printf("%s SR: %.1f\n", b.Name, *b.StrikeRate)
}
func main() {
sr := 142.5
show(Batter{Name: "Rohit", StrikeRate: &sr})
show(Batter{Name: "Jadeja"})
}Practice (0/4 done)
What does this print? a := 5 p := &a *p = *p * 2 fmt.Println(a)
What does this print? func reset(n *int) { n = nil } ... x := 3 reset(&x) fmt.Println(x)
Which line crashes? 1: var s *Student 2: fmt.Println(s == nil) 3: fmt.Println(s.Name)
Write func swap(a, b *int) that swaps two integers in the caller. Then write func applyDiscount(price *int, percent int) that lowers the price in place. Call both from main and print the results.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Interfaces: behaviour, not family treesPointers, interfaces and errors · same module
- any, type assertions and type switchesPointers, interfaces and errors · same module
- Errors as values: wrap, Is and AsPointers, interfaces and errors · same module
- Go language interview questionsCareers and interviews
- Pointers, the stack and the heapC++ Programming (modern C++ and DSA) · References, pointers, arrays and strings
- Addresses and pointersC Programming (from zero to systems) · Pointers
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is the type of &x when x is a float64?
Answer: *float64
& on a float64 gives a *float64.
What is the zero value of a pointer?
Answer: nil
An unset pointer is nil.
Can you do p++ on a pointer in normal Go code?
Answer: No, Go has no pointer arithmetic
Pointer arithmetic is not allowed (outside the unsafe package).
Is it safe to return &local from a function?
Answer: Yes, the compiler moves it to the heap if needed
Escape analysis keeps the value alive as long as it is referenced.
How does Go provide polymorphism without inheritance?Related
Answer: Interfaces satisfied implicitly
Any type with the right methods can be used through an interface.
For a struct pointer s, what is s->name the same as?Related
Answer: (*s).name
The arrow operator dereferences the pointer and then picks the member.
What does slices.Index(s, x) return when x is not in s?Related
Answer: -1
Like many Go search functions, it returns -1 for "not found".
How should a pointer be printed with printf?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Pointers, interfaces and errors” before its exam: Interfaces: behaviour, not family trees, any, type assertions and type switches, Errors as values: wrap, Is and As, panic and recover: only for the truly unexpected.
- Module 4 exam: Pointers, interfaces and errors · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Packages, testing and generics. 46 topics left in the course before the final exam.