result.go 4.2 KB

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