result.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package result
  2. import (
  3. "fmt"
  4. "reflect"
  5. "runtime"
  6. mKs "gitp78su.ipnodns.ru/svi/kern/v4/lev0/core_spec"
  7. "gitp78su.ipnodns.ru/svi/kern/v4/lev0/defs"
  8. mKh "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers"
  9. )
  10. // Result — обёртка вокруг результата с возможной ошибкой.
  11. //
  12. // Может быть либо только полезное значение, либо только ошибка.
  13. type Result[T any] struct {
  14. val T // Полезное значение
  15. isCheck bool // Если проверено
  16. err error // Ошибка
  17. }
  18. // NewOk -- возвращает успешный Result с значением.
  19. func NewOk[T any](result T) mKs.IResult[T] {
  20. // Для некоторых типов нужна дополнительная проверка через reflect
  21. v := reflect.ValueOf(result)
  22. switch v.Kind() {
  23. case reflect.Pointer, reflect.Slice, reflect.Map, reflect.Chan, reflect.Func, reflect.Interface:
  24. mKh.Hassert(!v.IsNil(), "NewOk(): result==nil")
  25. }
  26. sf := &Result[T]{
  27. val: result,
  28. }
  29. runtime.SetFinalizer(sf, sf.destroy)
  30. return sf
  31. }
  32. // NewErr -- возвращает Result с ошибкой.
  33. func NewErr[T any](err error) mKs.IResult[T] {
  34. mKh.Hassert(err != nil, "NewError(): err==nil")
  35. sf := &Result[T]{
  36. err: err,
  37. }
  38. runtime.SetFinalizer(sf, sf.destroy)
  39. return sf
  40. }
  41. // WrapErr -- оборачивает существующий Result с ошибкой с новой ошибкой.
  42. func WrapErr[T any](res mKs.IResult[T], err error) mKs.IResult[T] {
  43. mKh.Hassert(res.IsErr(), "WrapErr(): result not have error")
  44. mKh.Hassert(err != nil, "WrapErr(): err==nil")
  45. err0 := res.Err() // Чтобы не было паники при финализации и обернуть ошибку
  46. err = fmt.Errorf("%v, err=\n\t%w", err0, err)
  47. sf := NewErr[T](err)
  48. return sf
  49. }
  50. func (sf *Result[T]) destroy(res *Result[T]) {
  51. if !res.isCheck {
  52. mKh.Hassert(false, "Result[T].destroy(): err not checked")
  53. }
  54. }
  55. // IsOk -- возвращает true, если Result содержит значение.
  56. func (sf *Result[T]) IsOk() bool {
  57. sf.isCheck = true
  58. return sf.err == nil
  59. }
  60. // IsErr -- возвращает true, если Result содержит ошибку.
  61. func (sf *Result[T]) IsErr() bool {
  62. sf.isCheck = true
  63. return sf.err != nil
  64. }
  65. // Ok -- возвращает значение, если оно есть, иначе паникует.
  66. func (sf *Result[T]) Ok() T {
  67. mKh.Hassert(sf.err == nil, "Result[T].Ok(): err(%v)!=nil", sf.err.Error())
  68. sf.isCheck = true
  69. return sf.val
  70. }
  71. // OkOr -- возвращает значение, если оно есть, или значение по умолчанию.
  72. func (sf *Result[T]) OkOr(defaultValue T) T {
  73. sf.isCheck = true
  74. if sf.err != nil {
  75. sf.val = defaultValue
  76. sf.err = nil
  77. }
  78. return sf.Ok()
  79. }
  80. // OkOrFn -- возвращает значение, если оно есть, или результат выполнения функции.
  81. func (sf *Result[T]) OkOrFn(fn func() T) T {
  82. mKh.Hassert(fn != nil, "Result[T].OkOrFn(): fn==nil")
  83. sf.isCheck = true
  84. if sf.err != nil {
  85. sf.val = fn()
  86. sf.err = nil
  87. }
  88. return sf.Ok()
  89. }
  90. // Err -- возвращает ошибку, если она есть.
  91. func (sf *Result[T]) Err() error {
  92. mKh.Hassert(sf.err != nil, "Result[T].Err(): err==nil")
  93. sf.isCheck = true
  94. return sf.err
  95. }
  96. // Error -- возвращает строковое представление ошибки, если она есть.
  97. func (sf *Result[T]) Error() string {
  98. mKh.Hassert(sf.err != nil, "Result[T].Error(): err==nil")
  99. sf.isCheck = true
  100. return sf.err.Error()
  101. }
  102. // Hassert -- проверяет, что нет ошибки (с паникой).
  103. func (sf *Result[T]) Hassert(msgFormat defs.Str, args ...any) T {
  104. strErr := ""
  105. if !sf.isCheck {
  106. strErr = fmt.Sprintf(", err=\n\t%v", sf.err)
  107. }
  108. msg := fmt.Sprintf(msgFormat.String()+strErr, args...)
  109. mKh.Hassert(sf.err == nil, defs.Str(msg))
  110. sf.isCheck = true
  111. return sf.val
  112. }
  113. // Assert -- проверяет, что нет ошибки (с паникой только на локальном стенде).
  114. func (sf *Result[T]) Assert(msgFormat defs.Str, args ...any) T {
  115. strErr := ""
  116. if !sf.isCheck {
  117. strErr = fmt.Sprintf(", err=\n\t%v", sf.err)
  118. }
  119. msg := fmt.Sprintf(msgFormat.String()+strErr, args...)
  120. mKh.Assert(sf.err == nil, defs.Str(msg))
  121. sf.isCheck = true
  122. return sf.val
  123. }