Modifying data via pointers - pointers

https://play.golang.org/p/DOhYaiH53Ek
I do not understand the *&p operation nor how a pointer *p which is an int() value NOT a memory address is able to modify its value i.e. valueX = valueY. I know that I must be misunderstanding something, but this code literally appears to be self-conflicting.
//point
package main
import "reflect"
var pt int = 27
func main() {
println(reflect.TypeOf(pt))
println("pt = ", pt) //value of pt
println("&pt = ", &pt) //memory address of pt
updatePointer(&pt)
println("pt = ", pt) //value of pt
}
func updatePointer(p *int) { //requires memory address of an int
println("&p = ", &p) //memory address of p
println("p = ", p) //memory address of pt
println("*p before = ", *p) //value of pt
println(*p == 27) //true
*p = 14 //27 = 14??????????
println("*p =", *p) //value of pt
println(reflect.TypeOf(&pt) == reflect.TypeOf(*&p)) //true!!!?????
println("*&p = ", *&p) //memory address which p's memory address evals to???? 0x800 (p) -> 0x900 (pt) = 0x800 (p)?
}
/*
Why can't I do the following?
func updatePointer(p *int){
p = 14
//OR
&p = 14
//OR
*&p = 14
}
*/

Considering *&p firstly lets simplify the example (removing all of the irrelevant stuff)
var pt int = 27
p := &pt // because &pt is passed as the argument into updatePointer
*p = 14 // This assigns 14 to whatever p points to (i.e. pt)
println(reflect.TypeOf(&pt) == reflect.TypeOf(*&p))
*& does nothing (and I can see no reason to use it in a real application); the statement gets the address of p (the &p bit) and then gets what the result points at (p). So this an be rewritten
println(reflect.TypeOf(&pt) == reflect.TypeOf(p))
p is pointing to pt so p == &pt (by definition this means that *p == pt). This means they are the same thing so will, of course, have the same type.
So why does *p = 14 work? You said that "*p which is an int() value NOT a memory address is able to modify its value" but that is not quite what the spec says:
For an operand x of pointer type *T, the pointer indirection *x
denotes the variable of type T pointed to by x. If x is nil, an
attempt to evaluate *x will cause a run-time panic.
So what *p = 14 is saying is set the variable that p points to to 14.
Now lets look at your second question:
// Why can't I do the following?
func updatePointer(p *int){
p = 14
//OR
&p = 14
//OR
*&p = 14
}
So p is a pointer to an integer (thats what *int means). Saying p = 14 is an attempt to set the pointer (not the int) to the value 14. 14 is an int not a pointer hence the compiler error cannot use 14 (type int) as type *int in assignment.
&p = 14 is saying set the address of p to 14. p is a *int so getting the address will give you a **int (a pointer to a pointer to an int). The compiler error you will get is cannot assign to &p and this is because the result of &p is not addressable. You could get around that by saying
x := &p
x = 14
and this will give you the error you might expect based upon what I said above: cannot use 14 (type int) as type **int in assignment.
*&p = 14 is basically the same as saying p=14 (it gets the address of p and then gets whatever the result points at whis will be p).
Pointers can get quite confusing (especially in contrived examples) and this article may help you understand.

Simplify. For example,
package main
import "fmt"
func f(q *int) {
fmt.Println(*q, q, &q, "f")
*q = 14
fmt.Println(*q, q, &q, "f")
}
func main() {
var i int = 27
var p *int = &i
fmt.Println(*p, p, &p, i, "main")
f(p)
fmt.Println(*p, p, &p, i, "main")
}
Output:
27 0x40e020 0x40c138 27 main
27 0x40e020 0x40c148 f
14 0x40e020 0x40c148 f
14 0x40e020 0x40c138 14 main
Errors:
/*
func g(r *int) {
// cannot use 14 (type int) as type *int in assignment
r = 14
// cannot assign to &r
&r = 14
// cannot use 14 (type int) as type *int in assignment
*(&r) = 14
}
*/
Playground: https://play.golang.org/p/Hwe3anFBTfD
In Go, all arguments are passed by value, as if by assignment. A pointer p to an int i is passed by value (q = p) to function f. The pointer q, a copy of p, is used to modify the value of i, *q = 14, *q dereferences type *int to type int.
The function g compiler error messages explain why the statements are illegal. For example, *&r = 14 is *(&r) = 14 is r = 14, cannot use 14 (type int) as type *int in assignment, r is type *int.
References:
A Tour of Go
The Go Programming Language Specification

