Pointers In Go
Pointers are objects that store a memory address. A pointer references a location in memory. A pointer is a simple, more concrete implementation of the more abstract reference data type. The term pointer applies to any data structures whose interface explicitly allows the pointer to be manipulated as a memory address. Several languages, especially low-level languages, support some type of pointer. Attempting to dereference a pointer whose value is not a valid memory address could cause a program to crash.
Concept Of Pointers
You have your house obviously which you live in, now there are times when people would want to know where you live, it makes no sense to always just take them outright to your house straight away, there are times when people want to know where you live but do not want to visit you. So on that occasion, you provide your address, and now your house address points to the location of your house.
If you are a beginner in Go then you'd better check this introduction to Go
Let's create a pointer
package main
import "fmt"
func main() void {
i := 10
p := &i
fmt.PrintLn(i)
fmt.PrintLn(p)
fmt.PrintLn(*p)
}
// 10
// 0xc000040250
// 10
To read more on Go at Netcreed
In the code snippet above, we create a variable of type int
, then we create a pointer p
that stores the memory address of i
. when we want to get the memory address of a variable, we use the &
operator, observing our use of type inference here. So what the heck is a memory address of a variable? Variables are labels that are used to store a value, each value is stored in a memory location and this memory location is known as the memory address on your computer ram while your code is running. The name of the variable is a tag to the value stored inside the address. A pointer such one expressed above is a reference to a memory location. let's see how they work with strings too
package main
import "fmt"
func main() void {
i := "sam"
p := &i
fmt.PrintLn(i)
fmt.PrintLn(p)
fmt.PrintLn(*p)
}
// sam
// 0xc000040250
// sam
When we are obtaining the value stored at that location we say we as dereferencing the pointer. We use *
to dereference a pointer, rather than returning to us the memory address, it will return to us the underlying value which is stored at that address.
Why Use Pointers?
They are primarily used for constructing references, which in turn are fundamental to constructing nearly all data structures, as well as in passing data between different parts of a program. We use pointers to pass data to a function by reference, that is to say, we get the underlying value which is stored at the address as opposed to the variable itself, this has some interesting consequences. When we start to work with structs, you will realize that structs are not mutable, any change to a struct will only create a copy of the original with the modified changes, and the change will not take effect on the original struct. We use structs to combat situations like this.
package main
import "fmt"
type Person struct {
name string
age int
gender string
hobbies []string
}
func NewPerson(_name string, age int) Person {
p := Person{
name: _name,
age: 0,
hobbies: []string{},
}
return p
}
func addHobby(hobby string, p Person) {
p.hobbies = append(p.hobbies, hobby)
}
We have created a simple struct
that serves as the blueprint for a Person
object, Structs like we said are quite immutable to changes, we will run the above code and observer that the hobby we try to append to the hobbies array gets ignored.
func main() {
sam := NewPerson("sam", 30)
fmt.Println(sam)
addHobby("singing", sam)
fmt.Println(sam)
}
// {sam 30 []} before
// {sam 30 []} after
Now let's modify the addHobby
function slightly, instead of accepting a variable of type Person
we will only accept a pointer to a Person
func addHobby(hobby string, p *Person) {
p.hobbies = append(p.hobbies, hobby)
}
func main() {
sam := NewPerson("sam", 30)
fmt.Println(sam)
and hobby("singing", &sam)
fmt.Println(sam)
}
// {sam 30 []} before
// {sam 30 [singing]} after
Should You use Pointers?
A common idea is that when you use pointers your application will be faster because you’ll avoid copying data around all the time. When Java came around, one of the complaints was that Java was slow because you’d be doing a pass-by-value all the time. Hence perhaps it’s no surprise that in Go we find the same idea persisting. Yet, Passing pointers in Go are often slower than passing values. This is a result of Go being a garbage-collected language. this post explains more on the subject.
That's it for this one, if you found it useful you can read more on Go at Netcreed