When you assign a value to a variable in Go, the value is stored at a particular address in your computer's memory.
You can use the reference operator &
to get this address, like so:
package main
import "fmt"
func main() {
var answer int = 42
fmt.Println(&answer) // Prints 0xc00001c030 or similar
}
When I run this code on my machine, it prints out 0xc00001c030
, which is the memory address of the answer
variable (expressed as a hexadecimal number). If you try running this code on your own computer, or on the Go playground, you'll probably get a different value.
What is a pointer?
When you use the &
operator on a variable it actually returns a pointer.
In simple terms, a pointer is a variable that holds the memory address of another variable. You can think of them as "pointing to" a specific spot in memory.
Like the variables that they point to, pointers in Go also have types. A pointer with the type *int
can only hold the memory address of an int
variable. And a pointer with the type *string
can only hold the memory address of a string
variable. And so on.
That might sound a bit confusing, so to illustrate let's rewrite the example above so that we assign &answer
to a variable instead of printing it directly. I'll use longhand variable declarations here (without type inference) to help make it explicit.
package main
import "fmt"
func main() {
// Declare an answer variable with the type int and assign the value 42.
var answer int = 42
// Declare an answerPtr variable with the type *int. Use the & operator to
// get a pointer to the answer variable and assign it as the value.
var answerPtr *int = &answer
fmt.Println(answerPtr) // Prints 0xc00001c030 or similar
}
So, in this example, the answerPtr
variable is a pointer with the type *int
, which contains the memory address of the answer
variable.
We can re-write this to use the more common :=
shorthand operator for the variable declarations like so:
package main
import "fmt"
func main() {
answer := 42
answerPtr := &answer
fmt.Println(answerPtr)
}
Dereferencing a pointer
You can use the dereference operator *
to read or set the underlying value that a pointer points to. This is often known as indirection.
Here's an example of using the dereference operator to read an underlying value:
package main
import "fmt"
func main() {
answer := 42
answerPtr := &answer
fmt.Println(answerPtr) // Prints 0xc00001c030 or similar
fmt.Println(*answerPtr) // Prints 42
}
Remember, the answerPtr
variable in the example above points to the answer
variable. By using the dereference operator *answerPtr
we can 'read through' to get the value of the answer
variable and print it out.
And we can also use the dereference operator to 'write through' and assign a new underlying value. Like so:
package main
import "fmt"
func main() {
answer := 42
answerPtr := &answer
*answerPtr = 99 // Use the dereference operator to assign a new value
fmt.Println(answer) // Prints 99
}
If you enjoyed this post...
You might like to check out my other Go tutorials on this site, or if you're after something more structured, my books Let's Go and Let's Go Further cover how to build complete, production-ready web apps and APIS with Go.