Method does not change the value of object if the object is in a slice - pointers

Here is my program:
package main
import (
"fmt"
)
type Number struct {
val int
}
func (num * Number) Increment () {
num.val += 1
}
func (num Number) Value() int {
return num.val
}
func main() {
numbers := []Number {
{val: 12},
{val: 7},
{val: 0},
}
for _, each := range numbers {
each.Increment()
fmt.Println(each.Value())
}
for _, each := range numbers {
fmt.Println(each.Value())
}
}
Here is the output:
13
8
1
12
7
0
First question: why does the Increment()method not update the value in the first for loop? I used pointer as the receiver so that val can be updated for sure, but why would the second for loop print out the original values of those Numbers?
Second question: what can be done so that when I iterate over a slice of Numbers and invoke the Increment() method, all Numbers are correctly incremented?
[Edit] I noticed that if I use index-based for loop and invoke the Increment() method, values will be correctly updated. Why?
for i := 0; i < len(numbers); i++ {
numbers[i].Increment()
}

This for range loop:
for _, each := range numbers {
iterates over the elements of the numbers slice, and in each iteration it assigns (copies) an element to the each loop variable.
Since your numbers slices is of type []Number, it will copy the Number struct into the each variable (whose type will be Number).
Then you call the Number.Increment() method on this variable. Since Increment() has pointer receiver, this is a shorthand for (&each).Increment(). So the address of this loop variable is taken and used as the receiver for the Increment() method. The Increment() method will properly change this loop variable, but this is independent, distinct, detached from the slice, so you are not modifying the element in the slice.
When you do:
for i := 0; i < len(numbers); i++ {
numbers[i].Increment()
}
Elements of numbers are not copied here. This:
numbers[i].Increment()
Indexes the numbers slice, and since Increment() has a pointer receiver, the address of numbers[i] is taken and used, which is the address of the element in the slice. So here, you will modify the Number struct value of the slice.
Note that you can also use for range here:
for i := range numbers {
numbers[i].Increment()
}
The first iteration variable when ranging over a slice is the index.
Also, if you would store pointers in your numbers slice (which would then have type of []*Number), the same thing would happen, but in that case the for range would copy pointers, not structs, and the pointer in the loop variable would point to the same Number struct value as the pointer in the slice would, so that would also work with your first for range variant.
All these are detailed in Spec: For statements, in the For statements with range clause subsection.

In your original version, the loop variable each is a copy of the Number struct. Notice that it is not a pointer to it, nor is it the copy of a pointer to it. That means, that there is a newly created Number in each iteration. You call a method on a pointer to this newly created instance, then it gets destroyed after the loop and your original data has not changed.
If you would instead use numbers := []*Number { ... and iterate over that, the each variable would be the copy of a pointer to Number. Using copies of pointers is the same as using pointers, because the copy points to the same memory location, thus if you then call the method, the data in the slice wil change.
For your edit: if you use numbers[i] then you reference the data inside the slice, obviously. As I stated above, the for range loop will create a copy of the items in its each variable.

Whenever you loop through the slice it creates a copy of original variable which is used as value and is incremented. But when you are using the index you are pointing to the value backed at that address which is than incremented and hence original value got changed.
Print the value of both variable to see the changes as:
for i, each := range numbers {
each.Increment()
fmt.Println(each, numbers[i])
}
you can also print the address of variable in a loop with the original value address to see that both variables have different address. Hence you are actually creating a local variable when iterating over numbers.
for i, each := range numbers {
each.Increment()
fmt.Printf("%p -- %p\n",&each, &numbers[i])
}
Working Code to check address on Go Playground

Related

Address of an element appended to a slice

I want to create element, add it to the slice and change it by its address. I expect that the change of the element from the outside will change also a slice. But after the addition, a new slice is created. I use serialization, so the use of an slice of addresses is not suitable, also the addition of elements occurs in different goroutines, so accessing the last added element is also not suitable.
package main
import (
"fmt"
)
func main() {
var a []int
b := 1
fmt.Println("old addr:", &b)
// old addr: 0x10414020
a = append(a, b)
fmt.Println("new addr:", &a[0])
// new addr: 0x10414028
}
play golang example
This is not an issue of append() creating a new slice header and backing array.
This is an issue of you appending b to the slice a, a copy of the value of the b variable will be appended. You append a value, not a variable! And by the way, appending (or assigning) makes a copy of the value being appended (or assigned).
Note that the address of b and a[0] will also be different if you do not call append() but instead preallocate the slice and simply assign b to a[0]:
var a = make([]int, 1)
b := 1
fmt.Println("old addr:", &b)
// old addr: 0x10414024
a[0] = b
fmt.Println("new addr:", &a[0])
// new addr: 0x10414020
Try it on the Go Playground.
The reason for this is because the variable b and a are distinct variables; or more precisely the variable b and a's backing array reserving the memory for its elements (including the memory space for a[0]), so their addresses cannot be the same!
You cannot create a variable placed to the same memory location of another variable. To achieve this "effect", you have pointers at your hand. You have to create a pointer variable, which you can set to point to another, existing variable. And by accessing and modifying the pointed value, effectively you are accessing and modifying the variable whose address you stored in the pointer.
If you want to store "something" in the a slice through which you can access and modify the "outsider" b variable, the easiest is to store its address, which will be of type *int.
Example:
var a []*int
b := 1
fmt.Println("b's addr:", &b)
a = append(a, &b)
fmt.Println("addr in a[0]:", a[0])
// Modify b via a[0]:
*a[0] = *a[0] + 1
fmt.Println("b:", b)
Output (try it on the Go Playground):
b's addr: 0x10414020
addr in a[0]: 0x10414020
b: 2
Assigning values always lets the runtime allocate new memory for the copied value and that allocated memory will have another address. If you append to a slice of values, you will always copy the variable.
If you have to access the elements from different go routines, you will have to make it thread safe. You have to do that, whether you are using values or references.
Quoted program behaves perfectly correct - addresses denote storage locations, b int is one such location and element inside the slice is other one.
You most probably need to store pointers not ints.
Now with regard to serialization - I am not sure what kind do you have in mind, but in general you could proceed like below:
type myArray []*int
var a myArray
//...
func (x myArray) Serialize() []byte { .... }
Where Serialize satisfies the interface used by your serializator.

What use case does pointers to pointer (eg **int) have?

This is pointers to pointers
package main
import "fmt"
func main() {
var num int
fmt.Println(&num) // 0x...0
makePointer(&num)
}
func makePointer(firstPointer *int) {
fmt.Println(firstPointer) // 0x...0
fmt.Println(&firstPointer) // 0x...1
makePointerToAPointer(&firstPointer)
}
func makePointerToAPointer(secondPointer **int) {
fmt.Println(secondPointer) // 0x...1
fmt.Println(&secondPointer) // 0x...2
}
When would you actually use this? You can properly come up with something where it would be easier to do something else, but that is not what I asking about. I really want to know where in production you would use this?
Pointers to pointers make sense in function parameters sometimes; not **int probably, but a pointer to a pointer to some struct, where you want the function to be able to change what object a variable points to, not just to change the contents of the struct. For example, there are a few functions in the internals of the Go compiler that take a **Node (see cmd/compile/internal/gc/racewalk.go).
I've also written a couple of functions myself that take a **html.Node; they operate on an HTML page that may or may not have already been parsed into a tree of *html.Nodes, and they may or may not need to parse the pageā€”but if they do, I want to keep the parsed tree around so that I don't have to parse it again. These are in github.com/andybalholm/redwood/prune.go.
They are much more common in languages that do not have multiple return values, since they can be used as a way to return an additional value that is a pointer. Many Objective-C methods take an NSError** as their last parameter so that they can optionally return an NSError*.
The goal to pass a pointer to something is if there is need to modify the pointed value. (We also use pointers to avoid copying large data structures when passing, but that is just for optimization.)
Like in this example:
func main() {
var i int
fmt.Println(i)
inc(&i)
fmt.Println(i)
}
func inc(i *int) {
*i++
}
Output is the expected (try it on the Go Playground):
0
1
If parameter of inc() would receive an int only, it could only modify the copy and not the original value, and so the caller would not observe the changed value.
Same goes with pointer to pointer to something. We use pointer to pointer to something, if we need to modify the pointed value, that is the pointed pointer. Like in this example:
func main() {
var i *int
fmt.Println(i)
alloc(&i, 1)
fmt.Println(i, *i)
setToNil(&i)
fmt.Println(i)
}
func alloc(i **int, initial int) {
*i = new(int)
**i = initial
}
func setToNil(i **int) {
*i = nil
}
Output (try it on the Go Playground):
<nil>
0x1040a130 1
<nil>
The reason why pointer to pointer is not really used is because modifying a pointed value can be substituted by returning the value, and assigning it at the caller:
func main() {
var i *int
fmt.Println(i)
i = alloc(1)
fmt.Println(i, *i)
i = setToNil()
fmt.Println(i)
}
func alloc(initial int) *int {
i := new(int)
*i = initial
return i
}
func setToNil() *int {
return nil // Nothing to do here, assignment happens at the caller!
}
Output is the same (address might be different) (try it on the Go Playground):
<nil>
0x1040a130 1
<nil>
This variant is easier to read and maintain, so this is clearly the favored and wide-spread alternative to functions having to modify a pointer value.
In languages where functions and methods can only have 1 return value, it usually requires additional "work" if the function also wants to return other values besides the pointer, e.g. a wrapper is to be created to accommodate the multiple return values. But since Go supports multiple return values, need for pointer to pointer basically drops to zero as it can be substituted with returning the pointer that would be set to the pointed pointer; and it does not require additional work and does not make code less readable.
This is a very similar case to the builtin append() function: it appends values to a slice. And since the slice value changes (its length increases, also the pointer in it may also change if a new backing array needs to be allocated), append() returns the new slice value which you need to assign (if you want to keep the new slice).
See this related question where a pointer to pointer is proposed (but also returning a pointer is also viable / preferred): Golang: Can the pointer in a struct pointer method be reassigned to another instance?
In the same way a pointer to a value lets you have many references to the same value for a consistent view of the value when it changes, a pointer to a pointer lets you have many references to the same reference for a consistent view of the pointer when it changes to point to a different location in memory.
I can't say I've ever seen it used in practice in Go that I can think of.

Modify dereferenced struct pointer changes most struct values, but not slices

I'm trying to create a shallow copy of a struct Board (a chessboard). Before saving a move to the board, I need to check if that move puts the mover in check.
To do so, within the Move method (method of a pointer), I dereference the pointer, update and check this possible board for Check. When I change the value of a single value of the Board type (such as possible.headers = "Possible Varient") the original b Board is not changed.
But here when I call a method updateBoard() it updates both boards. I still receive the error (cannot move into check), but the main thread thinks b.board (the board position) has been changed.
func (b *Board) Move(orig, dest int) error {
// validation
...
// Update
possible := *b // A 'shallow copy'?
possible.updateBoard(orig, dest, val, isEmpassant, isCastle)
king := possible.findKingPositionOfThePlayerWhoMoved()
isCheck := possible.isInCheck(king) // bool takes the king to check for
if isCheck {
return errors.New("Cannot move into Check")
}
b.updateBoard(orig, dest, val, empassant, isCastle)
return nil
Strangely, not all the the values updated by updateBoard() change. So the b.toMove value doesn't change, but the b.board value does (the position of the pieces). This means if I pass possible := b instead, the game will only ever be white's move (toMove is alternated in the updateBoard() method). With possible := *b, turn alternation works until one moves into check. Then the move is applied to b.board, but the error is thrown back and it remains the checked-players turn (meaning possible.updateBoard() didn't update b.toMove.
Edit
As abhink pointed out, in Go Slices usage and internals,
Slicing does not copy the slice's data. It creates a new slice value that points to the original array.
b.board, a []byte, always points to its original value (even when the struct which holds it is dereferenced. abhink's answer uses the Go func copy(dst, src []Type) int, https://golang.org/pkg/builtin/#copy , a shortcut for copying the values of the pointers.
Since b.board is a slice type, it is a reference type (https://blog.golang.org/go-slices-usage-and-internals) and behaves like a pointer. So any changes made to possible.board will show up in b. You can try making a copy of b.board like so:
func (b *Board) Move(orig, dest int) error {
// validation
...
// Update
possible := *b // A 'shallow copy'?
boardCopy := make([]byte, len(b.board))
copy(boardCopy, b.board)
possible.board = boardCopy
possible.updateBoard(orig, dest, val, isEmpassant, isCastle)
// ...
Note that you'll have to do something like this for all reference types.
Dereferencing does NOT make a copy. It returns the original value your pointer points to.
You get a copy because you are assigning that value to a new variable. In go every assignment makes a copy as does every pass to a function. If you assign or pass a reference, that reference is copied.
In your case you copy the value b points to. In that struct there are pointers like the b.board slice (slices have a pointer to an underlying array). So go is creating a copy of the slice. The copy still points to the same array as the slice in the original b variable. If you change that array, it is changed for both your boards.
You will need to implement a copy function to your Board struct that correctly creates a copy of your struct handling each variable depending on its type and returns that new board.
Something like:
func (b *Board) copy() *Board {
boardCopy := make([]byte, len(b.board))
copy(boardCopy, b.board)
return &Board{
moveTo: b.moveTo,
board: boardCopy
...
}
}
Hope that helps and my explanation wasn't confusing :)

After copying the original object is still being modified

In the following code why is the value of n being modified? (playground link)
package main
import (
"fmt"
"math/big"
)
func main() {
n := big.NewInt(5)
nCopy := new(big.Int)
*nCopy = *n
// The values of "n" and "nCopy" are expected to be the same.
fmt.Println(n.String(), nCopy.String(), &n, &nCopy)
nCopy.Mod(nCopy, big.NewInt(2))
// The values of "n" and "nCopy", I would think, should be different.
fmt.Println(n.String(), nCopy.String(), &n, &nCopy)
}
Reading this answer seems to say that the third line in my example's main() should make a copy of the contents of n. The addresses of the two variables which are output in the two Println statements also seem to show that the two big.Ints are stored in separate memory locations.
I realize that instead of using *nCopy = *n I could use nCopy.Set(n) and my final Println would display what I expect it to. But I am curious why *nCopy = *n seems to retain a "link" between the two pointers.
An Int is a struct with a nat field. A nat is a slice.
When you copy the Int, the original and copy share the backing array for the nat. Modifications through one Int to the backing array are visible to the other Int.
Assignment is not a deep copy. Assignment of a struct value is equivalent to assigning the fields in the struct individually. Assignment of a slice does not copy the backing array.

How can I access variables in vector<struct> *obj?

How would I get my variables out of a vector?
I can't use the binary insertion operators or the equal operators.
Earlier, I declared a vector<someStruct> *vObj and allocated it, then returned the vObj
and called it in this function:
vector<sameStruct> firstFunc();
for (unsigned int x = 0; x < v->size(); x++)
{
v[x];
}
when I debug it, v[x] now has the full contents of the original vector, as it did before without the subscript/index.
But I don't think I've done anything to progress beyond that.
I just have about 4 variables inside my vector; when I debug it, it has the information that I need, but I can't get to it.
As it is written v is a pointer to a vector of structs.
When you index directly into v all you are doing is pointer arithmatic. v[x] is the vector of structs at position x (assuming that v is an array if it is just a single object at the end of the pointer then v[x] for x>0 is just garbage). This is because it is applying the [x] not to the vector pointed to by v but to the pointer v itself.
You need to dereference the pointer and then index into the vector using something like:
(*v)[x];
At this point you have a reference to the object at the xth position of the vector to get at its member functions / variables use:
(*v)[x].variable;
or
(*v)[x].memberfunction(parameters);
If you do not want to dereference the vector then access the element within it you might try something like:
v->at(x);
v->at(x).variable;
v->at(x).memberfunction;
This way you are accessing a member function of an object in exactly the same manner as when you called:
v->size();
I hope that this helps.
To use the [] operator to access elements you must do so on object, not a pointer to an object.
Try;
(*vec)[x];
E.g.
for (int i = 0; i < vec->size(); i++)
{
printf("Value at %d is %d\n", i, (*vec)[i]);
}
Note that when calling functions on a pointer you usually use the -> operator instead of the . operator, but you could easily do (*vec).some_func(); instead.
Operators such as [], --, ++ and so on can act both on objects and pointers. With objects they act as function calls, but on pointers they act as mathematical operations on the address.
For example;
pointer[nth];
*(pointer + nth);
Have exactly the same effect - they return the nth object from the start of the pointer. (note the location of the * in the second example, it's called after the offset is applied.
Two other tips;
You can also avoid the need to dereference like this by passing the vector as a reference, not a pointer. It's not always a suitable option but it does lead to cleaner code.
void my_func(std::vector<int>& vector)
{
// vector can then be used as a regular variable
}
If you're going to be passing vectors of a specific type to functions a lot then you can use a typedef both for clarity and to save on typing.
typedef std::vector<int> IntVector;
void my_func(IntVector& vector)
{
}

Resources