修改取消引用的结构指针会更改大多数结构值,但不会更改切片 [英] Modify dereferenced struct pointer changes most struct values, but not slices

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

问题描述

我正在尝试创建结构板(棋盘)的浅表副本.在保存对板的移动之前,我需要检查该移动是否使移动器处于检查状态.

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.

要这样做,请在Move方法(指针方法)中,取消引用指针,更新并检查此 可能 面板进行检查.当我更改Board类型的单个值(例如possible.headers = "Possible Varient")的值时,原始的b Board不会更改.

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.

但是在这里,当我调用方法updateBoard()时,它将更新两个板.我仍然收到错误消息(无法进入检查状态),但是主线程认为b.board(板卡位置)已更改.

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

奇怪的是,并非所有由updateBoard()更新的值都改变.因此,b.toMove值不变,但b.board值却不变(片段的位置).这意味着,如果我改为通过possible := b,则游戏将只能进行白色移动(toMove在updateBoard()方法中交替进行).使用possible := *b,轮流交替工作,直到进入检查状态为止.然后将移动应用于b.board,但该错误被抛回,并且保留了已检查玩家的回合(表示possible.updateBoard()并未更新b.toMove.

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.

修改

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

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([]byte)始终指向其原始值(即使对包含它的结构进行了取消引用.abhink的答案也使用Go func copy(dst, src []Type) int

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.

推荐答案

由于b.board是切片类型,因此它是引用类型(

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天全站免登陆