這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
2.1 運算式
語言設計簡練,保留字不多。
break default func interface selectcase defer go map structchan else goto package switchconst fallthrough if range typecontinue for import return var
2.2 運算子
全部運算子、分隔字元,以及其他符號。
+ & += &= && == != ( )- | -= |= || < <= [ ]* ^ *= ^= <- > >= { }/ << /= <<= ++ = := , ;% >> %= >>= -- ! ... . :&^ &^=
運算子結合律全部從左至右。
優先順序 運算子 說明------------+---------------------------------------------+----------------------------high * / & << >> & &^+ - |" ^== != < <= < >=<- channel&&low ||
簡單位元運算示範。
0110 & 1011 = 0010 AND 都為 1。0110 | 1011 = 1111 OR ⾄至少⼀一個為 1。0110 ^ 1011 = 1101 XOR 只能⼀一個為 1。0110 &^ 1011 = 0100 AND NOT 清除標誌位。
標誌位操作。
a := 0a |= 1 << 2 // 0000100: 在 bit2 設定標誌位。a |= 1 << 6 // 1000100: 在 bit6 設定標誌位a = a &^ (1 << 6) // 0000100: 清除 bit6 標誌位。
不支援運算子多載。尤其需要注意,"++"、"--" 是語句而非運算式。
n := 0p := &n// b := n++ // syntax error// if n++ == 1 {} // syntax error// ++n // syntax errorn++*p++ // (*p)++
沒有 "~",取反運算也用 "^"。
x := 1x, ^x // 0001, -0010
2.3 初始化
初始化綜合物件,必須使用類型標籤,且左大括弧必須在類型尾部。
// var a struct { x int } = { 100 } // syntax error// var b []int = { 1, 2, 3 } // syntax error// c := struct {x int; y string} // syntax error: unexpected semicolon or newline// {// }var a = struct{ x int }{100}var b = []int{1, 2, 3}
初始化值以 "," 分隔。可以分多行,但最後一行必須以 "," 或 "}" 結尾。
a := []int{ 1, 2 // Error: need trailing comma before newline in composite literal}a := []int{ 1, 2, // ok}b := []int{ 1, 2 } // ok
2.4 控制流程
2.4.1 IF
很特別的寫法:
- 可省略條件運算式括弧。
- 支援初始化語句,可定義代碼塊局部變數。
- 代碼塊左大括弧必須在條件運算式尾部。
例如:
x := 0// if x > 10 // Error: missing condition in if statement// {// }if n := "abc"; x > 0 { // 初始化語句未必就是定義變數,比如 println("init") 也是可以的。 println(n[2])} else if x < 0 { // 注意 else if 和 else 左大括弧位置。 println(n[1])} else { println(n[0])}
不支援三元操作符 "a > b ? a : b"。
2.4.2 For
支援三種迴圈方式,包括類 while 文法。
s := "abc"for i, n := 0, len(s); i < n; i++ { // 常見的 for 迴圈,支援初始化語句。 println(s[i])}n := len(s)for n > 0 { // 替代 while (n > 0) {} println(s[n]) // 替代 for (; n > 0;) {} n--}for { // 替代 while (true) {} println(s) // 替代 for (;;) {}}
不要期望編譯器能理解你的想法,在初始化語句中計算出全部結果是個好主意。
2.4.3 Range
類似迭代器操作,返回 (索引, 值) 或 (鍵, 值)。
1st value 2nd value------------------+-------------------+------------------+-------------------string index s[index] unicode, runearray/slice index s[index]map key m[key]channel element
可忽略不想要的傳回值,或用 "_" 這個特殊變數。
s := "abc"for i := range s { // 忽略 2nd value,支援 string/array/slice/map。 println(s[i])}for _, c := range s { // 忽略 index。 println(c)}for range s { // 忽略全部傳回值,僅迭代。 ...}m := map[string]int{"a": 1, "b": 2}for k, v := range m { // 返回 (key, value)。 println(k, v)}
注意,range 會複製對象。
a := [3]int{0, 1, 2}for i, v := range a { // index、value 都是從複製品中取出。 if i == 0 { // 在修改前,我們先修改原數組。 a[1], a[2] = 999, 999 fmt.Println(a) // 確認修改有效,輸出 [0, 999, 999]。 } a[i] = v + 100 // 使用複製品中取出的 value 修改原數組。}fmt.Println(a) // 輸出 [100, 101, 102]。
建議改用參考型別,其底層資料不會被複製。
另外兩種參考型別 map、channel 是指標封裝,而不像 slice 是 struct。
下一篇: Go 邊看邊練 -《Go 學習筆記》系列(五)
- 本系列是基於雨痕的《Go 學習筆記》(第四版)整理彙編而成,非常感謝雨痕的辛勤付出與分享!
- 轉載請註明:文章轉載自:駭客與畫家的社區 [http://symphony.b3log.org]
- 如果你覺得本章節做得不錯,請在下面打賞一下吧~