Please explain &, and * pointers

pointer is used to point towards address and it stores the memory address

Adding one example to help understand pointer vs address:

Demo code

package main

import "fmt"

func main() {
    var y int
    var pointerToY *int
    var x int
    //var willThrowErrorVariable int

    y = 10
    pointerToY = &y
    //willThrowErrorVariable = &y 
    x = *pointerToY

    fmt.Println("y: ",y)
    fmt.Println("y's address using pointerToY: ",pointerToY)

    y = 4
    fmt.Println("====================================================")
    fmt.Println("Address of y after its value is changed: ",pointerToY)
    fmt.Println("value of y using pointer after its value is changed: ",*pointerToY)
    fmt.Println("Value of x after y value is changed: ",x)
}

output

y:  10
y's address using pointerToY:  0x414020
====================================================
Address of y after its value is changed:  0x414020
value of y using pointer after its value is changed:  4
Value of x after y value is changed:  10

As we can see, the value might change but the address(&) remains same and so the pointer(*) points to the value of address.

In above example,

  1. pointerToY holds the pointer to refer address of y.
  2. x holds the value which we pass to it using pointer to address of y.
  3. After changing the value of y , the x still has 10 but if we try to access the value using pointer to address (pointerToY) , we get 4

In your example above you defined u as type User, but not a pointer to a User. So you need the &u because the Decode function in the json package is expecting an address or pointer.

If you created the instance of User like this: u := new(User) it would be a pointer since the new function returns a pointer. You could also create a pointer to a user like this: var u *User. If you did either of those, you would have to take out the & in the call to Decode for it to work.

Pointers are basically variables that hold addresses. When you put the & in front of a variable it returns the address. The * could be read as 'redirect of'. So when you create a pointer like this:

var x *int

This can be read as x will redirect to an int. And when you assign a value to x you would give it an address like this: y := 10 x = &y

Where y is some int. So if you were to print out x, you would get the address of y, but if you printed out *x you would redirect to the what x points to which is y's value which is 10. If you were to print out &x, you would get the address of the pointer, x, itself.

If you tried to print out *y, which is just an int, not a pointer, it would throw an error because you would be redirecting with some value that is not an address to redirect to.

Run the below for some pointer fun:

package main

import "fmt"

func main() {
    var y int
    var pointerToY *int
    var pointerToPointerToInt **int

    y = 10
    pointerToY = &y
    pointerToPointerToInt = &pointerToY

    fmt.Println("y: ", y)
    fmt.Println("pointerToY: ", pointerToY)
    fmt.Println("pointerToPointerToInt: ", pointerToPointerToInt)

    fmt.Println("&y: ", &y)     // address of y
    fmt.Println("&pointerToY: ", &pointerToY)// address of pointerToY
    fmt.Println("&pointerToPointerToInt: ", &pointerToPointerToInt) // address of pointerToPointerToInt

    // fmt.Println(*y) throws an error because 
    // you can't redirect without an address.. 
    // y only has int value of 10
    fmt.Println("*pointerToY: ", *pointerToY) // gives the value of y
    fmt.Println("*pointerToPointerToInt: ", *pointerToPointerToInt)     // gives the value of pointerToY which is the address of y

    fmt.Println("**pointerToPointerToInt: ", **pointerToPointerToInt)    // this gives 10, because we are redirecting twice to get y

    if pointerToY == *pointerToPointerToInt {
        fmt.Println("'pointerToY == *pointerToPointerToInt' are the same!")
    }

    if pointerToY == &y {
        fmt.Println("'pointerToY == &y' are the same!")
    }

    if &pointerToY == pointerToPointerToInt {
        fmt.Println("'&pointerToY == pointerToPointerToInt' are the same!")
    }

    if y == **pointerToPointerToInt {
        fmt.Println("'y == **pointerToPointerToInt' are the same!")
    }

    if pointerToY == *pointerToPointerToInt {
        fmt.Println("'pointerToY == *pointerToPointerToInt' are the same!")
    }

}

Hope this helps!


A simple example showing the code execution sequence.

   import (
        "fmt"
    )

    func main() {
        x := 0
        fmt.Println("Step 1", x)
        foo(&x)
        fmt.Println("Step 4", x)
    }

    func foo(y *int) {

        fmt.Println("Step 2", *y)
        *y = 100
        fmt.Println("Step 3", *y)
    }
/*
 Steps  Result
   1      0
   2      0
   3      100
   4      100
 */

I will quote one smart dude:

& in front of variable name is used to retrieve the address of where this variable’s value is stored. That address is what the pointer is going to store.

* in front of a type name, means that the declared variable will store an address of another variable of that type (not a value of that type).

* in front of a variable of pointer type is used to retrieve a value stored at given address. In Go speak this is called dereferencing.

source: http://piotrzurek.net/2013/09/20/pointers-in-go.html

Tags:

Pointers

Go