DEV Community

Cover image for Go Functions: Pointer vs Value params
Bruno Henrique Gusmão Vasconcelos
Bruno Henrique Gusmão Vasconcelos

Posted on

Go Functions: Pointer vs Value params

In Golang we have the concept of pointers. It works similar to languages like C, C++ and represents the memory address where the variable value is stored.

You can see more about pointers here, since it is not the objective of this post.

From this concept, we can have functions that works with pointer params and value params.

The difference is the way we declare the function and how the variable will be handled during manipulation.

The code

To better explain the differences we will create a struct so we can manipulate its attributes inside the function, declare a variable with the struct type, and the functions. One with pointer param and a function with value param.

So, we will have the struct User containing Name and Github:

type User struct {
    Name   string
    Github string
}

And the functions responsible to change the Name attribute and print the struct values.

func changeAndLogPointer(user *User) {
    user.Name = "Bruno Vasconcelos"
    fmt.Printf("Name: %s, Github: %s\n", user.Name, user.Github)
}

func changeAndLogValue(user User) {
    user.Name = "Bruno Vasconcelos"
    fmt.Printf("Name: %s, Github: %s\n", user.Name, user.Github)
}

Note that the first one (changeAndLogPointer) receives a pointer and the second one (changeAndLogValue) a value.

So we will execute a main function that uses the pointer approach

func main() {
    user := &User{Name: "Bruno", Github: "brunohgv"}
    changeAndLogPointer(user)
    fmt.Printf("Name: %s, Github: %s\n", user.Name, user.Github)
}

The result of the execution is:

Name: Bruno Vasconcelos, Github: brunohgv
Name: Bruno Vasconcelos, Github: brunohgv

It happens because when a pointer is used, all changes are related to the memory address that the value is stored. I means that any changes to the parameter will impact the variable that was passed as param.

Now we will execute the function using a value:

func main() {
    user := &User{Name: "Bruno", Github: "brunohgv"}
    changeAndLogValue(*user)
    fmt.Printf("Name: %s, Github: %s\n", user.Name, user.Github)
}

And the result is:

Name: Bruno Vasconcelos, Github: brunohgv
Name: Bruno, Github: brunohgv

Why is this happening?
Since we are passing the value as parameter, the Go compiler will create another memory space to handle this variable internally. It means that any changes inside the function will impact in an internal variable, keeping the original one untouched.

So, what is the best approach?

Well, it depends. The pointer is a better option if you want to change the original value, than use that modified values in the future.
If your objective is to prevent changes and manipulate it only inside the function, the value is the best approach.

There are other usages for any of the approaches, but understand the basics is the best way to decide what will be the best choice for your application.

Discussion (0)