以下是一些不够严谨的分析。

参照文档进行研究,Go必然有这么几个特点:

<<

而从表象上来看:

  1. 静态求值的规则是先不顾代码范围,强制求值,之后再塞回目标的存储空间中
  2. 对变量左移的时候,会直接考虑存储空间大小,将左移的数据丢弃
<<
const c_i8 uint8 = 255
var i16 uint16
i16 = uint16(c_i8 << 4) // constant 4080 overflows uint8
i16 = uint16(uint8(255) << 4) // constant 4080 overflows uint8

对于第2条,如下的代码都可以正确执行:

var i8 uint8
var i8_2 uint8 = 255
i8 = i8_2 << 4
fmt.Printf("%x\n", i8) // f0
i8_2 <<= 4
fmt.Printf("%x\n", i8_2) // f0
& 0xFF
const c_i8 uint8 = 255
var i16 uint16
i16 = uint16(uint(c_i8) << 4 & 0xFF)
fmt.Printf("%x\n", i16)

更深入的分析期待其他回答者的补充。