go

Go Constants can't overflow

jhall

Jonathan Hall

Posted on June 23, 2023

Go Constants can't overflow

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

Quoting the Go spec:

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.

var x int8
x += 256
Enter fullscreen mode Exit fullscreen mode

will predictably complain:

256 (untyped int constant) overflows int8
Enter fullscreen mode Exit fullscreen mode

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:

var x int8
x += 2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Enter fullscreen mode Exit fullscreen mode

It still produces essentially the same error:

2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (untyped int constant) overflows int8
Enter fullscreen mode Exit fullscreen mode

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.

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. 😉


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.

💖 💪 🙅 🚩
jhall
Jonathan Hall

Posted on June 23, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Where GitOps Meets ClickOps
devops Where GitOps Meets ClickOps

November 29, 2024

How to Use KitOps with MLflow
beginners How to Use KitOps with MLflow

November 29, 2024