Howl

this is where i come to cry.

>

Pointers in Go

January 29, 2016

In the process of learning Go, I struggled in the process of learning how I should use pointers. It’s not very easy to find an handy guide online, so for all of the people on the interwebz who are attempting to learn Go and have come across pointers and haven’t understood completely anything, here’s a guide for you to help you out, made in words easy enough to understand even for a complete beginner.

For absolute beginners

Assume you’re in a world where laws of physics don’t exist and everything can be done programmatically, even delivering to someone’s home. You’ve just ordered a bottle of water from amazon. Before you used pointers, you would have done a function like this:

func (w water) deliver(house House) {
	house.PostBox = append(house.PostBox, w)
}

There’s something very wrong in this. In the request handler for the bottle order, if we check the house’s postbox contents after calling the function deliver, there is no water. What happened is that, instead of making a postman deliver the bottle of water to your house, we have copied an instance of your house into the deliver function, so now we have two houses being identical. Then we added an element to the PostBox of our copied house, and then when the function ended the copied house is destroyed. But the problem is, the original house got nothing into its postbox! To solve this, we use pointers.

In the real world

Let’s take some code.

package main

import "fmt"

func main() {
	caller()
}

func caller() {
	num := 5
	fmt.Println(num)
	sum(num, 2)
	fmt.Println(num)
}
func sum(num, add int) {
	num += add
}

// $ go run test.go
// 5
// 5

So, our sum function isn’t working, because the number is the same. How can we fix this?

func caller() {
	num := 5
	fmt.Println(num)
	sum(&num, 2)
	fmt.Println(num)
}
func sum(num *int, add int) {
	*num += add
}

// $ go run test.go
// 5
// 7

What? Well, it’s actually fairly easy once you get the gist.

  1. In the function caller, num is an int.
  2. In the function sum, num is a POINTER to an int, which is transcribed as an asterisk + the actual type, so *int.
  3. In the function caller, in order to pass to sum the value of num by reference (the address of the house rather than the house itself), we are using &.
  4. In the function sum, we are using *num not because pointers must always be called by having an asterisk behind them. We’re using *num because we can’t add an *int to an int, so we are converting *int to an int, while still keeping num a reference and making changes to it.

tl;dr:

  1. *type is used to declare a type of a variable or the return value of a function. There’s no &type.
  2. &var is used to actually pass a variable pointer to a function, and satisfies *type (if var satisfies type, that is).
  3. *var is used to get the actual value of the variable passed via &type, removing the pointer info, so that you can use its value in calls to function which require a variable of that type, not a pointer to a variable of that type, and so on with operations.

This can be slightly confusing for the double use of * in types and vars, but practice makes perfect.

© Morgan Bazalgette 2015-2017