Does dereferencing struct pointer copy the struct? - pointers

I have this code:
type countHolder struct {
count int
}
func main() {
a := &countHolder{1}
b := *a
a.count = 2
println(b.count)
}
I expected the output to be 2, but the output was 1.
My understanding was that:
a := &countHolder{1} // a is pointer to struct with data starting at address x
b := *a // b now equals address x
a.count = 2 // the struct stored at address x has its count value changed to 2
Where am I wrong? is b := *a creating a copy of the struct?

From the fine specification:
For an operand x of type T, the address operation &x generates a pointer of type *T to x. [...]
For an operand x of pointer type *T, the pointer indirection *x denotes the variable of type T pointed to by x. [...]
That means that the unary & operator gives you the address of something so a in:
a := &countHolder{1}
is a pointer. The unary * operator in:
b := *a
dereferences the pointer a and leaves you with a countHolder struct on the right side so b is a copy of the struct that a points to. Since b is a copy of the struct, modifying a.count:
a.count = 2
(which could also be written as (*a).count = 2) won't have any affect on b.
You could also have a look at (https://play.golang.org/p/Zubs8qYBA_K):
func main() {
a := &countHolder{1}
b := *a
fmt.Printf("%T\n%T\n", a, b)
}
to have a quick look at what types a and b are (*counterHolder and counterHolder, respectively, in this case).

Related

Pointer in func parameter: copy by value or by pointer

here is the code:
package main
import "fmt"
func double(x *int) {
fmt.Printf("pointer of pointer #1: %p\n", &x)
fmt.Printf("pointer#1 : %p\n", x)
*x += *x
x = nil
fmt.Printf("pointer#2 : %p\n", x)
fmt.Printf("pointer of pointer #2: %p\n", &x)
}
func main() {
var a = 3
double(&a)
fmt.Println(a) // 6
fmt.Printf("pointer a in main: %p\n", &a)
p := &a
double(p)
fmt.Println(a, p == nil) // 12 false
fmt.Printf("pointer p in main: %p\n", p)
fmt.Printf("pointer of pointer p in main: %p\n", &p)
}
or in playground.
Question 1: pointer parameters in functions get copy of pointer or get directly pointer?
Question 2: why value x in double function is the same as &a in main func?
Question 3: if x has the same value as &a then why when x = nil &a stil has value and not nil?
Question 1: pointer parameters in functions get copy of pointer or get directly pointer?
The distinction this question is trying to make suggests a certain lack of background understanding.
Think of a pointer as a number / address which can be used to access some other data. A copy of this address just copies a number. Is 42 the same as a "copy of 42"? Yes, in a sense.
x := &value // x holds the address of value now
y := x // and now y does, too
Given the above two lines, assigning x to something else does absolutely nothing to change value or &value. It simply reassigns x to another address. However, doing something like *x = 999 changes value itself because x holds the address of value and the redirection *x means access to value.
If this isn't 100% clear, try to work through the Tour of Go starting here.
Question 2: why value x in double function is the same as &a in main func?
Because of the explanation above. &a is the address of a - it's a number, think 42 again (the real address is something like 0x40e020, but let's call it 42 for simplicity). When you pass it into a function accepting a *int, 42 gets copied and x in double becomes 42. Now both x inside double and &a outside it have the address of a in them.
Question 3: if x has the same value as &a then why when x = nil &a stil has value and not nil?
Because x just has the value 42 in it, which happens to be the address of a. If you assign anything else to x, that doesn't change the address of a, does it? It changes x. x will no longer point to a.

go's big.Int underlying value mutates when value points to another instance

