为了账号安全,请及时绑定邮箱和手机立即绑定

Go 切片突变最佳实践

Go 切片突变最佳实践

Go
慕田峪7331174 2023-08-07 16:45:32
当切片传递时,很难预测底层原始数组是否正在发生变异,或者原始数组的副本是否正在发生变异a = [3]int {0, 1, 2}s = a[:]s[0] = 10a[0] == s[0] // trues = append(s, 3)s[0] = 20a[0] == s[0] // false假设今天我有这样的处理a = [3]int {0, 1, 2}s = some_func(a[:]) // returns sliceprocess(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 operationsprocess(s) // a is not getting mutated because some_func caused the underlying array to be copied那么切片的最佳实践是什么?
查看完整描述

1 回答

?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

如果一个函数确实就地修改了切片的底层数组,并且承诺它总是就地修改底层数组,那么该函数通常应该按值获取切片参数并且不返回更新的切片: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当然,它可以采用指向数组对象的指针,并就地修改数组,但这不太灵活,因为数组大小随后会被烘焙到类型中。


查看完整回答
反对 回复 2023-08-07
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信