我正在学习Golang,我来自PHP背景。我有时很难理解一些核心功能。
具体来说,现在我正在构建一个Hearths游戏并且我已经创建了一个CardStack类型,它有一些方便的方法可以在卡片堆栈中使用(读取:玩家的手,丢弃堆......),例如{ {1}},DrawCards(...)
...
问题我的问题是函数AppendCards(...)
更改了参数func (c* CardStack) DrawCards(cards []deck.Card) ([]deck.Card, error) {...}
,我无法弄清楚为什么或如何避免这种情况。
这是我的CardStack:
cards []deck.Card
这是我的type CardStack struct {
cards []deck.Card
}
方法:
DrawCards
进一步解释 - 特别是在func (c *CardStack) DrawCards(cards []deck.Card) ([]deck.Card, error) {
return c.getCardsSlice(cards, true)
}
// Returns cards that are missing
func (c *CardStack) getCardsSlice(cards []deck.Card, rm bool) ([]deck.Card, error) {
var err error
var returnc = []deck.Card{}
for _, card := range cards {
fmt.Println("BEFORE c.findCard(cards): ")
deck.PrintCards(cards) // In my example this will print out {Kc, 8d}, which is what I expect it to be
_, err = c.findCard(card, rm) // AFTER THIS LINE THE cards VAR IS CHANGED
fmt.Println("AFTER c.findCard(cards): ")
deck.PrintCards(cards) // In my example this will print out {8d, 8d}, which is not at all what I expected
if err != nil {
return returnc, err
}
}
return returnc, nil
}
// Expects string like "Ts" or "2h" (1. face 2. suit)
func (c *CardStack) findCard(cc deck.Card, rm bool) (deck.Card, error) {
for i, card := range c.GetCards() {
if cc == card {
return c.cardByIndex(i, rm)
}
}
return deck.Card{}, fmt.Errorf("Card not found")
}
func (c *CardStack) cardByIndex(n int, rm bool) (deck.Card, error) {
if n > len(c.GetCards()) {
return deck.Card{}, fmt.Errorf("Index out of bounds")
}
card := c.GetCards()[n]
if rm {
c.SetCards(append(c.GetCards()[:n], c.GetCards()[n+1:]...))
}
return card, nil
}
中使用原始值调用的findCard(...)
方法(我添加了注释以指示它发生的位置)。
如果有任何帮助,这是我用于调试的getCardsSlice
方法的一部分:
main()
我做错了什么,我应该怎么做呢。
感谢任何形式的帮助。
修改:
整个CardStack文件:http://pastebin.com/LmhryfGc
EDIT2 :
我迟早要把它放在github上(希望代码看起来半好),这里是 - https://github.com/d1am0nd/hearths-go/tree/cardstack/redo
答案 0 :(得分:5)
在您的示例中,cards
中DrawCards
的值是CardsStack.cards
切片的子切片,它在同一支持数组中引用值。
当您致电findCard
并从CardStack.cards
切片中移除卡片时,您正在操作cards
参数正在使用的相同数组。
如果需要切片的副本,则需要分配新切片并复制每个元素。要在您的示例中执行此操作,您可以:
ssCopy := make([]deck.Card, len(ss))
copy(ssCopy, ss)
cards.DrawCards(ssCopy)