<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 多個返回值 Go的其中一個不同尋常的特點是,函數和方法可以返回多個值。這種形式可以用來改進C程序中幾個笨拙的語言風格:返回一個錯誤,例如`-1`對應于`EOF`,同時修改一個由地址傳遞的參數。 在C中,一個寫錯誤是由一個負的計數和一個隱藏在易變位置(a volatile location)的錯誤代碼來表示的。在Go中,`Write`可以返回一個計數*和*一個錯誤:“是的,你寫了一些字節,但并沒有全部寫完,由于設備已經被填滿了”。在程序包`os`的文件中,`Write`方法的簽名是: ~~~ func (file *File) Write(b []byte) (n int, err error) ~~~ 正如文檔所言,其返回寫入的字節數和一個非零的`error`,當`n``!=`?`len(b)`的時候。這是一種常見的風格;更多的例子可以參見錯誤處理章節。 類似的方法使得不再需要傳遞一個返回值指針來模擬一個引用參數。這里有一個非常簡單的函數,用來從字節切片中的一個位置抓取一個數,返回該數和下一個位置。 ~~~ func nextInt(b []byte, i int) (int, int) { for ; i < len(b) && !isDigit(b[i]); i++ { } x := 0 for ; i < len(b) && isDigit(b[i]); i++ { x = x*10 + int(b[i]) - '0' } return x, i } ~~~ 你可以使用它來掃描輸入切片`b`中的數字,如: ~~~ for i := 0; i < len(b); { x, i = nextInt(b, i) fmt.Println(x) } ~~~ ## 命名的結果參數 Go函數的返回或者結果“參數”可以給定一個名字,并作為一個普通變量來使用,就像是輸入參數一樣。當被命名時,它們在函數起始處被初始化為對應類型的零值;如果函數執行了沒有參數的`return`語句,則結果參數的當前值便被作為要返回的值。 名字并不是強制的,但是可以使代碼更加簡短清晰:它們也是文檔。如果我們將`nextInt`的結果進行命名,則其要返回的`int`是對應的哪一個就很顯然了。 ~~~ func nextInt(b []byte, pos int) (value, nextPos int) { ~~~ 因為命名結果是被初始化的,并且與沒有參數的return綁定在一起,所以它們即簡單又清晰。這里是一個`io.ReadFull`的版本,很好地使用了這些特性: ~~~ func ReadFull(r Reader, buf []byte) (n int, err error) { for len(buf) > 0 && err == nil { var nr int nr, err = r.Read(buf) n += nr buf = buf[nr:] } return } ~~~ ## 延期執行 Go的`defer`語句用來調度一個函數調用(*被延期的*函數),使其在執行`defer`的函數即將返回之前才被運行。這是一種不尋常但又很有效的方法,用于處理類似于不管函數通過哪個執行路徑返回,資源都必須要被釋放的情況。典型的例子是對一個互斥解鎖,或者關閉一個文件。 ~~~ // Contents returns the file's contents as a string. func Contents(filename string) (string, error) { f, err := os.Open(filename) if err != nil { return "", err } defer f.Close() // f.Close will run when we're finished. var result []byte buf := make([]byte, 100) for { n, err := f.Read(buf[0:]) result = append(result, buf[0:n]...) // append is discussed later. if err != nil { if err == io.EOF { break } return "", err // f will be closed if we return here. } } return string(result), nil // f will be closed if we return here. } ~~~ 對像`Close`這樣的函數調用進行延期,有兩個好處。首先,其確保了你不會忘記關閉文件,如果你之后修改了函數增加一個新的返回路徑,會很容易犯這樣的錯。其次,這意味著關閉操作緊挨著打開操作,這比將其放在函數結尾更加清晰。 被延期執行的函數,它的參數(包括接收者,如果函數是一個方法)是在*defer*執行的時候被求值的,而不是在*調用*執行的時候。這樣除了不用擔心變量隨著函數的執行值會改變,這還意味著單個被延期執行的調用點可以延期多個函數執行。這里有一個簡單的例子。 ~~~ for i := 0; i < 5; i++ { defer fmt.Printf("%d ", i) } ~~~ 被延期的函數按照LIFO的順序執行,所以這段代碼會導致在函數返回時打印出`4 3 2 1 0`。一個更加真實的例子,這是一個跟蹤程序中函數執行的簡單方法。我們可以編寫幾個類似這樣的,簡單的跟蹤程序: ~~~ func trace(s string) { fmt.Println("entering:", s) } func untrace(s string) { fmt.Println("leaving:", s) } // Use them like this: func a() { trace("a") defer untrace("a") // do something.... } ~~~ 利用被延期的函數的參數是在`defer`執行的時候被求值這個事實,我們可以做的更好些。trace程序可以為untrace程序建立參數。這個例子: ~~~ func trace(s string) string { fmt.Println("entering:", s) return s } func un(s string) { fmt.Println("leaving:", s) } func a() { defer un(trace("a")) fmt.Println("in a") } func b() { defer un(trace("b")) fmt.Println("in b") a() } func main() { b() } ~~~ 會打印出 ~~~ entering: b in b entering: a in a leaving: a leaving: b ~~~ 對于習慣于其它語言中的塊級別資源管理的程序員,`defer`可能看起來很奇怪,但是它最有趣和強大的應用正是來自于這樣的事實,這是基于函數的而不是基于塊的。我們將會在`panic`和`recover`章節中看到它另一個可能的例子。
                  <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>

                              哎呀哎呀视频在线观看