去 - 修改解引用的结构指针改变大多数结构值,但不改变切片 [英] Go - modify dereferenced struct pointer changes most struct values, but not slices

查看:164
本文介绍了去 - 修改解引用的结构指针改变大多数结构值,但不改变切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个struct Board(棋盘)的浅拷贝。在保存移动到董事会之前,我需要检查这一举动是否会让移动者进入检查状态。



为此,在Move方法(指针的方法) ,我取消引用指针,更新并检查此 可能的 棋盘。当我更改Board类型的单个值的值(例如 possible.headers =Possible Varient)时,原始的 b 董事会不变。

但是当我调用updateBoard()方法时,它会更新两个主板。我仍然收到错误(无法移入检查),但主线程认为 b.board (板子位置)已被更改。

  func(b * Board)Move(orig,dest int)error {
//验证
...
/ /更新
可能:= * b //一个浅拷贝?
possible.updateBoard(orig,dest,val,isEmpassant,isCastle)

king:= possible.findKingPositionOfThePlayerWhoMoved()
isCheck:= possible.isInCheck(king)// bool如果isCheck {b $ b return errors.New(无法移入检查)
}
b.updateBoard(orig,dest, val,empassant,isCastle)
return nil

奇怪的是,并非所有的值都被更新 updateBoard()更改。所以 b.toMove 的值不会改变,但是 b.board 的值不会改变(块的位置)。这意味着如果我传递可能:= b ,游戏只会是白色的移动(toMove在updateBoard()方法中交替出现)。使用可能:= * b ,交替操作直到有人进入检查。然后这个举动被应用于 b.board ,但是错误被抛回并且它仍然是checked-players turn(意思是 possible.updateBoard() $ b

正如abhink指出的那样,在 Go Slices用法和内部中,


切片不会复制切片的数据,它会创建一个指向原始数组的新切片值。 b

b.board ,a [] byte ,始终指向它的原始值(即使结构持有它是解除引用。abhink的答案使用Go func copy(dst,src [] Type)int https://golang.org/pkg/builtin/#copy ,一个复制指针值的快捷方式。

解决方案 b.board 是一个切片类型,它是一个引用类型( https://blog.golang.org/go-slices-usage-and-internals ),其行为就像一个指针。因此,对 possible.board 所做的任何更改都将显示在 b 中。您可以尝试复制 b.board ,如下所示:

  func(b * Board)Move(orig,dest int)error {
//验证
...
//更新
可能:= * b // A'shallow复制'?
boardCopy:= make([] byte,len(b.board))
copy(boardCopy,b.board)
possible.board = boardCopy

possible .updateBoard(orig,dest,val,isEmpassant,isCastle)

// ...

请注意,您必须为所有参考类型执行此类操作。


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.

这篇关于去 - 修改解引用的结构指针改变大多数结构值,但不改变切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