Merge pull request #1758 from thaJeztah/bump_some_deps

Update some dependencies
This commit is contained in:
Silvin Lubecki 2019-03-20 21:26:33 +01:00 committed by GitHub
commit 91339e1108
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 206 additions and 109 deletions

View File

@ -43,10 +43,10 @@ github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
github.com/hashicorp/golang-lru 0fb14efe8c47ae851c0034ed7a448854d3d34cf3 github.com/hashicorp/golang-lru 0fb14efe8c47ae851c0034ed7a448854d3d34cf3
github.com/hashicorp/go-version 23480c0 github.com/hashicorp/go-version 23480c0
github.com/imdario/mergo v0.3.6 github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0 github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0
github.com/json-iterator/go 1624edc4454b8682399def8740d46db5e4362ba4 # 1.1.5 github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6
github.com/mattn/go-shellwords v1.0.3 github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5
github.com/matttproud/golang_protobuf_extensions v1.0.1 github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/Microsoft/hcsshim v0.8.6 github.com/Microsoft/hcsshim v0.8.6
github.com/Microsoft/go-winio v0.4.12 github.com/Microsoft/go-winio v0.4.12
@ -62,7 +62,7 @@ github.com/opencontainers/runc 2b18fe1d885ee5083ef9f0838fee39b62d653e30
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
github.com/peterbourgon/diskv 5f041e8faa004a95c88a202771f4cc3e991971e6 # v2.0.1 github.com/peterbourgon/diskv 5f041e8faa004a95c88a202771f4cc3e991971e6 # v2.0.1
github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
github.com/prometheus/client_golang c5b7fccd204277076155f10851dad72b76a49317 # v0.8.0 github.com/prometheus/client_golang c5b7fccd204277076155f10851dad72b76a49317 # v0.8.0
github.com/prometheus/client_model 6f3806018612930941127f2a7c6c453ba2c527d2 github.com/prometheus/client_model 6f3806018612930941127f2a7c6c453ba2c527d2
github.com/prometheus/common 7600349dcfe1abd18d72d3a1770870d9800a7801 github.com/prometheus/common 7600349dcfe1abd18d72d3a1770870d9800a7801

View File

@ -13,6 +13,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl
[![Build Status][1]][2] [![Build Status][1]][2]
[![Coverage Status][7]][8] [![Coverage Status][7]][8]
[![Sourcegraph][9]][10] [![Sourcegraph][9]][10]
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield)
[1]: https://travis-ci.org/imdario/mergo.png [1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo [2]: https://travis-ci.org/imdario/mergo
@ -27,7 +28,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl
### Latest release ### Latest release
[Release v0.3.6](https://github.com/imdario/mergo/releases/tag/v0.3.6). [Release v0.3.7](https://github.com/imdario/mergo/releases/tag/v0.3.7).
### Important note ### Important note
@ -217,6 +218,21 @@ If I can help you, you have an idea or you are using Mergo in your projects, don
Written by [Dario Castañé](http://dario.im). Written by [Dario Castañé](http://dario.im).
## Top Contributors
[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0)
[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1)
[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2)
[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3)
[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4)
[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5)
[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6)
[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7)
## License ## License
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large)

View File

@ -72,6 +72,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf
case reflect.Struct: case reflect.Struct:
srcMap := src.Interface().(map[string]interface{}) srcMap := src.Interface().(map[string]interface{})
for key := range srcMap { for key := range srcMap {
config.overwriteWithEmptyValue = true
srcValue := srcMap[key] srcValue := srcMap[key]
fieldName := changeInitialCase(key, unicode.ToUpper) fieldName := changeInitialCase(key, unicode.ToUpper)
dstElement := dst.FieldByName(fieldName) dstElement := dst.FieldByName(fieldName)

View File

@ -26,9 +26,10 @@ func hasExportedField(dst reflect.Value) (exported bool) {
} }
type Config struct { type Config struct {
Overwrite bool Overwrite bool
AppendSlice bool AppendSlice bool
Transformers Transformers Transformers Transformers
overwriteWithEmptyValue bool
} }
type Transformers interface { type Transformers interface {
@ -40,6 +41,8 @@ type Transformers interface {
// short circuiting on recursive types. // short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
overwrite := config.Overwrite overwrite := config.Overwrite
overwriteWithEmptySrc := config.overwriteWithEmptyValue
config.overwriteWithEmptyValue = false
if !src.IsValid() { if !src.IsValid() {
return return
@ -74,7 +77,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
} }
} }
} else { } else {
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
dst.Set(src) dst.Set(src)
} }
} }
@ -125,7 +128,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
dstSlice = reflect.ValueOf(dstElement.Interface()) dstSlice = reflect.ValueOf(dstElement.Interface())
} }
if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
dstSlice = srcSlice dstSlice = srcSlice
} else if config.AppendSlice { } else if config.AppendSlice {
if srcSlice.Type() != dstSlice.Type() { if srcSlice.Type() != dstSlice.Type() {
@ -136,7 +139,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
dst.SetMapIndex(key, dstSlice) dst.SetMapIndex(key, dstSlice)
} }
} }
if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map { if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) {
continue continue
} }
@ -151,7 +154,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
if !dst.CanSet() { if !dst.CanSet() {
break break
} }
if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
dst.Set(src) dst.Set(src)
} else if config.AppendSlice { } else if config.AppendSlice {
if src.Type() != dst.Type() { if src.Type() != dst.Type() {
@ -191,7 +194,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
return return
} }
default: default:
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
dst.Set(src) dst.Set(src)
} }
} }

