DEV Community

Cover image for Let's Go Pointer
Adjie Djaka Permana
Adjie Djaka Permana

Posted on • Updated on

Let's Go Pointer

Pre-requisite


  • I assume that you have installed and configured Go in your machine
  • I assume you want to learn about pointer especially in Go
  • I advice you to clone my repository
git clone https://github.com/codewithdjaeger/go-with-golang.git

cd go-with-golang/pointer
Enter fullscreen mode Exit fullscreen mode

What is this Pointer?


Pointer is a special variable. It stores the memory address of where the value is stored instead of the value itself. Simply, it stores the address of someone who has something. So, when the something that is owned by the someone is changed then the value in the pointer also changed.

pointer concept

Someone's address analogically is the memory address. It is always found as a hexadecimal value (e.g. 0xFF etc.), a number starting with 0x is hexadecimal. For the real example, I'll show you this code written in Go Lang.

var someone int = 10
var pointer *int = &someone

fmt.Println("Memory address of someone is", pointer)

// Output:
// Memory address of someone is 0xc000014098
Enter fullscreen mode Exit fullscreen mode

From the example above, we know that pointer has the value of &someone and why would that happen? Despite we know that someone is assigned with 10. If you notice it already, yes, it is because of that suspicious & preceding the variable name and what exactly is it?

What Exactly Address and Dereferencing Operator Is?


It is one of two notations for declaring pointer variables. The & notation also called as address operator is used to get the memory address of the variable and it is always used preceding its variable name while the other, * notation also called as dereferencing operator, can be used preceding variable type, as the above example, or preceding its variable name.

If the address operator is used to get the memory address of its variable, so, what does the dereferencing operator do? Actually, it depends on how you use it. When it preceding variable type, it is used for declaring the pointer variable. While it is preceding its variable name, it is used to access the value that is stored in the memory address.

fmt.Println("Memory address of someone accessed by address operator is", &someone)
fmt.Println("Value of someone accessed by dereferencing operator is", *pointer)

// Output:
// Memory address of someone accessed by address operator is 0xc000014098
// Value of someone accessed by dereferencing operator is 10
Enter fullscreen mode Exit fullscreen mode

What Actually This Pointer Things Do?


To answer this question that's bother your head, first, let's take a look at this.

var someone int = 10
var someoneElse int = someone

fmt.Println("Hello, someone's value is", someone)
fmt.Println("And someone else's value is", someoneElse)

someone = 20
fmt.Print("\n")

fmt.Println("Yeay, someone's value is changed to", someone)
fmt.Println("Oh no, someone else's value still", someoneElse)

// Output: 
// Hello, someone's value is 10
// And someone else's value is 10        

// Yeay, someone's value is changed to 20
// Oh no, someone else's value still 10
Enter fullscreen mode Exit fullscreen mode

Really? So, what?

Okay, what I want to emphasize from the code above is when someone's value is changed, someoneElse's still, despite it has been assigned with the value of someone.

But why? What's wrong with that?

Okay, now take a look at this.

var someone int = 10
var someoneElse *int = &someone

fmt.Println("Hello, someone's value is", someone)
fmt.Println("And someone else's value is", *someoneElse)

someone = 20
fmt.Print("\n")

fmt.Println("Yeay, someone's value is changed to", someone)
fmt.Println("and finally, someone else's value is changed to", *someoneElse)

// Output:
// Hello, someone's value is 10
// And someone else's value is 10

// Yeay, someone's value is changed to 20
// and finally, someone else's value is changed to 20
Enter fullscreen mode Exit fullscreen mode

From the last example, both someone and someoneElse value changed. It is not because of the notation, because it's just used to accessed the value, but it is because the pointer.

The first example show us that someoneElse has the value of someone, yes, that's right. But, actually despite they have the same value, their address are different as you can see from the example below.

var someone int = 10
var someoneElse int = someone

fmt.Println("Here, someone's memory address is", &someone)
fmt.Println("And someone else's memory address is", &someoneElse)

// Output :
// Here, someone's memory address is 0xc000014098
// And someone else's memory address is 0xc0000140b0
Enter fullscreen mode Exit fullscreen mode

Yes, they're pointing to the different memory addresses and that explains why when someone's value is changed, someoneElse's not.

Are There Any Different Ways to Do Pointer in GO?


yes, there are.

Firstly, You must know that Go's compiler is smart enough to determine what type of value is assigned to a variable. So, you can use shorthand such as := to declare pointer instead of using regular declaration and let the compiler handle the rest. Take a look at the example below.

someone := 10
someoneElse := &someone

fmt.Println("Here, someone's value is", someone)
fmt.Println("And someone else's value is", *someoneElse)

// Output :
// Here, someone's value is 10
// And someone else's value is 10
Enter fullscreen mode Exit fullscreen mode

Also, the array will return a pointer when you assign its slice to a variable like the example below.

someoneArray := []int{1, 2, 3}
someoneElseArray := someoneArray

fmt.Println("Here, someone array's value is", someoneArray)
fmt.Println("And someone else array's value is", someoneElseArray)

someoneArray[0] = 10
fmt.Print("\n")

fmt.Println("Yeay, someone array's value is changed to", someoneArray)
fmt.Println("And also someone else array's value is changed to", someoneElseArray)

// Output :
// Here, someone array's value is [1 2 3]
// And someone else array's value is [1 2 3]

// Yeay, someone array's value is changed to [10 2 3]        
// And also someone else array's value is changed to [10 2 3]
Enter fullscreen mode Exit fullscreen mode

Lastly, you may use new() to return a pointer while using struct. like the example below.

package main

import "fmt"

type someoneStruct struct {
    value int
}

func main() {
    someone := new(someoneStruct)
    someoneElse := someone

    fmt.Println("Here, someone's value is", someone.value)
    fmt.Println("And someone else's value is", someoneElse.value)

    someone.value = 10
    fmt.Print("\n")

    fmt.Println("Yeay, someone's value is changed to", someone.value)
    fmt.Println("And also someone else's value is changed to", someoneElse.value)
}

// Output :
// Here, someone's value is 0
// And someone else's value is 0

// Yeay, someone's value is changed to 10        
// And also someone else's value is changed to 10
Enter fullscreen mode Exit fullscreen mode

Conclusions


  • Pointer stores the memory address of a value instead of the value itself.
  • To declare the pointer variable you must use dereferencing operator (*) and address operator (&).
  • In Go, you can use shorthand (:=) to declare pointer variable and you can use slice of array or new() on a struct to return a pointer.

Discussion (0)