| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- package ktypes
- import (
- "fmt"
- "reflect"
- "runtime"
- . "gitp78su.ipnodns.ru/svi/kern/kc/helpers"
- )
- // Result — обёртка вокруг результата с возможной ошибкой
- //
- // Может быть либо только полезное значение, либо только ошибка
- type Result[T any] struct {
- val T // Полезное значение
- isErr bool // Если содержит ошибку
- isCheck bool // Если проверено
- err error // Ошибка
- }
- // NewOk -- возвращает успешный Result с значением
- func NewOk[T any](result T) Result[T] {
- // Для некоторых типов нужна дополнительная проверка через reflect
- v := reflect.ValueOf(result)
- switch v.Kind() {
- case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Chan, reflect.Func, reflect.Interface:
- Hassert(!v.IsNil(), "NewOk(): result==nil")
- }
- sf := Result[T]{
- val: result,
- }
- runtime.SetFinalizer(&sf, sf.destroy)
- return sf
- }
- // NewErr -- возвращает Result с ошибкой
- func NewErr[T any](err error) Result[T] {
- Hassert(err != nil, "NewError(): err==nil")
- sf := Result[T]{
- err: err,
- isErr: true,
- }
- runtime.SetFinalizer(&sf, sf.destroy)
- return sf
- }
- // WrapErr -- оборачивает существующий Result с ошибкой с новой ошибкой
- func WrapErr[T any](res Result[T], err error) Result[T] {
- Hassert(res.IsErr(), "WrapErr(): result not have error")
- Hassert(err != nil, "WrapErr(): err==nil")
- err0 := res.Err()
- err = fmt.Errorf("%v, err=\n\t%w", err0, err)
- sf := NewErr[T](err)
- runtime.SetFinalizer(&sf, sf.destroy)
- return sf
- }
- func (sf *Result[T]) destroy(res *Result[T]) {
- if !res.isCheck {
- Hassert(false, "Result[T].destroy(): err not checked")
- }
- }
- // IsOk -- возвращает true, если Result содержит значение
- func (sf *Result[T]) IsOk() bool {
- sf.isCheck = true
- return !sf.isErr
- }
- // IsErr -- возвращает true, если Result содержит ошибку
- func (sf *Result[T]) IsErr() bool {
- sf.isCheck = true
- return sf.isErr
- }
- // Val -- возвращает значение, если оно есть, иначе паникует
- func (sf *Result[T]) Val() T {
- Hassert(!sf.isErr, "Result[T].Val(): err(%v)!=nil", sf.err)
- return sf.val
- }
- // ValOr -- возвращает значение, если оно есть, или значение по умолчанию
- func (sf *Result[T]) ValOr(defaultValue T) T {
- sf.isCheck = true
- if sf.isErr {
- return defaultValue
- }
- return sf.val
- }
- // ValOrFn -- возвращает значение, если оно есть, или результат выполнения функции
- func (sf *Result[T]) ValOrFn(fn func() T) T {
- Hassert(fn != nil, "Result[T].ValOrFn(): fn==nil")
- sf.isCheck = true
- if sf.isErr {
- return fn()
- }
- return sf.val
- }
- // Err -- возвращает ошибку, если она есть
- func (sf *Result[T]) Err() error {
- Hassert(sf.isErr, "Result[T].Err(): err==nil")
- sf.isCheck = true
- return sf.err
- }
- // Error -- возвращает строковое представление ошибки, если она есть
- func (sf *Result[T]) Error() string {
- Hassert(sf.isErr, "Result[T].Error(): err==nil")
- sf.isCheck = true
- return sf.err.Error()
- }
- // Hassert -- проверяет, что нет ошибки (с паникой)
- func (sf *Result[T]) Hassert(msgFormat string, args ...any) {
- strErr := ""
- if sf.isErr {
- strErr = fmt.Sprintf(", err=\n\t%v", sf.err)
- }
- msg := fmt.Sprintf(msgFormat+strErr, args...)
- Hassert(!sf.isErr, msg)
- sf.isCheck = true
- }
- // Assert -- проверяет, что нет ошибки (с паникой только на локальном стенде)
- func (sf *Result[T]) Assert(msgFormat string, args ...any) {
- strErr := ""
- if sf.isErr {
- strErr = fmt.Sprintf(", err=\n\t%v", sf.err)
- }
- msg := fmt.Sprintf(msgFormat+strErr, args...)
- Assert(!sf.isErr, msg)
- sf.isCheck = true
- }
|