精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

關(guān)于Go程序錯(cuò)誤處理的一些建議

開(kāi)發(fā) 前端
今天給大家總結(jié)三點(diǎn) Go 代碼錯(cuò)誤處理相關(guān)的最佳實(shí)踐給大家。

[[426144]]

 Go 的錯(cuò)誤處理這塊是日常被大家吐槽較多的地方,我在工作中也觀察到一些現(xiàn)象,比較嚴(yán)重的是在各層級(jí)的邏輯代碼中對(duì)錯(cuò)誤的處理有些重復(fù)。

比如,有人寫(xiě)代碼就會(huì)在每一層都判斷錯(cuò)誤并記錄日志,從代碼層面看,貌似很?chē)?yán)謹(jǐn),但是如果看日志會(huì)發(fā)現(xiàn)一堆重復(fù)的信息,等到排查問(wèn)題時(shí)反而會(huì)造成干擾。

今天給大家總結(jié)三點(diǎn) Go 代碼錯(cuò)誤處理相關(guān)的最佳實(shí)踐給大家。

這些最佳實(shí)踐也是網(wǎng)上一些前輩分享的,我自己實(shí)踐后在這里用自己的語(yǔ)言描述出來(lái),希望能對(duì)大家有所幫助。

認(rèn)識(shí)error

Go 程序通過(guò) error 類(lèi)型的值表示錯(cuò)誤

