那么,为什么它们(下面的 No.1 和 No.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 <<<
}
当然,它们是不同的:No.2 相当“肤浅”。
当更改t.local[i]
时,如果使用No.2,她将导致原始字符串出现乱码。
最佳答案
您的“No.1”方法附加到一个 nil
slice ,这保证了如果提供的参数超过零,将分配一个新的后备数组。
您的“No.2”方法不会创建新 slice ,它只是对参数进行 slice 。
如果通过传递现有 slice 来调用Assign()
,则第二种方法将存储该 slice ,并且如果其元素被修改,它将反射(reflect)在存储的 slice 中。
让我们稍微修改一下您的示例来测试它:
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()
时,修改传递的 slice 不会影响 local
slice 。
使用 Assing2()
时,local
slice 的元素反射(reflect)原始 slice 中所做的更改。
请阅读相关博客文章:
The Go Blog: Go Slices: usage and internals
The Go Blog: Arrays, slices (and strings): The mechanics of 'append'
关于arrays - Go 中这两种 "slice copy"方法有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62652960/