Go语言的内置函数len()
返回一个带符号的int
,为什么不使用uint
呢?len()
有可能返回负数吗?
据我所知,答案是否定的:
- 数组:“元素的数量称为长度,并且永远不为负。”
- 切片:“在任何时候,以下关系都成立:
0 <= len(s) <= cap(s)
英寸 - Map“Map元素的数量称为其长度”。(我在规范中找不到任何明确将其限制为非负值的内容,但我很难理解为什么Map中的元素少于0)
- 字符串“字符串值是一个(可能是空的)字节序列....字符串的长度s(以字节为单位)可以使用内置函数
len()
来发现“(同样,很难理解一个序列怎么会有负数的字节) - 通道缓冲区中排队的通道元素数(同上)
4条答案
按热度按时间7gcisfzg1#
len()
(和cap()
)返回int
,因为它是用来索引切片和数组的(而不是uint
),所以问题更多的是“为什么Go语言在没有负索引的情况下使用有符号整数来索引切片/数组?"答案很简单:计算一个索引是很常见的,如果用无符号的整数来计算,这样的计算很容易下溢。一些无辜的代码,比如
i := a-b+7
,可能会产生i == 4294967291
,因为a
和b
的无辜值是6和10。这样的索引很可能会溢出你的切片。很多索引计算都发生在0附近,使用无符号整数很难正确计算,这些错误隐藏在数学上完全合理的公式后面,这既不安全也不方便。这是基于经验的权衡:使用无符号整数进行索引计算时,往往会发生下溢,而如果使用有符号整数进行索引计算,则上溢不太常见。
此外:在这些情况下,使用无符号整数基本上没有任何好处。
y53ybaqx2#
有一个正在进行的建议“issue 31795 Go 2: change
len
,cap
to return untyped int if result is constant“Go 1.14(2010年第1季度)* 可能 * 会包含此功能
我们应该能够对
len
和cap
执行此操作,而不会出现问题--事实上,通过修改后的类型检查器对stdlib进行类型检查时发现,stdlib中没有任何类型将CL 179184视为PoC:这仍然是实验性。
由于noted below通过peterSO,此已关闭。
Robert Griesemer说明:
正如你所提到的,使len总是无类型化的问题是结果的大小。对于布尔值(也包括字符串),大小是已知的,不管是什么类型的布尔值(或字符串)。
添加了Russ Cox:
我不确定这里的成本是否值得收益。今天有一个简单的规则:
len(x)
具有类型int
。将类型更改为依赖于x
的类型将以非正交的方式与各种代码更改交互。例如,在建议的语义下,以下代码将编译:但是假设有人想要修改
x
以进行测试或类似的操作,那么他们就使用s/const/var/
,这通常是相当安全的,但是现在f(len(x))
调用无法进行类型检查,那么它为什么会工作就变得很神秘了。这种变化似乎增加了比删除更多的粗糙边缘。
pkln4tw63#
长度和容量
内置函数len和cap接受各种类型的参数,并返回int类型的结果。实现保证结果总是适合int类型。
Golang是强类型语言,因此如果
len()
是uint
,则代替:你应该写:
或:
另请参阅:
uint
32位或64位int
与uint
大小相同uintptr
一个无符号整数,其大小足以存储指针值的未解释位也为了与C:CGo的
C.size_t
和大小的数组在C中的类型是int
。wtlkbnrh4#
根据规范:
长度是数组类型的一部分;数组a的长度可以使用内置函数
len
来发现。元素可以通过整数索引0
到len(a)-1
来寻址。数组类型总是一维的,但可以组合成多维类型。我意识到,说规范规定 X 可能有点循环,因为规范规定 Y,但由于长度不能超过
int
,因此len
返回uint
-exclusive值与返回负值一样不可能。