Related

C Pointer Basics

I have a question about the following code snippet:
#include <stdio.h>
int main() {
int x, *p = &x, *m = p;
//p = NULL;
//*p = NULL;
printf("%d\n", *m);
return 0;
}
When I set p = NULL and run the program, I get an indeterminate value, but if I set *p = NULL the program will print 0. I'm aware that the distinction between the two lines is setting pointer p = NULL vs the object p points to = NULL, but don't understand why the output is different.
The first line of code makes x an integer, p a pointer that points to x, and m a pointer whose value is that of p, which is the address of x.
Setting p to NULL has no effect on the value of m, which points to x.
Setting *p to NULL sets x to NULL, since p points to x. Since m also points to x, setting x to NULL causes *m (the value of x) to be zero.

Does dereferencing a struct return a new copy of struct?

Why when we reference struct using (*structObj) does Go seem to return a new copy of structObj rather than return the same address of original structObj? This might be some misunderstanding of mine, so I seek clarification
package main
import (
"fmt"
)
type me struct {
color string
total int
}
func study() *me {
p := me{}
p.color = "tomato"
fmt.Printf("%p\n", &p.color)
return &p
}
func main() {
p := study()
fmt.Printf("&p.color = %p\n", &p.color)
obj := *p
fmt.Printf("&obj.color = %p\n", &obj.color)
fmt.Printf("obj = %+v\n", obj)
p.color = "purple"
fmt.Printf("p.color = %p\n", &p.color)
fmt.Printf("p = %+v\n", p)
fmt.Printf("obj = %+v\n", obj)
obj2 := *p
fmt.Printf("obj2 = %+v\n", obj2)
}
Output
0x10434120
&p.color = 0x10434120
&obj.color = 0x10434140 //different than &p.color!
obj = {color:tomato total:0}
p.color = 0x10434120
p = &{color:purple total:0}
obj = {color:tomato total:0}
obj2 = {color:purple total:0} // we get purple now when dereference again
Go playground
When you write
obj := *p
You are copying the value of struct pointed to by p (* dereferences p). It is similar to:
var obj me = *p
So obj is a new variable of type me, being initialized to the value of *p. This causes obj to have a different memory address.
Note that obj if of type me, while p is of type *me. But they are separate values. Changing a value of a field of obj will not affect the value of that field in p (unless the me struct has a reference type in it as a field, i.e. slice, map or channels. See here and here.). If you want to bring about that effect, use:
obj := p
// equivalent to: var obj *me = p
Now obj points to the same object as p. They still have different addresses themselves, but hold within them the same address of the actual me object.
No, "assignment" always creates a copy in Go, including assignment to function and method arguments. The statement obj := *p copies the value of *p to obj.
If you change the statement p.color = "purple" to (*p).color = "purple" you will get the same output, because dereferencing p itself does not create a copy.
tl;dr Dereferencing (using the * operator) in Go does not make a copy. It returns the value the pointer points to.

panic: assignment to entry in nil map on single simple map

