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,
pointerToY
holds the pointer to referaddress
ofy
.x
holds the value which we pass to it usingpointer
toaddress
ofy
.- After changing the value of
y
, thex
still has10
but if we try to access the value usingpointer
toaddress
(pointerToY) , we get4
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