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

m1m5dgzv  于 2022-12-07  发布在  Go
关注(0)|答案(4)|浏览(269)

Go语言的内置函数len()返回一个带符号的int,为什么不使用uint呢?
len()有可能返回负数吗?
据我所知,答案是否定的:

  • 数组:“元素的数量称为长度,并且永远不为负。”
  • 切片:“在任何时候,以下关系都成立:0 <= len(s) <= cap(s)英寸
  • Map“Map元素的数量称为其长度”。(我在规范中找不到任何明确将其限制为非负值的内容,但我很难理解为什么Map中的元素少于0)
  • 字符串“字符串值是一个(可能是空的)字节序列....字符串的长度s(以字节为单位)可以使用内置函数len()来发现“(同样,很难理解一个序列怎么会有负数的字节)
  • 通道缓冲区中排队的通道元素数(同上)
7gcisfzg

7gcisfzg1#

len()(和cap())返回int,因为它是用来索引切片和数组的(而不是uint),所以问题更多的是“为什么Go语言在没有负索引的情况下使用有符号整数来索引切片/数组?"
答案很简单:计算一个索引是很常见的,如果用无符号的整数来计算,这样的计算很容易下溢。一些无辜的代码,比如i := a-b+7,可能会产生i == 4294967291,因为ab的无辜值是6和10。这样的索引很可能会溢出你的切片。很多索引计算都发生在0附近,使用无符号整数很难正确计算,这些错误隐藏在数学上完全合理的公式后面,这既不安全也不方便。
这是基于经验的权衡:使用无符号整数进行索引计算时,往往会发生下溢,而如果使用有符号整数进行索引计算,则上溢不太常见。
此外:在这些情况下,使用无符号整数基本上没有任何好处。

y53ybaqx

y53ybaqx2#

有一个正在进行的建议“issue 31795 Go 2: change len , cap to return untyped int if result is constant
Go 1.14(2010年第1季度)* 可能 * 会包含此功能
我们应该能够对lencap执行此操作,而不会出现问题--事实上,通过修改后的类型检查器对stdlib进行类型检查时发现,stdlib中没有任何类型
CL 179184视为PoC:这仍然是实验性。
由于noted below通过peterSO,此已关闭。
Robert Griesemer说明:
正如你所提到的,使len总是无类型化的问题是结果的大小。对于布尔值(也包括字符串),大小是已知的,不管是什么类型的布尔值(或字符串)。
添加了Russ Cox
我不确定这里的成本是否值得收益。今天有一个简单的规则:len(x)具有类型int。将类型更改为依赖于x的类型将以非正交的方式与各种代码更改交互。例如,在建议的语义下,以下代码将编译:

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

但是假设有人想要修改x以进行测试或类似的操作,那么他们就使用s/const/var/,这通常是相当安全的,但是现在f(len(x))调用无法进行类型检查,那么它为什么会工作就变得很神秘了。
这种变化似乎增加了比删除更多的粗糙边缘。

pkln4tw6

pkln4tw63#

长度和容量
内置函数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一个无符号整数,其大小足以存储指针值的未解释位
也为了与C:CGoC.size_t和大小的数组在C中的类型是int

wtlkbnrh

wtlkbnrh4#

根据规范:
长度是数组类型的一部分;数组a的长度可以使用内置函数len来发现。元素可以通过整数索引0len(a)-1来寻址。数组类型总是一维的,但可以组合成多维类型。
我意识到,说规范规定 X 可能有点循环,因为规范规定 Y,但由于长度不能超过int,因此len返回uint-exclusive值与返回负值一样不可能。

相关问题