Your "No.1" approach appends to a nil
slice which guarantees that a new backing array will be allocated if there are more than zero params provided.
Your "No.2" approach doesn't create a new slice, it just slices the param.
If Assign()
is called by passing an existing slice, the 2nd approach will store that, and if its elements are modified, it will be reflected in the stored slice.
Let's modify your example a little to test it:
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 <<<
}
Testing it:
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)
Output (try it on the Go Playground):
[a b c]
[a b c]
[a b c]
[x b c]
As you can see, when using Assing1()
, the local
slice is not affected by modifying the passed slice.
When using Assing2()
, elements of the local
slice reflect the changes made in the original.
Please read relevant blog posts:
The Go Blog: Go Slices: usage and internals
The Go Blog: Arrays, slices (and strings): The mechanics of 'append'