Pointer
In Go a pointer is represented using the *
character followed by the type of the stored value.
*
is also used to "dereference" pointer variables. Dereferencing a pointer gives us access to the value the pointer points to.
When we write *xPtr = 0
we are saying "store the int 0 in the memory location that xPtr
refers to".
- If we try
xPtr = 0
instead we will get a compiler error becausexPtr
is not anint
it's a*int
, which can only be given another*int
.
We use the &
operator to find the address of a variable. &x
returns a *int
(pointer to an int
) because x
is an int
. This is what allows us to modify the original variable. &x
in main and xPtr
in zero refer to the same memory location.
When we use the &
operator in front of a variable c
, we are talking about the place where c
is stored. When we use the *
operator, we are talking about the variable c
itself.
We can get the memory address of a variable by prepending it with an &
i := 7
fmt.Println(&i) // 0xc420014090
As expected, the inc
function wouldn't cause the value of i
to change, since i
is copied by value, so x
in the inc
function is just a copy, which gets incremented, but then is discarded, since the function doesn't return anything.
func main() {
i := 7
inc(i)
fmt.Println(i) // 7
}
func inc(x int) {
x++
}
If we want to modify the value of i
here, then we can do so by passing a pointer to the variable to inc
. In this case, the inc
function receives a value at that memory reference and is able to modify the original version.
func main() {
i := 7
// pass the pointer of `i` to the `inc` function
inc(&i)
fmt.Println(i) // 7
}
// here, we say "the function accepts a pointer that, when dereferenced, is an integer"
func inc(x *int) {
// dereference the pointer before incrementing; otherwise we'd be incrementing the memory address (ie. 0xc420014090).
*x++
}
Use-cases
Pointers give us the ability to define a function that accepts a pointer as an argument so that the original variable can be modified from within the function.
func zero(xPtr *int) {
*xPtr = 0
}
func main() {
x := 5
zero(&x)
fmt.Println(x) // x is 0
}
- this also has the added benefit of not having to copy the value into a local function version on each method call.
Pointers are extremely useful when paired with structs.
Backlinks