Search for:

Go Pointer to Pointer (Double Pointer)

In Go, you can have pointers to pointers, also known as double pointers. This concept is particularly useful when you need to modify the value of a pointer itself, such as when dynamically allocating memory or when you want to pass a pointer by reference to a function. Here’s an example of using a pointer to a pointer:

package main

import "fmt"

func main() {
    x := 42
    p := &x         // Pointer to x
    pp := &p        // Pointer to the pointer p

    fmt.Println("Value of x:", x)
    fmt.Println("Value pointed to by p:", *p)
    fmt.Println("Value of p (address of x):", p)
    fmt.Println("Value pointed to by pp (value of p):", *pp)

    // Modifying the value of x through the pointer to pointer
    **pp = 99

    fmt.Println("Value of x after modification:", x)
}

Output:

Value of x: 42
Value pointed to by p: 42
Value of p (address of x): 0xc0000140a0
Value pointed to by pp (value of p): 0xc0000140a0
Value of x after modification: 99

In this example, we start by creating an integer variable x. We then create a pointer p that points to x, and a pointer pp that points to the pointer p. By using *p, we access the value of x, and by using *pp, we access the value of p. Since p is a pointer to x, and pp is a pointer to p, modifying **pp is equivalent to modifying the value of x.

Using pointers to pointers allows you to work with the value of a pointer itself, which can be useful in situations where you need to update a pointer’s value dynamically.

Here’s another example that demonstrates the concept of pointers to pointers (double pointers) with a dynamic memory allocation scenario:

package main

import "fmt"

func allocateMemory(val int) **int {
    p := new(int)    // Create an int pointer
    *p = val         // Set the value of the int pointer

    pp := &p         // Create a pointer to the int pointer
    return pp        // Return the pointer to pointer
}

func main() {
    pp := allocateMemory(42)  // Get the pointer to pointer

    fmt.Println("Value of x (through double pointer):", **pp)
}

Output :

Value of x (through double pointer): 42

In this example, the allocateMemory function dynamically allocates memory for an integer using new(int). It then sets the value of the integer through the pointer p. After that, it creates a pointer pp that points to the pointer p, effectively returning a pointer to pointer from the function.

In the main function, we call allocateMemory with the value 42 and get a pointer to pointer. By using **pp, we can access the value of the integer that was allocated dynamically in the allocateMemory function.

This example illustrates how double pointers can be used to handle scenarios where you need to modify or return pointers dynamically.

Pointer to a Struct in Golang

In Go, you can create a pointer to a struct in the same way you create a pointer to any other type. Pointers to structs are useful when you want to modify the struct’s fields directly, especially when dealing with larger data structures.

Here’s an example of creating and using a pointer to a struct:

package main

import "fmt"

type Person struct {
    FirstName string
    LastName  string
    Age       int
}

func main() {
    // Create a struct instance
    person := Person{
        FirstName: "John",
        LastName:  "Doe",
        Age:       30,
    }

    // Create a pointer to the struct
    personPtr := &person

    // Modify struct fields through the pointer
    personPtr.Age = 31

    // Access struct fields through the pointer
    fmt.Println("First Name:", personPtr.FirstName)
    fmt.Println("Last Name:", personPtr.LastName)
    fmt.Println("Age:", personPtr.Age)
}

Output :

First Name: John
Last Name: Doe
Age: 31

In this example, we define a Person struct with FirstName, LastName, and Age fields. We create an instance of the struct named person. Then, we create a pointer to the person instance using &person. We can modify and access the struct fields directly through the pointer.

Keep in mind that modifying fields through a pointer to a struct affects the original struct, making pointers a useful tool for modifying data in a shared manner.

Here’s another example that demonstrates using a pointer to a struct, along with a function that accepts a pointer to a struct as an argument:

package main

import "fmt"

type Student struct {
    Name  string
    Age   int
    Grade string
}

func updateStudent(s *Student, newName string, newAge int) {
    s.Name = newName
    s.Age = newAge
}

func main() {
    // Create a struct instance
    student := Student{
        Name:  "Alice",
        Age:   18,
        Grade: "A",
    }

    // Create a pointer to the struct
    studentPtr := &student

    fmt.Println("Before Update:")
    fmt.Println("Name:", studentPtr.Name)
    fmt.Println("Age:", studentPtr.Age)
    fmt.Println("Grade:", studentPtr.Grade)

    // Call function to update struct fields
    updateStudent(studentPtr, "Bob", 19)

    fmt.Println("\nAfter Update:")
    fmt.Println("Name:", studentPtr.Name)
    fmt.Println("Age:", studentPtr.Age)
    fmt.Println("Grade:", studentPtr.Grade)
}

Output :

Before Update:
Name: Alice
Age: 18
Grade: A

After Update:
Name: Bob
Age: 19
Grade: A

In this example, we define a Student struct and a function updateStudent that takes a pointer to a Student struct as an argument. Inside the function, we modify the fields of the struct using the pointer. In the main function, we create a Student instance, create a pointer to it, and then pass the pointer to the updateStudent function to modify its fields. As you can see, the changes made inside the function are reflected outside as well.