补充业务异常

This commit is contained in:
yumaojun03 2025-05-11 17:19:48 +08:00
parent 66ba346f23
commit fad998ea15
6 changed files with 215 additions and 0 deletions

View File

@ -4,7 +4,9 @@ import (
"context"
"122.51.31.227/go-course/go18/book/v3/config"
"122.51.31.227/go-course/go18/book/v3/exception"
"122.51.31.227/go-course/go18/book/v3/models"
"gorm.io/gorm"
)
var Book = &BookController{}
@ -37,6 +39,9 @@ func (c *BookController) GetBook(ctx context.Context, in *GetBookRequest) (*mode
bookInstance := &models.Book{}
// 需要从数据库中获取一个对象
if err := config.DB().Where("id = ?", in.BookNumber).Take(bookInstance).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, exception.ErrNotFound("book number: %d not found", in.BookNumber)
}
return nil, err
}

View File

@ -20,6 +20,10 @@ func (c *CommentController) AddComment(ctx context.Context, in *AddCommentReques
// 业务处理的细节
// 多个业务模块 进行交互
book, err := Book.GetBook(ctx, NewGetBookRequest(in.BookNumber))
// if exception.IsApiException(err, exception.CODE_NOT_FOUND) {
// }
if err != nil {
// 获取查询不到报错
return nil, err

View File

@ -0,0 +1,88 @@
# 业务异常
## 异常的定义
```go
// 用于描述业务异常
// 实现自定义异常
// return error
type ApiException struct {
// 业务异常的编码, 50001 表示Token过期
Code int `json:"code"`
// 异常描述信息
Message string `json:"message"`
// 不会出现在Boyd里面, 序列画成JSON, http response 进行set
HttpCode int `json:"-"`
}
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
//
// type error interface {
// Error() string
// }
func (e *ApiException) Error() string {
return e.Message
}
```
## 异常的比对, 对于 Error Code 更加准确
```go
// 通过 Code 来比较错误
func IsApiException(err error, code int) bool {
var apiErr *ApiException
if errors.As(err, &apiErr) {
return apiErr.Code == code
}
return false
}
```
## 内置了一些全局异常,方便快速使用
```go
func ErrServerInternal(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_SERVER_ERROR,
Message: fmt.Sprintf(format, a...),
HttpCode: 500,
}
}
func ErrNotFound(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_NOT_FOUND,
Message: fmt.Sprintf(format, a...),
HttpCode: 404,
}
}
func ErrValidateFailed(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_PARAM_INVALIDATE,
Message: fmt.Sprintf(format, a...),
HttpCode: 400,
}
}
```
## 返回自定义异常
```go
// 需要从数据库中获取一个对象
if err := config.DB().Where("id = ?", in.BookNumber).Take(bookInstance).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, exception.ErrNotFound("book number: %d not found", in.BookNumber)
}
return nil, err
}
```
## 判断自定义异常
```go
if exception.IsApiException(err, exception.CODE_NOT_FOUND) {
// 异常处理逻辑
}
```

View File

@ -0,0 +1,35 @@
package exception
import (
"fmt"
)
const (
CODE_SERVER_ERROR = 5000
CODE_NOT_FOUND = 404
CODE_PARAM_INVALIDATE = 400
)
func ErrServerInternal(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_SERVER_ERROR,
Message: fmt.Sprintf(format, a...),
HttpCode: 500,
}
}
func ErrNotFound(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_NOT_FOUND,
Message: fmt.Sprintf(format, a...),
HttpCode: 404,
}
}
func ErrValidateFailed(format string, a ...any) *ApiException {
return &ApiException{
Code: CODE_PARAM_INVALIDATE,
Message: fmt.Sprintf(format, a...),
HttpCode: 400,
}
}

View File

@ -0,0 +1,59 @@
package exception
import (
"errors"
"github.com/infraboard/mcube/v2/tools/pretty"
)
func NewApiException(code int, message string) *ApiException {
return &ApiException{
Code: code,
Message: message,
}
}
// 用于描述业务异常
// 实现自定义异常
// return error
type ApiException struct {
// 业务异常的编码, 50001 表示Token过期
Code int `json:"code"`
// 异常描述信息
Message string `json:"message"`
// 不会出现在Boyd里面, 序列画成JSON, http response 进行set
HttpCode int `json:"-"`
}
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
//
// type error interface {
// Error() string
// }
func (e *ApiException) Error() string {
return e.Message
}
func (e *ApiException) String() string {
return pretty.ToJSON(e)
}
func (e *ApiException) WithMessage(msg string) *ApiException {
e.Message = msg
return e
}
func (e *ApiException) WithHttpCode(httpCode int) *ApiException {
e.HttpCode = httpCode
return e
}
// 通过 Code 来比较错误
func IsApiException(err error, code int) bool {
var apiErr *ApiException
if errors.As(err, &apiErr) {
return apiErr.Code == code
}
return false
}

View File

@ -0,0 +1,24 @@
package exception_test
import (
"testing"
"122.51.31.227/go-course/go18/book/v3/exception"
)
func CheckIsError() error {
return exception.ErrNotFound("book %d not found", 1)
}
func TestException(t *testing.T) {
err := CheckIsError()
t.Log(err)
// 怎么获取ErrorCode, 断言这个接口的对象的具体类型
if v, ok := err.(*exception.ApiException); ok {
t.Log(v.Code)
t.Log(v.String())
}
t.Log(exception.IsApiException(err, exception.CODE_NOT_FOUND))
}