Vol*_*ker 21
len()
(和cap()
)返回,int
因为这是用于索引切片和数组(而不是uint
)的内容.所以问题是"当没有负指数时,为什么Go使用有符号整数来索引切片/数组?".
答案很简单:计算索引很常见,如果在无符号整数中完成,这种计算往往容易下溢.有些无辜类似的代码i := a-b+7
可能会产生i == 4294967291
针对无辜值a
和b
6和10这样的指数可能会溢出你的切片.大量的索引计算发生在0左右,并且使用无符号整数来纠正这些错误并且这些错误隐藏在数学上完全合理和合理的公式之后.这既不安全也不方便.
这是基于经验的权衡:对于使用无符号整数执行的索引计算,通常会发生下溢,而如果使用有符号整数进行索引计算,则溢出更不常见.
另外:在这些情况下使用无符号整数基本上没有任何好处.
小智 5
内置函数len和cap接受各种类型的参数并返回int类型的结果.该实现保证结果始终适合int.
Golang是强类型语言,所以如果len()
是,uint
那么代替:
i := 0 // int
if len(a) == i {
}
Run Code Online (Sandbox Code Playgroud)
你应该写:
if len(a) == uint(i) {
}
Run Code Online (Sandbox Code Playgroud)
要么:
if int(len(a)) == i {
}
Run Code Online (Sandbox Code Playgroud)
另见:
uint
32位或64位
int
与无符号整数相同的大小,uint
uintptr
足以存储指针值的未解释位
还用于与C兼容性:CGO的C.size_t
阵列的在C和大小的类型的int
.
有一个正在进行的提案“问题 31795 Go 2: change len
,cap
如果结果是常量,则返回无类型的 int ”
它可能包含在 Go 1.14(2010 年第一季度)中
我们应该能够做到这一点的
len
,并cap
没有问题-实际上没有任何的STDLIB作为类型检查经修改的型检查显示它
参见CL 179184作为 PoC:这仍然是实验性的。
罗伯特·格里泽默解释说:
正如您所指出的,使 len 始终无类型的问题在于结果的大小。对于布尔值(以及字符串),大小是已知的,无论是哪种布尔值(或字符串)。
我不确定这里的成本是否值得。今天有一个简单的规则:
len(x)
有类型int
。更改类型以取决于x
将与各种代码更改以非正交方式交互的内容。例如,在提议的语义下,此代码编译:Run Code Online (Sandbox Code Playgroud)const x string = "hello" func f(uintptr) ... f(len(x))
但是假设然后有人出现并希望能够进行修改
x
以进行测试或类似的事情,所以他们s/const/var/
. 这通常是相当安全的,但现在f(len(x))
调用无法进行类型检查,而且它为什么会起作用将是神秘的。这种变化似乎可能会增加比删除更多的粗糙边缘。