add Current/Next function for package gerror

This commit is contained in:
John
2020-10-17 17:17:10 +08:00
parent 0b1d49af4b
commit 7725d9aaaf
3 changed files with 90 additions and 3 deletions

View File

@ -26,6 +26,12 @@ type ApiCause interface {
Cause() error
}
// ApiLevel is the interface for Current/Next feature.
type ApiLevel interface {
Current() error
Next() error
}
// New creates and returns an error which is formatted from given text.
func New(text string) error {
if text == "" {
@ -120,3 +126,27 @@ func Stack(err error) string {
}
return ""
}
// Current creates and returns the current level error.
// It returns nil if current level error is nil.
func Current(err error) error {
if err == nil {
return nil
}
if e, ok := err.(ApiLevel); ok {
return e.Current()
}
return nil
}
// Next returns the next level error.
// It returns nil if current level error or the next level error is nil.
func Next(err error) error {
if err == nil {
return nil
}
if e, ok := err.(ApiLevel); ok {
return e.Next()
}
return nil
}

View File

@ -27,6 +27,7 @@ const (
var (
// goRootForFilter is used for stack filtering purpose.
// Mainly for development environment.
goRootForFilter = runtime.GOROOT()
)
@ -36,8 +37,11 @@ func init() {
}
}
// Error implements the interface of Error, it returns the error as string.
// Error implements the interface of Error, it returns all the error as string.
func (err *Error) Error() string {
if err == nil {
return ""
}
if err.text != "" {
if err.error != nil {
return err.text + ": " + err.error.Error()
@ -49,6 +53,9 @@ func (err *Error) Error() string {
// Cause returns the root cause error.
func (err *Error) Cause() error {
if err == nil {
return nil
}
loop := err
for loop != nil {
if loop.error != nil {
@ -66,8 +73,8 @@ func (err *Error) Cause() error {
// Format formats the frame according to the fmt.Formatter interface.
//
// %v, %s : Print the error string;
// %-v, %-s : Print current error string;
// %v, %s : Print all the error string;
// %-v, %-s : Print current level error string;
// %+s : Print full stack error list;
// %+v : Print the error string and full stack error list;
func (err *Error) Format(s fmt.State, verb rune) {
@ -120,6 +127,28 @@ func (err *Error) Stack() string {
return buffer.String()
}
// Current creates and returns the current level error.
// It returns nil if current level error is nil.
func (err *Error) Current() error {
if err == nil {
return nil
}
return &Error{
error: nil,
stack: err.stack,
text: err.text,
}
}
// Next returns the next level error.
// It returns nil if current level error or the next level error is nil.
func (err *Error) Next() error {
if err == nil {
return nil
}
return err.error
}
// formatSubStack formats the stack for error.
func formatSubStack(st stack, buffer *bytes.Buffer) {
index := 1

View File

@ -127,3 +127,31 @@ func Test_Stack(t *testing.T) {
//fmt.Printf("%+v", err)
})
}
func Test_Current(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.Wrap(err, "3")
t.Assert(err.Error(), "3: 2: 1")
t.Assert(gerror.Current(err).Error(), "3")
})
}
func Test_Next(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err := errors.New("1")
err = gerror.Wrap(err, "2")
err = gerror.Wrap(err, "3")
t.Assert(err.Error(), "3: 2: 1")
err = gerror.Next(err)
t.Assert(err.Error(), "2: 1")
err = gerror.Next(err)
t.Assert(err.Error(), "1")
err = gerror.Next(err)
t.Assert(err, nil)
})
}