I was under the impression that the assignment to entry in nil map error would only happen if we would want to assign to a double map, that is, when a map on a deeper level is trying to be assigned while the higher one doesn't exist, e.g.:
var mm map[int]map[int]int
mm[1][2] = 3
But it also happens for a simple map (though with struct as a key):
package main
import "fmt"
type COO struct {
x int
y int
}
var neighbours map[COO][]COO
func main() {
for i := 0; i < 30; i++ {
for j := 0; j < 20; j++ {
var buds []COO
if i < 29 {
buds = append(buds, COO{x: i + 1, y: j})
}
if i > 0 {
buds = append(buds, COO{x: i - 1, y: j})
}
if j < 19 {
buds = append(buds, COO{x: i, y: j + 1})
}
if j > 0 {
buds = append(buds, COO{x: i, y: j - 1})
}
neighbours[COO{x: i, y: j}] = buds // <--- yields error
}
}
fmt.Println(neighbours)
}
What could be wrong?
You need to initialize neighbours: var neighbours = make(map[COO][]COO)
See the second section in: https://blog.golang.org/go-maps-in-action
You'll get a panic whenever you try to insert a value into a map that hasn't been initialized.
In Golang, everything is initialized to a zero value, it's the default value for uninitialized variables.
So, as it has been conceived, a map's zero value is nil. When trying to use an non-initialized map, it panics. (Kind of a null pointer exception)
Sometimes it can be useful, because if you know the zero value of something you don't have to initialize it explicitly:
var str string
str += "42"
fmt.Println(str)
// 42 ; A string zero value is ""
var i int
i++
fmt.Println(i)
// 1 ; An int zero value is 0
var b bool
b = !b
fmt.Println(b)
// true ; A bool zero value is false
If you have a Java background, that's the same thing: primitive types have a default value and objects are initialized to null;
Now, for more complex types like chan and map, the zero value is nil, that's why you have to use make to instantiate them. Pointers also have a nil zero value. The case of arrays and slice is a bit more tricky:
var a [2]int
fmt.Println(a)
// [0 0]
var b []int
fmt.Println(b)
// [] ; initialized to an empty slice
The compiler knows the length of the array (it cannot be changed) and its type, so it can already instantiate the right amount of memory. All of the values are initialized to their zero value (unlike C where you can have anything inside your array). For the slice, it is initialized to the empty slice [], so you can use append normally.
Now, for structs, it is the same as for arrays. Go creates a struct with all its fields initialized to zero values. It makes a deep initialization, example here:
type Point struct {
x int
y int
}
type Line struct {
a Point
b Point
}
func main() {
var line Line
// the %#v format prints Golang's deep representation of a value
fmt.Printf("%#v\n", line)
}
// main.Line{a:main.Point{x:0, y:0}, b:main.Point{x:0, y:0}}
Finally, the interface and func types are also initialized to nil.
That's really all there is to it. When working with complex types, you just have to remember to initialize them. The only exception is for arrays because you can't do make([2]int).
In your case, you have map of slice, so you need at least two steps to put something inside: Initialize the nested slice, and initialize the first map:
var buds []COO
neighbours := make(map[COO][]COO)
neighbours[COO{}] = buds
// alternative (shorter)
neighbours := make(map[COO][]COO)
// You have to use equal here because the type of neighbours[0] is known
neighbours[COO{}] = make([]COO, 0)

Please explain &, and * pointers

There have been multiple instances where the compiler throws an error when I try to pass variables as arguments inside Go functions. I've been able to debug this sometimes by using a pointer in front of the variable. Both &, and * pointers seem to clear the error. Though, I'd like to understand why. I'm wondering what the difference between &, and * is, and when each should be used. Thank you!
func (ctx *NewContext) SendNotification(rw http.ResponseWriter, req *http.Request, p httprouter.Params) {
decoder := json.NewDecoder(req.Body)
var u User
if err := decoder.Decode(&u); err != nil {
http.Error(rw, "could not decode request", http.StatusBadRequest)
return
}
}
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!
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
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
*/
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 refer address of y.
x holds the value which we pass to it using pointer to address of y.
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
For this answer I will try to explain it with a variable value. A pointer can point also to a struct value.
& returns a pointer, which points to a variable value.
* reads the variable value to which the pointer is pointing.
Example:
func zero(xPointer *int) {
*xPointer = 0
fmt.Println(*xPointer)
}
func main() {
x := 1
zero(&x)
fmt.Println(x) // x is 0
}
I would like to explain the concept of pointers(* and &) with an example:
Think of an example where we want to increment a variable by 1 with help of a function.
package main
import (
"fmt"
)
func main() {
x := 7
fmt.Print(inc(x))
}
func inc(x int) int {
return x + 1
}
Explanation of above: We have a function func inc(x int) int which takes an integer and returns an integer with performing an increment.
Note: Kindly pay attention that func inc(x int) int returns an int, Now what happens if we do not have a return type with that
function?? This is solved by the pointer.
Look at the below code:
package main
import (
"fmt"
)
func main() {
x := 7
inc(&x)
fmt.Print(x)
}
func inc(x *int) {
*x++
}
Explanation of the above code:
Now as our function func inc(x *int) does not have a return type we cannot get any incremented value from this function but what we can do is that we can send a location(address) to this function and tell it to increment the value at this location by one and now we can access that location from inside main() and our job is done.
A quick tip: * in front of a variable means what is stored in that variable?? and & in front of a variable means what is the internal address of that variable?

Type conversion from (type *int) to type int

I want to convert a pointer *int to its real value int, in Go language.
How do you do it?
Just use the * operator. For example:
var i int = 10 // `i` is an integer, with value 10
var p *int = &i // `p` is a pointer to an integer, its value is a memory address
var n int = *p // `n` is again an integer, with value 10
Once you get the hang of what's happening, the above code can be written in a more idiomatic (and simpler) way like this, assuming that we're inside a function:
i := 10
p := &i
n := *p

Resources