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

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在并發編程中,錯誤處理可能難以正確運行。有時候,我們花了很多時間思考我們的各種流程將如何共享信息和協調,卻忘記考慮如何優雅地處理錯誤。Go避開了流行的錯誤異常模型,Go認為錯誤處理非常重要,并且在開發程序時,我們應該像關注算法一樣關注它。本著這種精神,讓我們來看看在處理多個并發進程時我們如何做到這一點。 思考錯誤處理時最根本的問題是,“應該由誰負責處理錯誤?”在某些情況下,程序需要停止傳遞堆棧中的錯誤,并將它們處理掉,這樣的操作應該何時執行呢? 在并發進程中,這樣的問題變得愈發復雜。因為一個并發進程獨立于其父進程或兄弟進程運行,所以可能很難推斷出錯誤是如何產生的。 下面的就展示了這樣的問題: ``` checkStatus := func(done <-chan interface{}, urls ...string, ) <-chan *http.Response { responses := make(chan *http.Response) go func() { defer close(responses) for _, url := range urls { resp, err := http.Get(url) if err != nil { fmt.Println(err) //1 continue } select { case <-done: return case responses <- resp: } } }() return responses } done := make(chan interface{}) defer close(done) urls := []string{"https://www.baidu.com", "https://badhost"} for response := range checkStatus(done, urls...) { fmt.Printf("Response: %v\n", response.Status) } ``` 1. 這個我們看到goroutine盡其最大努力展示錯誤信號。但也僅僅是展示出來,它還能做什么? 它無法傳回! 如果錯誤種類太多怎么辦? 再請求一遍嗎? 這會輸出: ``` Response: 200 OK Get https://badhost: dial tcp: lookup badhost on 127.0.1.1:53: no such host ``` 我們看到代碼中并沒有給goroutine更多的選擇以處理可能出現的錯誤。它不能簡單的把這個錯誤不加任何處理的拋棄掉,所以當前唯一明智的做法是:它會打印錯誤并希望受到程序使用者的關注。別把你的goroutine像這樣放到如此尷尬的處境之下。我建議你把程序的關注點分離:一般來說,你的并發進程應該把錯誤發送到你的程序的另一部分,這樣程序狀態的完整信息就被保留下來,并留出余地讓使用者可以做出更明智的決定來處理它。我們對上面的例子做了一點點修改: ``` type Result struct { //1 Error error Response *http.Response } checkStatus := func(done <-chan interface{}, urls ...string) <-chan Result { //2 results := make(chan Result) go func() { defer close(results) for _, url := range urls { var result Result resp, err := http.Get(url) result = Result{Error: err, Response: resp} //3 select { case <-done: return case results <- result: //4 } } }() return results } done := make(chan interface{}) defer close(done) urls := []string{"https://www.baidu.com", "https://badhost"} for result := range checkStatus(done, urls...) { if result.Error != nil { //5 fmt.Printf("error: %v", result.Error) continue } fmt.Printf("Response: %v\n", result.Response.Status) } ``` 1. 這里我們創建一個包含*http.Response和goroutine循環迭代中可能出現的錯誤類型。 2. 該行返回一個可讀取的通道,以檢索循環迭代的結果。 3. 在這里,我們創建一個Result實例,并設置Error和Response字段。 4. 這是我們將結果寫入通道。 5. 在這里,在我們的main goroutine中,我們能夠自行處理由checkStatus中出現的錯誤,并獲取詳細的響應信息。 這會輸出: ``` Response: 200 OK error: Get https://badhost: dial tcp: lookup badhost on 127.0.1.1:53: no such host ``` 這里要注意的關鍵是我們如何將潛在的結果與潛在的錯誤結合起來。我們已經成功地將錯誤處理的擔憂從生產者中分離出來。這是可取的,因為生成goroutine的goroutine(在這種情況下是我們的main goroutine)擁有更多關于正在運行的程序的上下文,并且可以做出關于如何處理錯誤的更明智的決定。 在前面的例子中,我們只是將錯誤寫入stdio,但我們可以做其他事情。 讓我們稍微修改我們的程序,以便在發生三個或更多錯誤時停止錯誤檢查: ``` done := make(chan interface{}) defer close(done) errCount := 0 urls := []string{"a", "https://www.baidu.com", "b", "c", "d"} for result := range checkStatus(done, urls...) { if result.Error != nil { fmt.Printf("error: %v\n", result.Error) errCount++ if errCount >= 3 { fmt.Println("Too many errors, breaking!") break } continue } fmt.Printf("Response: %v\n", result.Response.Status) } ``` 這會輸出: ``` error: Get a: unsupported protocol scheme "" Response: 200 OK error: Get b: unsupported protocol scheme "" error: Get c: unsupported protocol scheme "" Too many errors, breaking! ``` 你可以看到,因為錯誤是從checkStatus返回的而不是在goroutine內部處理的,所以錯誤處理遵循熟悉的Go規范。 這是個簡單的例子,但不難想象在更大更復雜的的程序下是什么樣子。這里的主要內容是,在構建從goroutines返回的價值時,應將錯誤視為一等公民。 如果你的goroutine可能產生錯誤,那么這些錯誤應該與你的結果類型緊密結合,并且通過相同的通信線路傳遞——就像常規的同步函數一樣。 * * * * * 學識淺薄,錯誤在所難免。我是長風,歡迎來Golang中國的群(211938256)就本書提出修改意見。
                  <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>

                              哎呀哎呀视频在线观看