如何在围棋中清除切片?

在 Go 中清除一个切片的适当方法是什么?

以下是我在 去论坛中的发现:

// test.go
package main


import (
"fmt"
)


func main() {
letters := []string{"a", "b", "c", "d"}
fmt.Println(cap(letters))
fmt.Println(len(letters))
// clear the slice
letters = letters[:0]
fmt.Println(cap(letters))
fmt.Println(len(letters))
}

是这样吗?

为了澄清,将清除缓冲区,以便可以重用它。

字节包中的 缓冲区,截断函数就是一个例子。

注意,Reset 只调用 Truncate (0) ,因此在这种情况下,第70行将计算: B.buf = b.buf [0:0]

Http://golang.org/src/pkg/bytes/buffer.go

// Truncate discards all but the first n unread bytes from the buffer.
60  // It panics if n is negative or greater than the length of the buffer.
61  func (b *Buffer) Truncate(n int) {
62      b.lastRead = opInvalid
63      switch {
64      case n < 0 || n > b.Len():
65          panic("bytes.Buffer: truncation out of range")
66      case n == 0:
67          // Reuse buffer space.
68          b.off = 0
69      }
70      b.buf = b.buf[0 : b.off+n]
71  }
72
73  // Reset resets the buffer so it has no content.
74  // b.Reset() is the same as b.Truncate(0).
75  func (b *Buffer) Reset() { b.Truncate(0) }
137347 次浏览

这完全取决于你对“清晰”的定义,其中一个有效的定义当然是:

slice = slice[:0]

但是有一个问题,如果片元素是 T 类型的:

var slice []T

然后执行 len(slice)为零,通过上述“技巧”,没有使任何元素的

slice[:cap(slice)]

有资格进行垃圾收集。在某些情况下,这可能是最佳方法。但它也可能是导致“内存泄漏”的原因之一——内存没有被使用,但是可能是可达的(在重新切片“片”之后) ,因此不是垃圾“可收集的”。

将切片设置为 nil是清除切片的最佳方法。运行中的 nil切片行为良好,将切片设置为 nil将向垃圾收集器释放底层内存。

看看操场

package main


import (
"fmt"
)


func dump(letters []string) {
fmt.Println("letters = ", letters)
fmt.Println(cap(letters))
fmt.Println(len(letters))
for i := range letters {
fmt.Println(i, letters[i])
}
}


func main() {
letters := []string{"a", "b", "c", "d"}
dump(letters)
// clear the slice
letters = nil
dump(letters)
// add stuff back to it
letters = append(letters, "e")
dump(letters)
}

指纹

letters =  [a b c d]
4
4
0 a
1 b
2 c
3 d
letters =  []
0
0
letters =  [e]
1
1
0 e

请注意,片可以很容易地使用别名,以便两个片指向相同的底层内存。设置为 nil将删除该别名。

此方法将容量更改为零。

出于自己的目的,我对这个问题进行了一些研究; 我有一些结构(包括一些指针) ,我想确保我得到了正确的结果; 最终在这个线程上,并希望分享我的结果。

为了练习,我在操场上玩了一会儿: Https://play.golang.org/p/9i4gpx3lny

结果是这样的:

package main


import "fmt"


type Blah struct {
babyKitten int
kittenSays *string
}


func main() {
meow := "meow"
Blahs := []Blah{}
fmt.Printf("Blahs: %v\n", Blahs)
Blahs = append(Blahs, Blah{1, &meow})
fmt.Printf("Blahs: %v\n", Blahs)
Blahs = append(Blahs, Blah{2, &meow})
fmt.Printf("Blahs: %v\n", Blahs)
//fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
Blahs = nil
meow2 := "nyan"
fmt.Printf("Blahs: %v\n", Blahs)
Blahs = append(Blahs, Blah{1, &meow2})
fmt.Printf("Blahs: %v\n", Blahs)
fmt.Printf("kittenSays: %v\n", *Blahs[0].kittenSays)
}

按原样运行该代码将显示“ meow”和“ meow2”变量的相同内存地址:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
Blahs: []
Blahs: [{1 0x1030e0f0}]
kittenSays: nyan

我认为它证实了结构是垃圾回收的。奇怪的是,取消注释的打印行,将为 meows 产生不同的内存地址:

Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
kittenSays: meow
Blahs: []
Blahs: [{1 0x1030e0f8}]
kittenSays: nyan

我认为这可能是由于印刷被推迟在某种程度上(?),但有趣的例子,一些记忆 mgmt 行为,和一个更多的投票:

[]MyStruct = nil