Pointers in Go like in any other language that have them are always a confusing concept, majorly because most developers dont have an understanding of computer memory, how stuff is allocated, types of memory etc.
In this article, i aim to share a more simplified approach to understanding how pointers work, when to use them and how to use them to build effective Go apps.
Today, i see many engineers picking up Go for the first time, and bringing along all the baggages they learn from other languages into it, and complicating things, and pointers are usually their first target for abuse, people throw pointers in every use, many of them think its a way to move thing be reference, or make it nullable.
So, what are pointers, A Pointer is a variable type, whose value, contains the address of another value in memory. And by memory here, we mean on the Heap.
Pointer variables are usually integer types, that is why in other languages, it is possible to do pointer arithmetic, for example in an array, it is possible to take the address of one item, and increment it to get the next.
But Go, doesn't support pointer arithmetic with good reason, pointer arithmetic are usually not trivial, memory allocations also dosen't have a fixed pattern a way it happens, and also thanks to the GC and de-allocations, it is a risky operation.
A. Pointers Enhance Performance
If you take a moment to think about pointers and how they work, you begin to see all the extra operations needed to use them, a runtime has to goto memory get the value of the pointer, then use that value to goto memory to resolve the value it holds, also when you want to now make a copy called pointer de-referencing, value has to be copied causing allocations. I see alot of engineers who say they use pointers for performance reasons, this is usually false, pointers don't speed up your applications.
B. Pointers Reduce Memory Allocation
In Go, by default everything is passed by value, including pointer variables, so when you pass a pointer variable with the intent to reduce allocations, then you might be mistaken.
But this is still somewhat a valid argument, the real values can be allocated on the heap, and the pointers allocated on the stack, reducing allocations on the heap and the work of the GC to clear them, but it comes with the cost of data integrity, what if a function changes the value's state ?, also how do you prevent deadlock in concurrent situations?
Like other programming constructs and tooling, everything has its use case. Knowing when to use pointers effectively, would save you many debugging hours and angry customers.
As a piece of advice, you can consider using pointers in situations where
You want a method you are calling to possibly change state of the value, then it is ok to pass the value as a pointer within that scope, then let the GC take over.
In situations where you want to prevent allocations of a huge values, then its probably ok to use pointers, also taking the precaution of encapsulating critical state that you dont want changed, and exposing getter functions. Also using locks to prevent deadlocks etc.
In conclusion, pointers are no silver bullets, they should be used very wisely and carefully. Also restating that you might not get that performance boost you are hoping for by using pointers everywhere, and there are benchmarks to prove it.