[翻譯] effective go 之 Control structures

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Control structures

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.

Go的控制結構和C接近 但是在關鍵的地方還是有些區別 Go中沒有while迴圈 switch用起來更加靈活 if和switch可以有可選的初始化語句 Go增加了新的控制結構 包含類型switch常用來判斷介面的動態類型 還有多路通訊複用的select(channel裡會使用到這個)文法上也有些細小的差別 控制結構並不需要圓括弧 但是花括弧是必不可少的


If

In Go a simple if looks like this:

Go中的if語句:

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

Since if and switch accept an initialization statement, it's common to see one used to set up a local variable.

if和switch可以有初始化語句 通常會定義局部變數

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.

在Go的標準庫源碼中 可以發現else經常是被省略掉的 特別是if語句中以break continue goto或者return結尾

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)


Redeclaration 重複申明

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 declaration is in the same scope as the existing declaration of v (if v is already declared in an outer scope, the declaration will create a new variable),
  • 第二次聲明和v在同樣的範圍下(如果v是在函數外定義的 函數體內再次定義v 就會建立一個新的變數v 並且覆蓋掉函數外的v)
  • the corresponding value in the initialization is assignable to v, and
  • 新的值對於v來說是可以接受的 類型必須一致
  • there is at least one other variable in the declaration that is being declared a new.
  • 第二次聲明時 必須至少和一個新的變數一起被聲明

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 


For

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中的whilefor condition { }// Like a C for(;;) C中的死迴圈for { }

Short declarations make it easy to declare the index variable right in the loop.

簡短的聲明形式 可以方便地在迴圈開始的位置定義遊標變數

sum := 0for 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 := 0for _, 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 0character 本 starts at byte position 3character 語 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 afor i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {    a[i], a[j] = a[j], a[i]}


Switch

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 > bfunc 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 typecase 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)}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.