Blog Cover

A Beginner's Guide to Pointers in Go

Author profile image
Aitor Alonso

Jun 29, 2024

3 min read

In Go, like the majority of programming languages (like C, C++, Rust, etc.), when you assign a value to a variable, that value is stored at a specific memory address in your computer.

You can use the reference operator & to find out this address, as shown below:

package main

import "fmt"

func main() {
    var myVar int = 35

    fmt.Println(&myVar) // Prints a memory address. Ex: 0xc000012028
}

Running this code on my computer, I get an output like 0xc000012028, which represents the memory address of the variable myVar (displayed in hexadecimal). If you run this code on your own machine or in the Go playground, you’ll likely see a different value.

Understanding pointers. What are they?

When you apply the & operator to a variable, it returns a pointer. A pointer is simply a variable that holds the memory address of another variable. You can imagine pointers as "pointing to" a specific location in memory.

Pointers in Go have types, just like the variables they reference. For example, a pointer of type *int can only store the memory address of an int variable, and a pointer of type *string can only store the memory address of a string variable.

This may seem a bit complex, so let's clarify by modifying the previous example to assign the address of myVar to a new variable instead of printing it. To make it clear, I will use explicit variable declarations without type inference.

package main

import "fmt"

func main() {
    // Declare myVar variable with the type int and assign the value 35.
    var myVar int = 35


    // Declare myVarPtr variable with the type *int. Use the & operator to
    // get a pointer to the myVar variable and assign it as the value.
    var myVarPtr *int = &myVar

    fmt.Println(myVarPtr) // Prints a memory address. Ex: 0xc000012028
}

In this case, the variable myVarPtr is a pointer of type *int, holding the memory address of the myVar variable.

We can rewrite this using the more common := shorthand for variable declarations, like this:

package main

import "fmt"

func main() {
    myVar := 35
    myVarPtr := &myVar

    fmt.Println(myVarPtr)
}

Using a pointer to access a value (dereferencing)

The dereference operator * allows you to read or change the value stored at the address a pointer refers to. This is also called indirection.

Here's an example of how to use the dereference operator to read a value:

package main

import "fmt"

func main() {
    myVar := 35
    myVarPtr := &myVar

    fmt.Println(myVarPtr)  // Prints a memory address. Ex: 0xc000012028
    fmt.Println(*myVarPtr) // Prints 35
}

In the above example, myVarPtr is a pointer to the myVar variable. By using *myVarPtr, we can access the value of myVar and print it out.

We can also use the dereference operator to modify the value at the memory address. For example:

package main

import "fmt"

func main() {
    myVar := 35
    myVarPtr := &myVar

    *myVarPtr = 88     // Use the dereference operator to assign a new value
    fmt.Println(myVar) // Prints 88
}

Wrapping up

That's the basics of pointers in Go. They are just variables that store memory addresses of other variables. You can use the reference operator & to get the memory address of a variable and the dereference operator * to access or modify the value stored at that address. This is useful when you need to pass a variable by reference to a function or when you want to modify the value of a variable from another function, or when you want to avoid copying large data structures.


I hope my article has helped you, or at least, that you have enjoyed reading it. I do this for fun and I don't need money to keep the blog running. However, if you'd like to show your gratitude, you can pay for my next coffee(s) with a one-time donation of just $1.00. Thank you!