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

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 :)

Related

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

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

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.

Passing by reference and value in Go to functions

I am a bit confused about passing by reference and value in Go.
I've seen this explained of the * in front of a type.
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).
This just doesn't make sense to me.
In Java if I was passing a Database instance into a function I would do
databaseFunction(DatabaseType db) {
// do something
}
However in the go example I have it's passed like so.
func PutTasks(db *sql.DB) echo.HandlerFunc {
}
Why do we need to have the asterisk in front of the type?
According to this cheat sheet, I found.
func PrintPerson(p *Person) ONLY receives the pointer address
(reference)
I don't understand why I would only want to send a pointer address as a parameter.
First, Go technically has only pass-by-value. When passing a pointer to an object, you're passing a pointer by value, not passing an object by reference. The difference is subtle but occasionally relevant. For example, you can overwrite the pointer value which has no impact on the caller, as opposed to dereferencing it and overwriting the memory it points to.
// *int means you *must* pass a *int (pointer to int), NOT just an int!
func someFunc(x *int) {
*x = 2 // Whatever variable caller passed in will now be 2
y := 7
x = &y // has no impact on the caller because we overwrote the pointer value!
}
As to your question "Why do we need to have the asterisk in front of the type?": The asterisk indicates that the value is of type pointer to sql.DB, rather than a value of type sql.DB. These are not interchangeable!
Why would you want to send a pointer address? So that you can share the value between the caller of a function and the function body, with changes made inside the function reflected in the caller (for example, a pointer is the only way that a "setter" method can work on an object). While Java passes objects by reference always, Go passes by value always (i.e. it creates a copy of the value in the function); if you pass something to a function, and that function modifies that value, the caller won't see those changes. If you want changes to propogate outside the function, you must pass a pointer.
See also: the Go tour section on Pointers, the Go spec section on pointers, the Go spec section on the address operators
The purpose of reference semantics is to allow a function to manipulate data outside its own scope. Compare:
func BrokenSwap(a int, b int) {
a, b = b, a
}
func RealSwap(a *int, b *int) {
*a, *b = *b, *a
}
When you call BrokenSwap(x, y), there is no effect, because the function receives and manipulates a private copy of the data. By contrast, when you call RealSwap(&x, &y), you actually exchange the values of the caller's x and y. Taking the address of the variables explicitly at the call site informs the reader that those variables may be mutated.
Pass by Reference :-
When you pass a same variable into a function by different name.
Below example from C++ (as Go doesnt have this concept), where a and a1 are same variable.
void swap(int& a1, int& b1)
{
int tmp = a1;
a1 = b1;
b1 = tmp;
}
int main()
{
int a = 10, b = 20;
swap(a, b);
cout << "a " << a << " b " << b ;
}
Go passes everything as data( means it copies the data from current active frame to new active frame of new function). So if you pass values it copies the value and advantage is safety from accidental modification. And when it passes address of variable its copied also into the new pointer variables but has advantage of efficiency since size of pointer is smaller.

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.

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.

Resources