Go语言小细节——表达式估值顺序

表达式估值

当估值一个表达式、赋值语句或者函数返回语句中的操作数时,所有的函数调用、方法调用和通道操作将按照它们在代码中的出现顺序进行估值。但是 Go 白皮书未指定表达式中其它估值顺序

目前 Go 的编译器官方维护有两种主流的,一个是 gc 编译器,一个是 gccgo 编译器,两种编译器打印出来的值不一样。

package main

var x, i = []int{1, 2}, 0
func f() int {i = 1; return 9}

func main() {
    x[i] = f()
    println(x[0], x[1])
}

// gc 编译器将打印出:1 9
// gccgo 编译器将打印出:9 2

一种说法是先估值函数 f,然后在估值 i,这样的结果就是 1,9
另一种说法是先估值变量 i,然后再估值函数 f,这样结果为 9,2
打印出 1 9 或者 9 2 都不违反 Go 语言白皮书。因为表达式 f() 和 i 之间的相对估值顺序未定义。

package main

import "fmt"

func f(p *int) int {
    *p = 123
    return *p
}

func g(x int) (a, b int) {
    return x, f(&x)
    // <=> a, b = x, f(&x);
    // return
}

func main() {
    fmt.Println(g(0))
}

// gc 编译器将打印出:123 123
// gccgo 编译器将打印出:0 123

同样,因为编译器的估值顺序不同,造成了两种不同的输出结果
编译器在估值 x 和 f 函数的时候,先估值 x,就会造成输出 0 123
如果先估值 f 函数,就会输出 123 123

package main

var _ = f("w", x)
var x = f("x", z)
var y = f("y", x)
var z = f("z")

func f(s string, deps ...int) int {
	print(s)
	return 0
}

func main() {}

// 将打印出 zxwy

全局变量的初始化顺序,首先初始化不依赖于其他全局变量的变量
每次初始化一个变量后就需要重新开始新的一轮初始化

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