去 - 修改复引用结构指针的变化最为结构值,而不是片(Go - modify dereference

2019-09-29 06:59发布

我试图创建一个结构板的浅拷贝(棋盘)。 保存移动到板之前,我需要检查,如果这一举动使推进器的检查。

要做到这一点,Move方法中(指针的方法),我的指针,更新和检查这个可能的董事会检查。 当我改变板类型的单个值的值(如possible.headers = "Possible Varient" )的原b板不被改变。

但在这里,当我调用一个方法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指出,在围棋片的使用和内部 ,

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

b.board ,一个[]byte ,总是指向其原始值(即使其持有该结构被取消引用 。abhink的答案使用转到func copy(dst, src []Type) int , https://golang.org /包装/内建/#拷贝 ,用于复制指针的值的快捷方式。

Answer 1:

由于b.board是一个切片类型,它是引用类型( 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)

    // ...

请注意,您必须对所有引用类型做这样的事情。



Answer 2:

解引用不进行复印。 它返回原来的价值你的指针指向。

你得到一份拷贝,因为你是该值赋给一个新的变量。 在旅途中每一项任务进行复印一样每个传递给一个函数。 如果分配或传递引用,该引用被复制。

在你的情况,你的值b点复制到。 在这种结构有喜欢b.board切片(切片有一个指针到下面的阵列)的指针。 所以去创造片的副本。 副本仍然指向同一阵列中与原来的b变量切片。 如果更改了阵列,它更改为您的主板。

你将需要实现复印功能的董事会结构是正确创建你的结构处理每个变量根据其类型的副本,并返回一个新的董事会。

就像是:

func (b *Board) copy() *Board {
  boardCopy := make([]byte, len(b.board))
  copy(boardCopy, b.board)

  return &Board{
    moveTo: b.moveTo,
    board: boardCopy
    ...
  }
}

希望帮助我的解释是不是混乱:)



文章来源: Go - modify dereferenced struct pointer changes most struct values, but not slices