Go言语很壮除夜并且如今也特别很是独霸的身风行 — 良多项目都是用Go言语来完成的,如Kubernetes 。中优置Go言语的雅措一个滑稽特点是它的多值前去下场供给了一种与其他编程言语不合的偏向措置编制 。 Go将error视为具有预定义圭表类型的手总值,其本身是独霸的身一个inte***ce圭表类型。可是中优置
,编写多层琐细筹划独霸法度圭表类型并独霸api泄漏独霸的雅措特点需求有包含更多凹凸文信息的error措置,而不单仅是手总一个值。 本文我们将参议若何封装Go的独霸的身error圭表类型以在独霸法度圭表类型中带来更除夜的价值
。
我们将重写的中优置Go里自带的error圭表类型,起首从一个自定义的雅措偏向圭表类型最早,该偏向圭表类型将在法度圭表类型中辨认为error圭表类型。手总是独霸的身以,我们引进一个封装了Go的中优置 error的新自定义Error圭表类型。
type GoError struct { error}当我们在Go中说error是雅措一个值时 ,它是字符串值 - 任何完成了Error() string函数的圭表类型都可以视作error圭表类型 。将字符串值视为error会使跨层的error措置宏壮化,是以措置error字符串信息真实不是切确的编制。所以我们可以把字符串和偏向码解耦:
type GoError struct { error Code string}如今对error的措置将基于偏向码Code字段而不是字符串。让我们经由过程凹凸文数据进一步对偏向字符串举办解耦,在凹凸文数据中可独霸i18n包举办国际化。
type GoError struct { error Code string Data map[string]inte***ce{ }}Data包含用于构造偏向字符串的凹凸文数据 。偏向字符串可以经由过程数据模板化:
//i18N def
"InvalidParamValue": "Invalid parameter value '{ { .actual}}', expected '{ { .expected}}' for '{ { .name}}'"
在i18N定义文件中,偏向码Code将会映照到独霸Data构建的模板化的偏向字符串中 。
error大年夜大年夜约产生发火在任何一层 ,有需求为每层供给措置error的选项 ,并在不丢损掉落踪落原始error值的气候下进一步独霸附加的凹凸文信息对error举办包装 。GoError筹划体可以用Causes进一步封装 ,用来保管全数偏向仓库。
type GoError struct { error Code string Data map[string]inte***ce{ } Causes []error}假定必须保管多个error数据,则causes是一个数组圭表类型,并将其设置为根本error圭表类型 ,以便在法度圭表类型中包含该启事的第三方偏向。
标识表记标帜层组件将有助于辨认error产生发火在哪一层,并且可以阻拦不须要的error wrap。比如 ,假定service圭表类型的error组件产生发火在处事层 ,则大年夜大年夜约不须要wrap error 。搜检组件信息将有助于阻拦泄漏给用户不睬应赐顾帮衬的error ,比如数据库error :
type GoError struct { error Code string Data map[string]inte***ce{ } Causes []error Component ErrComponent}type ErrComponent stringconst ( ErrService ErrComponent = "service" ErrRepo ErrComponent = "repository" ErrLib ErrComponent = "library")添加一个偏向照顾圭表类型多么可以支撑error分类,以便于体味甚么偏向圭表类型 。比如,可以屈就照顾圭表类型(如NotFound)对error举办分类,像DbRecordNotFound、ResourceNotFound 、UserNotFound等等的error都可以回类为 NotFound error 。这在多层独霸法度圭表类型斥地过程中特别很是有效,并且是可选的封装:
type GoError struct { error Code string Data map[string]inte***ce{ } Causes []error Component ErrComponent ResponseType ResponseErrType}type ResponseErrType stringconst ( BadRequest ResponseErrType = "BadRequest" Forbidden ResponseErrType = "Forbidden" NotFound ResponseErrType = "NotFound" AlreadyExists ResponseErrType = "AlreadyExists")在多半气候下,展示error会举办重试。retry字段可以经由过程设置Retryable标识表记标帜来决意可否要举办error重试:
type GoError struct { error Code string Message string Data map[string]inte***ce{ } Causes []error Component ErrComponent ResponseType ResponseErrType Retryable bool}经由过程定义一个带有GoError完成的显式error接口,可以简化error搜检:
package goerrtype Error inte***ce { error Code() string Message() string Cause() error Causes() []error Data() map[string]inte***ce{ } String() string ResponseErrType() ResponseErrType SetResponseType(r ResponseErrType) Error Component() ErrComponent SetComponent(c ErrComponent) Error Retryable() bool SetRetryable() Error}有了上述的封装编制,更次要的是对error举办笼统 ,将这些封装保管在不合中心,并供给error函数的可重用性
func ResourceNotFound(id, kind string, cause error) GoError { data := map[string]inte***ce{ }{ "kind": kind, "id": id} return GoError{ Code: "ResourceNotFound", Data: data, Causes: []error{ cause}, Component: ErrService, ResponseType: NotFound, Retryable: false, }}这个error函数笼统了ResourceNotFound这个error,斥地者可独霸这个函数来前去error对象而不是每次成立一个新的对象 :
//UserServiceuser, err := u.repo.FindUser(ctx, userId)if err != nil { if err.ResponseType == NotFound { return ResourceNotFound(userUid, "User", err) } return err}我们演示了若何独霸添加凹凸文数据的自定义Go的error圭表类型,从而使得error在多层独霸法度圭表类型中更居心义。你可以在这里[1]看到无缺的代码完成和定义。
到此这篇关于Go独霸中优雅措置Error的文章就引见到这了,更多相干Go优雅措置Error内容请搜刮完竣下载之前的文章或延续不雅不雅不雅不雅鉴赏上面的相干文章希看大年夜师往后多多支撑完竣下载 !
参考材料
[1] 这里: https://gist.github.com/prathabk/744367cbfc70435c56956f650612d64b
文章推荐: