为什么len()返回一个有符号的值?

时间:2016-08-22 21:22:36

标签: go signed

Go内置len() function会返回已签名的int。为什么不使用uint

len()是否有可能返回负面内容? 据我所知,答案是否定的:

  • Arrays:"元素数量称为长度,绝不是负数。"
  • Slices:&#34;以下关系随时关注:0 <= len(s) <= cap(s)&#34;
  • Maps&#34;地图元素的数量称为其长度&#34;。 (我无法在规范中找到任何明确将其限制为非负值的内容,但我很难理解地图中的元素数量少于0)
  • Strings&#34;字符串值是一个(可能是空的)字节序列....字符串s的长度(以字节为单位的大小)可以使用内置函数{ {1}}&#34; (再次,很难看出序列如何具有负数字节)
  • Channels&#34;在通道缓冲区中排队的元素数量(同上)

4 个答案:

答案 0 :(得分:20)

len()(和cap())返回int,因为这是用于索引切片和数组(不是uint)的内容。所以问题是更多&#34;为什么Go在没有负指数时使用有符号整数来索引切片/数组?&#34;。

答案很简单:计算索引很常见,如果在无符号整数中完成,这种计算往往容易下溢。像i := a-b+7这样的无辜代码可能会为i == 4294967291a的6和10的无辜值产生b。这样的索引可能会溢出你的切片。大量的索引计算发生在0左右,并且使用无符号整数来纠正这些错误并且这些错误隐藏在数学上完全合理和合理的公式之后。这既不安全也不方便。

这是基于经验的权衡:对于使用无符号整数进行的索引计算,往往会发生下溢,而如果使用有符号整数进行索引计算,则溢出更不常见。

此外:在这些情况下使用无符号整数基本上没有任何好处。

答案 1 :(得分:5)

  

Length and capacity

     

内置函数len和cap接受各种类型的参数   返回int类型的结果。实施保证了   结果总是适合int。

Golang是强类型语言,因此如果len()uint,则代替:

i := 0 // int
if len(a) == i {
}  

你应该写:

if len(a) == uint(i) {
}

或:

if int(len(a)) == i {
}

另见:

  

uint 32或64位
  intuint相同的大小   uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value

同样为了与C:CGo兼容,C.size_t和C中数组的大小属于int类型。

答案 2 :(得分:3)

有一个正在进行的提案“ issue 31795 Go 2: change len, cap to return untyped int if result is constant

可能包含在Go 1.14(2010年第一季度)中

  

我们应该能够在lencap上做到这一点,而不会出现问题-实际上,stdlib中没有任何东西,因为通过修改后的类型检查器显示的类型进行了检查

CL 179184视为PoC:这仍处于实验阶段。


截至noted belowpeterSO,此事务已关闭。

Robert Griesemer解释:

  

正如您所指出的,使len始终为非类型的问题是结果的大小。
  对于布尔值(以及字符串),无论哪种布尔值(或字符串),大小都是已知的。

Russ Cox added

  

我不确定这里的成本是否值得。今天有一条简单的规则: len(x)的类型为int
  更改类型以取决于x是什么,将以非正交的方式与各种代码更改交互。
  例如,在建议的语义下,此代码编译:

const x string = "hello"
func f(uintptr)
...
f(len(x))
  

但是假设有人来了,并且希望能够修改x进行测试或类似的操作,所以他们s/const/var/
  通常,这是相当安全的,但是现在f(len(x))调用无法进行类型检查,并且它为什么能起作用,这将是一个神秘的事情。

     

此更改似乎会添加比删除的粗糙边缘。

答案 3 :(得分:2)

来自the spec:

  

长度是数组类型的一部分;它必须求值为可由类型int的值表示的非负常量。可以使用内置函数len发现数组a的长度。元素可以通过整数索引0len(a)-1来处理。数组类型总是一维的,但可以组合成多维类型。

我意识到说规范指示 X 可能有点循环,因为规范规定了 Y ,但由于长度不能超过{的最大值{1}} int同样不可能返回len - 独占值,因为它返回负值。