View File

@ -10,10 +10,6 @@ A high-performance 100% compatible drop-in replacement of "encoding/json"
You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go)
```
Go开发者们请加入我们滴滴出行平台技术部 taowen@didichuxing.com
```
# Benchmark # Benchmark
![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) ![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png)

View File

@ -312,6 +312,10 @@ func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) { func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
any := *(*Any)(ptr) any := *(*Any)(ptr)
if any == nil {
stream.WriteNil()
return
}
any.WriteTo(stream) any.WriteTo(stream)
} }

View File

@ -77,14 +77,12 @@ func (iter *Iterator) ReadFloat32() (ret float32) {
} }
func (iter *Iterator) readPositiveFloat32() (ret float32) { func (iter *Iterator) readPositiveFloat32() (ret float32) {
value := uint64(0)
c := byte(' ')
i := iter.head i := iter.head
// first char // first char
if i == iter.tail { if i == iter.tail {
return iter.readFloat32SlowPath() return iter.readFloat32SlowPath()
} }
c = iter.buf[i] c := iter.buf[i]
i++ i++
ind := floatDigits[c] ind := floatDigits[c]
switch ind { switch ind {
@ -107,7 +105,7 @@ func (iter *Iterator) readPositiveFloat32() (ret float32) {
return return
} }
} }
value = uint64(ind) value := uint64(ind)
// chars before dot // chars before dot
non_decimal_loop: non_decimal_loop:
for ; i < iter.tail; i++ { for ; i < iter.tail; i++ {
@ -145,9 +143,7 @@ non_decimal_loop:
} }
// too many decimal places // too many decimal places
return iter.readFloat32SlowPath() return iter.readFloat32SlowPath()
case invalidCharForNumber: case invalidCharForNumber, dotInNumber:
fallthrough
case dotInNumber:
return iter.readFloat32SlowPath() return iter.readFloat32SlowPath()
} }
decimalPlaces++ decimalPlaces++
@ -218,14 +214,12 @@ func (iter *Iterator) ReadFloat64() (ret float64) {
} }
func (iter *Iterator) readPositiveFloat64() (ret float64) { func (iter *Iterator) readPositiveFloat64() (ret float64) {
value := uint64(0)
c := byte(' ')
i := iter.head i := iter.head
// first char // first char
if i == iter.tail { if i == iter.tail {
return iter.readFloat64SlowPath() return iter.readFloat64SlowPath()
} }
c = iter.buf[i] c := iter.buf[i]
i++ i++
ind := floatDigits[c] ind := floatDigits[c]
switch ind { switch ind {
@ -248,7 +242,7 @@ func (iter *Iterator) readPositiveFloat64() (ret float64) {
return return
} }
} }
value = uint64(ind) value := uint64(ind)
// chars before dot // chars before dot
non_decimal_loop: non_decimal_loop:
for ; i < iter.tail; i++ { for ; i < iter.tail; i++ {
@ -286,9 +280,7 @@ non_decimal_loop:
} }
// too many decimal places // too many decimal places
return iter.readFloat64SlowPath() return iter.readFloat64SlowPath()
case invalidCharForNumber: case invalidCharForNumber, dotInNumber:
fallthrough
case dotInNumber:
return iter.readFloat64SlowPath() return iter.readFloat64SlowPath()
} }
decimalPlaces++ decimalPlaces++

