Go语言 - for循环条件中的uint32类型(类型不匹配int和uint32)

24

为了保持类型严格性,当大小不能为负数时,我有时会将其存储为uint。在for循环中使用时,我希望它看起来像这样:

var size uint32 = 8
for i := 0; i < size; {
    n := //doesn't matter how how this value is determined
    i += n
}

然而,我收到了如下错误信息:invalid operation: i < size (mismatched types int and uint32)

将for循环重写为指定类型的方式如下:

for var i uint32 = 0; i < size; {

产生这个编译器错误:syntax error: var declaration not allowed in for initializer

唯一的解决方法是:

for i := 0; uint32(i) < size; {

或者

var i uint32 = 0
for i < size {

第一种方法效率低下,因为我在每次迭代中都进行了类型转换,而第二种方法则不够优雅。有没有更好的方法来解决这个问题?


1
var uint32 size = 8 应该改为 var size uint32 = 8,类型应该在左值之后。 - thwd
已修复,谢谢。老习惯难改吧... - Rick Smith
2
Go语言不使用“cast”这个词,uint32(i)是一种类型转换。更重要的是,在这种情况下没有效率问题。到目前为止,go中的整数都是32位的,因此这种特定的类型转换没有运行时开销,它只是在编译时影响类型检查。此外,i := uint(0)和uint32(i) < size这两种解决方案并不等价!它们生成不同的代码,并且在i变为负数的情况下会产生不同的结果。关于n的声明的注释在这方面是不正确的。如果它可能返回一个负数,结果可能会令人惊讶。 - Sonia
在这里添加“类型严格性”有什么好处?我甚至很难想象使用uint32而不是int来表示大小可以捕获到什么假想错误。 - Paul Hankin
uint32被作为参数传递。如果创建了一个负数,将会导致调用者明显不想要的行为。使用uint32将会在编译时产生错误并通知程序员他们犯了一个错误,从而更快地发现错误。稍微相关的是,大小最终被发送到tcp数据包中,这允许用相同数量的字节表示更大的数字。 - Rick Smith
1个回答

43

您可以做:

for i := uint32(0); i < size; {
    //whatever
}

通常情况下,即使大小永远不会为负数,我也不建议使用无符号整数。我不知道有什么好处。只有在我有意要溢出时才使用无符号整数。


2
据说OP在C语言中有很强的背景,熟悉size_t类型。 - kostix
或者您可以逆向迭代,避免转换...... for i := size - 1; i >= 0; { ...引入难以发现的漏洞,这就是为什么无符号类型很危险的原因。 - Paul Hankin
使用范围运算符时是否有解决方案?例如 for i := range arr { - sinned
很抱歉,不是的。@sinned - Stephen Weinberg
我选择在循环头后直接创建一个单独的变量 ui := uint32(i)。这不像其他我想到的解决方案那么丑陋... - sinned

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接