In this post, we are going to look at pointers in Go. Pointers appear in lower level programming languages. These features let us get closer to the hardware. We can see where the data is being stored in our memory. Slices, in fact, are pointers to arrays in Go. So when we mutate the length of a slice in Go, it reassigns itself to a different array behind the scenes.

Putting Our Nose on the Hardware.

We can use this type of behavior to our advantage with smaller data structures. Pointers in Go allow us to manipulate data without having to pass it from one place to another. As a consequence, we can use them when we are dealing with multiple threads and more complex data structures. We can also use them in functions. Let’s look at an example.

In this example, we have two functions, one that uses a pointer and one that doesn’t. Neither of these functions have return statements. Therefore, there is no effect from re-assigning the variable inside of the first function. The second function has an effect on our variable in main because we are passing a memory location rather then a value.

We can’t directly use arithmetic on pointers in Go. This is a consequence of Go having garbage collection. However, once we assign a value to a pointer it will continue to point to that value for the pointer’s lifetime. The only exception to this guarantee is in the case of nil pointers.

pointers-memoryPointing with Pointers

To fully understand pointers, we need to first understand how variables look behind the scenes. All variables are like boxes. Inside of these boxes are values. These boxes need to be stored somewhere, however, and that place is the memory. Because variables can have different types, the boxes also have different sizes.

In Go, we can create variables that contain these memory addresses. Basically, theses variables are pointing to the location where the boxes are being held. That is why, we call these variables pointers.

In Go, when we pass a variable to a function, we are copying the box with the value into that function. This means that the new copy of that box has a different location in the memory. If we use a pointer instead of just a normal parameter, we can pass the original box into the function. This is why in our pointer function above, we see the variable value change without a return statement.

Now that we have a grasp of pointers, lets take a look at a simple example.

Notice that in this example we use the * and the & signs for different reasons. The & before a variable lets us assign a pointer to the memory address of the variable. The * before a pointer lets us see what the pointer is pointing at. As we get deeper into Go and start to look at interfaces and structs, we will start to see pointers more and more. These other data types will help us understand why pointers are so powerful. 

Conclusion

In this post, we looked at pointers in Go. We went over the basic idea of pointers as references to memory and we looked at how go treats variables on the hardware side.  In our next few posts we will start to look at structs and interfaces and then continue on to Go-routines and channels.