Pointers in Go
| & takes the address | |
| * follows it | |
| Pointers as parameters | |
| When pointers pay off |
& takes the address
Every variable lives at an address in memory, and the & operator reveals it as a pointer value. Storing that pointer lets other code find and share the same variable instead of a copy.
package main
import "fmt"
func main() {
x := 10
p := &x
fmt.Println(*p)
fmt.Println(&x == p)
}
go run main.go
10
true
Printing a pointer shows a machine address, so examples here print the pointed to value or a comparison instead. For a deeper reference with extra examples, see the article on pointers.
* follows it
The * operator follows a pointer back to the variable it points at. Reading *p loads the stored value, and assigning to *p rewrites the original variable through the pointer.
package main
import "fmt"
func main() {
x := 10
p := &x
fmt.Println(*p)
*p = 20
fmt.Println(x)
}
10
20
The star has two jobs that context keeps apart: declaring a pointer type, as in *int, and following a pointer value, as in *p. Read the declaration as pointer to int and the expression as value at p.
Pointers as parameters
Function arguments arrive as copies, so a function that must change the caller variable takes a pointer instead. The caller passes &x and the function writes through its parameter.
package main
import "fmt"
func double(n *int) {
*n = *n * 2
}
func main() {
x := 21
double(&x)
fmt.Println(x)
}
42
Without the pointer, double would only change its own local copy and main would still print 21. Choose pointer parameters only for functions that truly need to mutate or to avoid copying.
When pointers pay off
Pointers pay off in three places: sharing large structs without copying them, letting functions update shared state, and expressing absence with nil. Everywhere else plain values keep programs simpler.
package main
import "fmt"
type User struct {
Name string
Age int
}
func birthday(u *User) {
u.Age++
}
func main() {
u := User{Name: "Ada", Age: 35}
birthday(&u)
fmt.Println(u)
}
{Ada 36}
A nil pointer points nowhere, so always check for nil before following one that might be empty. Go keeps pointer arithmetic out of the language, which removes a whole family of memory bugs.
Next: Structs
Article author: Arthur Isaev