Go 語言函數:并發(fā)任務執(zhí)行中的錯誤處理技術
在 Golang 中使用并發(fā)函數執(zhí)行任務時,處理錯誤至關重要。本文介紹了多種錯誤處理技術,并提供了有關如何將它們應用于實際場景的實戰(zhàn)案例。
錯誤處理技術
1. 返回值
最簡單的方法是使用返回值來傳遞錯誤。函數可以返回錯誤值,調用者可以檢查該值并采取適當的措施。
func getSum(a, b int) (int, error) {
if a < 0 || b < 0 {
return 0, errors.New("inputs must be non-negative")
}
return a + b, nil
}
2. 拋出異常
Go 語言提供了一個內置的異常機制??梢允褂?panic 函數拋出異常,由調用者使用 recover 函數捕獲。
立即學習“go語言免費學習筆記(深入)”;
func getArea(width, height int) (int, error) {
if width < 0 || height < 0 {
panic("invalid width or height")
}
return width * height, nil
}
3. channel
通道提供了另一種用于并發(fā)任務錯誤處理的機制??梢詣?chuàng)建一個接收錯誤的 channel,然后將該 channel 傳遞給任務 goroutine。如果任務出錯,goroutine 將向 channel 發(fā)送錯誤。
func getAverage(numbers []int) (float64, error) {
errCh := make(chan error)
go func() {
sum := 0
for _, n := range numbers {
sum += n
}
avg := float64(sum) / float64(len(numbers))
if len(numbers) == 0 {
errCh <- errors.New("empty slice")
} else {
errCh <- nil
}
}()
select {
case err := <-errCh:
return 0, err
case <-time.After(1 * time.Second):
return 0, errors.New("timeout")
}
}
實戰(zhàn)案例
文件讀取并處理
以下函數使用并發(fā) goroutine 讀取并處理文件中的行。錯誤通過 channel 傳遞。
func processLines(filePath string) ([][]string, error) {
errCh := make(chan error)
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
lines := [][]string{}
nLines := 0
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
nLines++
go func(line string) {
parts := strings.Split(line, ",")
errCh <- processLine(parts)
}(line)
}
for i := 0; i < nLines; i++ {
err := <-errCh
if err != nil {
return nil, err
}
}
return lines, nil
}
HTTP 請求并發(fā)
以下函數使用并發(fā) goroutine 發(fā)出 HTTP 請求。錯誤通過返回的 channel 傳遞。
func sendRequests(urls []string) ([][]byte, error) {
respCh := make(chan []byte, len(urls))
errCh := make(chan error, len(urls))
for _, url := range urls {
go func(url string) {
resp, err := http.Get(url)
if err != nil {
errCh <- err
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errCh <- err
} else {
respCh <- body
}
}
}(url)
}
responses := [][]byte{}
for i := 0; i < len(urls); i++ {
select {
case resp := <-respCh:
responses = append(responses, resp)
case err := <-errCh:
return nil, err
}
}
return responses, nil
}