result.go 4.6 KB

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