-
Notifications
You must be signed in to change notification settings - Fork 1
Home
youn edited this page Apr 25, 2021
·
3 revisions
答案是需要的。Wrap error 的意义是保留原始错误,可以添加自定义信息,以及保留调用堆栈。
一般第三方lib的error是不保存堆栈的,而和第三方lib打交道的模块就是repository层,所以可以在这一层Warp error一直往上抛,并且在最上层去做error的处理。
我的想法是可以统一作为错误处理,如果上层业务不觉得sql.ErrNoRows是错误的话,可以判断错误是否是sql.ErrNoRows,如果是的话,就吃掉错误,做正确的处理逻辑。 这个是repository层的处理逻辑。
我觉得是可以的。这样做的好处是,可以统一在repository层去关注错误码。而不需要在上层去做错误的判断,再去做业务错误码处理。而且,如果repository返回多种类型的错误,都需要上层去做多次错误判断,这样是不太好的。
func (u *UserRepository) Get(ctx context.Context, id int64) (user domain.User, err error) {
tx := u.db.WithContext(ctx)
err = tx.First(&user, id).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
err = errors.Wrap(UserNotFoundError, fmt.Sprintf("get user failed. id: %d. \n err: %s \n", id, err.Error()))
} else {
err = errors.Wrap(UserUnkonwError, fmt.Sprintf("get user failed. id: %d. \n err: %s \n", id, err.Error()))
}
}
return
}
当server层拿到这个错误后,可以使用erorrs.As(err, &myErr{}),转化自己error,然后取出里面的code,message去做接口的响应。
func Render(c *gin.Context, err error) {
var myErr = &MyErr{}
if errors.As(err, myErr) {
// todo
c.String(myErr.Code, myErr.Message)
} else {
c.String(500, err.Error())
}
}