Hi,你們好,我是明哥。python
在本身學習 Golang 的這段時間裏,我寫了詳細的學習筆記放在個人我的微信公衆號 《Go編程時光》,對於 Go 語言,我也算是個初學者,所以寫的東西應該會比較適合剛接觸的同窗,若是你也是剛學習 Go 語言,不防關注一下,一塊兒學習,一塊兒成長。git
個人在線博客:http://golang.iswbm.com
個人 Github:github.com/iswbm/GolangCodingTimegithub
因爲 Go 使用的是詞法做用域,而詞法做用域依賴於語句塊。因此在講做用域時,須要先了解一下 Go 中的語句塊是怎麼一回事?golang
通俗地說,語句塊是由花括弧({}
)所包含的一系列語句。shell
語句塊內部聲明的名字是沒法被外部塊訪問的。這個塊決定了內部聲明的名字的做用域範圍,也就是做用域。編程
用花括弧包含的語句塊,屬於顯示語句塊。數組
在 Go 中還有不少的隱式語句塊:bash
前面三點好理解,第四點舉幾個例子微信
for 循環完後,不能再使用變量 i編程語言
for i := 0; i < 5; i++ { fmt.Println(i) }
if 語句判斷完後,一樣不能再使用變量 i
if i := 0; i >= 0 { fmt.Println(i) }
switch 語句完了後,也是否是再使用變量 i
switch i := 2; i * 4 { case 8: fmt.Println(i) default: fmt.Println(「default」) }
且每一個 switch 語句的子句都是一個隱式的語句塊
switch i := 2; i * 4 { case 8: j := 0 fmt.Println(i, j) default: // "j" is undefined here fmt.Println(「default」) } // "j" is undefined here
變量的聲明,除了聲明其類型,其聲明的位置也有講究,不一樣的位置決定了其擁有不一樣的做用範圍,說白了就是我這個變量,在哪裏可用,在哪裏不可用。
根據聲明位置的不一樣,做用域能夠分爲如下四個類型:
以上的四種做用域,從上往下,範圍從大到小,爲了表述方便,我這裏本身將範圍大的做用域稱爲高層做用域,而範圍小的稱爲低層做用域。
對於做用域,有如下幾點總結:
在這裏要注意一下,不要將做用域和生命週期混爲一談。聲明語句的做用域對應的是一個源代碼的文本區域;它是一個編譯時的屬性。
而一個變量的生命週期是指程序運行時變量存在的有效時間段,在此時間區域內它能夠被程序的其餘部分引用;是一個運行時的概念。
根據局部做用域內變量的可見性,是不是靜態不變,能夠將編程語言分爲以下兩種:
具體什麼是動態做用域,這裏用 Shell 的代碼演示一下,你就知道了
#!/bin/bash func01() { local value=1 func02 } func02() { echo "func02 sees value as ${value}" } # 執行函數 func01 func02
從代碼中,能夠看到在 func01 函數中定義了個局部變量 value,按理說,這個 value 變量只在該函數內可用,但因爲在 shell 中的做用域是動態的,因此在 func01中也能夠調用 func02 時,func02 能夠訪問到 value 變量,此時的 func02 做用域能夠當成是 局部做用域中(func01)的局部做用域。
但若脫離了 func01的執行環境,將其放在全局環境下或者其餘函數中, func02 是訪問不了 value 變量的。
因此此時的輸出結果是
func02 sees value as 1 func02 sees value as
但在 Go 中並不存在這種動態做用域,好比這段代碼,在func01函數中,要想取得 name 這個變量,只能從func01的做用域或者更高層做用域裏查找(文件級做用域,包級做用域和內置做用域),而不能從調用它的另外一個局部做用域中(由於他們在層級上屬於同一級)查找。
import "fmt" func func01() { fmt.Println("在 func01 函數中,name:", name) } func main() { var name string = "Python編程時光" fmt.Println("在 main 函數中,name:", name) func01() }
所以你在執行這段代碼時,會報錯,提示在func01中的name還未定義。
參考文章:https://studygolang.com/articles/12632
系列導讀
24. 超詳細解讀 Go Modules 前世此生及入門使用