Golang中切片长度改变但容量不变的解决方案
Golang中切片长度改变但容量不变的解决方案 我想问一个问题。有没有这样的函数:切片长度改变但容量不变?因为我不想重新分配内存,这会带来开销。
例如: 切片长度=5,切片容量=10;调整大小后切片长度=0,切片容量=10。
你的代码确实将长度设为0而保持容量不变。但我不确定这是否会带来时间开销和内存重新分配。期待你的回答。
更多关于Golang中切片长度改变但容量不变的解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
它创建了一个新的切片,但这仅占用12字节(在64位机器上),同时复用了底层数组。
我相当确定,这会在先前填充的切片或后续子切片上创建一个"写时复制"的切片。
在追加操作时,是否正确定义了哪个切片会被重新分配?或者这是未定义行为?
只需创建一个包含零个元素的新切片
package main
import (
"fmt"
)
func main() {
// 原始切片
s := []int{1, 2, 3, 4, 5}
fmt.Printf("原始切片: %v\n", s)
fmt.Printf("原始切片地址: %p\n", &s[0])
// 创建零长度切片(共享相同底层数组)
empty := s[:0]
fmt.Printf("零长度切片: %v\n", empty)
fmt.Printf("零长度切片地址: %p\n", &s[0])
}
在这个示例中,您可以看到底层数组的地址保持不变。
也许这个例子能说明问题:https://play.golang.org/p/fGwnKN70dmk
在这个示例中,a 和 b 是两个指向同一数组的切片,这就是为什么向 b 追加元素后,打印 a 时能看到变化的原因…
编辑:我刚刚完整阅读了关于重新分配的问题。从这个其他示例来看,似乎并没有发生重新分配,内部只是修改了 len:https://play.golang.org/p/xGlzY2xd2Lg。但 Johan 和 Norbert 提到确实会发生,所以我需要再仔细研究一下。
进一步编辑:在这篇文章中提到,切片操作不会复制切片的数据。它会创建一个指向原始数组的新切片值。但Effective Go中提到:只要切片仍然在底层数组的限制范围内,就可以更改其长度;只需将其分配给自身的切片即可。在我看来,我们遇到的情况属于后者。
在Go语言中,可以通过重新切片(reslicing)来改变切片的长度而不改变其容量,从而避免重新分配内存。这通过调整切片的起始和结束索引实现。
以下是一个示例代码:
package main
import "fmt"
func main() {
// 创建一个初始切片,长度为5,容量为10
slice := make([]int, 5, 10)
fmt.Printf("初始状态: 长度=%d, 容量=%d\n", len(slice), cap(slice))
// 通过重新切片将长度设为0,容量保持不变
slice = slice[:0]
fmt.Printf("调整后: 长度=%d, 容量=%d\n", len(slice), cap(slice))
// 验证容量未变,可以重新使用底层数组
slice = append(slice, 1, 2, 3)
fmt.Printf("追加元素后: 长度=%d, 容量=%d, 内容=%v\n", len(slice), cap(slice), slice)
}
输出结果:
初始状态: 长度=5, 容量=10
调整后: 长度=0, 容量=10
追加元素后: 长度=3, 容量=10, 内容=[1 2 3]
在这个例子中,通过 slice = slice[:0] 将切片长度重置为0,而容量保持为10不变。这利用了切片底层数组的现有空间,避免了内存重新分配。后续可以使用 append 函数向切片添加新元素,直到长度超过容量才会触发重新分配。

