Pointers

A pointer is a variable whose value is a memory address. Pointers are defined using an ampersand (the & character), known as the address operator, followed by the name of a variable

A pointer’s type is fixed, which means that when you create a pointer to an int, for example, you change the value that it points to, but you can’t use it to point to the memory address used to store a different type, such as a float64. This restriction is important, pointers are not just memory addresses but, rather, memory addresses that may store a specific type of value.

The type of a pointer is based on the type of the variable from which it is created, prefixed with an asterisk (the * character). The type of variable named second is *int, because it was created by applying the address operator to the first variable, whose value is int. When you see the type *int, you know it is a variable whose value is a memory address that stores an int variable.

first := 100 var second *int = &first first++ println("First:", first) println("Second:", second)

Following a Pointer

The phrase following a pointer means reading the value at the memory address that the pointer refers to, and it is done using an asterisk (the * character). The asterisk tells Go+ to follow the pointer and get the value at the memory location. This is known as dereferencing the pointer.

first := 100 second := &first first++ *second++ var myNewPointer *int myNewPointer = second *myNewPointer++ println("First:", first) println("Second:", *second)

The first new statement defines a new variable, which I have done with the var keyword to emphasize that the variable type is *int, meaning a pointer to an int value. The next statement assigns the value of the second variable to the new variable, meaning that the values of both second and myNewPointer are the memory location of the first value. Following either pointer accesses the same memory location, which means incrementing myNewPointer affects the value obtained by following the second pointer.

A common misconception is that the first and second variables have the same value, but that’s not what is happening. There are two values. There is an int value that can be accessed using the variable named first. There is also an *int value that stores the memory location of the first value. The *int value can be followed, which will access the stored int value. But, because the *int value is, well, a value, it can be used in its own right, which means that it can be assigned to other variables, used as an argument to invoke a function, and so on.

Understanding Pointer Zero Values

Pointers that are defined but not assigned a value have the zero-value nil.

The pointer second is defined but not initialized with a value and is written out using the println function. The address operator is used to create a pointer to the first variable, and the value of second is written out again.

A runtime error will occur if you follow a pointer that has not been assigned a value

first := 100 var second *int println(second) second = &first println(second)

Pointing at Pointers

Given that pointers store memory locations, it is possible to create a pointer whose value is the memory address of another pointer.

first := 100 second := &first third := &second println(first) println(*second) println(**third)

The syntax for following chains of pointers can be awkward. In this case, two asterisks are required. The first asterisk follows the pointer to the memory location to get the value stored by the variable named second, which is an *int value. The second asterisk follows the pointer named second, which gives access to the memory location of the value stored by the first variable. This isn’t something you will need to do in most projects, but it does provide a nice confirmation of how pointers work and how you can follow the chain to get to the data value.

Next example: For Each