error 類(lèi)型是一個(gè)內(nèi)建接口類(lèi)型,該接口只規(guī)定了一個(gè)返回字符串值的 Error 方法。

  1. type error interface { 
  2.     Error() string 

Go 語(yǔ)言的函數(shù)經(jīng)常會(huì)返回一個(gè) error 值,調(diào)用者通過(guò)測(cè)試 error 值是否是 nil 來(lái)進(jìn)行錯(cuò)誤處理。

  1. i, err := strconv.Atoi("42"
  2. if err != nil { 
  3.     fmt.Printf("couldn't convert number: %v\n", err) 
  4.     return 
  5. fmt.Println("Converted integer:", i) 

error 為 nil 時(shí)表示成功;非 nil 的 error 表示失敗。

自定義錯(cuò)誤記得要實(shí)現(xiàn)error接口

我們經(jīng)常會(huì)定義符合自己需要的錯(cuò)誤類(lèi)型,但是記住要讓這些類(lèi)型實(shí)現(xiàn) error 接口,這樣就不用在調(diào)用方的程序里引入額外的類(lèi)型。

比如下面我們自己定義了 myError 這個(gè)類(lèi)型,如果不實(shí)現(xiàn) error 接口的話,調(diào)用者的代碼中就會(huì)被 myError 這個(gè)類(lèi)型侵入。比如下面的 run 函數(shù),在定義返回值類(lèi)型時(shí),直接定義成 error 即可。

  1. package myerror 
  2.  
  3. import ( 
  4.  "fmt" 
  5.  "time" 
  6.  
  7. type myError struct { 
  8.  Code int 
  9.  When time.Time 
  10.  What string 
  11.  
  12. func (e *myError) Error() string { 
  13.  return fmt.Sprintf("at %v, %s, code %d"
  14.   e.When, e.What, e.Code) 
  15.  
  16. func run() error { 
  17.  return &MyError{ 
  18.     1002
  19.     time.Now(), 
  20.     "it didn't work"
  21.  } 
  22.  
  23. func TryIt() { 
  24.  if err := run(); err != nil { 
  25.   fmt.Println(err) 
  26.  } 

如果 myError 不實(shí)現(xiàn) error 接口的話,這里的返回 值類(lèi)型就要 定義成 myError 類(lèi)型。 可想而知,緊接著調(diào)用者的程序里就要通過(guò) myError.Code == xxx  來(lái)判斷到底是哪種具體的錯(cuò)誤(當(dāng)然想要這么干得先把 myError 改成導(dǎo)出的 MyError )。

那調(diào)用者判斷自定義 error 是具體哪種錯(cuò)誤的時(shí)候應(yīng)該怎么辦呢, myError 并未向包外暴露,答案是通過(guò)向包外暴露檢查錯(cuò)誤行為的方法來(lái)實(shí)現(xiàn)。

  1. myerror.IsXXXError(err)  
  2. ... 

抑或是通過(guò)比較 error 本身與包向外暴露的常量錯(cuò)誤是否相等來(lái)判斷,比如操作文件時(shí)常用來(lái)判斷文件是否結(jié)束的 io.EOF 。

類(lèi)似的還有 gorm.ErrRecordNotFound 等各種開(kāi)源包對(duì)外暴露的錯(cuò)誤常量。

  1. if err != io.EOF { 
  2.     return err 

錯(cuò)誤處理常犯的錯(cuò)誤

先看一段簡(jiǎn)單的程序,看大家能不能發(fā)現(xiàn)一些細(xì)微的問(wèn)題

  1. func WriteAll(w io.Writer, buf []byte) error { 
  2.     _, err := w.Write(buf) 
  3.     if err != nil { 
  4.         log.Println("unable to write:", err) // annotated error goes to log file 
  5.         return err                           // unannotated error returned to caller 
  6.     } 
  7.     return nil 
  8.  
  9. func WriteConfig(w io.Writer, conf *Config) error { 
  10.     buf, err := json.Marshal(conf) 
  11.     if err != nil { 
  12.         log.Printf("could not marshal config: %v", err) 
  13.         return err 
  14.     } 
  15.     if err := WriteAll(w, buf); err != nil { 
  16.         log.Println("could not write config: %v", err) 
  17.         return err 
  18.     } 
  19.     return nil 
  20.  
  21. func main() { 
  22.     err := WriteConfig(f, &conf) 
  23.     fmt.Println(err) // io.EOF 

錯(cuò)誤處理常犯的兩個(gè)問(wèn)題

上面程序的錯(cuò)誤處理暴露了兩個(gè)問(wèn)題:

1. 底層函數(shù) WriteAll 在發(fā)生錯(cuò)誤后,除了向上層返回錯(cuò)誤外還向日志里記錄了錯(cuò)誤,上層調(diào)用者做了同樣的事情,記錄日志然后把錯(cuò)誤再返回給程序頂層。

因此在日志文件中得到一堆重復(fù)的內(nèi)容

  1. unable to write: io.EOF 
  2. could not write config: io.EOF 
  3. ... 

2. 在程序的頂部,雖然得到了原始錯(cuò)誤,但沒(méi)有相關(guān)內(nèi)容,換句話說(shuō)沒(méi)有把 WriteAll 、 WriteConfig 記錄到 log 里的那些信息包裝到錯(cuò)誤里,返回給上層。

針對(duì)這兩個(gè)問(wèn)題的解決方案可以是,在底層函數(shù) WriteAll 、 WriteConfig 中為發(fā)生的錯(cuò)誤添加上下文信息,然后將錯(cuò)誤返回上層,由上層程序最后處理這些錯(cuò)誤。

一種簡(jiǎn)單的包裝錯(cuò)誤的方法是使用 fmt.Errorf 函數(shù),給錯(cuò)誤添加信息。

  1. func WriteConfig(w io.Writer, conf *Config) error { 
  2.     buf, err := json.Marshal(conf) 
  3.     if err != nil { 
  4.         return fmt.Errorf("could not marshal config: %v", err) 
  5.     } 
  6.     if err := WriteAll(w, buf); err != nil { 
  7.         return fmt.Errorf("could not write config: %v", err) 
  8.     } 
  9.     return nil 
  10. func WriteAll(w io.Writer, buf []byte) error { 
  11.     _, err := w.Write(buf) 
  12.     if err != nil { 
  13.         return fmt.Errorf("write failed: %v", err) 
  14.     } 
  15.     return nil 

給錯(cuò)誤附加上下文信息

fmt.Errorf 只是給錯(cuò)誤添加了簡(jiǎn)單的注解信息,如果你想在添加信息的同時(shí)還加上錯(cuò)誤的調(diào)用棧,可以借助 github.com/pkg/errors 這個(gè)包提供的錯(cuò)誤包裝能力。

  1. //只附加新的信息 
  2. func WithMessage(err error, message string) error 
  3.  
  4. //只附加調(diào)用堆棧信息 
  5. func WithStack(err error) error 
  6.  
  7. //同時(shí)附加堆棧和信息 
  8. func Wrap(err error, message string) error 

有包裝方法,就有對(duì)應(yīng)的解包方法, Cause 方法會(huì)返回包裝錯(cuò)誤對(duì)應(yīng)的最原始錯(cuò)誤--即會(huì)遞歸地進(jìn)行解包。

  1. func Cause(err error) error 

下面是使用 github.com/pkg/errors 改寫(xiě)后的錯(cuò)誤處理程序

  1. func ReadFile(path string) ([]byte, error) { 
  2.     f, err := os.Open(path) 
  3.     if err != nil { 
  4.         return nil, errors.Wrap(err, "open failed"
  5.     } 
  6.     defer f.Close() 
  7.     buf, err := ioutil.ReadAll(f) 
  8.     if err != nil { 
  9.         return nil, errors.Wrap(err, "read failed"
  10.     } 
  11.     return buf, nil 
  12. func ReadConfig() ([]byte, error) { 
  13.     home := os.Getenv("HOME"
  14.     config, err := ReadFile(filepath.Join(home, ".settings.xml")) 
  15.     return config, errors.WithMessage(err, "could not read config"
  16.  
  17.  
  18. func main() { 
  19.     _, err := ReadConfig() 
  20.     if err != nil { 
  21.         fmt.Printf("original error: %T %v\n", errors.Cause(err), errors.Cause(err)) 
  22.         fmt.Printf("stack trace:\n%+v\n", err) 
  23.         os.Exit(1
  24.     } 

上面格式化字符串時(shí)用的 %+v 是在 % v 基礎(chǔ)上,對(duì)值進(jìn)行展開(kāi),即展開(kāi)復(fù)合類(lèi)型值,比如結(jié)構(gòu)體的字段值等明細(xì)。

這樣既能給錯(cuò)誤添加調(diào)用棧信息,又能保留對(duì)原始錯(cuò)誤的引用,通過(guò) Cause 可以還原到最初始引發(fā)錯(cuò)誤的原因。

總結(jié)

總結(jié)一下,錯(cuò)誤處理的原則就是:

  1. 錯(cuò)誤只在邏輯的最外層處理一次,底層只返回錯(cuò)誤。

  2. 底層除了返回錯(cuò)誤外,要對(duì)原始錯(cuò)誤進(jìn)行包裝,增加錯(cuò)誤信息、調(diào)用棧等這些有利于排查的上下文信息。

 

責(zé)任編輯:張燕妮 來(lái)源: 網(wǎng)管叨bi叨
相關(guān)推薦

2021-09-27 10:04:03

Go程序處理

2020-08-20 10:16:56

Golang錯(cuò)誤處理數(shù)據(jù)

2014-11-17 10:05:12

Go語(yǔ)言

2021-04-29 09:02:44

語(yǔ)言Go 處理

2015-08-26 08:31:35

核心程序員成長(zhǎng)

2011-04-27 09:21:09

程序員

2015-08-26 09:31:26

程序員建議

2025-06-06 06:45:54

2021-09-13 07:53:31

Go錯(cuò)誤處理

2025-03-31 00:29:44

2022-09-05 08:55:15

Go2提案語(yǔ)法

2025-06-30 09:49:11

2025-09-05 01:55:00

Go并發(fā)錯(cuò)誤項(xiàng)目

2011-07-13 09:13:56

Android設(shè)計(jì)

2019-10-30 14:58:45

MVCAndroid表現(xiàn)層

2022-12-12 08:53:53

Go版本方式

2009-11-26 15:10:08

VS2005資源

2020-12-17 06:25:05

Gopanic 模式

2023-10-26 15:49:53

Go日志

2021-09-27 23:28:29

Go多協(xié)程并發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

性少妇videosexfreexxx片| b站大片免费直播| 182tv在线播放| 顶级嫩模精品视频在线看| 久久久久五月天| 一级特级黄色片| 69堂免费精品视频在线播放| 亚洲三级免费观看| 精品一区二区三区日本| 国内av在线播放| 国产伊人精品| 一区二区三区亚洲| 中文字幕永久免费| 欧洲精品一区二区三区| 一区二区三区久久| 色乱码一区二区三在线看| 国产毛片在线视频| 男女精品视频| 欧美激情综合亚洲一二区| 亚洲国产精品无码久久久久高潮 | 午夜肉伦伦影院| 老司机精品影院| 久久嫩草精品久久久久| 亚洲自拍偷拍色图| 中文天堂在线播放| 在线亚洲观看| 欧美激情精品久久久| 欧美成人久久久免费播放| 精品视频高潮| 日韩午夜电影在线观看| 波多野结衣天堂| 涩涩视频在线播放| 悠悠色在线精品| 亚洲一区精彩视频| 成人av一区| 久久这里只有精品6| 成人区精品一区二区| 国产又粗又猛视频免费| 男女激情视频一区| 人人做人人澡人人爽欧美| 日本熟女一区二区| 欧美~级网站不卡| 精品久久久91| 日本不卡一二区| 欧美一级精品| 在线精品播放av| 一级片久久久久| 国内精品久久久久久久影视简单| 日韩第一页在线| 熟妇人妻久久中文字幕| 高清一区二区三区| 亚洲国产91精品在线观看| 国产成人精品一区二区三区在线观看| 国产在线一区不卡| 这里只有精品视频在线观看| 视频在线观看免费高清| 日本免费成人| 69成人精品免费视频| 中文字幕亚洲影院| 国产欧美88| 欧美一二三在线| 亚洲欧美激情一区二区三区| 视频二区欧美| 亚洲第一免费网站| 波多野结衣先锋影音| 香蕉人人精品| 中文字幕精品—区二区| 正在播放国产对白害羞| 99re6这里只有精品| 俺去亚洲欧洲欧美日韩| 日本一级二级视频| 精品动漫一区| 欧美中文在线视频| 亚洲欧美日韩激情| 美女一区二区三区| 91九色露脸| 少妇精品高潮欲妇又嫩中文字幕| 成人97人人超碰人人99| 欧美视频1区| 在线免费av网站| 一区二区三区四区在线播放| 国产 日韩 欧美在线| 成人福利视频| 欧美嫩在线观看| 国产女主播在线播放| 亚洲动漫在线观看| 色偷偷av亚洲男人的天堂| 欧美日韩在线视频免费| 国产日韩一区二区三区在线播放 | 日韩一区二区三区色| 亚洲成人精品久久久| 国产sm调教视频| 亚洲欧美一级二级三级| 2019中文字幕在线观看| 中文字幕永久在线视频| 国产 欧美在线| 日韩精品一区二区三区外面 | 你懂的一区二区三区| 日韩中文字幕视频| 制服.丝袜.亚洲.中文.综合懂色| 日本亚洲免费观看| 国产伦精品一区二区三区视频孕妇| 五月天婷婷视频| 国产精品不卡一区二区三区| 欧美视频在线观看网站| 欧洲美女精品免费观看视频 | 91久久精品国产91性色tv| 一区二区三区四区毛片| 偷窥自拍亚洲色图精选| 草民午夜欧美限制a级福利片| 国产区在线观看视频| 激情成人午夜视频| 欧美日韩一区二 | 亚洲精品欧美激情| 日韩精品一区二区三区不卡| 伊人久久大香线蕉av超碰| 国产一级揄自揄精品视频| 久久精品视频9| 国产真实乱子伦精品视频| 欧美日韩国产三区| 黄页在线观看免费| 欧美精品日韩综合在线| 国产毛片久久久久久久| 日韩天天综合| 97视频热人人精品| 国产在线一区二区视频| 欧美视频一区二区| 成人h动漫精品一区| 午夜久久久久| 亚洲www永久成人夜色| av资源网在线观看| 色8久久精品久久久久久蜜| 在线视频 日韩| 亚洲视频久久| 91在线在线观看| 精品欧美色视频网站在线观看| 欧美在线小视频| 小早川怜子久久精品中文字幕| 亚洲国产专区校园欧美| http;//www.99re视频| 免费在线观看av| 日本韩国欧美一区二区三区| 三级电影在线看| 日韩一级网站| 九九99玖玖| 国产精品论坛| 亚洲精品ady| www..com国产| 99国产精品久久久| 日韩免费视频播放| 美国成人xxx| 欧美影院久久久| 国产在线电影| 欧美亚州韩日在线看免费版国语版| 爱爱免费小视频| 翔田千里一区二区| 日韩精品久久久| 国产国产一区| 久久视频免费在线播放| 国产av无码专区亚洲av| 亚洲精品乱码久久久久久黑人| 美女被艹视频网站| 午夜精品av| 精品国产一区二区三区四区精华| 蜜桃视频m3u8在线观看| 亚洲美女精品久久| 亚洲午夜在线播放| 成人欧美一区二区三区| 在线免费黄色小视频| 黄色日韩在线| 任我爽在线视频精品一| 免费视频成人| 欧美激情a∨在线视频播放| 天堂成人在线视频| 色偷偷88欧美精品久久久| 毛片视频免费播放| 国产大陆a不卡| 国产精品后入内射日本在线观看| 嫩草一区二区三区| 成人性生交大片免费看视频直播| 超碰在线网址| 精品一区二区三区四区在线| 国产精品欧美综合| 亚洲精选视频免费看| 女同性恋一区二区三区| 欧美aaaaa成人免费观看视频| 黄色www在线观看| 欧美美女在线直播| 91精品久久久久久久| 77thz桃花论族在线观看| 亚洲日本中文字幕免费在线不卡| 国产精品久久久久精| 午夜激情综合网| 香蕉久久久久久久| 丁香啪啪综合成人亚洲小说| 少妇性l交大片| 亚洲欧美一区在线| 午夜久久资源| 成人知道污网站| 国产精品视频自拍| а√在线中文在线新版| 久久精品国产精品| 欧美女子与性| 欧美第一区第二区| 又骚又黄的视频| 精品久久久久久国产| 99热6这里只有精品| 99re热这里只有精品免费视频| 亚洲娇小娇小娇小| 久久免费高清| 亚洲国产精品无码av| 久久国产精品成人免费观看的软件| 国产91社区| 国产高清亚洲| 国产精品成人在线| 麻豆网站免费在线观看| 欧美精品性视频| 中国日本在线视频中文字幕| 日韩毛片中文字幕| 亚洲免费成人网| 777奇米四色成人影色区| 国产真人无遮挡作爱免费视频| 亚洲午夜视频在线观看| 久久免费看少妇高潮v片特黄| 中文字幕乱码一区二区免费| 精品人妻一区二区三区日产乱码卜| 国产成人av在线影院| 超碰在线资源站| 青青草一区二区三区| 91九色在线观看视频| 亚洲日本视频| 国内少妇毛片视频| 欧美精品国产| 法国空姐在线观看免费| 亚洲成人国产| 免费久久久久久| 天天插综合网| 一区二区三区国| 久久一区二区中文字幕| 天堂精品一区二区三区| 俺要去色综合狠狠| 色播亚洲视频在线观看| 精品免费视频| 亚欧精品在线| 久久中文字幕av| 亚洲图色在线| 日韩夫妻性生活xx| 一区二区三区四区五区视频| 欧美日韩在线观看视频小说| 亚洲精品乱码久久久久久蜜桃91 | 轻点好疼好大好爽视频| 国产综合视频| 成年人看的毛片| 夜夜夜久久久| av观看免费在线| 日本视频中文字幕一区二区三区| 午夜激情福利在线| 麻豆精品视频在线观看视频| 亚洲va在线va天堂va偷拍| 九九久久精品视频| 69久久精品无码一区二区 | 97se亚洲综合在线| jazzjazz国产精品久久| 极品校花啪啪激情久久| 一本色道久久综合亚洲精品酒店 | 亚洲色图88| 岛国大片在线播放| 母乳一区在线观看| 91亚洲精品久久久蜜桃借种| 国产精品一区二区三区乱码 | 国产日产欧美一区| 影音先锋男人看片资源| 亚洲欧美国产毛片在线| 日本五十路女优| 欧美偷拍一区二区| 国产日韩欧美视频在线观看| 亚洲变态欧美另类捆绑| 日本高清中文字幕二区在线| 自拍偷拍亚洲精品| 综合久久2019| 热re99久久精品国产66热| 国产91亚洲精品久久久| 99c视频在线| 欧美美女在线| 真人做人试看60分钟免费| 99精品久久久| 亚洲欧美偷拍另类| 成人妖精视频yjsp地址| 怡红院一区二区三区| 一区二区三区国产| 欧美brazzers| 日韩欧美的一区二区| 国产最新视频在线| 欧美成人三级视频网站| 国产精品专区免费| 99久久99久久精品国产片| 美女网站一区| 国产一线二线三线女| 免费成人美女在线观看.| 亚洲午夜久久久久久久久| 欧美激情一区不卡| 五月婷婷开心网| 欧美日韩免费高清一区色橹橹| 亚洲欧美另类一区| www亚洲欧美| 国产欧美一区二区三区精品酒店| 91成人免费视频| 国产成人调教视频在线观看| 国产成a人亚洲精v品在线观看| 蜜桃av一区二区三区电影| 精品无码在线视频| 亚洲精品一二三四区| 中文字幕乱码在线观看| 亚洲精品美女视频| 天天色天天射天天综合网| 国产精品你懂得| 亚洲宅男网av| 国产精品无码人妻一区二区在线| 精品一二三四在线| 国产综合精品久久久久成人av | 中文字幕一区二区三区免费看| 精品国产一区二区三区久久久蜜月| 欧美激情办公室videoshd| 国产不卡av在线免费观看| 久久人人爽人人爽人人片av不| 警花观音坐莲激情销魂小说| 麻豆国产精品官网| 韩国三级hd中文字幕| 偷拍与自拍一区| 亚洲伦理在线观看| 欧美激情视频在线观看| 成人短视频软件网站大全app| 日韩福利视频| 水蜜桃久久夜色精品一区的特点| 日本黄色动态图| 亚洲 欧美综合在线网络| wwwav网站| 欧美日韩999| 日韩精品视频中文字幕| 黄色一级视频播放| 韩国精品久久久| 男人的午夜天堂| 在线不卡a资源高清| 调教视频免费在线观看| 国产精品视频免费在线| 精品日韩欧美一区| 亚洲欧美在线精品| 欧美国产精品一区二区| 一级黄色片在线看| www.色综合| 免费一级欧美片在线观看网站| 在线观看成人免费| 丁香一区二区三区| 亚洲 欧美 日韩 综合| 亚洲精品在线看| 国产精品久久..4399| 天堂中文字幕在线| 日韩欧美中文免费| 毛片在线播放网站| 国产成人久久久| 999国产精品视频| 成年人性生活视频| 亚洲福中文字幕伊人影院| 无码精品一区二区三区在线| 欧美一级在线亚洲天堂| 欧美亚洲精品在线| 天天综合成人网| 亚洲一级不卡视频| 青青久在线视频| 国产欧美精品一区二区| 欧美另类专区| 一本加勒比北条麻妃| 欧美亚洲免费在线一区| 成人无遮挡免费网站视频在线观看| 99国产在线| 丝袜美腿成人在线| 久久一级免费视频| 日韩精品一区二区三区在线播放| 久国产精品视频| 久久精品一级爱片| 96日本xxxxxⅹxxx17| 久久久久久久久久久亚洲| 日韩av三区| 午夜免费在线观看精品视频| 久久亚州av| 欧美成人福利在线观看| 一个色妞综合视频在线观看| 亚洲av成人精品日韩在线播放| 国产精品欧美风情| 欧美 日韩 国产 一区| 熟女少妇一区二区三区| 欧美精品一二三区| 麻豆视频在线观看免费网站黄| 亚洲免费久久| 国产成人av电影在线观看| 无码人妻丰满熟妇区bbbbxxxx| 色噜噜国产精品视频一区二区| 国产福利资源一区| 日本中文字幕精品—区二区| 亚洲美女在线国产|