Go语言小细节——变量估值规则

变量与常量的估值

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 的类型为尚未确定的类型,在编译时,如果右操作数为变量,那么编辑器在移位操作的规则中判定,1 的类型为最终程序需要赋值的变量类型,也就是 x 的类型 byte,byte 只有8位,程序需要左移10位,所以最终变量溢出,变为0
  2. 当移位操作的右操作数为常量时,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 的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章