那么,为什么它们(下面的1号和2号)不同?
type T1 struct {
local []string
}
func (t *T1) Assign(param ...string) {
t.local = nil
t.local = append(t.local, param...) // No.1 <<<
t.local = param[:] // No.2 <<<
}
他们是不同,可以肯定的是:第二名非常“浅”。
当t.local[i]
发生一次更改时,如果使用2号,她将使原始字符串乱码。
答案 0 :(得分:2)
您的“ No.1”方法将附加到nil
切片上,这可以确保如果提供的参数超过零,则将分配新的支持数组。
您的“第二”方法不会创建新的切片,而只是对参数进行切片。
如果通过传递现有切片来调用Assign()
,则第二种方法将存储该切片,并且如果修改其元素,它将反映在存储的切片中。
让我们稍微修改一下示例以对其进行测试:
type T1 struct {
local []string
}
func (t *T1) Assign1(param ...string) {
t.local = nil
t.local = append(t.local, param...) // No.1 <<<
}
func (t *T1) Assign2(param ...string) {
t.local = nil
t.local = param[:] // No.2 <<<
}
测试:
t1 := &T1{}
s := []string{"a", "b", "c"}
t1.Assign1(s...)
fmt.Println(t1.local)
s[0] = "x"
fmt.Println(t1.local)
s = []string{"a", "b", "c"}
t1.Assign2(s...)
fmt.Println(t1.local)
s[0] = "x"
fmt.Println(t1.local)
输出(在Go Playground上尝试):
[a b c]
[a b c]
[a b c]
[x b c]
如您所见,使用Assing1()
时,local
片不受修改传递的片的影响。
使用Assing2()
时,local
切片的元素反映了原始文档中所做的更改。
请阅读相关博客文章:
The Go Blog: Go Slices: usage and internals
The Go Blog: Arrays, slices (and strings): The mechanics of 'append'
答案 1 :(得分:0)
当切片容量不足时,append
函数会分配一个新的后备阵列 。
使用[:]
进行拆分,只是实例化了一个新的 slice标头,该标头指向相同的后备数组。
请考虑以下代码段:
func main() {
a := make([]int, 4, 5)
fmt.Println("Len", len(a)) // 4
fmt.Println("Cap", cap(a)) // 5
fmt.Printf("Array 0th: %p\n", &a[0]) // memory address of the first element of backing array
a = append(a, 10)
fmt.Printf("Array 0th: %p\n", &a[0]) // same memory address as before
b := a[:]
fmt.Printf("Array 0th: %p\n", &b[0]) // same memory address as before
a = append(a, 10) // grow over capacity
fmt.Printf("Array 0th: %p\n", &a[0]) // different memory address
}
您可以在the official Go blog上找到有关切片的更多信息。