pointers - 修改取消引用的结构指针会更改大多数结构值,但不会更改 slice

标签 pointers methods go slice chess

我正在尝试创建 struct Board(棋盘)的浅拷贝。在将移动保存到棋盘之前,我需要检查该移动是否使移动器处于检查状态。

为此,在 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,但错误被抛回并且它仍然是检查玩家轮到(意味着 possible.updateBoard() 没有更新 b .toMove.

编辑

正如 abhink 指出的那样,在 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,一个 []byte,始终指向其原始值(即使保存它的结构被取消引用。 abhink 的回答使用了 Go func copy(dst, src []Type) int, https://golang.org/pkg/builtin/#copy,这是一种复制指针值的快捷方式。

最佳答案

因为 b.board 是一个 slice 类型,它是一个引用类型 ( https://blog.golang.org/go-slices-usage-and-internals ) 并且表现得像一个指针。因此,对 possible.board 所做的任何更改都将显示在 b 中。您可以尝试制作 b.board 的副本,如下所示:

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)

    // ...

请注意,您必须对所有引用类型执行类似的操作。

关于pointers - 修改取消引用的结构指针会更改大多数结构值,但不会更改 slice ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38263511/

相关文章:

go - 如何在 Go 中定义位文字?

c++ - 从 "parent"项指针获取 `std::tuple` "children"

c++ - 在文件中写入字符数组时出现访问冲突

c# - 如何在其方法中获取结构的地址?

class - 如何找到调用此方法的 ABAP 程序/FM?

java - 从方法返回一个字符

java - 制作一种将对象随机放置在屏幕上的方法。

json - 如何在 Go 中动态处理 JSON 响应中缺失的字段

go - 如何在 net.Con 中正确分块消息并阻止广播 sleep

c - 打印有很多限制的字符串