Skip to content

Xerror

xerror 错误处理逻辑封装

源码:

用法:

go
import (
    "github.com/duke-git/lancet/v2/xerror"
)

目录

文档

New

创建XError对象实例。

函数签名:

go
type XError struct {
    id      string
    message string
    stack   *stack
    cause   error
    values  map[string]any
}

func New(format string, args ...any) *XError

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("error")
    fmt.Println(err.Error())

    // Output:
    // error
}

Wrap

根据error对象创建XError对象实例,可添加message。

函数签名:

go
func Wrap(cause error, message ...any) *XError

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("wrong password")
    wrapErr := xerror.Wrap(err, "error")

    fmt.Println(wrapErr.Error())

    // Output:
    // error: wrong password
}

Unwrap

从error对象中解构出XError。

函数签名:

go
func Unwrap(err error) *XError

示例:运行

go
package main

import (
    "fmt"
    "github.com/pkg/errors"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err1 := xerror.New("error").With("level", "high")
    wrapErr := errors.Wrap(err1, "oops")

    err := xerror.Unwrap(wrapErr)

    values := err.Values()
    fmt.Println(values["level"])

    // Output:
    // high
}

XError_Wrap

创建新的XError对象并将消息和id复制到新的对象中。

函数签名:

go
func (e *XError) Wrap(cause error) *XError

示例:运行

go
package main

import (
    "fmt"
    "errors"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err1 := xerror.New("error").With("level", "high")
    err2 := err1.Wrap(errors.New("invalid username"))

    fmt.Println(err2.Error())

    // Output:
    // error: invalid username
}

XError_Unwrap

解构XEerror为error对象。适配github.com/pkg/errors。

函数签名:

go
func (e *XError) Unwrap() error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err1 := xerror.New("error").With("level", "high")
    err2 := err1.Wrap(errors.New("invalid username"))

    err := err2.Unwrap()

    fmt.Println(err.Error())

    // Output:
    // invalid username
}

XError_With

添加与XError对象的键和值。

函数签名:

go
func (e *XError) With(key string, value any) *XError

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("error").With("level", "high")

    errLevel := err.Values()["level"]

    fmt.Println(errLevel)

    // Output:
    // high
}

XError_Id

设置XError对象的id。

函数签名:

go
func (e *XError) Id(id string) *XError

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err1 := xerror.New("error").Id("e001")
    err2 := xerror.New("error").Id("e001")
    err3 := xerror.New("error").Id("e003")

    equal := err1.Is(err2)
    notEqual := err1.Is(err3)

    fmt.Println(equal)
    fmt.Println(notEqual)

    // Output:
    // true
    // false
}

XError_Is

检查目标error是否为XError,两个错误中的error.id是否匹配。

函数签名:

go
func (e *XError) Is(target error) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err1 := xerror.New("error").Id("e001")
    err2 := xerror.New("error").Id("e001")
    err3 := xerror.New("error").Id("e003")

    equal := err1.Is(err2)
    notEqual := err1.Is(err3)

    fmt.Println(equal)
    fmt.Println(notEqual)

    // Output:
    // true
    // false
}

XError_Values

返回由With设置的键和值的映射。将合并所有XError键和值。

函数签名:

go
func (e *XError) Values() map[string]any

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("error").With("level", "high")

    errLevel := err.Values()["level"]

    fmt.Println(errLevel)

    // Output:
    // high
}

XError_StackTrace

返回与pkg/error兼容的堆栈信息。

函数签名:

go
func (e *XError) StackTrace() StackTrace

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("error")

    stacks := err.Stacks()

    fmt.Println(stacks[0].Func)
    fmt.Println(stacks[0].Line)

    containFile := strings.Contains(stacks[0].File, "xxx.go")
    fmt.Println(containFile)
}

XError_Info

返回可打印的XError对象信息。

函数签名:

go
func (e *XError) Info() *errInfo

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    cause := errors.New("error")
    err := xerror.Wrap(cause, "invalid username").Id("e001").With("level", "high")

    errInfo := err.Info()

    fmt.Println(errInfo.Id)
    fmt.Println(errInfo.Cause)
    fmt.Println(errInfo.Values["level"])
    fmt.Println(errInfo.Message)

    // Output:
    // e001
    // error
    // high
    // invalid username
}

XError_Error

实现标准库的error接口。

函数签名:

go
func (e *XError) Error() string

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    err := xerror.New("error")
    fmt.Println(err.Error())

    // Output:
    // error
}

TryUnwrap

检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则TryUnwrap使用err发生panic。

函数签名:

go
func TryUnwrap[T any](val T, err error) T

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    result1 := xerror.TryUnwrap(strconv.Atoi("42"))
    fmt.Println(result1)

    _, err := strconv.Atoi("4o2")
    defer func() {
        v := recover()
        result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
        fmt.Println(result2)
    }()

    xerror.TryUnwrap(strconv.Atoi("4o2"))

    // Output:
    // 42
    // true
}

TryCatch

简单实现的java风格异常处理(try-catch-finally)。try catch不符合go错误处理风格,谨慎使用。

函数签名:

go
func NewTryCatch(ctx context.Context) *TryCatch

func (tc *TryCatch) Try(tryFunc func(ctx context.Context) error) *TryCatch

func (tc *TryCatch) Catch(catchFunc func(ctx context.Context, err error)) *TryCatch

func (tc *TryCatch) Finally(finallyFunc func(ctx context.Context)) *TryCatch

func (tc *TryCatch) Do()

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/xerror"
)

func main() {
    calledFinally := false
    calledCatch := false

    tc := xerror.NewTryCatch(context.Background())

    tc.Try(func(ctx context.Context) error {
        return errors.New("error in try block")
    }).Catch(func(ctx context.Context, err error) {
        calledCatch = true
    }).Finally(func(ctx context.Context) {
        calledFinally = true
    }).Do()

    fmt.Println(calledCatch)
    fmt.Println(calledFinally)

    // Output:
    // true
    // true
}