是否正在结束一个惯用的切片?

时间:2013-07-06 06:18:29

标签: go slice idioms

我正在阅读Go的compress/flate包,我发现了这段奇怪的代码[1]:

n := int32(len(list))
list = list[0 : n+1]
list[n] = maxNode()

在上下文中,list保证指向具有更多数据的数组。这是一个私有函数,因此不能在库外滥用。

对我而言,这似乎是一个可怕的黑客应该是运行时异常。例如,以下D代码生成RangeError:

auto x = [1, 2, 3];
auto y = x[0 .. 2];
y = y[0 .. 3];

使用以下内容可以更简单地(并且看起来更安全)来滥用切片:

x := []int{1, 2, 3}
y = x[:2]
y = append(y, 4) // x is now [1, 2, 4] because of how append works

但是这两种解决方案看起来都非常黑客和可怕,恕我直言,不应该像他们那样工作。这种事情被认为是惯用的Go代码吗?如果是这样,以上哪一项更多惯用?

[1] - http://golang.org/src/pkg/compress/flate/huffman_code.go#L136

2 个答案:

答案 0 :(得分:9)

这不是滥用切片,这只是完美地使用切片:数组上的窗口。

我将从another related answer I made

中提取此插图
 array : [0 0 0 0 0 0 0 0 0 0 0 0]
 array :  <----   capacity   --->
 slice :     [0 0 0 0]
 slice :      <---- capacity ---> 

当数组大于切片时,如果你知道你没有离开底层数组(可以使用cap()进行验证),则通过扩展一个更大的切片是正常的和标准的。 / p>

关于你提供的错误代码,例如,是的,它可能是危险的,但数组和切片是这些语言的最基本结构之一,如果你想避免这些错误,你必须在使用它们之前理解它们。我个人认为任何编码人员不仅应该知道API,还应该what are slices


在您链接的代码中,一个简短的分析表明,由于list被创建为

,因此不可能出现溢出
list := make([]literalNode, len(freq)+1)

稍后调整为count,且不能大于len(freq)

list = list[0:count]

有人可能更喜欢一些注释,但由于包含list = list[0 : n+1]的函数是私有的并且只从一个地方调用,因此也可以认为注释详细程度和代码模糊声音之间的平衡是正确的。有太多注释隐藏代码是很痛苦的,任何需要阅读此代码的人都可以像我一样轻松检查没有溢出。

答案 1 :(得分:1)

它不能是运行时异常,因为语言规范规定切片操作的上限是切片的容量,而不是切片的长度。