<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] Go的控制結構與C的相關,但是有重要的區別。沒有`do`或者`while`循環,只有一個稍微廣義的`for`;`switch`更加靈活;`if`和`switch`接受一個像`for`那樣可選的初始化語句;`break`和`continue`語句接受一個可選的標號來指定中斷或繼續什么;還有一些新的控制結構,包括類型switch和多路通信復用器(multiway communications multiplexer),`select`。語句也稍微有些不同:沒有圓括號,并且控制結構體必須總是由大括號包裹。 ## If Go中,簡單的`if`看起來是這樣的: ~~~ if x > 0 { return y } ~~~ 強制的大括號可以鼓勵大家在多行中編寫簡單的`if`語句。不管怎樣,這是一個好的風格,特別是當控制結構體包含了一條控制語句,例如`return`或者`break`。 既然`if`和`switch`接受一個初始化語句,那么常見的方式是用來建立一個局部變量。 ~~~ if err := file.Chmod(0664); err != nil { log.Print(err) return err } ~~~ 在Go的庫中,你會發現當`if`語句不會流向下一條語句時—也就是說,控制結構體結束于`break`,`continue`,`goto`或者`return`—則不必要的`else`會被省略掉。 ~~~ f, err := os.Open(name) if err != nil { return err } codeUsing(f) ~~~ 這個例子是一種常見的情況,代碼必須防范一系列的錯誤條件。如果成功的控制流是沿著頁面往下走,來消除它們引起的錯誤情況,那么代碼會非常易讀。由于錯誤情況往往會結束于`return`語句,因此代碼不需要有`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) ~~~ ## 重新聲明和重新賦值 另外:上一章節的最后一個例子,展示了`:=`短聲明形式的工作細節。該聲明調用了`os.Open`進行讀取, ~~~ f, err := os.Open(name) ~~~ 該語句聲明了兩個變量,`f`和`err`。幾行之后,又調用了`f.Stat`進行讀取, ~~~ d, err := f.Stat() ~~~ 這看起來像是又聲明了`d`和`err`。但是,注意`err`在兩條語句中都出現了。這種重復是合法的:`err`是在第一條語句中被聲明,而在第二條語句中只是被*重新賦值*。這意味著使用之前已經聲明過的`err`變量調用`f.Stat`,只會是賦給其一個新的值。 在`:=`聲明中,變量`v`即使已經被聲明過,也可以出現,前提是: * 該聲明和`v`已有的聲明在相同的作用域中(如果`v`已經在外面的作用域里被聲明了,則該聲明將會創建一個新的變量 §) * 初始化中相應的值是可以被賦給`v`的 * 并且,聲明中至少有其它一個變量將被聲明為一個新的變量 這種不尋常的屬性純粹是從實用主義方面來考慮的。例如,這會使得在一個長的`if-else`鏈中,很容易地使用單個`err`值。你會經常看到這種用法。 § 值得一提的是,在Go中,函數參數和返回值的作用域與函數體的作用域是相同的,雖然它們在詞法上是出現在包裹函數體的大括號外面。 ## For Go的`for`循環類似于—但又不等同于—C的。它統一了`for`和`while`,并且沒有`do-while`。有三種形式,其中只有一個具有分號。 ~~~ // Like a C for for init; condition; post { } // Like a C while for condition { } // Like a C for(;;) for { } ~~~ 短聲明使得在循環中很容易正確的聲明索引變量。 ~~~ sum := 0 for i := 0; i < 10; i++ { sum += i } ~~~ 如果你是在數組,切片,字符串或者map上進行循環,或者從channel中進行讀取,則可以使用`range`子句來管理循環。 ~~~ for key, value := range oldMap { newMap[key] = value } ~~~ 如果你只需要range中的第一項(key或者index),則可以丟棄第二個: ~~~ for key := range m { if key.expired() { delete(m, key) } } ~~~ 如果你只需要range中的第二項(value),則可以使用*空白標識符*,一個下劃線,來丟棄第一個: ~~~ sum := 0 for _, value := range array { sum += value } ~~~ 空白標識符有許多用途,這在[后面的章節](http://www.hellogcc.org/effective_go.html#blank)中會有介紹。 對于字符串,`range`會做更多的事情,通過解析UTF-8來拆分出單個的Unicode編碼點。錯誤的編碼會消耗一個字節,產生一個替代的符文(rune)U+FFFD。(名字(與內建類型相關聯的)`rune`是Go的術語,用于指定一個單獨的Unicode編碼點。詳情參見[the language specification](http://golang.org/ref/spec#Rune_literals))循環 ~~~ for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding fmt.Printf("character %#U starts at byte position %d\n", char, pos) } ~~~ 會打印出 ~~~ character U+65E5 '日' starts at byte position 0 character U+672C '本' starts at byte position 3 character U+FFFD '?' starts at byte position 6 character U+8A9E '語' starts at byte position 7 ~~~ 最后,Go沒有逗號操作符,并且`++`和`--`是語句而不是表達式。因此,如果你想在`for`中運行多個變量,你需要使用并行賦值(盡管這樣會阻礙使用`++`和`--`)。 ~~~ // 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] } ~~~ ## Switch Go的`switch`要比C的更加通用。表達式不需要為常量,甚至不需要為整數,case是按照從上到下的順序進行求值,直到找到匹配的。如果`switch`沒有表達式,則對`true`進行匹配。因此,可以—按照語言習慣—將`if`-`else`-`if`-`else`鏈寫成一個`switch`。 ~~~ 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 } ~~~ switch不會自動從一個case子句跌落到下一個case子句。但是case可以使用逗號分隔的列表。 ~~~ func shouldEscape(c byte) bool { switch c { case ' ', '?', '&', '=', '#', '+', '%': return true } return false } ~~~ 雖然和其它類C的語言一樣,使用`break`語句來提前中止`switch`在Go中幾乎不怎么常見。不過,有時候是需要中斷包含它的循環,而不是switch。在Go中,可以通過在循環上加一個標號,然后“breaking”到那個標號來達到目的。該例子展示了這些用法。 ~~~ Loop: for n := 0; n < len(src); n += size { switch { case src[n] < sizeOne: if validateOnly { break } size = 1 update(src[n]) case src[n] < sizeTwo: if n+1 >= len(src) { err = errShortInput break Loop } if validateOnly { break } size = 2 update(src[n] + src[n+1]<<shift) } } ~~~ 當然,`continue`語句也可以接受一個可選的標號,但是只能用于循環。 作為這個章節的結束,這里有一個對字節切片進行比較的程序,使用了兩個`switch`語句: ~~~ // 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 } ~~~ ## 類型switch switch還可用于獲得一個接口變量的動態類型。這種*類型switch*使用類型斷言的語法,在括號中使用關鍵字`type`。如果switch 在表達式中聲明了一個變量,則變量會在每個子句中具有對應的類型。比較符合語言習慣的方式是在這些case里重用一個名字,實際上是在每個case里聲名一個新的變量,其具有相同的名字,但是不同的類型。 ~~~ var t interface{} t = functionOfSomeType() switch t := t.(type) { default: fmt.Printf("unexpected type %T", t) // %T prints whatever type t has case bool: fmt.Printf("boolean %t\n", t) // t has type bool case int: fmt.Printf("integer %d\n", t) // t has type int case *bool: fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool case *int: fmt.Printf("pointer to integer %d\n", *t) // t has type *int } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看