package utils import ( "bytes" "errors" "fmt" "strconv" "strings" ) var ( ErrUnImplemented = errors.New("not implemented") ErrNilParameter = errors.New("nil parameter") ErrNilOrWrongParameter = errors.New("nil or wrong parameter") ErrWrongParameter = errors.New("wrong parameter") ErrInvalidData = errors.New("invalid data") ErrNoMatch = errors.New("no matched") ErrInvalidNumber = errors.New("invalid number") ErrInvalidWrite = errors.New("readfrom, invalid write result") ErrShortRead = errors.New("short read") //io包有ErrShortWrite,却没有ShortRead ErrHandled = errors.New("handled") ErrFailed = errors.New("failed") //最无脑的Err, 在能描述清楚错误时不要使用 ErrFailed ) type InvalidDataErr string // return err == e || err == ErrInvalidData func (e InvalidDataErr) Is(err error) bool { return err == e || err == ErrInvalidData } func (e InvalidDataErr) Error() string { return string(e) } // nothing special. Normally, N==0 means no error type NumErr struct { N int E error } func (ne NumErr) Error() string { return ne.E.Error() + ", " + strconv.Itoa(ne.N) } func (e NumErr) Is(target error) bool { return errors.Is(e.E, target) } func (ef NumErr) Unwarp() error { return ef.E } // nothing special type NumStrErr struct { N int Prefix string } func (ne NumStrErr) Error() string { return ne.Prefix + strconv.Itoa(ne.N) } // an err with a buffer, nothing special type ErrBuffer struct { Err error Buf *bytes.Buffer } func (e ErrBuffer) Is(target error) bool { return errors.Is(e.Err, target) } func (ef ErrBuffer) Unwarp() error { return ef.Err } func (ef ErrBuffer) Error() string { if ef.Buf != nil { return ef.Err.Error() + ", with Buffer,len " + strconv.Itoa(ef.Buf.Len()) } else { return ef.Err.Error() + ", with nil Buffer." } } // ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况. 类似 fmt.Errorf. type ErrInErr struct { ErrDesc string ErrDetail error Data any ExtraIs []error } func (e ErrInErr) Error() string { return e.String() } func (e ErrInErr) Unwarp() error { return e.ErrDetail } func (e ErrInErr) Is(target error) bool { if e.ErrDetail == target { return true } else if errors.Is(e.ErrDetail, target) { return true } else if len(e.ExtraIs) > 0 { for _, v := range e.ExtraIs { if errors.Is(v, target) { return true } } } return false } func (e ErrInErr) String() string { if e.Data != nil { if e.ErrDetail != nil { return fmt.Sprintf(" [ %s , Detail: %s, Data: %v ] ", e.ErrDesc, e.ErrDetail.Error(), e.Data) } return fmt.Sprintf(" [ %s , Data: %v ] ", e.ErrDesc, e.Data) } if e.ErrDetail != nil { return fmt.Sprintf(" [ %s , Detail: %s ] ", e.ErrDesc, e.ErrDetail.Error()) } return e.ErrDesc } type Errs struct { List []ErrsItem } type ErrsItem struct { Index int E error } func (ee *Errs) Add(e ErrsItem) { ee.List = append(ee.List, e) } func (e Errs) OK() bool { return len(e.List) == 0 } func (e Errs) String() string { var sb strings.Builder for _, err := range e.List { sb.WriteString(strconv.Itoa(err.Index)) sb.WriteString(", ") if err.E != nil { sb.WriteString(err.E.Error()) } sb.WriteString("\n") } return sb.String() } func (e Errs) Error() string { return e.String() }