mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add error code feature for package gerror
This commit is contained in:
@ -13,7 +13,7 @@ func main() {
|
||||
key := "key"
|
||||
|
||||
// 第一次锁带时间
|
||||
gmlock.Lock(key, 1000)
|
||||
gmlock.Lock(key)
|
||||
glog.Println("lock1")
|
||||
// 这个时候上一次的计时解锁已失效
|
||||
gmlock.Unlock(key)
|
||||
|
||||
@ -14,73 +14,71 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ApiStack is the interface for Stack feature.
|
||||
type ApiStack interface {
|
||||
// apiCode is the interface for Code feature.
|
||||
type apiCode interface {
|
||||
Error() string // It should be an error.
|
||||
Code() int
|
||||
}
|
||||
|
||||
// apiStack is the interface for Stack feature.
|
||||
type apiStack interface {
|
||||
Error() string // It should be an error.
|
||||
Stack() string
|
||||
}
|
||||
|
||||
// ApiCause is the interface for Cause feature.
|
||||
type ApiCause interface {
|
||||
// apiCause is the interface for Cause feature.
|
||||
type apiCause interface {
|
||||
Error() string // It should be an error.
|
||||
Cause() error
|
||||
}
|
||||
|
||||
// ApiCurrent is the interface for Current feature.
|
||||
type ApiCurrent interface {
|
||||
// apiCurrent is the interface for Current feature.
|
||||
type apiCurrent interface {
|
||||
Error() string // It should be an error.
|
||||
Current() error
|
||||
}
|
||||
|
||||
// ApiNext is the interface for Next feature.
|
||||
type ApiNext interface {
|
||||
// apiNext is the interface for Next feature.
|
||||
type apiNext interface {
|
||||
Error() string // It should be an error.
|
||||
Next() error
|
||||
}
|
||||
|
||||
// New creates and returns an error which is formatted from given text.
|
||||
func New(text string) error {
|
||||
if text == "" {
|
||||
return nil
|
||||
}
|
||||
return &Error{
|
||||
stack: callers(),
|
||||
text: text,
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Newf returns an error that formats as the given format and args.
|
||||
func Newf(format string, args ...interface{}) error {
|
||||
return &Error{
|
||||
stack: callers(),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSkip creates and returns an error which is formatted from given text.
|
||||
// The parameter <skip> specifies the stack callers skipped amount.
|
||||
func NewSkip(skip int, text string) error {
|
||||
if text == "" {
|
||||
return nil
|
||||
}
|
||||
return &Error{
|
||||
stack: callers(skip),
|
||||
text: text,
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Newf returns an error that formats as the given format and args.
|
||||
func Newf(format string, args ...interface{}) error {
|
||||
if format == "" {
|
||||
return nil
|
||||
}
|
||||
return &Error{
|
||||
stack: callers(),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// NewfSkip returns an error that formats as the given format and args.
|
||||
// NewSkipf returns an error that formats as the given format and args.
|
||||
// The parameter <skip> specifies the stack callers skipped amount.
|
||||
func NewfSkip(skip int, format string, args ...interface{}) error {
|
||||
if format == "" {
|
||||
return nil
|
||||
}
|
||||
func NewSkipf(skip int, format string, args ...interface{}) error {
|
||||
return &Error{
|
||||
stack: callers(skip),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +92,7 @@ func Wrap(err error, text string) error {
|
||||
error: err,
|
||||
stack: callers(),
|
||||
text: text,
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,13 +107,91 @@ func Wrapf(err error, format string, args ...interface{}) error {
|
||||
error: err,
|
||||
stack: callers(),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCode creates and returns an error that has error code and given text.
|
||||
func NewCode(code int, text string) error {
|
||||
return &Error{
|
||||
stack: callers(),
|
||||
text: text,
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCodef returns an error that has error code and formats as the given format and args.
|
||||
func NewCodef(code int, format string, args ...interface{}) error {
|
||||
return &Error{
|
||||
stack: callers(),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCodeSkip creates and returns an error which has error code and is formatted from given text.
|
||||
// The parameter <skip> specifies the stack callers skipped amount.
|
||||
func NewCodeSkip(code, skip int, text string) error {
|
||||
return &Error{
|
||||
stack: callers(skip),
|
||||
text: text,
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCodeSkipf returns an error that has error code and formats as the given format and args.
|
||||
// The parameter <skip> specifies the stack callers skipped amount.
|
||||
func NewCodeSkipf(code, skip int, format string, args ...interface{}) error {
|
||||
return &Error{
|
||||
stack: callers(skip),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WrapCode wraps error with code and text.
|
||||
// It returns nil if given err is nil.
|
||||
func WrapCode(code int, err error, text string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &Error{
|
||||
error: err,
|
||||
stack: callers(),
|
||||
text: text,
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WrapCodef wraps error with code and format specifier.
|
||||
// It returns nil if given <err> is nil.
|
||||
func WrapCodef(code int, err error, format string, args ...interface{}) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &Error{
|
||||
error: err,
|
||||
stack: callers(),
|
||||
text: fmt.Sprintf(format, args...),
|
||||
code: code,
|
||||
}
|
||||
}
|
||||
|
||||
// Cause returns the error code of current error.
|
||||
// It returns -1 if it has no error code or it does not implements interface Code.
|
||||
func Code(err error) int {
|
||||
if err != nil {
|
||||
if e, ok := err.(apiCode); ok {
|
||||
return e.Code()
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Cause returns the root cause error of <err>.
|
||||
func Cause(err error) error {
|
||||
if err != nil {
|
||||
if e, ok := err.(ApiCause); ok {
|
||||
if e, ok := err.(apiCause); ok {
|
||||
return e.Cause()
|
||||
}
|
||||
}
|
||||
@ -127,7 +204,7 @@ func Stack(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
if e, ok := err.(ApiStack); ok {
|
||||
if e, ok := err.(apiStack); ok {
|
||||
return e.Stack()
|
||||
}
|
||||
return ""
|
||||
@ -139,7 +216,7 @@ func Current(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if e, ok := err.(ApiCurrent); ok {
|
||||
if e, ok := err.(apiCurrent); ok {
|
||||
return e.Current()
|
||||
}
|
||||
return err
|
||||
@ -151,7 +228,7 @@ func Next(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if e, ok := err.(ApiNext); ok {
|
||||
if e, ok := err.(apiNext); ok {
|
||||
return e.Next()
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
// Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
@ -20,10 +20,11 @@ type Error struct {
|
||||
error error // Wrapped error.
|
||||
stack stack // Stack array, which records the stack information when this error is created or wrapped.
|
||||
text string // Error text, which is created by New* functions.
|
||||
code int // Error code if necessary.
|
||||
}
|
||||
|
||||
const (
|
||||
gFILTER_KEY = "/errors/gerror/gerror"
|
||||
stackFilterKey = "/errors/gerror/gerror"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -49,7 +50,19 @@ func (err *Error) Error() string {
|
||||
}
|
||||
return err.text
|
||||
}
|
||||
return err.error.Error()
|
||||
if err.error != nil {
|
||||
err.error.Error()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Code returns the error code.
|
||||
// It returns -1 if it has no error code.
|
||||
func (err *Error) Code() int {
|
||||
if err == nil {
|
||||
return -1
|
||||
}
|
||||
return err.code
|
||||
}
|
||||
|
||||
// Cause returns the root cause error.
|
||||
@ -63,7 +76,7 @@ func (err *Error) Cause() error {
|
||||
if e, ok := loop.error.(*Error); ok {
|
||||
// Internal Error struct.
|
||||
loop = e
|
||||
} else if e, ok := loop.error.(ApiCause); ok {
|
||||
} else if e, ok := loop.error.(apiCause); ok {
|
||||
// Other Error that implements ApiCause interface.
|
||||
return e.Cause()
|
||||
} else {
|
||||
@ -165,7 +178,7 @@ func formatSubStack(st stack, buffer *bytes.Buffer) {
|
||||
for _, p := range st {
|
||||
if fn := runtime.FuncForPC(p - 1); fn != nil {
|
||||
file, line := fn.FileLine(p - 1)
|
||||
if strings.Contains(file, gFILTER_KEY) {
|
||||
if strings.Contains(file, stackFilterKey) {
|
||||
continue
|
||||
}
|
||||
// Avoid stack string like "<autogenerated>"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
// Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
@ -12,13 +12,13 @@ import "runtime"
|
||||
type stack []uintptr
|
||||
|
||||
const (
|
||||
gMAX_STACK_DEPTH = 32
|
||||
maxStackDepth = 32
|
||||
)
|
||||
|
||||
// callers returns the stack callers.
|
||||
func callers(skip ...int) stack {
|
||||
var (
|
||||
pcs [gMAX_STACK_DEPTH]uintptr
|
||||
pcs [maxStackDepth]uintptr
|
||||
n = 3
|
||||
)
|
||||
if len(skip) > 0 {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
// Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
@ -155,3 +155,45 @@ func Test_Next(t *testing.T) {
|
||||
t.Assert(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Code(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := errors.New("123")
|
||||
t.Assert(gerror.Code(err), -1)
|
||||
t.Assert(err.Error(), "123")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := gerror.NewCode(1, "123")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "123")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := gerror.NewCodef(1, "%s", "123")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "123")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := gerror.NewCodeSkip(1, 0, "123")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "123")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := gerror.NewCodeSkipf(1, 0, "%s", "123")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "123")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := errors.New("1")
|
||||
err = gerror.Wrap(err, "2")
|
||||
err = gerror.WrapCode(1, err, "3")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "3: 2: 1")
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
err := errors.New("1")
|
||||
err = gerror.Wrap(err, "2")
|
||||
err = gerror.WrapCodef(1, err, "%s", "3")
|
||||
t.Assert(gerror.Code(err), 1)
|
||||
t.Assert(err.Error(), "3: 2: 1")
|
||||
})
|
||||
}
|
||||
|
||||
@ -92,6 +92,12 @@ type (
|
||||
handler *handlerItem // Handler object.
|
||||
}
|
||||
|
||||
// errorStack is the interface for Stack feature.
|
||||
errorStack interface {
|
||||
Error() string
|
||||
Stack() string
|
||||
}
|
||||
|
||||
// Request handler function.
|
||||
HandlerFunc = func(r *Request)
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ func niceCallFunc(f func()) {
|
||||
case gEXCEPTION_EXIT, gEXCEPTION_EXIT_ALL:
|
||||
return
|
||||
default:
|
||||
if _, ok := e.(gerror.ApiStack); ok {
|
||||
if _, ok := e.(errorStack); ok {
|
||||
// It's already an error that has stack info.
|
||||
panic(e)
|
||||
} else {
|
||||
|
||||
@ -121,7 +121,7 @@ func (m *Middleware) Next() {
|
||||
loop = false
|
||||
}
|
||||
}, func(exception error) {
|
||||
if e, ok := exception.(gerror.ApiStack); ok {
|
||||
if e, ok := exception.(errorStack); ok {
|
||||
// It's already an error that has stack info.
|
||||
m.request.error = e
|
||||
} else {
|
||||
|
||||
@ -445,7 +445,7 @@ func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]s
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if e := recover(); e != nil {
|
||||
err = gerror.NewfSkip(1, "%v", e)
|
||||
err = gerror.NewSkipf(1, "%v", e)
|
||||
}
|
||||
}()
|
||||
var (
|
||||
@ -545,7 +545,7 @@ func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if e := recover(); e != nil {
|
||||
err = gerror.NewfSkip(1, "%v", e)
|
||||
err = gerror.NewSkipf(1, "%v", e)
|
||||
}
|
||||
}()
|
||||
var (
|
||||
|
||||
@ -54,7 +54,7 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if e := recover(); e != nil {
|
||||
err = gerror.NewfSkip(1, "%v", e)
|
||||
err = gerror.NewSkipf(1, "%v", e)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ func doStructs(params interface{}, pointer interface{}, mapping ...map[string]st
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
if e := recover(); e != nil {
|
||||
err = gerror.NewfSkip(1, "%v", e)
|
||||
err = gerror.NewSkipf(1, "%v", e)
|
||||
}
|
||||
}()
|
||||
// If given <params> is JSON, it then uses json.Unmarshal doing the converting.
|
||||
|
||||
Reference in New Issue
Block a user