為什麼Go的自定義error有時候會記憶體溢位

2021-10-25 06:07:36 字數 1976 閱讀 7384

分享乙個在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...