Go Pointers! Let’s talk about it…
A pointer, as name suggests, is a variable that points to a location in the memory of your system where a value is stored rather than a value itself. Basically, it is an address to the value stored in memory. The definition is simple but this concept can be a little tricky to wrap your head around.
When I first developed a good understanding of pointers in Go, I asked myself, “How can I explain this concept to a 5-year-old?” Well, I don’t know if I can find words to explain this to a 5 year old, but I will still attempt to give you a simplistic and comprehensive understanding.
Let’s write a small piece of code:
package main
import "fmt"
type animal struct {
name string
sound string
}
func main() {
myAnimal := animal{
name: "Cat",
sound: "Meeeaaawwwwww",
}
myAnimal.updateAttributes("Cow", "Mooooooooo")
myAnimal.print("Updated Structure")
}
func (p animal) updateAttributes(newName string, sound string) {
p.name = newName
p.sound = sound
}
func (p animal) print(text string) {
result := fmt.Sprintf("%s ==> %+v \n \n", text, p)
fmt.Printf("%+v", result)
}
Let’s break this down:
- We are creating an animal,
cat
which has attributes defined in typeanimal
. - Now, I want to update
myAnimal
from acat
to acow
. To do so, I am calling my receiver functioncat.updateAttributes("cow", "mooooooooo")
to update the attributesname
andsound
. - Finally, I have invoked another receiver function
print
to print my updated animal.
Let’s run our go module using go run .
:
//Output: Updated Structure ==> { name:Cat sound:Meeeaaawwwwww zooInfo:{ town:California email:abc@xyz.com pinCode:12345 } }
Wooops… as you can see, my animal is still a cat
.
Let’s see what gets printed inside the receiver function:
func (p animal) updateAttributes(newName string, sound string) {
p.name = newName
p.sound = sound
// Let's call the print command here!
p.print("Tadaaa")
}
//Output
Tadaaaa ==> {
name:cow
sound:Mooooooooo
}
Here is what happens in the background:
In nutshell, Go creates an entirely new struct
when a myAnimal
is passed from one function to another and p
, the receiver function argument becomes a new struct
altogether.
In other words,
p
has its value stored in a different memory location thanmyAnimal
.
For making changes in the original struct
, we can use *
and &
operators.
The ‘*’ and ‘&’ operator
Let’s modify our main function and receiver function updateAttributes a bit:
func main() {
myAnimal := animal{
name: "Cat",
sound: "Meeeaaawwwwww",
}
//STEP#1. Print the original struct myAnimal
myAnimal.print("Original Structure")
//STEP#2. Create a pointer
myAnimalPointer := &myAnimal
//STEP#3. myAnimalPointer will still have access
//to receiver functions of myAnimal.
//So let's update myAnimalPointer value attributes
myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")
//STEP#4. Print the myAnimal values and see if the
//original struct values changed
myAnimal.print("Updated Struct")
}
//STEP#3.1: We'll access the value attributes using * operator
//and make the changes in the orginal struct value
func (p *animal) updateAttributes(newName string, sound string) {
(*p).name = newName
(*p).sound = sound
}
Let’s talk about “main” function: Creation of a pointer
myAnimal := animal{
name: "Cat",
sound: "Meeeaaawwwwww"
}
myAnimalPointer := &myAnimal
myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")
//OR We can simply do something like
(&myAnimal).updateAttributes("Dog", "Woof Woof Woof") //Same thing!
myAnimal.print("Updated Struct")
}
Using the &
operator, we can create a pointer and we can get the address in memory where the value of the myAnimal
is stored. We have assigned &myAnimal
pointer to myAnimalPointer
variable.
Let’s talk about the receiver function “updateAttributes” : Retrieving value from the pointer
func (p *animal) updateAttributes(newName string, sound string) {
(*p).name = newName
(*p).sound = sound
}
p
is the pointer that function receives when invoked.
*animal
is not a pointer but a mere description of what this function expects when invoked.
The value in memory that pointer p
references to, can be accessed using the *
operator.
Using brackets, (*p)
, will give you the access to the struct
attributes.
Let’s run the code again:
go run .
//Output
Original Structure ==> {name:Cat sound:Meeeaaawwwwww}
Updated Struct ==> {name:Dog sound:Woof Woof Woof}
Woohooo 🎉… we have updated the original struct myAnimal with the power of pointers.
A Gotcha moment…
“abracadabra”, let the code appear…
func main() {
myAnimal := animal{
name: "Cat",
sound: "Meeeaaawwwwww",
}
myAnimal.print("Original Structure")
//Let's comment the 2 lines below
//myAnimalPointer := &myAnimal
//myAnimalPointer.updateAttributes("Dog", "Woof Woof Woof")
//Let's use our same old myAnimal struct without creating a pointer
myAnimal.updateAttributes("Dog", "Woof Woof Woof")
myAnimal.print("Updated Struct")
}
func (p *animal) updateAttributes(newName string, sound string) {
(*p).name = newName
(*p).sound = sound
}
Go automatically takes care of pointer creation in the background so that you don’t have to. And that’s how, you will get the same result:
go run .
Original Structure ==> {name:Cat sound:Meeeaaawwwwww}
Updated Struct ==> {name:Dog sound:Woof Woof Woof}
The new Keyword
Lets create a pointer using a new
keyword:
package main
import "fmt"
type animal struct {
name string
sound string
}
func (p *animal) updateAttributes(newName string, sound string) {
(*p).name = newName
(*p).sound = sound
}
func main() {
// LOOK OVER HERE!!!
myAnimal := new(animal)
myAnimal.updateAttributes("Dog", "Woof Woof Woof")
fmt.Printf("%+v", *myAnimal)
}
//Output:
{name:Dog sound:Woof Woof Woof}%
Official Definition:
The
new
takes type as an argument, allocates enough memory to fit a value of that type and returns a pointer to it.
I hope, I was able to make this concept a little easier to grasp for all my lovely readers and followers like yourself. If you feel, something can be improved, please drop a comment and I will look into it.
Have a lovely day!
. . .
Note of thanks ❤️
Thank you for stopping by. Hope, you find this article useful. Please follow me on medium and help me reach 1k followers 🙏🏻. That will truly encourage me to put out more content.
P.S.: If you feel something can be improved or lacks proper explanation, drop me a note in the comment box or mail me at shiva.chaturvedi91@gmail.com. After all, you can teach me a thing or two as well.