Detecting over-/underflow for uint64+int64
I really like that you put those tests together in the playground, thanks!

I am not a fan of losing information that may be useful. You will always need to check 0-value results to see if they indicate an overflow/underflow condition, so it's just simpler to return a useful result for those times when overflow is OK.... why return 0 when the actual remaining result is just as good?

More specifically, you will always have code like:

value, ok := addUintInt64(x, y)
if !ok {
   ....
}


so why force the 0 in to the value for !ok?

In addition, the magnitude of an int64 is never going to exceed half the magnitude of a uint64, so a double-overflow is not possible, and the logic required to check an overflow condition is a case of checking the change, or the direction of the change, of the sign-bit of the equivalent int64 value.

Perhaps this is best described if you handle the complete calculation in int64 space, and convert the result to uint64 - and realize that the MSB of the uint is the sign bit of the int.

The following conditions are all OK:


the sign bit does not change after the addition, then there's no overflow condition (no possibility of wrap)
the sign bit changes, but the int value was positive and the source sign bit was not set
the sign bit changes, but the int value was negative and the source sign bit was set


This is easy to codify in Go as:

result := uint64(int64(x) + y)
before := x &gt;&gt; 63
after := result &gt;&gt; 63
ok := before == after || (before == 0 &amp;&amp; y &gt;= 0) || (before == 1 &amp;&amp; y &lt; 0)


The above calculates in int64 space, wraps back to uint64 space, and computes the overflow conditions....

Using your same test cases (with the 0 return value for !ok) you can see this in the playground.

I would rather return the result though even if !ok, to avoid the additional check, so it would be the function:

func addUintInt64(x uint64, y int64) (uint64, bool) {
    result := uint64(int64(x) + y)
    before := x &gt;&gt; 63
    after := result &gt;&gt; 63
    ok := before == after || (before == 0 &amp;&amp; y &gt;= 0) || (before == 1 &amp;&amp; y &lt; 0)
    return result, ok
}