小编典典

工作是否超出了切片的习惯用法?

go

我正在阅读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


阅读 217

收藏
2020-07-02

共1个答案

小编典典

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

我将从另一个相关的答案中获取此插图:

 array : [0 0 0 0 0 0 0 0 0 0 0 0]
 array :  <----   capacity   --->
 slice :     [0 0 0 0]
 slice :      <---- capacity --->

当数组大于切片时,通常情况下,如果您知道自己不会超出基础数组,可以通过扩展一个切片来获取更大的切片(可以使用进行验证cap())。

以您的错误代码为例,是的,这很危险,但是数组和切片是语言的最基本结构之一,如果要避免此类错误,必须在使用它们之前先了解它们。我个人认为,任何去编码器不应该只知道API,而且
什么 是切片


在您链接到的代码中,简短的分析表明,不可能像list创建时那样发生溢出。

list := make([]literalNode, len(freq)+1)

并在以后调整为count不能大于len(freq)

list = list[0:count]

可能还希望再添加一些注释,但是由于包含的函数list = list[0 : n+1]是私有的,并且只能从一个地方调用,因此也可以认为注释详细程度和代码晦涩度之间的平衡听起来不错。隐藏太多的注释会隐藏代码,这很痛苦,需要阅读此代码的任何人都可以像我一样轻松地检查是否没有溢出。

2020-07-02