| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package result
- import (
- "fmt"
- "reflect"
- "runtime"
- "gitp78su.ipnodns.ru/svi/kern/v4/lev0/defs/def_spec"
- mKh "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers"
- )
- // Result — обёртка вокруг результата с возможной ошибкой.
- //
- // Может быть либо только полезное значение, либо только ошибка.
- type Result[T any] struct {
- val T // Полезное значение
- isCheck def_spec.Bool // Если проверено
- err error // Ошибка
- }
- var (
- str5 = def_spec.ATxt("NewOk(): result==nil")
- )
- // NewOk -- возвращает успешный Result с значением.
- func NewOk[T any](result T) def_spec.IResult[T] {
- // Для некоторых типов нужна дополнительная проверка через reflect
- v := reflect.ValueOf(result)
- switch v.Kind() {
- case reflect.Pointer, reflect.Slice, reflect.Map, reflect.Chan, reflect.Func, reflect.Interface:
- isNil := def_spec.Bool(v.IsNil())
- mKh.If(isNil).Hassert(str5)
- }
- sf := &Result[T]{
- val: result,
- }
- runtime.SetFinalizer(sf, sf.destroy)
- return sf
- }
- var (
- str6 = def_spec.ATxt("NewErr(): err==nil")
- )
- // NewErr -- возвращает Result с ошибкой.
- func NewErr[T any](err error) def_spec.IResult[T] {
- mKh.If(err == nil).Hassert(str6)
- sf := &Result[T]{
- err: err,
- }
- runtime.SetFinalizer(sf, sf.destroy)
- return sf
- }
- var (
- str7 = def_spec.ATxt("WrapErr(): result not have error")
- str8 = def_spec.ATxt("WrapErr(): err==nil")
- )
- // WrapErr -- оборачивает существующий Result с ошибкой с новой ошибкой.
- func WrapErr[T any](res def_spec.IResult[T], err error) def_spec.IResult[T] {
- mKh.If(res.IsOk()).Hassert(str7)
- mKh.If(err == nil).Hassert(str8)
- err0 := res.Err() // Чтобы не было паники при финализации и обернуть ошибку
- err = fmt.Errorf("%v, err=\n\t%w", err0, err)
- sf := NewErr[T](err)
- return sf
- }
- var (
- str9 = def_spec.ATxt("Result[T].destroy(): err not checked")
- )
- func (sf *Result[T]) destroy(res *Result[T]) {
- mKh.If(!res.isCheck).Hassert(str9)
- }
- // IsOk -- возвращает true, если Result содержит значение.
- func (sf *Result[T]) IsOk() def_spec.Bool {
- sf.isCheck = true
- return sf.err == nil
- }
- // IsErr -- возвращает true, если Result содержит ошибку.
- func (sf *Result[T]) IsErr() def_spec.Bool {
- sf.isCheck = true
- return sf.err != nil
- }
- // Ok -- возвращает значение, если оно есть, иначе паникует.
- func (sf *Result[T]) Ok() T {
- mKh.If(sf.err != nil).Hassert("Result[T].Ok(): err!=nil, err=\n\t%v", sf.err)
- sf.isCheck = true
- return sf.val
- }
- // OkOr -- возвращает значение, если оно есть, или значение по умолчанию.
- func (sf *Result[T]) OkOr(defaultValue T) T {
- sf.isCheck = true
- if sf.err != nil {
- sf.val = defaultValue
- sf.err = nil
- }
- return sf.Ok()
- }
- var (
- str11 = def_spec.ATxt("Result[T].OkOrFn(): fn==nil")
- )
- // OkOrFn -- возвращает значение, если оно есть, или результат выполнения функции.
- func (sf *Result[T]) OkOrFn(fn func() T) T {
- mKh.If(fn == nil).Hassert(str11)
- sf.isCheck = true
- if sf.err != nil {
- sf.val = fn()
- sf.err = nil
- }
- return sf.Ok()
- }
- var (
- str12 = def_spec.ATxt("Result[T].Err(): err==nil")
- )
- // Err -- возвращает ошибку, если она есть.
- func (sf *Result[T]) Err() error {
- mKh.If(sf.err == nil).Hassert(str12)
- sf.isCheck = true
- return sf.err
- }
- const str13 = "Result[T].Error(): err==nil"
- // Error -- возвращает строковое представление ошибки, если она есть.
- func (sf *Result[T]) Error() string {
- mKh.If(sf.err == nil).Hassert(str13)
- sf.isCheck = true
- return sf.err.Error()
- }
- // Hassert -- проверяет, что нет ошибки (с паникой).
- func (sf *Result[T]) Hassert(msgFormat def_spec.ATxt, args ...any) T {
- if sf.err != nil {
- txtErr := def_spec.Sprintf("Result[T].Hassert(): have error, err=\n\t%v", sf.err)
- mKh.If(sf.err != nil).Hassert(txtErr)
- }
- sf.isCheck = true
- return sf.val
- }
- // Assert -- проверяет, что нет ошибки (с паникой только на локальном стенде).
- func (sf *Result[T]) Assert(msgFormat def_spec.ATxt, args ...any) T {
- if sf.err != nil {
- txtErr := def_spec.Sprintf("Result[T].Assert(): have error, , err=\n\t%v", sf.err)
- mKh.If(sf.err != nil).Assert(txtErr, args...)
- }
- sf.isCheck = true
- return sf.val
- }
|