The control structures of Go are related to those of C but differ in important ways. There is no do or while loop, only a slightly generalized for; switch is more flexible; if and switch accept an optional initialization statement like that of for; and there are new control structures including a type switch and a multiway communications multiplexer, select. The syntax is also slightly different: there are no parentheses and the bodies must always be brace-delimited. express
Go的控制結構和C接近 可是在關鍵的地方仍是有些區別 Go中沒有while循環 switch用起來更加靈活 if和switch能夠有可選的初始化語句 Go增長了新的控制結構 包含類型switch經常使用來判斷接口的動態類型 還有多路通訊複用的select(channel裏會使用到這個)語法上也有些細小的差異 控制結構並不須要圓括號 可是花括號是必不可少的 數組
In Go a simple if looks like this: app
Go中的if語句: ide
if x > 0 { return y }
Mandatory braces encourage writing simple if statements on multiple lines. It's good style to do so anyway, especially when the body contains a control statement such as a return or break. 函數
強制添加花括號鼓勵你們把簡單的if語句也寫成多行 這是比較好的代碼風格 特別是if語句裏有return 或者 break oop
Since if and switch accept an initialization statement, it's common to see one used to set up a local variable. post
if和switch能夠有初始化語句 一般會定義局部變量 flex
if err := file.Chmod(0664); err != nil { log.Print(err) return err }
In the Go libraries, you'll find that when an if statement doesn't flow into the next statement—that is, the body ends in break, continue, goto, or return—the unnecessary else is omitted. this
在Go的標準庫源碼中 能夠發現else常常是被省略掉的 特別是if語句中以break continue goto或者return結尾 lua
f, err := os.Open(name) if err != nil { return err } codeUsing(f)
This is an example of a common situation where code must guard against a sequence of error conditions. The code reads well if the successful flow of control runs down the page, eliminating error cases as they arise. Since error cases tend to end in return statements, the resulting code needs no else statements.
下面這段代碼 展現了Go中經常使用的錯誤判斷 以及處理方式 因爲產生錯誤後 直接就返回了 因此這裏並不須要else語句
f, err := os.Open(name) if err != nil { return err } d, err := f.Stat() if err != nil { f.Close() return err } codeUsing(f, d)
An aside: The last example in the previous section demonstrates a detail of how the := short declaration form works. The declaration that calls os.Open reads,
上面的那個例子 其實還展現瞭如何使用 := 聲明變量
f, err := os.Open(name) // 這句定義了兩個變量f err
d, err := f.Stat() // 從f中讀數據
which looks as if it declares d and err. Notice, though, that err appears in both statements. This duplication is legal: err is declared by the first statement, but only re-assigned in the second. This means that the call to f.Stat uses the existing err variable declared above, and just gives it a new value.
初略地看 上面兩句第一了d和err 可是有沒有注意到err在上面兩句中出現了 這種狀況是合法的 err只是在第一句中被定義 在第二句中僅僅給err賦值 也就是說 f.Stat使用了已定義的err變量 僅僅給了它一個新的值
In a := declaration a variable v may appear even if it has already been declared, provided:
符合如下條件時 := 聲明一個已經定義過的變量v是合法的:
This unusual property is pure pragmatism, making it easy to use a single err value, for example, in a long if-else chain. You'll see it used often.
這個奇葩特性絕對體現了實用主義 能夠更加方便地使用err
The Go for loop is similar to—but not the same as—C's. It unifies for and while and there is no do-while. There are three forms, only one of which has semicolons.
Go中的for循環相似C 而且它把C中的while給吞併了 Go中沒有do while這樣的結構 for有三種形式 只有一種會用到分號
// Like a C for 和C中for循環相似 可是這裏沒有圓括號哦 for init; condition; post { } // Like a C while C中的while for condition { } // Like a C for(;;) C中的死循環 for { }
Short declarations make it easy to declare the index variable right in the loop.
簡短的聲明形式 能夠方便地在循環開始的位置定義遊標變量
sum := 0 for i := 0; i < 10; i++ { sum += i }
If you're looping over an array, slice, string, or map, or reading from a channel, a range clause can manage the loop.
若是你想遍歷數組 slice 字符串 map 或者從channel裏讀數據 你可使用range
for key, value := range oldMap { newMap[key] = value }
If you only need the first item in the range (the key or index), drop the second:
range返回key(或者遊標位置)以及相應的值 好比range一個數組['a','b','c'] range的結果就是
1 ‘a'
2 'b'
3 'c' 若是你只想要range的第一個元素(上面的1 2 3)能夠這樣寫:
for key := range m { if expired(key) { delete(m, key) } }
If you only need the second item in the range (the value), use the blank identifier, an underscore, to discard the first:
若是你只想要第二個元素(上面的'a' 'b' 'c')可使用空標識符 _, 丟棄range返回的第一個元素:
sum := 0 for _, value := range array { sum += value }
For strings, the range does more work for you, breaking out individual Unicode characters by parsing the UTF-8. Erroneous encodings consume one byte and produce the replacement rune U+FFFD. The loop
在遍歷字符串時 Go作了不少幕後的工做 對於每一個Unicode字符使用UTF8解碼 沒法解碼的字符佔用一個字節 而且使用U+FFFD代替【U+FFFD就是"�" (U+FFFD)】 下面這個循環
for pos, char := range "日本語" { fmt.Printf("character %c starts at byte position %d\n", char, pos) }
會輸出:
character 日 starts at byte position 0 character 本 starts at byte position 3 character 語 starts at byte position 6
Finally, Go has no comma operator and ++ and -- are statements not expressions. Thus if you want to run multiple variables in a for you should use parallel assignment.
Go沒有逗號操做符 ++和--是語句而不是表達式 若是你想同時給多個變量賦值 你只能:
// Reverse a for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 { a[i], a[j] = a[j], a[i] }
Go's switch is more general than C's. The expressions need not be constants or even integers, the cases are evaluated top to bottom until a match is found, and if theswitch has no expression it switches on true. It's therefore possible—and idiomatic—to write an if-else-if-else chain as a switch.
Go的switch結構比C更加通用 它的表達式不須要非得是常量 或者整數 case語句從頭開始執行 直到和某個case匹配 因此可使用switch來改寫if-else-if-else
func unhex(c byte) byte { switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } return 0 }
There is no automatic fall through, but cases can be presented in comma-separated lists.
Go的switch並不像C那樣 若是不加break 會致使和某個case匹配後 繼續執行以後的case 可是可使用逗號分割的列表來達到此目的
func shouldEscape(c byte) bool { switch c { case ' ', '?', '&', '=', '#', '+', '%': return true } return false }
Here's a comparison routine for byte slices that uses two switch statements:
下面這個函數 使用兩個switch來比較兩個byte slice
// Compare returns an integer comparing the two byte slices, // lexicographically. // The result will be 0 if a == b, -1 if a < b, and +1 if a > b func Compare(a, b []byte) int { for i := 0; i < len(a) && i < len(b); i++ { switch { case a[i] > b[i]: return 1 case a[i] < b[i]: return -1 } } switch { case len(a) < len(b): return -1 case len(a) > len(b): return 1 } return 0 }
A switch can also be used to discover the dynamic type of an interface variable. Such a type switch uses the syntax of a type assertion with the keyword type inside the parentheses. If the switch declares a variable in the expression, the variable will have the corresponding type in each clause.
switch能夠用來判斷接口的動態類型 type switch使用類型斷言 T.(type) T是某個接口變量 這個用法只有在switch中才是合法的
switch t := interfaceValue.(type) { default: fmt.Printf("unexpected type %T", t) // %T prints type case bool: fmt.Printf("boolean %t\n", t) case int: fmt.Printf("integer %d\n", t) case *bool: fmt.Printf("pointer to boolean %t\n", *t) case *int: fmt.Printf("pointer to integer %d\n", *t) }