Go允许算术运算溢出而不是抛出异常是预期的行为吗?

Maz*_*ryt -3 integer-overflow go

我正在将一些Go代码移植到Rust,我意识到在乘法过程中发生溢出时Rust会慌乱,而Go允许溢出发生。

下面的测试代码不会引起溢出,但是会打印出减少的值。(通过以下网址测试:https : //play.golang.org/

func main() {
    fmt.Println("test\n")
    var key uint64 = 15000;

    key = key*2862933555777941757 + 1

    fmt.Println(key)
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 9

规格:整数溢出:

对于无符号整数值,运算+,-,*和<<以2 n为模,其中n无符号整数类型的位宽。松散地说,这些无符号整数运算在溢出时会丢弃高位,并且程序可能依赖于“环绕”

对于有符号整数,+,-,*,/和<<操作可能会合法溢出,并且结果值存在,并由有符号整数表示形式,操作及其操作数确定性地定义。溢出不会引起运行时恐慌在不发生溢出的假设下,编译器可能不会优化代码。例如,它可能不会假定x < x + 1始终为真。

如上所述,存在溢出并且不会引起运行时恐慌。

但是必须小心,就好像您有一个常量表达式一样,因为它们具有任意精度,如果要将结果转换为不适合目标类型的有效范围的固定精度,则会导致编译时间-错误。

例如:

const maxuint64 = 0xffffffffffffffff
var key uint64 = maxuint64 * maxuint64

fmt.Println(key)
Run Code Online (Sandbox Code Playgroud)

以上收益:

constant 340282366920938463426481119284349108225 overflows uint64
Run Code Online (Sandbox Code Playgroud)

maxuint64 * maxuint64是一个正确计算的常数表达式(其值为340282366920938463426481119284349108225),但是当将此值分配给keytype变量时uint64,由于无法用type值表示此值,因此会导致编译时错误uint64。但这不是运行时的恐慌。

查看相关问题:

Golang:故意int溢出

Go编译器对常量表达式和其他表达式的评估是否有所不同

如何在字符串中存储一个大的float64而不会溢出?

在Go中将uint16强制转换为int16的正确方法