Conversions between numeric types

March 6, 2024

So we’ve gone through the high-level conversion stuff… now we dive into some particulars. Today, numeric conversions.

Conversions between numeric types

For the conversion of non-constant numeric values, the following rules apply:

  1. When converting between integer types, if the value is a signed integer, it is sign extended to implicit infinite precision; otherwise it is zero extended. It is then truncated to fit in the result type’s size. For example, if v := uint16(0x10F0), then uint32(int8(v)) == 0xFFFFFFF0. The conversion always yields a valid value; there is no indication of overflow.

In other words, the fact that the sign uses a single bit of a signed integer’s capacity won’t impact the precision during conversion. But you can still suffer data loss during such a conversion, if the target’s type has less precision (either in terms of bits, or sign).

  1. When converting a floating-point number to an integer, the fraction is discarded (truncation towards zero).

Simple enough. No rounding happens… just truncation.

var π float64 = 3.14159
var pi = int(π) // 3
  1. When converting an integer or floating-point number to a floating-point type, or a complex number to another complex type, the result value is rounded to the precision specified by the destination type. For instance, the value of a variable x of type float32 may be stored using additional precision beyond that of an IEEE-754 32-bit number, but float32(x) represents the result of rounding x’s value to 32-bit precision. Similarly, x + 0.1 may use more than 32 bits of precision, but float32(x + 0.1) does not.

So in this case rounding actually happens, not truncation. This means that when you convert between floating point or complex types, the absolute value of the result may be larger than the absolute value of the original.

var a float64 = 1.0000003
var b = float32(a) // 1.0000004

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

We saw a similar note last month when looking at floating point operators: An implementation may choose to panic in certain cases. I suspect both of these “implementation-dependent” rules exist to allow working on CPU architectures without different floating point support.

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Non-constant conversions, part 2

Today we’ll finish the list of non-constant conversion rules that don’t relate to type parameters. Conversions … x’s type and T are both integer or floating point types. x’s type and T are both complex types. x is an integer or a slice of bytes or runes and T is a string type. x is a string and T is a slice of bytes or runes. x is a slice, T is an array [Go 1.


Comparison operators, continued

Yesterday we started on comparison operators. Today we’ll continue, but there are a lot of types to cover, so I’ll break this down into a two or three parts, to keep each day’s email easily digestible. Recall that we had just been introduced to the concepts of ordered and comparable, and this is where we pick up… Comparison operators … These terms and the result of the comparisons are defined as follows:


Type Conversion & struct tgs

We’ve already mentioned that struct tags are ignored when doing conversion between struct types. Now we see where that’s defined, along with an example: Conversions … Struct tags are ignored when comparing struct types for identity for the purpose of conversion: type Person struct { Name string Address *struct { Street string City string } } var data *struct { Name string `json:"name"` Address *struct { Street string `json:"street"` City string `json:"city"` } `json:"address"` } var person = (*Person)(data) // ignoring tags, the underlying types are identical I don’t think there’s much else to say about that, so let’s move on, and finish up this section.

Get daily content like this in your inbox!

Subscribe