Receivers & Pointers - Go Intro (II)

Receiver functions in Go

By now we probably know how to declare a function in go from the intro section. Now we’ll learn how to declare a receiver functions (spoiler alert: It’s a method)

We would learn that we can add behavior to a struct with this Receiver functions (Spoiler alert: Methods)

1
2
3
4
5
6
7
func (p person) print() {
fmt.Printf("%+v", p)
}

func (p person) updateName(newFirstName string) {
p.firstName = newFirstName
}

We see that this functions receives a variable p of type person which is a struct of type person. And we can call these functions with the struct the following way

1
2
3
4
5
6
7
lucas =: person{
name: "Lucas Contreras",
age: 100,
}

lucas.print() // {name:Lucas Contreras age:100}
lucas.updateName("Pedro Alfonso") // Name will not change due to pointers.

Pointers in Go

I’ll assume that you already know about pointers and show you how pointers works on Go really quickly. Spoiler: They work pretty much like in C.

Go is a *”pass by value”* language, so every time we pass a value to a function we are passing a copy of that value to the function to operate with, no the real value.

Here are two examples dealing with pointers

Without pointers:

1
2
3
4
5
6
7
8
9
10
11
12
package main
import "fmt"

func main() {
my_greet := "Hola como estás"
add_name_to_greet(my_greet, "John Doe")
fmt.Println(my_greet) // This will print "Hola como estás" without the name
}

func add_name_to_greet(greet string, name string) {
greet = greet + name
}

With pointers:

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"

func main() {
my_greet := "Hola como estas "
add_name_to_greet(&my_greet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet) // This will print "Hola como estás John Doe"}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

Another alternative whit pointers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"

func main() {
my_greet := "Hola como estas " // Acé es donde C haría el Malloc !
var pointerGreet *string
pointerGreet = &my_greet

add_name_to_greet(pointerGreet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet)
}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

This last happens only for Value Types in go, which are int, float, string, bool and structs. But that’s not the same for Reference Types. So let’s see how we deal with pointers in this case.

Pointers with Reference Types (Slices)

In the case of slices this works just fine since a Slice is a pointer to the head of an array. So copying that pointer will create a pointer that points to the same array.

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"

func main() {
mySlice := []string{"Hola","como","estas?"}
updateSlice(mySlice)
fmt.Println(mySlice)
}

func updateSlice( slice []string) {
//slice = append(slice, "John Doe")
slice[0] = "Hello"
}

This also applies for Maps, Channels, Pointers itself and functions.

Value Types Reference Types
int slices
floats maps
strings channels
bool pointers
structs functions

The & and the *

1
2
3
4
5
*variableName // Makes refence to the value that the pointer... points.

*type // This is also a type. A type of "type pointer"

& variableName // Makes reference to memory address.

So just to recap:

  • To turn address into value : *address

  • To turn value into address: &value

  • To declare some variable as *”pointer to something of type type (eg. person)”* : var contre *person

Exercise:

Why this wont work

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
import "fmt"

func main() {
var my_greet *string
*my_greet = "Hola como estas"

add_name_to_greet(my_greet, "John Doe") // We pass the memory address where our greet is located (pointer)
fmt.Println(my_greet)
}

func add_name_to_greet(greet *string, name string) { // We take this pointer as parameter
*greet += name //We take the Value of the pointer and change it
}

Spoiler: I initialize the pointer that point to nil (nowhere) and tried to assigned a value to

Receivers: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/5-Receivers.md
Pointers: https://github.com/contre95/notes/blob/master/Digitales/Apuntes/Coding/Go/6-Pointers.md


Author: Lucas Contreras