在Go中清除切片的适当方法是什么?
以下是我在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))
}
Run Code Online (Sandbox Code Playgroud)
它是否正确?
为了澄清,缓冲区被清除,因此可以重复使用.
一个例子是bytes包中的Buffer.Truncate函数.
请注意,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) }
Run Code Online (Sandbox Code Playgroud)
Nic*_*ood 183
将切片设置nil
为清除切片的最佳方法. nil
go中的切片表现得非常好,设置切片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)
}
Run Code Online (Sandbox Code Playgroud)
打印
letters = [a b c d]
4
4
0 a
1 b
2 c
3 d
letters = []
0
0
letters = [e]
1
1
0 e
Run Code Online (Sandbox Code Playgroud)
请注意,切片很容易混叠,以便两个切片指向相同的底层内存.设置nil
将删除该别名.
此方法将容量更改为零.
zzz*_*zzz 107
这完全取决于你对'清晰'的定义.其中一个有效的肯定是:
slice = slice[:0]
Run Code Online (Sandbox Code Playgroud)
但是有一个问题.如果切片元素是T类型:
var slice []T
Run Code Online (Sandbox Code Playgroud)
然后强制len(slice)
为零,通过上面的"技巧", 不做任何元素
slice[:cap(slice)]
Run Code Online (Sandbox Code Playgroud)
有资格进行垃圾收集.在某些情况下,这可能是最佳方法.但它也可能是"内存泄漏"的原因 - 内存未使用,但可能可达(在重新切片'切片'之后),因此不是垃圾"可收集".
小智 5
为了我自己的目的,我正在研究这个问题;我有一个结构体(包括一些指针),我想确保我做对了;结束了这个线程,并想分享我的结果。
为了练习,我做了一个小操场: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)
}
Run Code Online (Sandbox Code Playgroud)
按原样运行该代码将显示“meow”和“meow2”变量的相同内存地址相同:
Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
Blahs: []
Blahs: [{1 0x1030e0f0}]
kittenSays: nyan
Run Code Online (Sandbox Code Playgroud)
我认为这证实了该结构是垃圾收集的。奇怪的是,取消注释打印行的注释,将为喵喵产生不同的内存地址:
Blahs: []
Blahs: [{1 0x1030e0c0}]
Blahs: [{1 0x1030e0c0} {2 0x1030e0c0}]
kittenSays: meow
Blahs: []
Blahs: [{1 0x1030e0f8}]
kittenSays: nyan
Run Code Online (Sandbox Code Playgroud)
我认为这可能是由于打印以某种方式被推迟(?),但有趣的说明了一些内存管理行为,还有一票赞成:
[]MyStruct = nil
Run Code Online (Sandbox Code Playgroud)