這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。聲明會給標識符綁定值,例如包、變數、類型等等。完成聲明後,有必要知道源碼中的標識符在哪些地方引用了被指定的值(簡單來講,就是一個標識符在哪裡是可用的)。Go 屬於詞法範圍,所以標識符的解析會依賴於它在代碼中聲明的位置。這種方式和動態範圍語言截然不同,動態範圍語言中標識符的可見度不依賴於被聲明的位置。看看下面這段 bash 指令碼:```bash#!/bin/bashf() {local v=1g}g() {echo "g sees v as $v"}h() {echo "h sees v as $v"}fgh```變數 v 是在函數 f 中定義的,但由於函數 g 被函數 f 調用,所以函數 g 可以訪問 v:```> ./scope.shg sees v as 1g sees v ash sees v as```當單獨調用函數 g 或者在函數 h 中調用 g 時,可以看到 v 並沒有被定義。動態範圍語言中的可見度並不是靜態不變(詞法範圍也被叫做靜態範圍),而是依賴於控制流程。當試圖編譯 Go 版本的類似代碼時會 報編譯錯誤:```gopackage mainimport "fmt"func f() {v := 1g()}func g() {fmt.Println(v) // "undefined: v"}func main() {f()}```Go 的詞法範圍使用了語句塊,所以在學習可見度規則前有必要先理解什麼是語句塊。語句塊是一連串的語句序列(空序列也算)。語句塊可以嵌套,並且被花括弧標識出來。```gopackage mainimport "fmt"func main() {{ // start outer blocka := 1fmt.Println(a){ // start inner blockb := 2fmt.Println(b)} // end inner block} // end outer block}```除了顯示標出的語句塊之外,還有一些隱式語句塊:- 主語句塊:包括所有源碼,- 包語句塊:包括該包中所有的源碼(一個包可能會包括一個目錄下的多個檔案),- 檔案語句塊:包括該檔案中的所有源碼,- for 語句本身也在它自身的隱式語句塊中:```gofor i := 0; i < 5; i++ {fmt.Println(i)}```所以在初始化語句中聲明的變數 i 可以在整個迴圈體的條件陳述式,後置語句以及嵌套塊中訪問。但在 for 語句之後使用 i 的操作會引起 “未定義:i ” 編譯錯誤。- if 語句也是它自身的隱式語句塊:```goif i := 0; i >= 0 {fmt.Println(i)}```if 語句允許聲明變數,當條件為真時該變數可以在嵌套塊中使用,抑或條件為假時在 else 語句塊中使用。 - switch 語句在它自身的隱式語句塊中:```goswitch i := 2; i * 4 {case 8:fmt.Println(i)default:fmt.Println(“default”)}```和 if 語句類似,可以使用臨時聲明變數作為 case 子句的開頭。- 每個 switch 語句中的子句都是一個隱式語句塊。```goswitch i := 2; i * 4 {case 8:j := 0fmt.Println(i, j)default:// "j" is undefined herefmt.Println(“default”)}// "j" is undefined here```如果文法規定每個 case 子句都屬於同一個文法塊的話,那麼就不會需要這個額外的例子。這將迫使每個子句都要使用花括弧,使得代碼變得不那麼易讀和簡潔。- select 語句中的每個子句都是一個隱式語句塊,和 switch 語句中的子句類似:```gotick := time.Tick(100 * time.Millisecond)LOOP:for {select {case <-tick:i := 0fmt.Println(“tick”, i)break LOOPdefault:// "i" is undefined herefmt.Println(“sleep”)time.Sleep(30 * time.Millisecond)}}// "i" is undefined here```[“Scope in Go”](https://medium.com/@mlowicki/scopes-in-go-a6042bb4298c) 解釋了範圍(可見度)。語句塊在定義範圍的整個機制中起著關鍵作用。## 資源- https://golang.org/ref/spec#Blocks
via: https://medium.com/golangspec/blocks-in-go-2f68768868f6
作者:Michał Łowicki 譯者:sunzhaohao 校對:polaris1119
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
380 次點擊