要知道底层原始数组是否正在发生突变,或者在传递切片时是否知道其原始数组的副本是否正在发生突变,这并不是很可预测的
a = [3]int {0, 1, 2}
s = a[:]
s[0] = 10
a[0] == s[0] // true
s = append(s, 3)
s[0] = 20
a[0] == s[0] // false
让我们今天说我进行了这种处理
a = [3]int {0, 1, 2}
s = some_func(a[:]) // returns slice
process(s) // a is getting mutated because so far some_func hasn't caused the underlying array to be copied
现在是明天
a = [3]int {0, 1, 2}
s = some_func(a[:]) // returns slice, does append operations
process(s) // a is not getting mutated because some_func caused the underlying array to be copied
那么切片的最佳实践是什么?
答案 0 :(得分:1)
如果函数确实确实修改了切片的基础数组,并且承诺总是 修改了基础数组,则该函数通常应采用切片按值指定参数,而不返回更新的切片: 1
// Mutate() modifies (the backing array of) s in place to achieve $result.
// See below for why it returns an int.
func Mutate(s []T) int {
// code
}
如果函数可以在适当的位置修改基础数组,但可能返回使用新数组的切片,则该函数应返回新的切片值,或采用指向切片的指针:
// Replace() operates on a slice of T, but may return a totally new
// slice of T.
func Replace(s []T) []T {
// code
}
此函数返回时,您应该假定基础数组(如果拥有)可以使用或可以不使用:
func callsReplace() {
var arr [10]T
s := Replace(arr[:])
// From here on, do not use variable arr directly as
// we don't know if it is s's backing array, or not.
// more code
}
但是Mutate()
承诺会就地修改数组。请注意,Mutate
通常需要返回实际更新的数组元素的数量:
func callsMutate() {
var arr [10]T
n := Mutate(arr[:])
// now work with arr[0] through arr[n]
// more code
}
1 当然,它可以使用指向数组对象的指针,并在适当的位置修改数组,但是灵活性不强,因为随后将数组大小转换为类型。