empty.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. // Package empty provides functions for checking empty/nil variables.
  7. package empty
  8. import (
  9. "reflect"
  10. "time"
  11. "github.com/gogf/gf/v2/internal/reflection"
  12. )
  13. // iString is used for type assert api for String().
  14. type iString interface {
  15. String() string
  16. }
  17. // iInterfaces is used for type assert api for Interfaces.
  18. type iInterfaces interface {
  19. Interfaces() []interface{}
  20. }
  21. // iMapStrAny is the interface support for converting struct parameter to map.
  22. type iMapStrAny interface {
  23. MapStrAny() map[string]interface{}
  24. }
  25. type iTime interface {
  26. Date() (year int, month time.Month, day int)
  27. IsZero() bool
  28. }
  29. // IsEmpty checks whether given `value` empty.
  30. // It returns true if `value` is in: 0, nil, false, "", len(slice/map/chan) == 0,
  31. // or else it returns false.
  32. func IsEmpty(value interface{}) bool {
  33. if value == nil {
  34. return true
  35. }
  36. // It firstly checks the variable as common types using assertion to enhance the performance,
  37. // and then using reflection.
  38. switch result := value.(type) {
  39. case int:
  40. return result == 0
  41. case int8:
  42. return result == 0
  43. case int16:
  44. return result == 0
  45. case int32:
  46. return result == 0
  47. case int64:
  48. return result == 0
  49. case uint:
  50. return result == 0
  51. case uint8:
  52. return result == 0
  53. case uint16:
  54. return result == 0
  55. case uint32:
  56. return result == 0
  57. case uint64:
  58. return result == 0
  59. case float32:
  60. return result == 0
  61. case float64:
  62. return result == 0
  63. case bool:
  64. return !result
  65. case string:
  66. return result == ""
  67. case []byte:
  68. return len(result) == 0
  69. case []rune:
  70. return len(result) == 0
  71. case []int:
  72. return len(result) == 0
  73. case []string:
  74. return len(result) == 0
  75. case []float32:
  76. return len(result) == 0
  77. case []float64:
  78. return len(result) == 0
  79. case map[string]interface{}:
  80. return len(result) == 0
  81. default:
  82. // =========================
  83. // Common interfaces checks.
  84. // =========================
  85. if f, ok := value.(iTime); ok {
  86. if f == nil {
  87. return true
  88. }
  89. return f.IsZero()
  90. }
  91. if f, ok := value.(iString); ok {
  92. if f == nil {
  93. return true
  94. }
  95. return f.String() == ""
  96. }
  97. if f, ok := value.(iInterfaces); ok {
  98. if f == nil {
  99. return true
  100. }
  101. return len(f.Interfaces()) == 0
  102. }
  103. if f, ok := value.(iMapStrAny); ok {
  104. if f == nil {
  105. return true
  106. }
  107. return len(f.MapStrAny()) == 0
  108. }
  109. // Finally, using reflect.
  110. var rv reflect.Value
  111. if v, ok := value.(reflect.Value); ok {
  112. rv = v
  113. } else {
  114. rv = reflect.ValueOf(value)
  115. }
  116. switch rv.Kind() {
  117. case reflect.Bool:
  118. return !rv.Bool()
  119. case
  120. reflect.Int,
  121. reflect.Int8,
  122. reflect.Int16,
  123. reflect.Int32,
  124. reflect.Int64:
  125. return rv.Int() == 0
  126. case
  127. reflect.Uint,
  128. reflect.Uint8,
  129. reflect.Uint16,
  130. reflect.Uint32,
  131. reflect.Uint64,
  132. reflect.Uintptr:
  133. return rv.Uint() == 0
  134. case
  135. reflect.Float32,
  136. reflect.Float64:
  137. return rv.Float() == 0
  138. case reflect.String:
  139. return rv.Len() == 0
  140. case reflect.Struct:
  141. var fieldValueInterface interface{}
  142. for i := 0; i < rv.NumField(); i++ {
  143. fieldValueInterface, _ = reflection.ValueToInterface(rv.Field(i))
  144. if !IsEmpty(fieldValueInterface) {
  145. return false
  146. }
  147. }
  148. return true
  149. case
  150. reflect.Chan,
  151. reflect.Map,
  152. reflect.Slice,
  153. reflect.Array:
  154. return rv.Len() == 0
  155. case
  156. reflect.Func,
  157. reflect.Ptr,
  158. reflect.Interface,
  159. reflect.UnsafePointer:
  160. if rv.IsNil() {
  161. return true
  162. }
  163. }
  164. }
  165. return false
  166. }
  167. // IsNil checks whether given `value` is nil, especially for interface{} type value.
  168. // Parameter `traceSource` is used for tracing to the source variable if given `value` is type of pinter
  169. // that also points to a pointer. It returns nil if the source is nil when `traceSource` is true.
  170. // Note that it might use reflect feature which affects performance a little.
  171. func IsNil(value interface{}, traceSource ...bool) bool {
  172. if value == nil {
  173. return true
  174. }
  175. var rv reflect.Value
  176. if v, ok := value.(reflect.Value); ok {
  177. rv = v
  178. } else {
  179. rv = reflect.ValueOf(value)
  180. }
  181. switch rv.Kind() {
  182. case reflect.Chan,
  183. reflect.Map,
  184. reflect.Slice,
  185. reflect.Func,
  186. reflect.Interface,
  187. reflect.UnsafePointer:
  188. return !rv.IsValid() || rv.IsNil()
  189. case reflect.Ptr:
  190. if len(traceSource) > 0 && traceSource[0] {
  191. for rv.Kind() == reflect.Ptr {
  192. rv = rv.Elem()
  193. }
  194. if !rv.IsValid() {
  195. return true
  196. }
  197. if rv.Kind() == reflect.Ptr {
  198. return rv.IsNil()
  199. }
  200. } else {
  201. return !rv.IsValid() || rv.IsNil()
  202. }
  203. }
  204. return false
  205. }