I have come across a bit of unexplained behavior of go's big.Int when pointing an instance of one big.Int to another.
I am knowledgeable that in order to set a value of a bit.Int's instance to another, one must use the Int.SetXXX setters, because they actually cause the underlying abs slice in big.Int to be copied to a newly allocated array. However, putting that aside for a moment, I'd like to know why the following behavior occurs.
Consider the following:
Wrong example (underlying value mutates):
func main() {
v1p := big.NewInt(1)
v2p := big.NewInt(2)
v1 := *v1p
v2 := *v2p
v2 = v1
v1.SetInt64(3)
fmt.Println(v1.Int64(), v2.Int64())
}
(run here: https://play.golang.org/p/WxAbmGdKG9b)
Correct example (value does not mutate):
func main() {
v1p := big.NewInt(1)
v2p := big.NewInt(2)
v1 := *v1p
v2 := *v2p
v2.Set(v1p)
v1.SetInt64(3)
fmt.Println(v1.Int64(), v2.Int64())
}
(run here: https://play.golang.org/p/16qsGhwHIWf)
If I understand correctly, the following should essentially demonstrate what happens in the wrong example:
func main() {
var a, b *int // analogous to the 2 big.Int pointers returned
c, d := 3, 3
a = &c // we set the pointers to point to something we can then dereference
b = &d
e := *a // e and f should now point to the values pointed to by the pointers
f := *b
// the rest is self-explanatory
e = f
c = 5
d = 4
fmt.Println(a, b, c, d, e, f)
}
(run here: https://play.golang.org/p/cx76bnmJhG7)
My only assumption is that somehow when copying the struct content onto v2 in the Wrong example, what happens is that abs slice does not get deep-copied but that the storage that it references is actually the same storage that the slice in v1 points to.
Is this really what happens? Is this the expected behavior according to the language spec too?
As pointed out by icza and Volker, since when dereferencing the big.Int pointer the actual value slice header struct is copied, pointing to the same underlying value, the resulting behavior is that the same underlying array gets referenced from multiple slices, resulting in one altering the other.

When does a pointer variable has its address changed?

Consider the following example and notice how the location of pointer variable a remains fixed, as expected:
var a *int
v1 := 1
v2 := 2
a = &v1
fmt.Printf("%p\n", &a) // output: 0x1040c128
a = &v2
fmt.Printf("%p\n", &a) // output: 0x1040c128
Now consider the following struct definition:
type foo struct {
bar int
}
If a is declared as a pointer variable to foo as in this example, its location in memory does not remain fixed.
var a *foo
v1 := foo{bar: 1}
v2 := foo{bar: 2}
a = &v1
fmt.Printf("%p\n", a) // output: 0x10414020
a = &v2
fmt.Printf("%p\n", a) // output: 0x10414024
Why is that?
Are you sure you just didn't make a typo and used fmt.Printf("%p\n", a) instead of fmt.Printf("%p\n", &a) because the first one uses &a and your second example uses a.
Long answer:
With
fmt.Printf("%p\n", a)
you're printing out the value of a which is of type *foo which is a pointer. Roughly speaking a pointer is a variable holding an address of a memory location. With
a = &v1
you set a to the address of v1
a = &v2
you set a to the address of v2. v1 and v2 have different locations in memory and thus you when you print the value of a you'll see exactly that.
If you use
var a *foo
v1 := foo{bar: 1}
v2 := foo{bar: 2}
a = &v1
fmt.Printf("%p\n", &a)
a = &v2
fmt.Printf("%p\n", &a)
then you'll see the same number printed twice because now you're printing out the location of a. So:
a = &v
fmt.Printf("%p\n", a) // prints location of v, not location of a
a = &v
fmt.Printf("%p\n", &a) // prints location of a, not location of v
Remark:
There's some ambiguity as to what people call a pointer and what an address. Some say that a pointer is an address because it contains an "address of a memory location" but a pointer is not actually a memory address depending on the exact context. Also, a points to b usually means that a is a pointer containing the address of b. Likewise, &v is either referred to as "the address of v" and "a pointer to v" which (at least in my opinion) are equally correct which is why I originally used "set a to a pointer to v".

Assign result of reflect.AppendSlice to pointer

I have troubles translating this piece of code, which is effectively a left rotate on a slice, into a more generic version which accepts interface{} as an input parameter.
func rotate(a *[]int, i int) {
x, b := (*a)[:i], (*a)[i:]
*a = append(b, x...)
}
I have troubles with the final assignment:
func rotateSlice(a interface{}, i int) {
v := reflect.ValueOf(a)
x, b := v.Elem().Slice(0, i), v.Elem().Slice(i, v.Elem().Len())
*a = reflect.AppendSlice(b, x)
}
The error message is invalid indirect of a (type {}). The value of a is interface{}, hence *a = would be to assign the right-hand value to the space where the pointer is pointing to. My call to AppendSlice returns Value though. I am not sure where the type assertion needs to happen, I suppose on the left-hand side?
a is an interface{} not a pointer, so you can't dereference it. Even if you have a pointer to a slice, you can't assigned the result ofreflect.AppendSlice, because it returns the type reflect.Value. You need to set the value via Value.Set.
https://play.golang.org/p/JCF8jsRJ_O
func rotateSlice(a interface{}, i int) {
v := reflect.ValueOf(a).Elem()
x, b := v.Slice(0, i), v.Slice(i, v.Len())
v.Set(reflect.AppendSlice(b, x))
}
Eliminate the use of the reflect package in Go 1.18 and later by using generics:
func rotateSlice[T any](a []T, i int) []T {
x, b := a[:i], a[i:]
return append(b, x...)
}
Call it like this: x = rotateSlice(x, 2)
Here's now to implement rotate using the reflect package.
Use Value.Set to set the value in the slice.
func rotateSlice(a interface{}, i int) {
v := reflect.ValueOf(a).Elem()
x, b := v.Slice(0, i), v.Slice(i, v.Len())
v.Set(reflect.AppendSlice(b, x))
}
Call the function with a pointer to a slice:
a := []string{"a", "b", "c", "d"}
roateSlice(&a, 2)
Run all of the examples on the playground.

What does range or map return?

Go has very neat multiple return values paradigm. But It looks like v, ok := map[key] and v, k := range m use different mechanism with same notation. Here is a simple example:
func f2() (k, v string) {
return "Hello", "World"
}
func main(){
k := f2() // Doesn't work : multiple-value f2() in single-value context
m := map[string]int{"One": 1}
// It works
v, ok := m["One"]
// How it all work?
v := m["One"]
for k := range m {}
}
In above example, k := f2() gives error as f2 returns two values, whereas v, ok := m["One"] and v := m["One"] - both expressions work without any error.
Why is that different behavior?
A fetch from the built in map, using range on a map, array or slice, and also type assertions allows for one or two variables. This is not the case for user defined functions and methods. If a function declares two return values, you must tell what to do with both of them, or ignore both:
k, _ := f2() // Specify what to do with each returned value
f2() // Ignoring both
Why? Because the specification says it is so:
Map (indexed expressions):
An index expression on a map a of type map[K]V may be used in an assignment or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
where the result of the index expression is a pair of values with types (V, bool). In this form, the value of ok is true if the key x is present in the map, and false otherwise. The value of v is the value a[x] as in the single-result form.
Range (for statement):
For each iteration, iteration values are produced as follows:
Range expression: m map[K]V
1st value: key k K
2nd value (if 2nd variable is present): m[k] V
Type assertion:
For an expression x of interface type and a type T, the primary expression
x.(T)
asserts that x is not nil and that the value stored in x is of type T.
and
If a type assertion is used in an assignment or initialization of the form
v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
the result of the assertion is a pair of values with types (T, bool)

Resources