When we call a function that takes an argument, that argument is copied to the function:
func zero(x int) { x = 0 } func main() { x := 5 zero(x) fmt.Println(x) // x is still 5 }
In this program the zero
function will not modify the original x
variable in the main
function. But what if we wanted to? One way to do this is to use a special data type known as a pointer:
func zero(xPtr *int) { *xPtr = 0 } func main() { x := 5 zero(&x) fmt.Println(x) // x is 0 }
Pointers reference a location in memory where a value is stored rather than the value itself. (They point to something else) By using a pointer (*int
) the zero
function is able to modify the original variable.
In Go a pointer is represented using the *
(asterisk) character followed by the type of the stored value. In the zero
function xPtr
is a pointer to an int
.
*
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 xPtr
refers to”. If we try xPtr = 0
instead we will get a compiler error because xPtr
is not an int
it's a *int
, which can only be given another *int
.
Finally 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.
Another way to get a pointer is to use the built-in new
function:
func one(xPtr *int) { *xPtr = 1 } func main() { xPtr := new(int) one(xPtr) fmt.Println(*xPtr) // x is 1 }
new
takes a type as an argument, allocates enough memory to fit a value of that type and returns a pointer to it.
In some programming languages there is a significant difference between using new
and &
, with great care being needed to eventually delete anything created with new
. Go is not like this, it's a garbage collected programming language which means memory is cleaned up automatically when nothing refers to it anymore.
Pointers are rarely used with Go's built-in types, but as we will see in the next chapter, they are extremely useful when paired with structs.
How do you get the memory address of a variable?
How do you assign a value to a pointer?
How do you create a new pointer?
What is the value of x after running this program:
func square(x *float64) { *x = *x * *x } func main() { x := 1.5 square(&x) }
Write a program that can swap two integers (x := 1; y := 2; swap(&x, &y)
should give you x=2
and y=1
).
← Previous | Index | Next → |