スライスには多くの問題があります。パフォーマンス上の理由から、スライスをスライスしても、基になる配列はコピーされません。これは、スライスのサブスライスが元のスライス変更のビューに従うことを意味します。
したがって、最初のスライスから分離する場合は、copy(from_slice、to_slice)を使用することを忘れないでください。
追加関数の場合、copy()を忘れると、さらに危険になり
ます。元のスライスに新しい値を保持するのに十分な容量がない場合、基になる配列はメモリとサイズを再割り当てします。これは、追加の結果が元の配列を指すことができるかどうかは、その初期容量に依存することを意味します。これは、見つけるのが難しい不確実なバグにつながる可能性があります。
以下のコードでは、サブスライスに値を追加する効果は、元のスライスの容量に依存することがわかります。
import "fmt"
// 切片是引用传递
func doStuff(value []string) {
fmt.Printf("value=%v\n", value)
value2 := value[:]
value2 = append(value2, "b", "c", "d")
fmt.Printf("value=%v, value2=%v\n", value, value2)
value2[0] = "1"
value2[1] = "2"
fmt.Printf("value=%v, value2=%v\n", value, value2)
}
func main() {
slice1 := []string{
"a"} // 长度 1, 容量 1
doStuff(slice1)
// Output:
// value=[a] -- ok
// value=[a], value2=[a b c d] -- ok: value 未改变, value2 被更新
// value=[a], value2=[1 2 c d] -- ok: value 未改变, value2 被更新
// 原因:slice1容量不够,value2利用append添加元素后,value2的底层数组将会重新分配内存和大小(与slice1内存地址不同)
slice10 := make([]string, 1, 10) // 长度 1, 容量 10
slice10[0] = "a"
doStuff(slice10)
// Output:
// value=[a] -- ok
// value=[a], value2=[a b c d] -- ok: value 未改变, value2 被更新
// value=[1], value2=[1 2 c d] -- value 改变了???
// 原因:slice10容量充足,value2利用append添加元素后,value2的底层数组不会重新分配内存和大小,与(与slice10内存地址相同)
}