Skip to content

Commit d799cfb

Browse files
authored
Merge pull request #1 from RyougiNevermore/master
fin v1
2 parents f98a74e + 7130da3 commit d799cfb

File tree

12 files changed

+531
-1
lines changed

12 files changed

+531
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010

1111
# Output of the go coverage tool, specifically when used with LiteIDE
1212
*.out
13+
14+
# idea
15+
.idea

README.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,65 @@
11
# errors
2-
stack errors for golang
2+
Stack errors for golang
3+
4+
Package errors provides simple error handling primitives.
5+
6+
`go get github.com/pharosnet/errors`
7+
8+
The traditional error handling idiom in Go is roughly akin to
9+
```go
10+
if err != nil {
11+
return err
12+
}
13+
```
14+
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
15+
16+
## Adding context to an error
17+
18+
The errors.Wrap function returns a new error that adds context to the original error. For example
19+
```go
20+
_, err := ioutil.ReadAll(r)
21+
if err != nil {
22+
return errors.Wrap(err)
23+
}
24+
```
25+
## Retrieving the cause of an error
26+
27+
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
28+
```go
29+
type Errors interface {
30+
Error() string
31+
Cause() error
32+
OccurTime() time.Time
33+
PCS() []uintptr
34+
Contains(error) bool
35+
Format(fmt.State, rune)
36+
}
37+
```
38+
`errors.Contains` will search target in error which implements `Errors`, For example:
39+
```go
40+
e1 := io.EOF
41+
e2 := errors.With(e1, "error2")
42+
e3 := errors.WithF(e2, "%s", "error3")
43+
44+
if errors.Contains(e3, e2) {
45+
// TODO ..
46+
}
47+
48+
if errors.Contains(e3, e1) {
49+
// TODO ...
50+
}
51+
```
52+
53+
[Read the examples for more usages.](https://github.com/pharosnet/errors/tree/master/example)
54+
55+
[Read the package documentation for more information](https://godoc.org/github.com/pharosnet/errors).
56+
57+
## Contributing
58+
59+
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
60+
61+
Before proposing a change, please discuss your change by raising an issue.
62+
63+
## License
64+
65+
GNU GENERAL PUBLIC LICENSE(v3)

config.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package errors
2+
3+
import (
4+
"fmt"
5+
"sync"
6+
"time"
7+
)
8+
9+
var _cfg *config
10+
var _once = new(sync.Once)
11+
12+
func init() {
13+
_once.Do(func() {
14+
_cfg = &config{loc: time.Local, depth: 1, skip: 3, formatFn: DefaultFormatFn}
15+
})
16+
}
17+
18+
type config struct {
19+
loc *time.Location
20+
depth int
21+
skip int
22+
formatFn Format
23+
}
24+
25+
func (c *config) SetTimeLocation(loc *time.Location) {
26+
if loc == nil {
27+
panic("errors set time location failed, loc is nil")
28+
}
29+
c.loc = loc
30+
}
31+
32+
func (c *config) SetStack(depth int, skip int) {
33+
if depth < 1 {
34+
panic(fmt.Errorf("errors set stack failed, depth valued %d is invalid", depth))
35+
}
36+
if skip < 1 {
37+
panic(fmt.Errorf("errors set stack failed, skip valued %d is invalid", skip))
38+
}
39+
c.depth = depth
40+
c.skip = skip
41+
}
42+
43+
func (c *config) SetFormatFunc(fn Format) {
44+
if fn == nil {
45+
panic("errors set format func failed")
46+
}
47+
c.formatFn = fn
48+
}
49+
50+
func Configure() *config {
51+
return _cfg
52+
}

env.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package errors
2+
3+
import (
4+
"os"
5+
"strings"
6+
)
7+
8+
func goEnv() []string {
9+
env := make([]string, 0, 2)
10+
// goroot
11+
goroot := os.Getenv("GOROOT")
12+
if len(goroot) > 0 {
13+
if strings.Contains(goroot, `\`) && strings.Contains(goroot, ":") { // win
14+
goroot = strings.Replace(goroot, `\`, "/", -1)
15+
}
16+
env = append(env, goroot)
17+
}
18+
gopath := os.Getenv("GOPATH")
19+
if len(gopath) == 0 {
20+
return env
21+
}
22+
if strings.Contains(gopath, `\`) && strings.Contains(gopath, ":") { // win
23+
gopath = strings.Replace(gopath, `\`, "/", -1)
24+
if strings.Contains(gopath, ";") {
25+
gopaths := strings.Split(gopath, ";")
26+
for _, item := range gopaths {
27+
env = append(env, strings.TrimSpace(item))
28+
}
29+
} else {
30+
env = append(env, strings.TrimSpace(gopath))
31+
}
32+
} else { // unix
33+
if strings.Contains(gopath, ":") {
34+
gopaths := strings.Split(gopath, ":")
35+
for _, item := range gopaths {
36+
env = append(env, strings.TrimSpace(item))
37+
}
38+
} else {
39+
env = append(env, strings.TrimSpace(gopath))
40+
}
41+
}
42+
return env
43+
}

errors.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package errors
2+
3+
import (
4+
"fmt"
5+
"time"
6+
)
7+
8+
func New(message string) error {
9+
return &errorUp{
10+
msg: message,
11+
cause: nil,
12+
pcs: callers(),
13+
occurred: timeNow(),
14+
}
15+
}
16+
17+
func ErrorF(format string, args ...interface{}) error {
18+
return &errorUp{
19+
msg: fmt.Sprintf(format, args...),
20+
cause: nil,
21+
pcs: callers(),
22+
occurred: timeNow(),
23+
}
24+
}
25+
26+
func With(cause error, message string) error {
27+
if cause == nil {
28+
return nil
29+
}
30+
return &errorUp{
31+
msg: message,
32+
cause: cause,
33+
pcs: callers(),
34+
occurred: timeNow(),
35+
}
36+
}
37+
38+
func WithF(cause error, format string, args ...interface{}) error {
39+
if cause == nil {
40+
return nil
41+
}
42+
return &errorUp{
43+
msg: fmt.Sprintf(format, args...),
44+
cause: cause,
45+
pcs: callers(),
46+
occurred: timeNow(),
47+
}
48+
}
49+
50+
func Wrap(e error) error {
51+
return &errorUp{
52+
msg: e.Error(),
53+
cause: nil,
54+
pcs: callers(),
55+
occurred: timeNow(),
56+
}
57+
}
58+
59+
func NewByAssigned(depth int, skip int, message string) error {
60+
return &errorUp{
61+
msg: message,
62+
cause: nil,
63+
pcs: callersByAssigned(depth, skip),
64+
occurred: timeNow(),
65+
}
66+
}
67+
68+
type errorUp struct {
69+
msg string
70+
cause error
71+
pcs []uintptr
72+
occurred time.Time
73+
}
74+
75+
func (e *errorUp) Error() string {
76+
return e.msg
77+
}
78+
79+
func (e *errorUp) OccurTime() time.Time {
80+
return e.occurred
81+
}
82+
83+
func (e *errorUp) PCS() []uintptr {
84+
return e.pcs
85+
}
86+
87+
func (e *errorUp) Format(s fmt.State, verb rune) {
88+
Configure().formatFn(s, verb, e)
89+
}
90+
91+
func (e *errorUp) Cause() error {
92+
if e.cause != nil {
93+
return e.cause
94+
}
95+
return nil
96+
}
97+
98+
func (e *errorUp) Contains(cause error) bool {
99+
if e.cause == nil {
100+
return false
101+
}
102+
err := e.cause
103+
if err != nil {
104+
if err == cause {
105+
return true
106+
}
107+
hasCause, ok := err.(Errors)
108+
if !ok {
109+
return false
110+
}
111+
return hasCause.Contains(cause)
112+
}
113+
return false
114+
}
115+
116+
func Contains(a error, b error) bool {
117+
if a == nil || b == nil {
118+
return false
119+
}
120+
e, ok := a.(Errors)
121+
if !ok {
122+
return false
123+
}
124+
return e.Contains(b)
125+
}
126+
127+
type Errors interface {
128+
Error() string
129+
Cause() error
130+
OccurTime() time.Time
131+
PCS() []uintptr
132+
Contains(error) bool
133+
Format(fmt.State, rune)
134+
}

example/contains.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/pharosnet/errors"
6+
"io"
7+
)
8+
9+
func main() {
10+
e1 := io.EOF
11+
e2 := errors.With(e1, "error2")
12+
e3 := errors.WithF(e2, "%s", "error3")
13+
14+
if errors.Contains(e3, e2) {
15+
// TODO ..
16+
}
17+
18+
if errors.Contains(e3, e1) {
19+
// TODO ...
20+
}
21+
22+
fmt.Println(errors.Contains(e3, e2))
23+
fmt.Println(errors.Contains(e3, e1))
24+
25+
}

example/json.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/pharosnet/errors"
6+
"io"
7+
)
8+
9+
func main() {
10+
errors.Configure().SetFormatFunc(errors.JsonFormatFn)
11+
e1 := io.EOF
12+
e2 := errors.With(e1, "error 2")
13+
fmt.Printf("%+v", e2)
14+
15+
// output:
16+
//
17+
// {
18+
// "msg": "error 2",
19+
// "occurTime": "2018-08-20 08:23:01.3592428 +0800 CST",
20+
// "stack": [
21+
// {
22+
// "fn": "main.main",
23+
// "home": "E:/golang/workspace",
24+
// "file": "github.com/pharosnet/errors/example/json.go",
25+
// "line": 12
26+
// }
27+
// ],
28+
// "cause": {
29+
// "msg": "EOF"
30+
// }
31+
// }
32+
}

example/new.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/pharosnet/errors"
6+
)
7+
8+
func main() {
9+
e := errors.New("some error")
10+
fmt.Println(e)
11+
e = errors.ErrorF("%s", "2")
12+
fmt.Println(e)
13+
e = errors.NewByAssigned(32, 3, "new by assigned")
14+
fmt.Printf("%+v\n", e)
15+
}

0 commit comments

Comments
 (0)