result.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package result
  2. import (
  3. "reflect"
  4. "runtime"
  5. mKs "gitp78su.ipnodns.ru/svi/kern/v4/lev0/core_spec"
  6. "gitp78su.ipnodns.ru/svi/kern/v4/lev0/defs"
  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 bool // Если проверено
  15. err defs.IErr // Ошибка
  16. }
  17. var (
  18. str5 = defs.Str("NewOk(): result==nil")
  19. )
  20. // NewOk -- возвращает успешный Result с значением.
  21. func NewOk[T any](result T) mKs.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. mKh.Hassert(!v.IsNil(), str5.Str())
  27. }
  28. sf := &Result[T]{
  29. val: result,
  30. }
  31. runtime.SetFinalizer(sf, sf.destroy)
  32. return sf
  33. }
  34. var(
  35. str6= defs.Str("NewErr(): err==nil")
  36. )
  37. // NewErr -- возвращает Result с ошибкой.
  38. func NewErr[T any](err defs.IErr) mKs.IResult[T] {
  39. mKh.Hassert(err != nil, str6.Str())
  40. sf := &Result[T]{
  41. err: err,
  42. }
  43. runtime.SetFinalizer(sf, sf.destroy)
  44. return sf
  45. }
  46. var(
  47. str7=defs.Str("WrapErr(): result not have error")
  48. str8=defs.Str("WrapErr(): err==nil")
  49. )
  50. // WrapErr -- оборачивает существующий Result с ошибкой с новой ошибкой.
  51. func WrapErr[T any](res mKs.IResult[T], err defs.IErr) mKs.IResult[T] {
  52. mKh.Hassert(res.IsErr(), str7.Str())
  53. mKh.Hassert(err != nil, str8.Str())
  54. err0 := res.Err() // Чтобы не было паники при финализации и обернуть ошибку
  55. err = defs.NewErr("%v, err=\n\t%w", err0, err)
  56. sf := NewErr[T](err)
  57. return sf
  58. }
  59. var(
  60. str9=defs.Str("Result[T].destroy(): err not checked")
  61. )
  62. func (sf *Result[T]) destroy(res *Result[T]) {
  63. if !res.isCheck {
  64. mKh.Hassert(false, str9.Str())
  65. }
  66. }
  67. // IsOk -- возвращает true, если Result содержит значение.
  68. func (sf *Result[T]) IsOk() bool {
  69. sf.isCheck = true
  70. return sf.err == nil
  71. }
  72. // IsErr -- возвращает true, если Result содержит ошибку.
  73. func (sf *Result[T]) IsErr() bool {
  74. sf.isCheck = true
  75. return sf.err != nil
  76. }
  77. // Ok -- возвращает значение, если оно есть, иначе паникует.
  78. func (sf *Result[T]) Ok() T {
  79. mKh.Hassert(sf.err == nil, "Result[T].Ok(): err!=nil, err=\n\t%v", sf.err)
  80. sf.isCheck = true
  81. return sf.val
  82. }
  83. // OkOr -- возвращает значение, если оно есть, или значение по умолчанию.
  84. func (sf *Result[T]) OkOr(defaultValue T) T {
  85. sf.isCheck = true
  86. if sf.err != nil {
  87. sf.val = defaultValue
  88. sf.err = nil
  89. }
  90. return sf.Ok()
  91. }
  92. var(
  93. str11=defs.Str("Result[T].OkOrFn(): fn==nil")
  94. )
  95. // OkOrFn -- возвращает значение, если оно есть, или результат выполнения функции.
  96. func (sf *Result[T]) OkOrFn(fn func() T) T {
  97. mKh.Hassert(fn != nil, str11.Str())
  98. sf.isCheck = true
  99. if sf.err != nil {
  100. sf.val = fn()
  101. sf.err = nil
  102. }
  103. return sf.Ok()
  104. }
  105. var(
  106. str12=defs.Str("Result[T].Err(): err==nil")
  107. )
  108. // Err -- возвращает ошибку, если она есть.
  109. func (sf *Result[T]) Err() error {
  110. mKh.Hassert(sf.err != nil, str12.Str())
  111. sf.isCheck = true
  112. return sf.err
  113. }
  114. // Error -- возвращает строковое представление ошибки, если она есть.
  115. func (sf *Result[T]) Error() string {
  116. mKh.Hassert(sf.err != nil, defs.Str("Result[T].Error(): err==nil"))
  117. sf.isCheck = true
  118. return sf.err.Error()
  119. }
  120. // Hassert -- проверяет, что нет ошибки (с паникой).
  121. func (sf *Result[T]) Hassert(msgFormat defs.AStr, args ...any) T {
  122. strErr := defs.AStr("")
  123. if !sf.isCheck {
  124. strErr = defs.Str(", err=\n\t%v", sf.err).Str()
  125. }
  126. msg := defs.Str(msgFormat+strErr, args...)
  127. mKh.Hassert(sf.err == nil, msg)
  128. sf.isCheck = true
  129. return sf.val
  130. }
  131. // Assert -- проверяет, что нет ошибки (с паникой только на локальном стенде).
  132. func (sf *Result[T]) Assert(msgFormat defs.AStr, args ...any) T {
  133. strErr := defs.Str("")
  134. if !sf.isCheck {
  135. strErr = defs.Str(", err=\n\t%v", sf.err).Str()
  136. }
  137. mKh.Assert(sf.err == nil, msgFormat+strErr, args...)
  138. sf.isCheck = true
  139. return sf.val
  140. }