result.go 4.1 KB

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