请考虑以下代码:
type TestStruct struct {
Name string
}
func TestSliceWithPool(t *testing.T) {
var slicePool = sync.Pool{
New: func() interface{} {
t.Log("i am created")
s := make([]interface{}, 0)
return s
},
}
s, _ := slicePool.Get().([]interface{})
t.Logf("Lenth: %d, Cap: %d, Pointer: %p", len(s), cap(s), s)
for i := 0; i < 9000; i++ {
st := &TestStruct{Name: "test"}
s = append(s, st)
}
for _, v := range s {
if value, ok := v.(TestStruct); ok {
if value.Name != "test" {
t.Error("u are changed!")
}
}
}
s = s[:0]
slicePool.Put(s)
s2, _ := slicePool.Get().([]interface{})
t.Logf("Lenth: %d, Cap: %d, Pointer: %p", len(s), cap(s), s)
for i := 0; i < 8000; i++ {
st := &TestStruct{Name: "test2"}
s2 = append(s2, st)
}
for _, v := range s2 {
if value, ok := v.(TestStruct); ok {
if value.Name != "test2" {
t.Error("u are changed!")
}
}
}
slicePool.Put(s2)
}测试结果如下:
slice_test.go:63: i am created
slice_test.go:70: Lenth: 0, Cap: 0, Pointer: 0x1019598
slice_test.go:86: Lenth: 0, Cap: 9728, Pointer: 0xc000500000为什么它只生成一次,但地址是不同的?为什么上限是9728?像这样用同一片有什么问题吗?
发布于 2022-07-07 06:46:50
为什么只生成一次,但地址不同?
因为在第一个for循环中,您将超出其容量(在New中设置为零)附加到它,并将append的结果重新分配给它。详细信息:Why does append() modify the provided slice? (See example)
,当我像这样使用相同的切片时,有什么问题吗?
可能会有。当您使用s重新设置s = s[:0]时,您正在重置长度,而不是容量。支持数组仍然与上一次追加和重新分配操作相同。
因此,如果再次添加到s2中,容量将不足以导致重新分配,最终将覆盖支持数组的第一个元素:
一个示范的例子:
func TestSliceWithPool(t *testing.T) {
var slicePool = sync.Pool{
New: func() interface{} {
t.Log("Created")
s := make([]interface{}, 0)
return s
},
}
s, _ := slicePool.Get().([]interface{})
for i := 0; i < 10; i++ {
s = append(s, i)
}
fmt.Println(s)
// ^ output: [0 1 2 3 4 5 6 7 8 9]
s = s[:0]
slicePool.Put(s)
s2, _ := slicePool.Get().([]interface{})
fmt.Println(s)
// ^ output: []
for i := 0; i < 5; i++ {
s2 = append(s2, i*10)
}
fmt.Println(s2)
// ^ output: [0 10 20 30 40]
fmt.Println(s2[:10])
// ^ output: [0 10 20 30 40 5 6 7 8 9]
}这可能是可以的,因为您现在有一个扩展容量不需要追加重新分配的片,但如果您的应用程序保持指向相同支持数组的其他片头(如s和s2),则也可能是内存泄漏,从而防止缓冲区的垃圾收集。
https://stackoverflow.com/questions/72893095
复制相似问题