DEV Community

Cover image for Golang Pointers and Functions: A Guide with Examples
Adrian DY
Adrian DY

Posted on

Golang Pointers and Functions: A Guide with Examples

In this article, we'll explore how Golang pointers work in functions, and we'll provide examples of using them with and without memory references.

What are Pointers in Golang?

A pointer is a variable that contains the memory address of another variable. In Golang, a pointer is represented by an asterisk (*) followed by the data type of the variable it points to. For example, the following code declares a pointer to an integer variable:

var ptr *int
Enter fullscreen mode Exit fullscreen mode

This declares a pointer named "ptr" that points to an integer variable. To assign the address of a variable to a pointer, use the "&" operator. For example:

var num int = 42
ptr = &num
Enter fullscreen mode Exit fullscreen mode

This assigns the address of the "num" variable to the "ptr" pointer. Now, the "ptr" pointer points to the "num" variable in memory.

Using Pointers in Functions

When a pointer is passed to a function, the function can modify the value of the variable it points to directly in memory. This is much more efficient than passing a copy of the variable to the function, which requires creating a new variable in memory.

Let's take a look at an example:

func updateValueWithRef(chain *string) {
    fmt.Printf("%p\n", &*chain)
    *chain = "Hello from function"
}
Enter fullscreen mode Exit fullscreen mode

This function takes a pointer to a string variable as its argument. Inside the function, we use the "*" operator to dereference the pointer and access the value of the variable it points to. Then, we can modify the value of the variable directly in memory by using the "=" assignment operator.

With Memory References

Now, let's take a look at an example of using a pointer with a memory reference:

chain := "Hello world"
fmt.Printf("%p\n", &chain)
fmt.Printf("Before function: %s\n", chain)
updateValueWithRef(&chain) // send a reference to the original
fmt.Printf("After function with pointer: %s\n", chain)
Enter fullscreen mode Exit fullscreen mode

In this example, we declare a string variable named "chain" and assign it the value "Hello world". We then print the memory address of the "chain" variable using the "&" operator.

Next, we call the "updateValueWithRef" function and pass it a reference to the "chain" variable using the "&" operator. Inside the function, we modify the value of the variable directly in memory using the "*" operator.

After the function call, we print the value of the "chain" variable again, and we can see that it has been modified by the function.

Without Memory References

To understand the difference between using a pointer with and without memory references, let's take a look at an example of using a pointer without a memory reference:

func updateValue(chain string) {
    fmt.Printf("%p\n", &chain)
    chain = "Hello from function"
}
Enter fullscreen mode Exit fullscreen mode

In this function, we take a string variable as its argument. Inside the function, we modify the value of the variable using the "=" assignment operator.

Now, let's call this function instead of the "updateValueWithRef" function in our previous example:

chain := "hello world"
fmt.Printf("%p\n", &chain)
fmt.Printf("Before function: %s\n", chain)
updateValue(chain) // send a copy, not reference
fmt.Printf("After function: %s\n", chain)
Enter fullscreen mode Exit fullscreen mode

In this example, we call the "updateValue" function and pass it a copy of the "chain" variable. Inside the function, we modify the value of the copy using the "=" assignment operator.

After the function call, we print the value of the "chain" variable again, and we can see that it has not been modified by the function.

Full code example:

package main

import "fmt"

func main() {
    chain := "Hello world"
    fmt.Printf("%p\n", &chain)
    fmt.Printf("Before function: %s\n", chain)
    updateValue(chain) // send a copy, not reference
    fmt.Printf("After function: %s\n", chain)
    updateValueWithRef(&chain) // send a reference
    fmt.Printf("After function with pinter: %s\n", chain)
}

func updateValue(chain string) {
    fmt.Printf("%p\n", &chain)
    chain = "Hello from function"
}

// TODO - pointers *
func updateValueWithRef(chain *string) {
    fmt.Printf("%p\n", &*chain)
    *chain = "Hello from function with ref"
}

/*
    Output:
    0xc00009e230
    Before function: Hello world
    0xc00009e250
    After function: Hello world
    0xc00009e230
    After function with pinter: Hello from function with ref
*/
Enter fullscreen mode Exit fullscreen mode

Conclusion

In conclusion, pointers are a powerful feature of Golang that enable developers to write more efficient code by manipulating data directly in memory. When using pointers in functions, it's important to understand the difference between using them with and without memory references, as this can affect how the function modifies the value of the variable it points to.

By understanding how pointers and functions work together in Golang, developers can write more efficient and scalable code that takes advantage of the language's unique features.

Top comments (1)

Collapse
 
xvbnm48 profile image
M Fariz Wisnu prananda

thanks for sharing