Go 切片突变最佳实践

当切片传递时,很难预测底层原始数组是否正在发生变异,或者原始数组的副本是否正在发生变异


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

那么切片的最佳实践是什么?


慕田峪7331174
浏览 127回答 1
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当然,它可以采用指向数组对象的指针,并就地修改数组,但这不太灵活,因为数组大小随后会被烘焙到类型中。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go