这是我遇到问题的功能:
func pruneattackoptions(currplayer int) (newoptions []string) {
if currplayer == 0 {
newoptions := make([]string, len(options))
copy(newoptions, options)
for i, y := range options {
c, d := parseposition(y)
fmt.Println(y)
fmt.Println(string(board[c][d]))
if string(board[c][d]) == "_" || unicode.IsLower(rune(board[c][d])) {
newoptions = append(options[:i], options[i+1:]...)
}
}
}
if currplayer == 1 {
for i, y := range options {
c, d := parseposition(y)
if string(board[c][d]) == "_" || unicode.IsUpper(rune(board[c][d])) {
newoptions = append(options[:i], options[i+1:]...)
}
}
}
return newoptions
}
这基本上是一个国际象棋游戏,我试图在游戏开始时删除白人球员的所有不可行选择,白人是大写字母,黑人是小写字母。
问题是,当我运行程序时,它不仅完全跳过了某些选项中的值,例如“ A4”,实际上还向新选项列表中添加了100个“ H8”副本,这是为什么发生的,我该如何解决它吗?
函数append
不保证将结果放入存储器的新区域。考虑以下代码:
package main
import (
"fmt"
)
func main() {
s0 := []string{"a", "b", "c", "d", "e", "f"}
// suppose I want to delete "c":
s1 := append(s0[:2], s0[3:]...)
// the last element in s0 was duplicated:
fmt.Printf("s0=%v\ns1=%v\n", s0, s1)
// you can see that s0 and s1 point to the same memory:
fmt.Printf("addr s0=%v\naddr s1=%v\n", &s0[0], &s1[0])
}
输出:
s0=[a b d e f f]
s1=[a b d e f]
addr s0=0xc000104120
addr s1=0xc000104120
如您所见,append
只是将“ c”之后的所有元素向左移动1。它在s0
使用的同一内存中进行了移动。这就是为什么“ f”被复制的原因。现在s0
和s1
都指向相同的内存,但是s1
短了1个元素。
正确的方法是有条件地附加元素,如下所示:
func removeC(options []string) (newoptions []string) {
newoptions = make([]string, 0, len(options))
for _, opt := range options {
if opt != "c" {
newoptions = append(newoptions, opt)
}
}
return
}
不是我make
包含0个元素的新切片,但保留的内存足以容纳len(options)
个元素。这不是必需的,但是它将避免在append
函数内部进行不必要的分配。