Operators
…
The right operand in a shift expression must have integer type or be an untyped constant representable by a value of type
uint
.
A bunch of examples demonstrating this follow in the spec, so I won’t provide my own.
… If the left operand of a non-constant shift expression is an untyped constant, it is first implicitly converted to the type it would assume if the shift expression were replaced by its left operand alone.
So what are we actually talking about here? This:
m := int64(3)
x := 5 << m // A non-constant shift expression, with an untyped const as the left operand
So what is x
’s type here? That’s what this sentence is describing when it says “it is first implicitly converted to the type it would assume if the shift expression were replaced by its left operand alone”.
In other words, x
’s type should match the type of the expression:
y := 5
And indeed it does:
var m = int64(3)
x := 5 << m
y := 5
fmt.Printf("%T %T\n", x, y) // int int
var a [1024]byte var s uint = 33 // The results of the following examples are given for 64-bit ints. var i = 1<<s // 1 has type int var j int32 = 1<<s // 1 has type int32; j == 0 var k = uint64(1<<s) // 1 has type uint64; k == 1<<33 var m int = 1.0<<s // 1.0 has type int; m == 1<<33 var n = 1.0<<s == j // 1.0 has type int32; n == true var o = 1<<s == 2<<s // 1 and 2 have type int; o == false var p = 1<<s == 1<<33 // 1 has type int; p == true var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift var v1 float32 = 1<<s // illegal: 1 has type float32, cannot shift var v2 = string(1<<s) // illegal: 1 is converted to a string, cannot shift var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression; w == 1<<33 var x = a[1.0<<s] // panics: 1.0 has type int, but 1<<33 overflows array bounds var b = make([]byte, 1.0<<s) // 1.0 has type int; len(b) == 1<<33 // The results of the following examples are given for 32-bit ints, // which means the shifts will overflow. var mm int = 1.0<<s // 1.0 has type int; mm == 0 var oo = 1<<s == 2<<s // 1 and 2 have type int; oo == true var pp = 1<<s == 1<<33 // illegal: 1 has type int, but 1<<33 overflows int var xx = a[1.0<<s] // 1.0 has type int; xx == a[0] var bb = make([]byte, 1.0<<s) // 1.0 has type int; len(bb) == 0
Quotes from The Go Programming Language Specification Version of August 2, 2023