分享乙個在go tour上看到的練習題,練習裡要求使用者自己定義乙個錯誤型別,實現error
介面,函式在引數不滿足條件的時候返回自定義的錯誤型別的值。練習中特別提示使用者不要在實現的error
方法裡直接使用fmt.sprint(e)
以避免造成程式記憶體溢位。
下面貼一下具體的練習題
從之前的練習中複製sqrt
函式,修改它使其返回error
值。
sqrt
接受到乙個負數時,應當返回乙個非 nil 的錯誤值。複數同樣也不被支援。
建立乙個新的型別
type errnegativesqrt float64
並為其實現
func (e errnegativesqrt) error() string
方法使其擁有error
值,通過errnegativesqrt(-2).error()
呼叫該方法應返回"cannot sqrt negative number: -2"
。
注意:在error
方法內呼叫fmt.sprint(e)
會讓程式陷入死迴圈。可以通過先轉換e
來避免這個問題:fmt.sprint(float64(e))
。這是為什麼呢?
修改sqrt
函式,使其接受乙個負數時,返回errnegativesqrt
值。
這裡只為敘述返回error的情況,所以請忽略sqrt函式的功能實現。
package main
import (
"fmt"
)type errnegativesqrt float64
func (e errnegativesqrt) error() string
func sqrt(x float64) (float64, error)
return 0, nil
}func main()
接下來**一下為什麼在練習中把值e
先轉換為float64型別後程式就不會再記憶體溢位。
fmt.sprint(e)
將呼叫e.error()
將e
轉換為字串。如果error()
方法呼叫fmt.sprint(e)
,則程式將遞迴直到記憶體溢位。可以通過將e
轉換成乙個非錯誤型別(未實現error介面)的值來避免這種情況。
實際上在error
方法中把error
值直接傳遞給fmt
包中print相關的函式都會導致無限迴圈。原因可以在fmt包的原始碼中找到。
switch verb {
case 'v', 's', 'x', 'x', 'q':
// is it an error or stringer?
// the duplication in the bodies is necessary:
// setting wasstring and handled, and deferring catchpanic,
switch v := p.field.(type) {
case error:
wasstring = false
handled = true
defer p.catchpanic(p.field, verb)
// 這裡呼叫了error方法
p.printfield(v.error(), verb, plus, false, depth)
return
通過鏈結可以在github上看到這塊詳細的原始碼 Go 自定義error錯誤
go的error比較靈活.但是自身對error處理的機制有不太好用,我們可以自定義錯誤輸出 只要所有實現了 error 方法的物件都可以,這裡給個比較簡單的demo,後續整理乙個error的優化封裝 package main import fmt type nameemtpyerror struct...
為什麼Go中有的自定義error會導致記憶體溢位
分享乙個在go tour上看到的練習題,練習裡要求使用者自己定義乙個錯誤型別,實現error介面,函式在引數不滿足條件的時候返回自定義的錯誤型別的值。練習中特別提示使用者不要在實現的error方法裡直接使用fmt.sprint e 以避免造成程式記憶體溢位。下面貼一下具體的練習題 從之前的練習中複製...
Go 自定義排序
go語言包中包含了排序包 sort,其中針對一般的strings int型別已經有了排序方法 sort.ints a int sort.strings a string 1 分別實現三個函式 func p myslice len int func p myslice less i,j int boo...