for
語句表明着循環。一條語句一般由關鍵字for
、初始化子句、條件表達式、後置子句和以花括號包裹的代碼塊組成。其中,初始化子句、條件表達式和後置子句之間需用分號分隔。示例以下:數組
for i := 0; i < 10; i++ { fmt.Print(i, " ") }
咱們能夠省略掉初始化子句、條件表達式、後置子句中的任何一個或多個,不過起到分隔做用的分號通常須要被保留下來,除非在僅有條件表達式或三者全被省略時分號才能夠被一同省略。
咱們能夠把上述的初始化子句、條件表達式、後置子句合稱爲for
子句。實際上,for
語句還有另一種編寫方式,那就是用range
子句替換掉for
子句。range
子句包含一個或兩個迭代變量(用於與迭代出的值綁定)、特殊標記:=
或=
、關鍵字range
以及range
表達式。其中,range
表達式的結果值的類型應該是可以被迭代的,包括:字符串類型、數組類型、數組的指針類型、切片類型、字典類型和通道類型。例如:編碼
for i, v := range "Go語言" { fmt.Printf("%d: %c\n", i, v) }
對於字符串類型的被迭代值來講,for
語句每次會迭代出兩個值。第一個值表明第二個值在字符串中的索引,而第二個值則表明該字符串中的某一個字符。迭代是以索引遞增的順序進行的。例如,上面的for
語句被執行後會在標準輸出上打印出:spa
0: G 1: o 2: 語 5: 言
能夠看到,這裏迭代出的索引值並非連續的。下面咱們簡單剖析一下此表象的本質。咱們知道,字符串的底層是以字節數組的形式存儲的。而在Go語言中,字符串到字節數組的轉換是經過對其中的每一個字符進行UTF-8編碼來完成的。字符串"Go語言"
中的每個字符與相應的字節數組之間的對應關係以下:3d
注意,一箇中文字符在通過UTF-8編碼以後會表現爲三個字節。因此,咱們用語[0]、語[1]和、語[2]分別表示字符'語'
經編碼後的第1、2、三個字節。對於字符'言'
,咱們如法炮製。指針
對照這張表格,咱們就可以解釋上面那條for
語句打印出的內容了,即:每次迭代出的第一個值所表明的是第二個字符值經編碼後的第一個字節在該字符串經編碼後的字節數組中的索引值。請你們真正理解這句話的含義。
對於數組值、數組的指針值和切片之來講,range
子句每次也會迭代出兩個值。其中,第一個值會是第二個值在被迭代值中的索引,而第二個值則是被迭代值中的某一個元素。一樣的,迭代是以索引遞增的順序進行的。
對於字典值來講,range
子句每次仍然會迭代出兩個值。顯然,第一個值是字典中的某一個鍵,而第二個值則是該鍵對應的那個值。注意,對字典值上的迭代,Go語言是不保證其順序的。
攜帶range
子句的for
語句還能夠應用於一個通道值之上。其做用是不斷地從該通道值中接收數據,不過每次只會接收一個值。注意,若是通道值中沒有數據,那麼for
語句的執行會處於阻塞狀態。不管怎樣,這樣的循環會一直進行下去。直至該通道值被關閉,for
語句的執行纔會結束。
最後,咱們來講一下break
語句和continue
語句。它們均可以被放置在for
語句的代碼塊中。前者被執行時會使其所屬的for
語句的執行當即結束,然後者被執行時會使當次迭代被停止(當次迭代的後續語句會被忽略)而直接進入到下一次迭代。code