We know every variable has a location in memory. In Go, a pointer is a special variable used to store the memory address of another variable. With pointers you can retrieve as well store in that memory address.
There are two ways to use pointers:
*Operator also termed as the dereferencing operator used to declare pointer variable and
access the value
stored in the address.& operator termed as address operator
used to return the memory address of a variable
or to access the address of a variable to a pointer.
The Book Analogy : To help us understand pointers practically
To help us understand this better let use use the analogy of a book. A book has pages, each page has a page number and each page has its own content. If I want certain content, and I know the page number and I know the content in the page, would it be easier to find by page number or skim the book looking for that content? My guess is it would be easier and faster to find the content by page number. Similarly that's what pointers are for in go. The & operator would generate a page number
, the *Operator would tell you the content on a given page number
.
package main
import "fmt"
func main() {
i, j := 42, 2701
p := &i // point to i
fmt.Println(*p) // read i through the pointer
*p = 21 // set i through the pointer
fmt.Println(i) // see the new value of i
p = &j // point to j
*p = *p / 37 // divide j through the pointer
fmt.Println(j) // see the new value of j
}
Why Do We Need Pointers?
In the 1960s, pointers gave programmers a way to pass a variable’s memory location and then dereference it for manipulation as needed. This provided a way of creating more complex data structures while still consuming less memory. Harold Lawson is credited with inventing pointers.
Instead of copying a large amount of data every time you need to pass it, programmers could pass its address. Going back to the book analogy, it’s easier to pass a function a page number than an entire page.
In Go, everything is passed by value. Every time you pass something to a function, the function gets a value, but it doesn’t have access to the original object. See what I mean by typing the following code out in the Go playground!
package main
import (
"fmt"
)
type Celebrity struct {
Name string
Vehicles []string
}
func (c Celebrity) newVehicle() {
c.Vehicles = append(c.Vehicles, "Ferari")
fmt.Println(c)
}
func main() {
c := Celebrity{Name: "Christiano Ronaldo", Vehicles: []string{"Rolls Royce"}}
c.newVehicle() // {Christiano Ronaldo [Rolls Royce Ferari]} -- the celebrity with a new Vehicle, Ferari!
fmt.Println(c) // Hey, wait! Where did the Ferari go?
}
Why did we get this result?
We passed a value of a Celebrity
to newVehicle() and added him a new vehicle. We still haven’t changed (or mutated) the original Celebrity.
Solution:
package main
import (
"fmt"
)
type Celebrity struct {
Name string
Vehicles []string
}
func (p *Celebrity) newVehicle() {
p.Vehicles = append(p.Vehicles, "Ferari")
fmt.Println(*p)
}
func main() {
c := Celebrity{Name: "Christiano Ronaldo", Vehicles: []string{"Rolls Royce"}}
p := &c // Let's make a pointer to celebrity!
p.newVehicle()
fmt.Println(c)
}
// Does Christiano have a new vehicle now? Yes!
At first understanding pointers was difficult for me, practice made me better. So if you are having trouble understanding pointers, it is ok. Take a break and keep learning.
Top comments (0)