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.