In case you missed it… It has come to my attention that Monday’s livestream went to the wrong stream on YouTube! This means if you followed the link I shared with you on Monday, you likely sat there waiting for 2 hours, only to be disappointed by a lack of live programming. 😞
Alas, the livestream did happen, just at a different link by accident. So here’s that link, so you can watch the replay, if you so desire.
Conversions
…
A constant value
x
can be converted to typeT
ifx
is representable by a value ofT
. As a special case, an integer constantx
can be explicitly converted to a string type using the same rule as for non-constantx
.
Not much to see here. The exception it mentions we’ll be getting to shortly, so I won’t go into those details now.
Converting a constant to a type that is not a type parameter yields a typed constant.
Recall that Go supports untyped constants. This is one of the concepts that gives Go some of the flexibility of a dynamically typed language.
const x = 3 // x is an unypted constant, and can be used as any numeric type, depending on context
uint(iota) // iota value of type uint float32(2.718281828) // 2.718281828 of type float32 complex128(1) // 1.0 + 0.0i of type complex128 float32(0.49999999) // 0.5 of type float32 float64(-1e-1000) // 0.0 of type float64 string('x') // "x" of type string string(0x266c) // "♬" of type string myString("foo" + "bar") // "foobar" of type myString string([]byte{'a'}) // not a constant: []byte{'a'} is not a constant (*int)(nil) // not a constant: nil is not a constant, *int is not a boolean, numeric, > or string type int(1.2) // illegal: 1.2 cannot be represented as an int string(65.0) // illegal: 65.0 is not an integer constant
The important thing to note here is that when you convert a constant, the result is still a constant.
Well, that is… unless…
Converting a constant to a type parameter yields a non-constant value of that type, with the value represented as a value of the type argument that the type parameter is instantiated with. For example, given the function:
func f[P ~float32|~float64]() { … P(1.1) … } the conversion `P(1.1)` results in a non-constant value of type `P` and the value `1.1` is represented as a `float32` or a `float64` depending on the type argument for `f`. Accordingly, if `f` is instantiated with a `float32` type, the numeric value of the expression `P(1.1) + 1.2` will be computed with the same precision as the corresponding non-constant `float32` addition.
So some of the benefits of using constants (for efficiency, or for greater precision) are lost when using generics.
This is unlikely to have a big impact, except in very rare cases.
Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)