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

全局變量的初始化順序,首先初始化不依賴於其他全局變量的變量
每次初始化一個變量後就需要重新開始新的一輪初始化

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