自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

要么返回錯誤值,要么輸出日志,別兩樣都做

開發(fā) 前端
在編寫Go代碼時,請記住要么返回錯誤值,要么輸出日志,不要兩者都做。通過合理地處理錯誤,我們可以編寫出更可靠、更易于調試的代碼。

1. 緣起

這周,一個產品團隊內進行Go代碼評審時,得到了一個結論:所有的if err != nil的地方都應該輸出錯誤日志。然而,這種做法并不是最佳實踐,它存在一些問題。

首先,打印過多的錯誤日志會導致日志文件變得冗長和難以閱讀。其次,重復的錯誤信息會增加冗余。此外,每一層都打印錯誤日志,一旦錯誤信息設計不當,可能會導致上下文信息的丟失。

讓我們來看一個示例,說明為什么同時輸出錯誤日志和返回錯誤值會導致問題。假設我們有一個五層的Go函數(shù)調用棧,其中最底層的函數(shù)level4Function出現(xiàn)了一個錯誤:

package main

import (
 "fmt"
 "log"
)

func main() {
 if err := topFunction(); err != nil {
  log.Printf("Error: %v", err)
 }
}

func topFunction() error {
 err := level1Function()
 if err != nil {
  log.Printf("topFunction: %v", err)
  return err
 }
 return nil
}

func level1Function() error {
 err := level2Function()
 if err != nil {
  log.Printf("level1Function: %v", err)
  return err
 }
 return nil
}

func level2Function() error {
 err := level3Function()
 if err != nil {
  log.Printf("level2Function: %v", err)
  return err
 }
 return nil
}

func level3Function() error {
 err := level4Function()
 if err != nil {
  log.Printf("level3Function: %v", err)
  return err
 }
 return nil
}

func level4Function() error {
 err := fmt.Errorf("something went wrong")
 log.Printf("level4Function: %v", err)
 return err
}

在這個示例中,我們在每個函數(shù)中都輸出錯誤日志并返回錯誤值。我們運行一下這個程序:

$go run main.go 
2024/04/14 23:10:05 level4Function: something went wrong
2024/04/14 23:10:05 level3Function: something went wrong
2024/04/14 23:10:05 level2Function: something went wrong
2024/04/14 23:10:05 level1Function: something went wrong
2024/04/14 23:10:05 topFunction: something went wrong
2024/04/14 23:10:05 Error: something went wrong

當我們運行程序時,日志文件會出現(xiàn)重復的錯誤信息,并且上下文信息不易于進行鏈式追蹤,因為每個函數(shù)只打印了特定錯誤的信息,而沒有提供之前錯誤的上下文。

2. 好的實踐技巧

為了解決上述問題,我們需要采用一種更好的實踐方法。面向調用層次較深的函數(shù)調用棧,我們應該只在最頂層的函數(shù)中輸出錯誤日志,而在下層函數(shù)中返回錯誤值。但是,我們需要精心構造錯誤值,以形成基于wrapped error的錯誤鏈。

讓我們修改示例代碼,按照最佳實踐進行錯誤處理:

package main

import (
 "fmt"
 "log"
)

func main() {
 if err := topFunction(); err != nil {
  log.Printf("Error: %v", err)
 }
}

func topFunction() error {
 err := level1Function()
 if err != nil {
  return fmt.Errorf("topFunction: %w", err)
 }
 return nil
}

func level1Function() error {
 err := level2Function()
 if err != nil {
  return fmt.Errorf("level1Function: %w", err)
 }
 return nil
}

func level2Function() error {
 err := level3Function()
 if err != nil {
  return fmt.Errorf("level2Function: %w", err)
 }
 return nil
}

func level3Function() error {
 err := level4Function()
 if err != nil {
  return fmt.Errorf("level3Function: %w", err)
 }
 return nil
}

func level4Function() error {
 err := fmt.Errorf("something went wrong")
 return fmt.Errorf("level4Function: %w", err)
}

在這個修改后的示例中,我們在每個函數(shù)中使用fmt.Errorf+%w將錯誤包裝為一個wrapped error,并將前一層的錯誤作為參數(shù)傳遞。通過這種方式,我們構建了一個錯誤鏈,其中每個錯誤都包含了之前發(fā)生的錯誤上下文。在最頂層的main函數(shù)中,我們使用日志庫輸出錯誤日志,下面是示例程序的運行結果:

2024/04/14 23:12:16 Error: topFunction: level1Function: level2Function: level3Function: level4Function: something went wrong

我們看到:通過這種方法,我們避免了重復的錯誤日志,并保留了錯誤的上下文信息,快速定位了根因。當運行修改后的程序時,我們會看到日志文件中只打印了完整的錯誤鏈,而不是重復的錯誤信息。通過調用鏈和精心設計的錯誤上下文,我們還可以看到函數(shù)調用鏈,這使得錯誤的調試和處理變得更加方便和可靠。

3. 小結

在前面的示例中,我們展示了同時輸出錯誤日志和返回錯誤值的問題,并介紹了如何使用wrapped error來構建錯誤鏈。通過合理地處理錯誤,我們可以提高代碼的可讀性和可維護性,同時也有助于快速定位和解決問題。

總之,在編寫Go代碼時,請記住要么返回錯誤值,要么輸出日志,不要兩者都做。通過合理地處理錯誤,我們可以編寫出更可靠、更易于調試的代碼。

責任編輯:武曉燕 來源: TonyBai
相關推薦

2012-11-26 10:11:41

移動支付平臺移動云計算

2012-05-14 17:27:46

2015-03-02 17:40:09

APP開發(fā)

2009-09-07 10:23:37

2013-12-04 10:13:51

銀行云計算BBVA

2011-11-11 16:20:22

編程

2012-02-09 10:41:33

小米手機雷軍

2015-05-04 09:49:43

IDCInterop大數(shù)據

2017-04-27 13:25:14

2016-12-14 12:27:29

2013-08-05 09:22:29

Gartner云服務

2015-01-14 10:18:51

智能手表可穿戴

2014-03-20 09:38:21

商用WifiWiFi

2020-09-25 11:24:14

TikTok

2024-08-20 08:00:00

谷歌AI搜索

2021-02-19 22:54:30

存儲市場存儲

2015-03-27 10:28:33

2020-05-14 10:42:42

裁員,技術管理,技術負

2016-01-15 11:10:58

智能汽車車聯(lián)網硬件技術

2023-09-25 07:33:55

固態(tài)硬盤4K讀寫
點贊
收藏

51CTO技術棧公眾號