<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Golang</span>
的優點很多,先前的文章中也有提到過,但也有很多槽點為Gopher所詬病,尤其是<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">錯誤處理</span>
。 在說錯誤和異常之前,先要說兩個概念:
錯誤處理:錯誤是業務中的一部分,是可以預見的。
異常處理:非業務的一部分,不可預見的。
首先看一下範例程式碼:
file, err := os.Open("/usr/local/test.txt")
Golang官方推薦上述程式碼中的錯誤處理方式,並建議<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">err</span>
放在傳回值的最後。我們在日常的編碼中也需要遵循這樣的規則來定義 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">func</span>
。
在Gopher间流传着这样一个笑话:一半时间在编写代码,一半时间在写错误处理。
示例代码:
func Open(name string) (*File, error) { return OpenFile(name, O_RDONLY, 0) }
但通常不是每个方法都需要处理 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">err</span>
,可以适当的将 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">err</span>
返回给上层函数,由上层函数统一打印或者处理错误。例如:<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">http</span>
路由中的错误可以在路由返回数据前处理,将错误信息和错误码格式化后返回给 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Client</span>
。
Golang的例外處理比較特立獨行,需要<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">defer</span>
<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">err</span>
<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">recover</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
三者搭配使用,而Java只要<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">try</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">{</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;"></span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">}</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">Catch</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
就可以搞定,還是來看範例程式碼:
package main import ( "fmt" ) func main() { test() } func test() { defer func() { if e := recover(); e != nil { fmt.Println("Worng!") } }() panic("panic") }
如上代码在 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">test</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
函数及其子函数中如果发生panic的错误,就会打印:
Worng!
当然,在每个方法最上面写这么一大堆冗余的代码是很不优雅的,也不符合面向对象的特性:<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">封装</span>
,于是便可以封装成 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">CoverErrorMessage</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
,而 <span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">test</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
函数改写如下:
package main import ( "fmt" ) func main() { test() } func test() { defer tools.CoverErrorMessage() panic("panic") } func CoverErrorMessage() { if message := recover(); message != nil { var err error switch x := message.(type) { case string: err = errors.New(x) case error: err = x default: err = errors.New("Unknow panic") } Logger.Error("Recovered panic error : ",err) } }
defer 处理异常时只能将
<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">recover</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
写在第一层函数中,否则将无法<span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">recover</span><span style="box-sizing: border-box;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;display: inline-block;padding-right: 2px;padding-left: 2px;font-size: 14px;">()</span>
到panic错误
以上是Golang的異常處理的詳細內容。更多資訊請關注PHP中文網其他相關文章!