From 009ce9063e487b4c4b45e7eb67ae83b2ab169d82 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 29 Jun 2019 23:35:32 +0800 Subject: [PATCH] improve gerror/glog --- g/crypto/gmd5/gmd5.go | 4 +-- g/crypto/gsha1/gsha1.go | 4 +-- g/errors/gerror/gerror.go | 37 +++++++++++++++++++++--- g/errors/gerror/gerror_test.go | 12 ++++---- g/internal/errors/errors.go | 48 -------------------------------- g/internal/errors/errors_test.go | 39 -------------------------- g/net/gtcp/gtcp_conn.go | 6 ++-- g/net/gtcp/gtcp_conn_pkg.go | 6 ++-- g/net/gtcp/gtcp_pool.go | 7 ++--- g/net/gtcp/gtcp_pool_pkg.go | 6 ++-- g/net/gudp/gudp_conn.go | 6 ++-- g/os/glog/glog_logger.go | 39 +++++++++++++------------- geg/errors/gerror/gerror1.go | 31 +++++++++++++++++++++ geg/errors/gerror/gerror2.go | 22 +++++++++++++++ 14 files changed, 130 insertions(+), 137 deletions(-) delete mode 100644 g/internal/errors/errors.go delete mode 100644 g/internal/errors/errors_test.go create mode 100644 geg/errors/gerror/gerror1.go create mode 100644 geg/errors/gerror/gerror2.go diff --git a/g/crypto/gmd5/gmd5.go b/g/crypto/gmd5/gmd5.go index 1a9a56ea3..2e46b2c11 100644 --- a/g/crypto/gmd5/gmd5.go +++ b/g/crypto/gmd5/gmd5.go @@ -13,7 +13,7 @@ import ( "io" "os" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" "github.com/gogf/gf/g/util/gconv" ) @@ -40,7 +40,7 @@ func EncryptFile(path string) (encrypt string, err error) { return "", err } defer func() { - err = errors.Wrap(f.Close(), "file closing error") + err = gerror.Wrap(f.Close(), "file closing error") }() h := md5.New() _, err = io.Copy(h, f) diff --git a/g/crypto/gsha1/gsha1.go b/g/crypto/gsha1/gsha1.go index e38a8299c..904625078 100644 --- a/g/crypto/gsha1/gsha1.go +++ b/g/crypto/gsha1/gsha1.go @@ -13,7 +13,7 @@ import ( "io" "os" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" "github.com/gogf/gf/g/util/gconv" ) @@ -37,7 +37,7 @@ func EncryptFile(path string) (encrypt string, err error) { return "", err } defer func() { - err = errors.Wrap(f.Close(), "file closing error") + err = gerror.Wrap(f.Close(), "file closing error") }() h := sha1.New() _, err = io.Copy(h, f) diff --git a/g/errors/gerror/gerror.go b/g/errors/gerror/gerror.go index 048d1e2fa..00978b2d0 100644 --- a/g/errors/gerror/gerror.go +++ b/g/errors/gerror/gerror.go @@ -10,6 +10,7 @@ package gerror import ( "bytes" "fmt" + "io" "runtime" "strings" @@ -17,14 +18,21 @@ import ( "github.com/pkg/errors" ) +// stacker is an interface for errors.StackTrace. type stacker interface { StackTrace() errors.StackTrace } +// stacker is an interface for errors.Cause. type causer interface { Cause() error } +// stackError is custom error for additional features. +type stackError struct { + error +} + const ( gFILTER_KEY = "/g/errors/gerror/gerror.go" ) @@ -53,7 +61,7 @@ func NewText(text string) error { if text == "" { return nil } - return errors.New(text) + return &stackError{errors.New(text)} } // Wrap wraps error with text. @@ -61,14 +69,14 @@ func Wrap(err error, text string) error { if err == nil { return nil } - return errors.Wrap(err, text) + return &stackError{errors.Wrap(err, text)} } // Wrapf returns an error annotating err with a stack trace // at the point Wrapf is called, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...interface{}) error { - return errors.Wrapf(err, format, args...) + return &stackError{errors.Wrapf(err, format, args...)} } // Cause returns the underlying cause of the error, if possible. @@ -83,10 +91,31 @@ func Wrapf(err error, format string, args ...interface{}) error { // be returned. If the error is nil, nil will be returned without further // investigation. func Cause(err error) error { - return errors.Cause(err) + return &stackError{errors.Cause(err)} +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %v, %s : Print the error string; +// %+v, %+s : Print the error stack list; +func (err *stackError) Format(s fmt.State, verb rune) { + switch verb { + case 's', 'v': + switch { + case s.Flag('+'): + io.WriteString(s, Stack(err.error)) + default: + io.WriteString(s, err.Error()) + } + } +} + +func (err *stackError) Cause() error { + return err.error } // Stack returns the stack callers as string. +// It returns am empty string id the does not support stacks. func Stack(err error) string { if err == nil { return "" diff --git a/g/errors/gerror/gerror_test.go b/g/errors/gerror/gerror_test.go index 737744d58..71aaa7d6c 100644 --- a/g/errors/gerror/gerror_test.go +++ b/g/errors/gerror/gerror_test.go @@ -9,7 +9,7 @@ package gerror_test import ( "testing" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" "github.com/gogf/gf/g/test/gtest" ) @@ -23,16 +23,16 @@ func nilError() error { func Test_Nil(t *testing.T) { gtest.Case(t, func() { - gtest.Assert(errors.New(interfaceNil()), nil) - gtest.Assert(errors.Wrap(nilError(), "test"), nil) + gtest.Assert(gerror.New(interfaceNil()), nil) + gtest.Assert(gerror.Wrap(nilError(), "test"), nil) }) } func Test_Wrap(t *testing.T) { gtest.Case(t, func() { - err := errors.New("1") - err = errors.Wrap(err, "func2 error") - err = errors.Wrap(err, "func3 error") + err := gerror.New("1") + err = gerror.Wrap(err, "func2 error") + err = gerror.Wrap(err, "func3 error") gtest.AssertNE(err, nil) gtest.Assert(err.Error(), "func3 error: func2 error: 1") }) diff --git a/g/internal/errors/errors.go b/g/internal/errors/errors.go deleted file mode 100644 index 7d6270869..000000000 --- a/g/internal/errors/errors.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 gf 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, -// You can obtain one at https://github.com/gogf/gf. - -// Package errors provides simple functions to manipulate errors. -// -// This package can be scalable due to https://go.googlesource.com/proposal/+/master/design/go2draft.md. -package errors - -import "github.com/gogf/gf/g/util/gconv" - -// errorWrapper is a simple wrapper for errors. -type errorWrapper struct { - s string -} - -// New returns an error that formats as the given value. -func New(value interface{}) error { - if value == nil { - return nil - } - return NewText(gconv.String(value)) -} - -// NewText returns an error that formats as the given text. -func NewText(text string) error { - if text == "" { - return nil - } - return &errorWrapper{ - s: text, - } -} - -// Wrap wraps error with text. -func Wrap(err error, text string) error { - if err == nil { - return nil - } - return NewText(text + ": " + err.Error()) -} - -// Error implements interface Error. -func (e *errorWrapper) Error() string { - return e.s -} diff --git a/g/internal/errors/errors_test.go b/g/internal/errors/errors_test.go deleted file mode 100644 index 7d0328baa..000000000 --- a/g/internal/errors/errors_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 gf 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, -// You can obtain one at https://github.com/gogf/gf. - -package errors_test - -import ( - "testing" - - "github.com/gogf/gf/g/internal/errors" - "github.com/gogf/gf/g/test/gtest" -) - -func interfaceNil() interface{} { - return nil -} - -func nilError() error { - return nil -} - -func Test_Nil(t *testing.T) { - gtest.Case(t, func() { - gtest.Assert(errors.New(interfaceNil()), nil) - gtest.Assert(errors.Wrap(nilError(), "test"), nil) - }) -} - -func Test_Wrap(t *testing.T) { - gtest.Case(t, func() { - err := errors.New("1") - err = errors.Wrap(err, "func2 error") - err = errors.Wrap(err, "func3 error") - gtest.AssertNE(err, nil) - gtest.Assert(err.Error(), "func3 error: func2 error: 1") - }) -} diff --git a/g/net/gtcp/gtcp_conn.go b/g/net/gtcp/gtcp_conn.go index 43ee80ec3..af57bf0fa 100644 --- a/g/net/gtcp/gtcp_conn.go +++ b/g/net/gtcp/gtcp_conn.go @@ -14,7 +14,7 @@ import ( "net" "time" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" ) // 封装的链接对象 @@ -209,7 +209,7 @@ func (c *Conn) RecvWithTimeout(length int, timeout time.Duration, retry ...Retry return nil, err } defer func() { - err = errors.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") + err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") }() data, err = c.Recv(length, retry...) return @@ -221,7 +221,7 @@ func (c *Conn) SendWithTimeout(data []byte, timeout time.Duration, retry ...Retr return err } defer func() { - err = errors.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") + err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") }() err = c.Send(data, retry...) return diff --git a/g/net/gtcp/gtcp_conn_pkg.go b/g/net/gtcp/gtcp_conn_pkg.go index 90b02ca97..f02a9affd 100644 --- a/g/net/gtcp/gtcp_conn_pkg.go +++ b/g/net/gtcp/gtcp_conn_pkg.go @@ -11,7 +11,7 @@ import ( "fmt" "time" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" ) const ( @@ -74,7 +74,7 @@ func (c *Conn) SendPkgWithTimeout(data []byte, timeout time.Duration, option ... return err } defer func() { - err = errors.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") + err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") }() err = c.SendPkg(data, option...) return @@ -147,7 +147,7 @@ func (c *Conn) RecvPkgWithTimeout(timeout time.Duration, option ...PkgOption) (d return nil, err } defer func() { - err = errors.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") + err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") }() data, err = c.RecvPkg(option...) return diff --git a/g/net/gtcp/gtcp_pool.go b/g/net/gtcp/gtcp_pool.go index ec706e344..a1a0e2050 100644 --- a/g/net/gtcp/gtcp_pool.go +++ b/g/net/gtcp/gtcp_pool.go @@ -9,10 +9,9 @@ package gtcp import ( "time" - "github.com/gogf/gf/g/internal/errors" - "github.com/gogf/gf/g/container/gmap" "github.com/gogf/gf/g/container/gpool" + "github.com/gogf/gf/g/errors/gerror" ) // 链接池链接对象 @@ -122,7 +121,7 @@ func (c *PoolConn) RecvWithTimeout(length int, timeout time.Duration, retry ...R return nil, err } defer func() { - err = errors.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") + err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") }() data, err = c.Recv(length, retry...) return @@ -134,7 +133,7 @@ func (c *PoolConn) SendWithTimeout(data []byte, timeout time.Duration, retry ... return err } defer func() { - err = errors.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") + err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") }() err = c.Send(data, retry...) return diff --git a/g/net/gtcp/gtcp_pool_pkg.go b/g/net/gtcp/gtcp_pool_pkg.go index 03a182de6..d62cdc122 100644 --- a/g/net/gtcp/gtcp_pool_pkg.go +++ b/g/net/gtcp/gtcp_pool_pkg.go @@ -9,7 +9,7 @@ package gtcp import ( "time" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" ) // 简单协议: (方法覆盖)发送数据 @@ -47,7 +47,7 @@ func (c *PoolConn) RecvPkgWithTimeout(timeout time.Duration, option ...PkgOption return nil, err } defer func() { - err = errors.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") + err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") }() data, err = c.RecvPkg(option...) return @@ -59,7 +59,7 @@ func (c *PoolConn) SendPkgWithTimeout(data []byte, timeout time.Duration, option return err } defer func() { - err = errors.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") + err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") }() err = c.SendPkg(data, option...) return diff --git a/g/net/gudp/gudp_conn.go b/g/net/gudp/gudp_conn.go index 2e6c9fdf0..663c16b7e 100644 --- a/g/net/gudp/gudp_conn.go +++ b/g/net/gudp/gudp_conn.go @@ -11,7 +11,7 @@ import ( "net" "time" - "github.com/gogf/gf/g/internal/errors" + "github.com/gogf/gf/g/errors/gerror" ) // 封装的UDP链接对象 @@ -182,7 +182,7 @@ func (c *Conn) RecvWithTimeout(length int, timeout time.Duration, retry ...Retry return nil, err } defer func() { - err = errors.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") + err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error") }() data, err = c.Recv(length, retry...) return @@ -194,7 +194,7 @@ func (c *Conn) SendWithTimeout(data []byte, timeout time.Duration, retry ...Retr return err } defer func() { - err = errors.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") + err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error") }() err = c.Send(data, retry...) return diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 84cca92a4..be9a6ca1f 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -12,7 +12,6 @@ import ( "fmt" "io" "os" - "runtime" "strings" "time" @@ -57,18 +56,6 @@ const ( F_TIME_STD = F_TIME_DATE | F_TIME_MILLI ) -var ( - // Default line break. - ln = "\n" -) - -func init() { - // Initialize log line breaks depending on underlying os. - if runtime.GOOS == "windows" { - ln = "\r\n" - } -} - // New creates and returns a custom logger. func New() *Logger { logger := &Logger{ @@ -270,13 +257,25 @@ func (l *Logger) print(std io.Writer, lead string, value ...interface{}) { buffer.WriteString(l.prefix + " ") } } - for k, v := range value { - if k > 0 { - buffer.WriteByte(' ') + tempStr := "" + valueStr := "" + for _, v := range value { + tempStr = gconv.String(v) + if len(valueStr) > 0 { + if valueStr[len(valueStr)-1] == '\n' { + if tempStr[0] == '\n' { + valueStr += tempStr[1:] + } else { + valueStr += tempStr + } + } else { + valueStr += " " + } + } else { + valueStr = tempStr } - buffer.WriteString(gconv.String(v)) } - buffer.WriteString(ln) + buffer.WriteString(valueStr + "\n") if l.flags&F_ASYNC > 0 { asyncPool.Add(func() { l.printToWriter(std, buffer) @@ -317,7 +316,7 @@ func (l *Logger) printStd(lead string, value ...interface{}) { func (l *Logger) printErr(lead string, value ...interface{}) { if l.stStatus == 1 { if s := l.GetStack(); s != "" { - value = append(value, ln+"Stack:"+ln+s) + value = append(value, "\nStack:\n"+s) } } // In matter of sequence, do not use stderr here, but use the same stdout. @@ -333,7 +332,7 @@ func (l *Logger) format(format string, value ...interface{}) string { // the optional parameter specify the skipped stack offset from the end point. func (l *Logger) PrintStack(skip ...int) { if s := l.GetStack(skip...); s != "" { - l.Println("Stack:" + ln + s) + l.Println("Stack:\n" + s) } else { l.Println() } diff --git a/geg/errors/gerror/gerror1.go b/geg/errors/gerror/gerror1.go new file mode 100644 index 000000000..4c12dc29e --- /dev/null +++ b/geg/errors/gerror/gerror1.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + + "github.com/pkg/errors" + + "github.com/gogf/gf/g/errors/gerror" +) + +func Test1() error { + return gerror.New("test") +} + +func Test2() error { + return gerror.Wrap(Test1(), "error test1") +} + +type stackTracer interface { + StackTrace() errors.StackTrace +} + +func main() { + err := Test2() + fmt.Printf("%s\n", err) + fmt.Printf("%v\n", err) + fmt.Printf("%+v\n", err) + fmt.Println(gerror.Stack(err)) + return + +} diff --git a/geg/errors/gerror/gerror2.go b/geg/errors/gerror/gerror2.go new file mode 100644 index 000000000..0147ee368 --- /dev/null +++ b/geg/errors/gerror/gerror2.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/gogf/gf/g/os/glog" + + "github.com/gogf/gf/g/errors/gerror" +) + +func OpenFile() error { + return gerror.New("permission denied") +} + +func OpenConfig() error { + return gerror.Wrap(OpenFile(), "configuration file opening failed") +} + +func main() { + glog.Println(OpenConfig()) + glog.Printf("unexpected error:\n%+s", OpenConfig()) + glog.Errorf("unexpected error:\n%+s", OpenConfig()) + +}