18 理解Go 語言中的 語句塊與作用域

2022-06-05 14:00:13 字數 3184 閱讀 3644

我的 github:github.com/iswbm/golangcodingtime

由於 go 使用的是詞法作用域,而詞法作用域依賴於語句塊。所以在講作用域時,需要先了解一下 go 中的語句塊是怎麼一回事?

通俗地說,語句塊是由花括弧({})所包含的一系列語句。

語句塊內部宣告的名字是無法被外部塊訪問的。這個塊決定了內部宣告的名字的作用域範圍,也就是作用域。

用花括弧包含的語句塊,屬於顯示語句塊。

在 go 中還有很多的隱式語句塊:

前面三點好理解,第四點舉幾個例子

for 迴圈完後,不能再使用變數 i

for i := 0; i < 5; i++
if 語句判斷完後,同樣不能再使用變數 i

if i := 0; i >= 0
switch 語句完了後,也是不是再使用變數 i

switch i := 2; i * 4
且每個 switch 語句的子句都是乙個隱式的語句塊

switch i := 2; i * 4 

// "j" is undefined here

變數的宣告,除了宣告其型別,其宣告的位置也有講究,不同的位置決定了其擁有不同的作用範圍,說白了就是我這個變數,在**可用,在**不可用。

根據宣告位置的不同,作用域可以分為以下四個型別:

以上的四種作用域,從上往下,範圍從大到小,為了表述方便,我這裡自己將範圍大的作用域稱為高層作用域,而範圍小的稱為低層作用域。

對於作用域,有以下幾點總結:

在這裡要注意一下,不要將作用域和生命週期混為一談。宣告語句的作用域對應的是乙個源**的文字區域;它是乙個編譯時的屬性。

而乙個變數的生命週期是指程式執行時變數存在的有效時間段,在此時間區域內它可以被程式的其他部分引用;是乙個執行時的概念。

根據區域性作用域內變數的可見性,是否是靜態不變,可以將程式語言分為如下兩種:

具體什麼是動態作用域,這裡用 shell 的**演示一下,你就知道了

#!/bin/bash

func01()

func02() "

}# 執行函式

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()

func main()

因此你在執行這段**時,會報錯,提示在func01中的name還未定義。

參考文章:

01. 開發環境的搭建(goland & vs code)

02. 學習五種變數建立的方法

03. 詳解資料型別:****整形與浮點型

04. 詳解資料型別:byte、rune與string

05. 詳解資料型別:陣列與切片

06. 詳解資料型別:字典與布林型別

07. 詳解資料型別:指標

08. 物件導向程式設計:結構體與繼承

09. 一篇文章理解 go 裡的函式

10. go語言流程控制:if-else 條件語句

11. go語言流程控制:switch-case 選擇語句

12. go語言流程控制:for 迴圈語句

13. go語言流程控制:goto 無條件跳轉

14. go語言流程控制:defer 延遲呼叫

15. 物件導向程式設計:介面與多型

16. 關鍵字:make 和 new 的區別?

17. 一篇文章理解 go 裡的語句塊與作用域

18. 學習 go 協程:goroutine

19. 學習 go 協程:詳解通道/通道

20. 幾個通道死鎖經典錯誤案例詳解

21. 學習 go 協程:waitgroup

22. 學習 go 協程:互斥鎖和讀寫鎖

23. go 裡的異常處理:panic 和 recover

24. 超詳細解讀 go modules 前世今生及入門使用

25. go 語言中關於包匯入必學的 8 個知識點

26. 如何開源自己寫的模組給別人用?

27. 說說 go 語言中的型別斷言?

28. 這五點帶你理解go語言的select用法

go語言中的輸出語句

package main import fmt func main print println函式可以傳遞若干個引數,引數之間可以用逗號隔開 引數可以是字串 數字 數學表示式等 格式化列印 可以使用printf來控制列印的輸出結果,與print和println不同,printf的第乙個引數必須是字串...

Go語言中nil的理解

現在對於golang語言的介紹比較少,寫一點自己對於nil的理解。首先,我們取源 中看一下創始人是怎麼定義的nil 翻譯如下 nil是乙個預先宣告的識別符號,表示指標 通道 函式 介面 對映或切片型別。因此,我們可以知道nil只能表示指標 通道 函式 介面 對映或切片nil是go語言中預先的識別符號...

如何理解go語言中的閉包

對於閉包的理解,按照下面2點切入即可 1,閉包函式的返回值是函式 2,返回的函式繫結在閉包函式內乙個變數上。對於第2條如果不好理解的話,可以這麼理解。把外層的函式去掉,把函式內定義的變數想象成全域性變數,把返回的函式想象成普通函式。本質上,就是返回了乙個函式,這個函式內操作的變數是在另乙個函式中定義...