变量与常量的估值
package main
func main() {
var n uint = 10
const N uint = 10
var x byte = (1 << n) / 100
var y byte = (1 << N) / 100
println(x, y) // 0 10
}
程序的打印结果值为:0,10
以上程序中,x 与 y 的输出不同,仅仅是因为在左移操作中,右操作数的类型不同导致的,一个为变量,一个为常量,具体原因如下:
- 上述程序,移位操作的左操作数 1 的类型为尚未确定的类型,在编译时,如果右操作数为变量,那么编辑器在移位操作的规则中判定,1 的类型为最终程序需要赋值的变量类型,也就是 x 的类型 byte,byte 只有8位,程序需要左移10位,所以最终变量溢出,变为0
- 当移位操作的右操作数为常量时,1 还是被认为是类型不确定的整数来进行处理,所以 1 << 10 = 1024, 1024 / 100 = 10
const N = 2
var m = 2
var _ float64 = 1 << N // 编译没问题
var _ = float64(1 << N) // 编译没问题
// 1被推断为float64类型
var _ float64 = 1 << m // 编译失败:浮点数不可被移位
var _ = float64(1 << m) // 编译失败:浮点数不可被移位
以上也是同理,当移位操作的右操作数为常量时,编译器会认定为类型不确定的整数,允许移位操作,但当右操作数为变量时,就会认定为是 float64 类型,浮点数是不能进行移位操作的,所以程序编译报错。
多值赋值语句的执行规则
var a []int = nil
a, a[0] = []int{1, 2}, 9
fmt.Println(a)
以上程序会在编译时报错,因为程序在执行多值赋值的时候,会进行以下两阶段:
// 第一阶段
x := &a; y := a; z := 0 // x,y,z可以理解为编译器生成的临时变量
// 第二阶段(不影响第一阶段)
*x = []int{1, 2}
y[z] = 9
所以在执行 a[0] = 9 的时候,此时的 a 还是为 nil 的