// 0.1.2 package errs import ( "fmt" "os" "runtime" "git.leolab.info/lib/replacer" ) type ErrCode string var Silent = false var StrFmt = "[ERROR] %date% %time% [%code%] %error% at %file%:%line% %func%" var Trace = false const ( ErrError ErrCode = "ErrError" ErrNoError ErrCode = "ErrNoError" ErrDSError ErrCode = "ErrDSError" ) type src struct { File string Line int Func string } //Структура ошибки // 0.1.0 type Err struct { dsId int64 Code ErrCode Msg string src src Prev *Err } //Реализация интерфейса error // 0.1.0 func (e *Err) Error() string { if e == nil { panic("NIL Error") } return e.Msg } //Получить "карту" ошибки // 0.1.4 func (e *Err) Map() map[string]interface{} { if e == nil { panic("NIL Error") } ret := map[string]interface{}{ "DSId": e.dsId, "Code": e.Code, "Msg": e.Msg, "Src": map[string]interface{}{ "File": e.src.File, "Line": e.src.Line, "Func": e.src.Func, }, } if e.Prev != nil { ret["Prev"] = e.Error() } return ret } //Создать ошибку // 0.1.4 func RaiseError(eCode ErrCode, msg string, prev ...*Err) *Err { e := &Err{ Code: eCode, Msg: msg, src: getSrc(2), Prev: nil, } if len(prev) > 0 { e.Prev = prev[0] } e = storeDS(e) logError(e) return e } //Передать ошибку выше // 0.1.4 func UpError(err *Err, args ...any) *Err { e := &Err{ Code: err.Code, Msg: err.Msg, src: getSrc(2), Prev: err, } if len(args) > 1 { for _, a := range args { switch v := a.(type) { case string: e.Msg = v case ErrCode: e.Code = v default: //Unknown } } } e = storeDS(e) if Trace { logError(e) } return e } //Преобразовать ошибку // 0.1.0 func Error(e error) *Err { err := &Err{ Code: ErrError, Msg: e.Error(), src: getSrc(2), Prev: nil, } err = storeDS(err) logError(err) return err } //Получить источник // 0.1.0 func getSrc(lvl int) (s src) { pc, file, line, ok := runtime.Caller(lvl) if !ok { return src{File: "undefined", Line: 0, Func: "undefined()"} } f := runtime.CallersFrames([]uintptr{pc}) ff, _ := f.Next() s = src{ File: file, Line: line, Func: ff.Function, } return s } //Получить строку по формату // 0.1.0 func (e *Err) getString() string { if e == nil { panic("Err is NIL") } r := replacer.New() r.Add("code", string(e.Code)) r.Add("file", e.src.File) r.Add("line", fmt.Sprintf("%v", e.src.Line)) r.Add("func", e.src.Func) r.Add("error", e.Msg) return r.ReplaceC(StrFmt) } //Вывести ошибку // 0.1.0 func logError(e *Err) { storeFS(e) if Silent { return } fmt.Fprintln(os.Stderr, e.getString()) }