Go Constants can't overflow
Tags: go
Published: 2023-06-23 12:50:04

Did you know that constants in Go can't overflow?

Quoting the [Go spec](https://go.dev/ref/spec#Constants):

> Numeric constants represent exact values of arbitrary precision and do not overflow. Consequently, there are no constants denoting the IEEE-754 negative zero, infinity, and not-a-number values.

Now this is a very interesting thing about constants in Go, and it’s something that confuses a lot of people. So let’s play around with this one a bit.

If you’re experienced with compiled languages, you’re probably already familiar with numeric overflows. Each language handles this differently, but in general, you can’t store more than 8 bits of data in an 8-bit variable.

```golang
var x int8
x += 256
```

will predictably complain:

```
256 (untyped int constant) overflows int8
```

But notice the parenthetical note in that error message: “untyped int constant”

We’ll talk more about untyped constants soon, but for now the interesting thing to point out is that it’s not the constant expression (i.e. `256`) that overflowed. It’s the variable assignment (i.e. `x +=`) that overflowed.

This is because, as quoted from the spec above, constants _do not overflow_.

You can create constant expressions in Go of arbitrary precision, and they’re valid. Check this out:

```golang
var x int8
x += 2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
```

It still produces essentially the same error:

```
2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (untyped int constant) overflows int8
```

That value is effectively a 312-bit integer (if my math isn’t off). There’s no data type in Go that can store a 312-bit integer. So you might expect that constant to overflow. But it doesn’t. Because constants _do not overflow_.

But as soon as you try to assign a constant to a variable, that _assignment_ may cause an overflow.

Jumping ahead a bit to the end of this section in the spec, we see a note on implementation requirements:

> Implementation restriction: Although numeric constants have arbitrary precision in the language, a compiler may implement them using an internal representation with limited precision. That said, every implementation must:
>
> - Represent integer constants with at least 256 bits.
> -Represent floating-point constants, including the parts of a complex constant, with a mantissa of at least 256 bits and a signed binary exponent of at least 16 bits.
> - Give an error if unable to represent an integer constant precisely.
> - Give an error if unable to represent a floating-point or complex constant due to overflow.
> - Round to the nearest representable constant if unable to represent a floating-point or complex constant due to limits on precision.
>
> These requirements apply both to literal constants and to the result of evaluating [constant expressions](https://go.dev/ref/spec#Constant_expressions).

So there’s a bit of a caveat to this “constants do not overflow” rule. An implementation may choose to round a constant representations to 256 bits, for example. So my 312-bit example above may be rounded to `2559999999999999972095373170245681839337968901451475214262959301931782193648482834514033246208` in such an implementation (again: if my math isn’t off).

So if you want to be super-paranoid, limit your constant literals to 256 bits of precision. 😉

<hr>

If you learned something reading this, you'll learn something every day by subscribing to my daily Go mailing list! Sign up for [Boldly Go: Daily](https://boldlygo.tech/daily).