View File

@ -2,12 +2,22 @@
package jsoniter package jsoniter
import "fmt" import (
"fmt"
"io"
)
func (iter *Iterator) skipNumber() { func (iter *Iterator) skipNumber() {
if !iter.trySkipNumber() { if !iter.trySkipNumber() {
iter.unreadByte() iter.unreadByte()
iter.ReadFloat32() if iter.Error != nil && iter.Error != io.EOF {
return
}
iter.ReadFloat64()
if iter.Error != nil && iter.Error != io.EOF {
iter.Error = nil
iter.ReadBigFloat()
}
} }
} }

View File

@ -338,7 +338,7 @@ func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
for i := 0; i < structType.NumField(); i++ { for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i) field := structType.Field(i)
tag, hastag := field.Tag().Lookup(ctx.getTagKey()) tag, hastag := field.Tag().Lookup(ctx.getTagKey())
if ctx.onlyTaggedField && !hastag { if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
continue continue
} }
tagParts := strings.Split(tag, ",") tagParts := strings.Split(tag, ",")

View File

@ -64,14 +64,26 @@ func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
return &numericMapKeyDecoder{decoderOfType(ctx, typ)} return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
default: default:
ptrType := reflect2.PtrTo(typ) ptrType := reflect2.PtrTo(typ)
if ptrType.Implements(textMarshalerType) { if ptrType.Implements(unmarshalerType) {
return &referenceDecoder{
&unmarshalerDecoder{
valType: ptrType,
},
}
}
if typ.Implements(unmarshalerType) {
return &unmarshalerDecoder{
valType: typ,
}
}
if ptrType.Implements(textUnmarshalerType) {
return &referenceDecoder{ return &referenceDecoder{
&textUnmarshalerDecoder{ &textUnmarshalerDecoder{
valType: ptrType, valType: ptrType,
}, },
} }
} }
if typ.Implements(textMarshalerType) { if typ.Implements(textUnmarshalerType) {
return &textUnmarshalerDecoder{ return &textUnmarshalerDecoder{
valType: typ, valType: typ,
} }

View File

@ -93,8 +93,7 @@ func (encoder *marshalerEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
stream.WriteNil() stream.WriteNil()
return return
} }
marshaler := obj.(json.Marshaler) bytes, err := json.Marshal(obj)
bytes, err := marshaler.MarshalJSON()
if err != nil { if err != nil {
stream.Error = err stream.Error = err
} else { } else {

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"os" "os"
"regexp" "regexp"
"strings"
) )
var ( var (
@ -21,13 +22,17 @@ func isSpace(r rune) bool {
return false return false
} }
func replaceEnv(s string) string { func replaceEnv(getenv func(string) string, s string) string {
if getenv == nil {
getenv = os.Getenv
}
return envRe.ReplaceAllStringFunc(s, func(s string) string { return envRe.ReplaceAllStringFunc(s, func(s string) string {
s = s[1:] s = s[1:]
if s[0] == '{' { if s[0] == '{' {
s = s[1 : len(s)-1] s = s[1 : len(s)-1]
} }
return os.Getenv(s) return getenv(s)
}) })
} }
@ -35,16 +40,24 @@ type Parser struct {
ParseEnv bool ParseEnv bool
ParseBacktick bool ParseBacktick bool
Position int Position int
// If ParseEnv is true, use this for getenv.
// If nil, use os.Getenv.
Getenv func(string) string
} }
func NewParser() *Parser { func NewParser() *Parser {
return &Parser{ParseEnv, ParseBacktick, 0} return &Parser{
ParseEnv: ParseEnv,
ParseBacktick: ParseBacktick,
Position: 0,
}
} }
func (p *Parser) Parse(line string) ([]string, error) { func (p *Parser) Parse(line string) ([]string, error) {
args := []string{} args := []string{}
buf := "" buf := ""
var escaped, doubleQuoted, singleQuoted, backQuote bool var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool
backtick := "" backtick := ""
pos := -1 pos := -1
@ -68,12 +81,12 @@ loop:
} }
if isSpace(r) { if isSpace(r) {
if singleQuoted || doubleQuoted || backQuote { if singleQuoted || doubleQuoted || backQuote || dollarQuote {
buf += string(r) buf += string(r)
backtick += string(r) backtick += string(r)
} else if got { } else if got {
if p.ParseEnv { if p.ParseEnv {
buf = replaceEnv(buf) buf = replaceEnv(p.Getenv, buf)
} }
args = append(args, buf) args = append(args, buf)
buf = "" buf = ""
@ -84,7 +97,7 @@ loop:
switch r { switch r {
case '`': case '`':
if !singleQuoted && !doubleQuoted { if !singleQuoted && !doubleQuoted && !dollarQuote {
if p.ParseBacktick { if p.ParseBacktick {
if backQuote { if backQuote {
out, err := shellRun(backtick) out, err := shellRun(backtick)
@ -100,18 +113,55 @@ loop:
backtick = "" backtick = ""
backQuote = !backQuote backQuote = !backQuote
} }
case ')':
if !singleQuoted && !doubleQuoted && !backQuote {
if p.ParseBacktick {
if dollarQuote {
out, err := shellRun(backtick)
if err != nil {
return nil, err
}
if r == ')' {
buf = buf[:len(buf)-len(backtick)-2] + out
} else {
buf = buf[:len(buf)-len(backtick)-1] + out
}
}
backtick = ""
dollarQuote = !dollarQuote
continue
}
backtick = ""
dollarQuote = !dollarQuote
}
case '(':
if !singleQuoted && !doubleQuoted && !backQuote {
if !dollarQuote && strings.HasSuffix(buf, "$") {
dollarQuote = true
buf += "("
continue
} else {
return nil, errors.New("invalid command line string")
}
}
case '"': case '"':
if !singleQuoted { if !singleQuoted && !dollarQuote {
doubleQuoted = !doubleQuoted doubleQuoted = !doubleQuoted
continue continue
} }
case '\'': case '\'':
if !doubleQuoted { if !doubleQuoted && !dollarQuote {
singleQuoted = !singleQuoted singleQuoted = !singleQuoted
continue continue
} }
case ';', '&', '|', '<', '>': case ';', '&', '|', '<', '>':
if !(escaped || singleQuoted || doubleQuoted || backQuote) { if !(escaped || singleQuoted || doubleQuoted || backQuote) {
if r == '>' && len(buf) > 0 {
if c := buf[0]; '0' <= c && c <= '9' {
i -= 1
got = false
}
}
pos = i pos = i
break loop break loop
} }
@ -119,19 +169,19 @@ loop:
got = true got = true
buf += string(r) buf += string(r)
if backQuote { if backQuote || dollarQuote {
backtick += string(r) backtick += string(r)
} }
} }
if got { if got {
if p.ParseEnv { if p.ParseEnv {
buf = replaceEnv(buf) buf = replaceEnv(p.Getenv, buf)
} }
args = append(args, buf) args = append(args, buf)
} }
if escaped || singleQuoted || doubleQuoted || backQuote { if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote {
return nil, errors.New("invalid command line string") return nil, errors.New("invalid command line string")
} }

24
vendor/github.com/mattn/go-shellwords/util_go15.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
// +build !go1.6
package shellwords
import (
"os"
"os/exec"
"runtime"
"strings"
)
func shellRun(line string) (string, error) {
var b []byte
var err error
if runtime.GOOS == "windows" {
b, err = exec.Command(os.Getenv("COMSPEC"), "/c", line).Output()
} else {
b, err = exec.Command(os.Getenv("SHELL"), "-c", line).Output()
}
if err != nil {
return "", err
}
return strings.TrimSpace(string(b)), nil
}

View File

@ -1,4 +1,4 @@
// +build !windows // +build !windows,go1.6
package shellwords package shellwords
@ -13,6 +13,9 @@ func shellRun(line string) (string, error) {
shell := os.Getenv("SHELL") shell := os.Getenv("SHELL")
b, err := exec.Command(shell, "-c", line).Output() b, err := exec.Command(shell, "-c", line).Output()
if err != nil { if err != nil {
if eerr, ok := err.(*exec.ExitError); ok {
b = eerr.Stderr
}
return "", errors.New(err.Error() + ":" + string(b)) return "", errors.New(err.Error() + ":" + string(b))
} }
return strings.TrimSpace(string(b)), nil return strings.TrimSpace(string(b)), nil

View File

@ -1,3 +1,5 @@
// +build windows,go1.6
package shellwords package shellwords
import ( import (
@ -11,6 +13,9 @@ func shellRun(line string) (string, error) {
shell := os.Getenv("COMSPEC") shell := os.Getenv("COMSPEC")
b, err := exec.Command(shell, "/c", line).Output() b, err := exec.Command(shell, "/c", line).Output()
if err != nil { if err != nil {
if eerr, ok := err.(*exec.ExitError); ok {
b = eerr.Stderr
}
return "", errors.New(err.Error() + ":" + string(b)) return "", errors.New(err.Error() + ":" + string(b))
} }
return strings.TrimSpace(string(b)), nil return strings.TrimSpace(string(b)), nil

View File

@ -1,4 +1,4 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives. Package errors provides simple error handling primitives.
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
Before proposing a change, please discuss your change by raising an issue. Before proposing a change, please discuss your change by raising an issue.
## Licence ## License
BSD-2-Clause BSD-2-Clause

View File

@ -6,7 +6,7 @@
// return err // return err
// } // }
// //
// which applied recursively up the call stack results in error reports // which when applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows // without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way // programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error. // that does not destroy the original value of the error.
@ -15,16 +15,17 @@
// //
// The errors.Wrap function returns a new error that adds context to the // The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called, // original error by recording a stack trace at the point Wrap is called,
// and the supplied message. For example // together with the supplied message. For example
// //
// _, err := ioutil.ReadAll(r) // _, err := ioutil.ReadAll(r)
// if err != nil { // if err != nil {
// return errors.Wrap(err, "read failed") // return errors.Wrap(err, "read failed")
// } // }
// //
// If additional control is required the errors.WithStack and errors.WithMessage // If additional control is required, the errors.WithStack and
// functions destructure errors.Wrap into its component operations of annotating // errors.WithMessage functions destructure errors.Wrap into its component
// an error with a stack trace and an a message, respectively. // operations: annotating an error with a stack trace and with a message,
// respectively.
// //
// Retrieving the cause of an error // Retrieving the cause of an error
// //
@ -38,7 +39,7 @@
// } // }
// //
// can be inspected by errors.Cause. errors.Cause will recursively retrieve // can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be // the topmost error that does not implement causer, which is assumed to be
// the original cause. For example: // the original cause. For example:
// //
// switch err := errors.Cause(err).(type) { // switch err := errors.Cause(err).(type) {
@ -48,16 +49,16 @@
// // unknown error // // unknown error
// } // }
// //
// causer interface is not exported by this package, but is considered a part // Although the causer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// Formatted printing of errors // Formatted printing of errors
// //
// All error values returned from this package implement fmt.Formatter and can // All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported // be formatted by the fmt package. The following verbs are supported:
// //
// %s print the error. If the error has a Cause it will be // %s print the error. If the error has a Cause it will be
// printed recursively // printed recursively.
// %v see %s // %v see %s
// %+v extended format. Each Frame of the error's StackTrace will // %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail. // be printed in detail.
@ -65,13 +66,13 @@
// Retrieving the stack trace of an error or wrapper // Retrieving the stack trace of an error or wrapper
// //
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface. // invoked. This information can be retrieved with the following interface:
// //
// type stackTracer interface { // type stackTracer interface {
// StackTrace() errors.StackTrace // StackTrace() errors.StackTrace
// } // }
// //
// Where errors.StackTrace is defined as // The returned errors.StackTrace type is defined as
// //
// type StackTrace []Frame // type StackTrace []Frame
// //
@ -85,8 +86,8 @@
// } // }
// } // }
// //
// stackTracer interface is not exported by this package, but is considered a part // Although the stackTracer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// See the documentation for Frame.Format for more details. // See the documentation for Frame.Format for more details.
package errors package errors
@ -192,7 +193,7 @@ func Wrap(err error, message string) error {
} }
// Wrapf returns an error annotating err with a stack trace // Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is call, and the format specifier. // at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil. // If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error { func Wrapf(err error, format string, args ...interface{}) error {
if err == nil { if err == nil {
@ -220,6 +221,18 @@ func WithMessage(err error, message string) error {
} }
} }
// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}
type withMessage struct { type withMessage struct {
cause error cause error
msg string msg string

View File

@ -46,7 +46,8 @@ func (f Frame) line() int {
// //
// Format accepts flags that alter the printing of some verbs, as follows: // Format accepts flags that alter the printing of some verbs, as follows:
// //
// %+s path of source file relative to the compile time GOPATH // %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d // %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) { func (f Frame) Format(s fmt.State, verb rune) {
switch verb { switch verb {
@ -79,6 +80,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). // StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) { func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb { switch verb {
case 'v': case 'v':
@ -136,43 +145,3 @@ func funcname(name string) string {
i = strings.Index(name, ".") i = strings.Index(name, ".")
return name[i+1:] return name[i+1:]
} }
func trimGOPATH(name, file string) string {
// Here we want to get the source file path relative to the compile time
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
// GOPATH at runtime, but we can infer the number of path segments in the
// GOPATH. We note that fn.Name() returns the function name qualified by
// the import path, which does not include the GOPATH. Thus we can trim
// segments from the beginning of the file path until the number of path
// separators remaining is one more than the number of path separators in
// the function name. For example, given:
//
// GOPATH /home/user
// file /home/user/src/pkg/sub/file.go
// fn.Name() pkg/sub.Type.Method
//
// We want to produce:
//
// pkg/sub/file.go
//
// From this we can easily see that fn.Name() has one less path separator
// than our desired output. We count separators from the end of the file
// path until it finds two more than in the function name and then move
// one character forward to preserve the initial path segment without a
// leading separator.
const sep = "/"
goal := strings.Count(name, sep) + 2
i := len(file)
for n := 0; n < goal; n++ {
i = strings.LastIndex(file[:i], sep)
if i == -1 {
// not enough separators found, set i so that the slice expression
// below leaves file unmodified
i = -len(sep)
break
}
}
// get back to 0 or trim the leading separator
file = file[i+len(sep):]
return file
}