A Beginner's Guide to Pointers in Go
Jun 29, 2024
3 min read
In Go, like the majority of programming languages (like C, C++, Rust, etc.), when you assign a value to a variable, that value is stored at a specific memory address in your computer.
You can use the reference operator &
to find out this address, as shown below:
package main
import "fmt"
func main() {
var myVar int = 35
fmt.Println(&myVar) // Prints a memory address. Ex: 0xc000012028
}
Running this code on my computer, I get an output like 0xc000012028
, which represents the memory address of the variable myVar
(displayed in hexadecimal). If you run this code on your own machine or in the Go playground, you’ll likely see a different value.
Understanding pointers. What are they?
When you apply the &
operator to a variable, it returns a pointer. A pointer is simply a variable that holds the memory address of another variable. You can imagine pointers as "pointing to" a specific location in memory.
Pointers in Go have types, just like the variables they reference. For example, a pointer of type *int
can only store the memory address of an int
variable, and a pointer of type *string
can only store the memory address of a string
variable.
This may seem a bit complex, so let's clarify by modifying the previous example to assign the address of myVar
to a new variable instead of printing it. To make it clear, I will use explicit variable declarations without type inference.
package main
import "fmt"
func main() {
// Declare myVar variable with the type int and assign the value 35.
var myVar int = 35
// Declare myVarPtr variable with the type *int. Use the & operator to
// get a pointer to the myVar variable and assign it as the value.
var myVarPtr *int = &myVar
fmt.Println(myVarPtr) // Prints a memory address. Ex: 0xc000012028
}
In this case, the variable myVarPtr
is a pointer of type *int
, holding the memory address of the myVar
variable.
We can rewrite this using the more common :=
shorthand for variable declarations, like this:
package main
import "fmt"
func main() {
myVar := 35
myVarPtr := &myVar
fmt.Println(myVarPtr)
}
Using a pointer to access a value (dereferencing)
The dereference operator *
allows you to read or change the value stored at the address a pointer refers to. This is also called indirection.
Here's an example of how to use the dereference operator to read a value:
package main
import "fmt"
func main() {
myVar := 35
myVarPtr := &myVar
fmt.Println(myVarPtr) // Prints a memory address. Ex: 0xc000012028
fmt.Println(*myVarPtr) // Prints 35
}
In the above example, myVarPtr
is a pointer to the myVar
variable. By using *myVarPtr
, we can access the value of myVar
and print it out.
We can also use the dereference operator to modify the value at the memory address. For example:
package main
import "fmt"
func main() {
myVar := 35
myVarPtr := &myVar
*myVarPtr = 88 // Use the dereference operator to assign a new value
fmt.Println(myVar) // Prints 88
}
Wrapping up
That's the basics of pointers in Go. They are just variables that store memory addresses of other variables. You can use the reference operator &
to get the memory address of a variable and the dereference operator *
to access or modify the value stored at that address. This is useful when you need to pass a variable by reference to a function or when you want to modify the value of a variable from another function, or when you want to avoid copying large data structures.