Equal
比较方法
错误对象支持比较, Equal
方法用于完整判断两个 error
是否相同。主要通过以下方法:
// Equal reports whether current error `err` equals to error `target`.
// Please note that, in default comparison for `Error`,
// the errors are considered the same if both the `code` and `text` of them are the same.
func Equal(err, target error) bool
接口定义
如果自定义的错误数据结构需要支持比较,需要自定义的错误结构实现以下接口:
// IEqual is the interface for Equal feature.
type IEqual interface {
Error() string
Equal(target error) bool
}
通过 GoFrame
框架错误组件创建的错误对象已经实现实现了该接口,组件默认比较逻辑判断错误码和错误信息。
信息
需要注意,如果两个错误均不带错误码,并且错误信息相等,那么组件认为两个错误相等。
使用示例
func ExampleEqual() {
err1 := errors.New("permission denied")
err2 := gerror.New("permission denied")
err3 := gerror.NewCode(gcode.CodeNotAuthorized, "permission denied")
fmt.Println(gerror.Equal(err1, err2))
fmt.Println(gerror.Equal(err2, err3))
// Output:
// true
// false
}
Is
判断错误链中是否包含目标错误
-
说明:
Is
方法用于判断错误链中是否包含特定的目标错误。该方法是对 Go 标准库errors.Is
的封装,保证了与标准库相同的性能。 -
格式:
Is(err, target error) bool
-
示例:
func ExampleIs() {
// 创建一个特定的错误作为目标
targetErr := gerror.New("target error")
// 包装错误
err1 := gerror.Wrap(targetErr, "wrap error 1")
err2 := gerror.Wrap(err1, "wrap error 2")
// 使用Is判断是否包含目标错误
fmt.Println(gerror.Is(err2, targetErr))
// 与不相关的错误进行判断
otherErr := gerror.New("other error")
fmt.Println(gerror.Is(err2, otherErr))
// Output:
// true
// false
}
As
将错误转换为特定类型
-
说明:
As
方法用于将错误链中的错误转换为特定类型。它会在错误链中查找第一个与目标类型匹配的错误,如果找到,则将其转换为目标类型并返回true
。该方法是对 Go 标准库errors.As
的封装,保证了与标准库相同的性能。 -
格式:
As(err error, target any) bool
-
示例:
// 自定义错误类型
type MyError struct {
Message string
Code int
}
// 实现error接口
func (e *MyError) Error() string {
return fmt.Sprintf("code: %d, message: %s", e.Code, e.Message)
}
func ExampleAs() {
// 创建一个自定义错误
originalErr := &MyError{Message: "database connection failed", Code: 500}
// 包装错误
err := gerror.Wrap(originalErr, "operation failed")
// 尝试将错误转换为MyError类型
var myErr *MyError
if gerror.As(err, &myErr) {
fmt.Println("Error code:", myErr.Code)
fmt.Println("Error message:", myErr.Message)
}
// 尝试转换为不匹配的类型
type OtherError struct{}
var otherErr *OtherError
fmt.Println(gerror.As(err, &otherErr))
// Output:
// Error code: 500
// Error message: database connection failed
// false
}
As
方法在以下场景中特别有用:
-
类型断言:当您需要从错误链中提取特定类型的错误信息时。
-
错误处理:根据错误类型执行不同的处理逻辑。
-
自定义错误恢复:当需要从错误中提取特定信息来实现错误恢复机制时。
下面是一个实际应用的例子:
package main
import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
)
// 数据库错误
type DBError struct {
Table string
Message string
}
func (e *DBError) Error() string {
return fmt.Sprintf("database error on table '%s': %s", e.Table, e.Message)
}
// 认证错误
type AuthError struct {
Username string
Message string
}
func (e *AuthError) Error() string {
return fmt.Sprintf("authentication error for user '%s': %s", e.Username, e.Message)
}
// 模拟数据库操作
func queryDatabase() error {
return gerror.Wrap(&DBError{
Table: "users",
Message: "connection timeout",
}, "database query failed")
}
// 模拟用户认证
func authenticateUser() error {
return gerror.Wrap(&AuthError{
Username: "john_doe",
Message: "invalid password",
}, "authentication failed")
}
// 处理不同类型的错误
func handleError(err error) {
// 尝试将错误转换为数据库错误
var dbErr *DBError
if gerror.As(err, &dbErr) {
fmt.Println("Database error detected:")
fmt.Println(" Table:", dbErr.Table)
fmt.Println(" Message:", dbErr.Message)
fmt.Println(" Recommended action: Check database connection and retry")
return
}
// 尝试将错误转换为认证错误
var authErr *AuthError
if gerror.As(err, &authErr) {
fmt.Println("Authentication error detected:")
fmt.Println(" Username:", authErr.Username)
fmt.Println(" Message:", authErr.Message)
fmt.Println(" Recommended action: Verify credentials and try again")
return
}
// 其他错误类型
fmt.Println("Unknown error:", err.Error())
}
func main() {
// 模拟数据库错误
err1 := queryDatabase()
handleError(err1)
fmt.Println()
// 模拟认证错误
err2 := authenticateUser()
handleError(err2)
}
运行结果:
Database error detected:
Table: users
Message: connection timeout
Recommended action: Check database connection and retry
Authentication error detected:
Username: john_doe
Message: invalid password
Recommended action: Verify credentials and try again