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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 5.7\. 函數 ### 5.7.1\. 多值返回 Go語言中函數和方法方法的一個有意思的特性是它們可以同時返回多個值。它可以比C語言 更簡潔的處理多個返回值的情況:例如在修改一個參數的同時獲取錯誤返回值 (-1或EOF)。 在傳統的C語言中,如果寫數據失敗的話,會在另外一個地方保存錯誤標志,而且錯誤標志很容易被 其他函數產生的錯誤覆蓋。在Go語言中,則可以在返回成功寫入的數據數目的同時,也可以返回有意義 的錯誤信息:“您已經寫了一些數據,但不是全部,因為設備在阻塞填充中”。對于os 包中的*File.Write函數,說明如下: ``` func (file *File) Write(b []byte) (n int, err Error) ``` 在函數的文檔中有函數返回值的描述:返回成功寫入的數據長度,如果n != len(b),則同時返回一個非non-nil的錯誤信息。 這是Go語言中,處理錯誤的常見方式。在后面的“錯誤處理”一節,會有更多的描述。 多個返回值還可以用于模擬C語言中通過指針的方式遍歷。下面的函數是從一個int數組中獲取 一個數據,然后移動到下一個位置。 ``` 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 } ``` 你還可以用這個方法來打印一個數組: ``` for i := 0; i < len(a); { x, i = nextInt(a, i) fmt.Println(x) } ``` ### 5.7.2\. 命名的結果參數 Go語言中,我們還可以給函數或方法的返回值命名,就像函數的輸入參數那樣。如果我們命名了返回值, 那么它們將在函數開始的時候被初始化為空。然后,在執行不帶參數的return語句時, 命名的返回值變量將被用于返回。 返回值命名并不強制使用,但是有時我們給名返回值命令可以產生更清晰的代碼,同時它也可以用于文檔。 例如,我們把nextInt的返回值命名: ``` func nextInt(b []byte, pos int) (value, nextPos int) { ``` 命名后,返回值會自動初始化,而且不需要在return中顯式寫出返回參數。下面的io.ReadFull 函數是另一個類似的例子: ``` func ReadFull(r Reader, buf []byte) (n int, err os.Error) { for len(buf) > 0 && err == nil { var nr int nr, err = r.Read(buf) n += nr buf = buf[nr:len(buf)] } return } ``` ### 5.7.3\. Defer Go 的 defer 語句安排一個函數調用(被 defer 的函數)延遲發生在執行 defer 的函數剛要返回之前。當函數無論怎樣返回,某資源必須釋放時,可用這種與眾不同、但有效的處理方式。傳統的例子包括解鎖互斥或關閉文件。 ``` // Contents returns the file's contents as a string. func Contents(filename string) (string, os.Error) { f, err := os.Open(filename, os.O_RDONLY, 0) 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 == os.EOF { break } return "", err // f will be closed if we return here. } } return string(result), nil // f will be closed if we return here. } ``` 這樣延遲一個函數有雙重優勢:一是你永遠不會忘記關閉文件,此錯誤在你事后編輯函數添加一個返回路徑時常常發生。二是關閉和打開靠在一起,比放在函數尾要清晰很多。 延遲函數的參量(包括接受者,如果函數是一個方法)的求值發生在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 執行時得值的特點,跟蹤函數可以安排未跟蹤函數的參量。 ``` 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>

                              哎呀哎呀视频在线观看