【发布时间】:2016-11-10 20:05:14
【问题描述】:
我正在尝试创建结构板(棋盘)的浅表副本。在将移动保存到棋盘之前,我需要检查该移动是否会检查移动器。
为此,在 Move 方法(指针方法)中,我取消引用指针,更新并检查此 可能板检查。当我更改Board类型的单个值(例如possible.headers = "Possible Varient")的值时,原来的b Board没有改变。
但是在这里,当我调用方法 updateBoard() 时,它会更新两个板。我仍然收到错误(无法进入检查),但主线程认为b.board(棋盘位置)已更改。
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
奇怪的是,并非所有updateBoard() 更新的值都发生了变化。所以b.toMove 值不会改变,但b.board 值会改变(棋子的位置)。这意味着如果我改为通过possible := b,游戏将永远是白棋的走法(toMove 在 updateBoard() 方法中交替使用)。使用possible := *b,轮流交替工作,直到一个进入检查状态。然后移动被应用到b.board,但错误被抛出并且它仍然是checked-players轮流(意思是possible.updateBoard()没有更新b.toMove。
编辑
正如 abhink 指出的,在Go Slices usage and internals,
切片不会复制切片的数据。它创建一个指向原始数组的新切片值。
b.board,一个[]byte,总是指向它的原始值(即使保存它的结构被取消引用。abhink 的答案使用Go func copy(dst, src []Type) int,https://golang.org/pkg/builtin/#copy,一个复制指针值的快捷方式。
【问题讨论】:
-
b.board是指针类型吗(board是指向某些板类型的指针)?如果是这样,那么浅拷贝possible := *b会创建一个新结构possible,它的board字段中的指针地址与b.board相同。现在通过引用possible.board完成的任何访问/修改都将更改b的值,因为两者共享相同的指针。 -
不,
b.board是[]byte
标签: pointers methods go slice chess