Building Cloud Expertise with centron - Our Tutorials

Whether you are a beginner or an experienced professional, our practical tutorials provide you with the knowledge you need to make the most of our cloud services.

Mastering Pointers in Go: A Comprehensive Guide

Discover how pointers influence the way data is handled in memory. We will show you how to use functions and methods to efficiently process and modify data.

When writing software in Go

When writing software in Go, you will create functions and methods. You pass data to these functions as arguments. Sometimes, the function needs a local copy of the data, and you don’t want the original to be modified. For example, if you are a bank and have a function that shows a user their account balance based on the chosen savings plan, you don’t want to change the customer’s actual account balance before they select a plan; you only want to use it for calculations. This is referred to as “by value” because you send the value of the variable to the function, but not the variable itself.

However, sometimes you want

However, sometimes you want the function to be able to modify the data in the original variable. For example, when a bank customer makes a deposit into their account, you want the deposit function to access the actual account balance, not a copy. In this case, you don’t need to pass the actual data to the function; you only need to tell the function where the data is stored in memory. A data type called a pointer holds the memory address of the data, not the data itself. The memory address tells the function where it can find the data, but not the value of the data. You can pass the pointer to the function instead of the data, and the function can then directly modify the original variable. This is referred to as “by reference” because the value of the variable is not passed to the function, only its location.

Definition and Usage of Pointers

When you use a pointer to a variable, there are several syntax elements you need to understand. The first is the use of the ampersand sign (&). When you put an ampersand sign before the name of a variable, you indicate that you want to obtain the address or a pointer to that variable. The second syntax element is the use of the asterisk (*) or dereference operator. When you declare a pointer variable, you precede the variable name with the type of the variable to which the pointer points, preceded by an asterisk, like this:

       var myPointer *int32 = &someint


This creates myPointer as a pointer to an int32 variable and initializes the pointer with the address of someint. The pointer actually does not contain an int32 but only the address of such a variable.

Let’s take a look at a pointer to a string

Let’s take a look at a pointer to a string. The following code declares both a value of a string and a pointer to a string:

package main

import "fmt"

func main() {
	var creature string = "shark"
	var pointer *string = &creature

	fmt.Println("creature =", creature)
	fmt.Println("pointer =", pointer)
}


Run the program with the following command:

When you run the program, it will output the value of the variable as well as the address in memory where the variable is stored (the pointer address). The memory address is a hexadecimal number and not meant for human readability. In practice, you probably won’t ever output a memory address to view it. We are showing it here for illustration purposes. Since each program is created in its own memory space, the value of the pointer will be different every time you run it, varying from the output shown here.

Output:
creature = shark
pointer = 0xc0000721e0

The variable we defined as “creature” and set to the string value “shark.” Then we created another variable named “pointer.” This time, we set the value of the pointer variable to the address of the “creature” variable. We store the address of a value in a variable using the ampersand sign. This means the pointer variable stores the address of the “creature” variable, not the actual value.

Therefore, when we printed the value of the pointer, we received the value 0xc0000721e0, which is the address where the “creature” variable is currently located in computer memory.

If you want to output the value of the variable

If you want to output the value of the variable pointed to by the pointer, you need to dereference that variable. The following code uses the asterisk (*) operator to dereference the pointer variable and retrieve its value:

package main

import "fmt"

func main() {
	var creature string = "shark"
	var pointer *string = &creature

	fmt.Println("creature =", creature)
	fmt.Println("pointer =", pointer)

	fmt.Println("*pointer =", *pointer)
}


When you run this code, you’ll see the following output:

Output:
creature = shark
pointer = 0xc000010200
*pointer = shark

The last line we added now dereferences the pointer variable and outputs the value stored at that address.

If you want to change the value stored

If you want to change the value stored at the pointer variable address, you can also use the dereference operator:

package main

import "fmt"

func main() {
	var creature string = "shark"
	var pointer *string = &creature

	*pointer = "dolphin"

	fmt.Println("creature =", creature)
}


When you run the above code, the output will be:

Output:
creature = dolphin

Although we assigned a new value to the pointer variable (and not the creature variable), the actual value of the creature variable was modified because the pointer held its memory address. This shows the power of pointers in Go, allowing you to directly manipulate the memory where data is stored.

Conclusion

Pointers are a powerful tool in Go that allow you to directly manipulate memory addresses. By understanding and using pointers effectively, you can improve the efficiency and versatility of your Go programs.

Function with Pointer Receiver

When you write a function, you can specify whether arguments are passed by value or by reference. Passed by value means a copy of the value is sent to the function, and any changes to that argument within that function only affect that variable in that function, not where it was passed from. However, if you pass by reference, meaning you pass a pointer to the argument, you can modify the value within the function and also change the value of the original variable it was passed from. You can learn more about how to define functions in our article “How to Define and Call Functions in Go.”

The decision of when to pass a pointer instead of a value depends on whether you want the value to be changed or not. If you don’t want the value to be changed, pass it by value. If you want the function to be able to modify the variable you pass, then you should pass it as a pointer.

To see the difference, let’s first look at a function that passes an argument by value:

    package main

    import "fmt"

    type Creature struct {
        Species string
    }

    func main() {
        var creature Creature = Creature{Species: "shark"}

        fmt.Printf("1) %+v\n", creature)
        changeCreature(creature)
        fmt.Printf("3) %+v\n", creature)
    }

    func changeCreature(creature Creature) {
        creature.Species = "jellyfish"
        fmt.Printf("2) %+v\n", creature)
    }

Now let’s look at a function that passes an argument by pointer:


    package main

    import "fmt"

    type Creature struct {
        Species string
    }

    func main() {
        var creature Creature = Creature{Species: "shark"}

        fmt.Printf("1) %+v\n", creature)
        changeCreatureByPointer(&creature)
        fmt.Printf("3) %+v\n", creature)
    }

    func changeCreatureByPointer(creature *Creature) {
        creature.Species = "turtle"
        fmt.Printf("2) %+v\n", creature)
    }


The results will show that when passed by value, the original variable remains unchanged, but when passed by pointer, the original variable is modified. This is a fundamental concept in programming that allows for more flexible and efficient code. Mastering Pointers in Go: A Comprehensive Guide

Ready to Implement Pointers in the Cloud?

Experience the power of Go pointers in a robust cloud environment. Join our test phase and harness the efficiency, speed, and reliability of our cloud platform tailored for Go developers. Don't just learn – deploy, test, and optimize with us!

Try for free!