func (f Frames) String() string {
	var buf bytes.Buffer
	for i, frame := range f {
		buf.WriteByte('\t')
		buf.WriteString(frame.Func)
		buf.WriteByte('(')
		buf.WriteString(frame.File)
		buf.WriteByte(':')
		buf.WriteString(strconv.Itoa(frame.Line))
		buf.WriteByte(')')
		if i < len(f)-1 {
			buf.WriteByte('\n')
		}
	}
	return buf.String()
}
String is used to satisfy the fmt.Stringer interface. It formats the stack
trace as a comma separated list of "file:line function".
package errors
import (
	"bytes"
	"encoding/json"
	"fmt"
	"path/filepath"
	"runtime"
	"strconv"
)
type Error interface {
	Message() string
	Inner() error
	Stack() Frames
	error
}
var (
	MarshalTrace = false
)
type errtype struct {
	message string
	inner   error
	stack   Frames
}
func (t *errtype) Message() string {
	return t.message
}
func (t *errtype) Stack() Frames {
	return t.stack
}
func (t *errtype) Inner() error {
	return t.inner
}
func (t *errtype) Error() string {
	if t.inner != nil {
		return t.message + ". " + t.inner.Error()
	}
	return t.message
}
func (t *errtype) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		fmt.Fprintf(s, "%s", t.message)
		if t.inner != nil {
			fmt.Fprintf(s, ". %s", t.inner.Error())
		}
		if s.Flag('+') {
			fmt.Fprint(s, "\n")
			fmt.Fprintf(s, "%s", t.stack.String())
		}
	case 's':
		fmt.Fprintf(s, "%s", t.message)
		if t.inner != nil {
			fmt.Fprintf(s, ". %s", t.inner.Error())
		}
	case 'q':
		fmt.Fprintf(s, "%q", t.message)
	}
}
func (t *errtype) MarshalJSON() ([]byte, error) {
	b, err := t.stack.MarshalJSON()
	if err != nil {
		return b, err
	}
	var buf bytes.Buffer
	fmt.Fprint(&buf, "{")
	fmt.Fprintf(&buf, `"message":%q`, t.message)
	if t.inner != nil {
		fmt.Fprintf(&buf, `,"inner":%q`, t.inner)
	}
	if t.stack != nil {
		fmt.Fprintf(&buf, `,"stack":%s`, b)
	}
	fmt.Fprint(&buf, "}")
	return buf.Bytes(), nil
}
func sprintf(format string, args ...interface{}) string {
	return fmt.Sprintf(format, args...)
}
func New(message string) Error {
	return new(message, 3)
}
func Errorf(message string, args ...interface{}) Error {
	return new(sprintf(message, args...), 3)
}
func new(message string, skip int) Error {
	return &errtype{
		message: message,
		stack:   Stack(skip),
	}
}
func Wrap(err error, message string) Error {
	return wrap(err, message, 3)
}
func Wrapf(err error, message string, args ...interface{}) Error {
	return wrap(err, sprintf(message, args...), 3)
}
func wrap(err error, message string, skip int) Error {
	if errT, ok := err.(*errtype); ok {
		errT.stack = nil  
	} else {
		err = &errtype{message: err.Error()}
	}
	return &errtype{
		message: message,
		inner:   err,
		stack:   Stack(skip),
	}
}
type Frame struct {
	File string `json:"file"`
	Line int `json:"line"`
	Func string `json:"func"`
}
type Frames []Frame