在Go中轻松安全地从一种数据类型转换为另一种数据类型
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

347 lines
7.8 KiB

  1. // Copyright © 2014 Steve Francia <spf@spf13.com>.
  2. //
  3. // Use of this source code is governed by an MIT-style
  4. // license that can be found in the LICENSE file.
  5. package cast
  6. import (
  7. "errors"
  8. "fmt"
  9. "html/template"
  10. "reflect"
  11. "strconv"
  12. "strings"
  13. "time"
  14. jww "github.com/spf13/jwalterweatherman"
  15. )
  16. func ToTimeE(i interface{}) (tim time.Time, err error) {
  17. i = indirect(i)
  18. jww.DEBUG.Println("ToTimeE called on type:", reflect.TypeOf(i))
  19. switch s := i.(type) {
  20. case time.Time:
  21. return s, nil
  22. case string:
  23. d, e := StringToDate(s)
  24. if e == nil {
  25. return d, nil
  26. }
  27. return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e)
  28. default:
  29. return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i)
  30. }
  31. }
  32. func ToDurationE(i interface{}) (d time.Duration, err error) {
  33. i = indirect(i)
  34. jww.DEBUG.Println("ToDurationE called on type:", reflect.TypeOf(i))
  35. switch s := i.(type) {
  36. case time.Duration:
  37. return s, nil
  38. case string:
  39. d, err = time.ParseDuration(s)
  40. return
  41. default:
  42. err = fmt.Errorf("Unable to Cast %#v to Duration\n", i)
  43. return
  44. }
  45. }
  46. func ToBoolE(i interface{}) (bool, error) {
  47. i = indirect(i)
  48. jww.DEBUG.Println("ToBoolE called on type:", reflect.TypeOf(i))
  49. switch b := i.(type) {
  50. case bool:
  51. return b, nil
  52. case nil:
  53. return false, nil
  54. case int:
  55. if i.(int) != 0 {
  56. return true, nil
  57. }
  58. return false, nil
  59. case string:
  60. return strconv.ParseBool(i.(string))
  61. default:
  62. return false, fmt.Errorf("Unable to Cast %#v to bool", i)
  63. }
  64. }
  65. func ToFloat64E(i interface{}) (float64, error) {
  66. i = indirect(i)
  67. jww.DEBUG.Println("ToFloat64E called on type:", reflect.TypeOf(i))
  68. switch s := i.(type) {
  69. case float64:
  70. return s, nil
  71. case float32:
  72. return float64(s), nil
  73. case int64:
  74. return float64(s), nil
  75. case int32:
  76. return float64(s), nil
  77. case int16:
  78. return float64(s), nil
  79. case int8:
  80. return float64(s), nil
  81. case int:
  82. return float64(s), nil
  83. case string:
  84. v, err := strconv.ParseFloat(s, 64)
  85. if err == nil {
  86. return float64(v), nil
  87. } else {
  88. return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
  89. }
  90. default:
  91. return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
  92. }
  93. }
  94. func ToIntE(i interface{}) (int, error) {
  95. i = indirect(i)
  96. jww.DEBUG.Println("ToIntE called on type:", reflect.TypeOf(i))
  97. switch s := i.(type) {
  98. case int:
  99. return s, nil
  100. case int64:
  101. return int(s), nil
  102. case int32:
  103. return int(s), nil
  104. case int16:
  105. return int(s), nil
  106. case int8:
  107. return int(s), nil
  108. case string:
  109. v, err := strconv.ParseInt(s, 0, 0)
  110. if err == nil {
  111. return int(v), nil
  112. } else {
  113. return 0, fmt.Errorf("Unable to Cast %#v to int", i)
  114. }
  115. case float64:
  116. return int(s), nil
  117. case bool:
  118. if bool(s) {
  119. return 1, nil
  120. } else {
  121. return 0, nil
  122. }
  123. case nil:
  124. return 0, nil
  125. default:
  126. return 0, fmt.Errorf("Unable to Cast %#v to int", i)
  127. }
  128. }
  129. // From html/template/content.go
  130. // Copyright 2011 The Go Authors. All rights reserved.
  131. // indirect returns the value, after dereferencing as many times
  132. // as necessary to reach the base type (or nil).
  133. func indirect(a interface{}) interface{} {
  134. if a == nil {
  135. return nil
  136. }
  137. if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
  138. // Avoid creating a reflect.Value if it's not a pointer.
  139. return a
  140. }
  141. v := reflect.ValueOf(a)
  142. for v.Kind() == reflect.Ptr && !v.IsNil() {
  143. v = v.Elem()
  144. }
  145. return v.Interface()
  146. }
  147. // From html/template/content.go
  148. // Copyright 2011 The Go Authors. All rights reserved.
  149. // indirectToStringerOrError returns the value, after dereferencing as many times
  150. // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
  151. // or error,
  152. func indirectToStringerOrError(a interface{}) interface{} {
  153. if a == nil {
  154. return nil
  155. }
  156. var errorType = reflect.TypeOf((*error)(nil)).Elem()
  157. var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
  158. v := reflect.ValueOf(a)
  159. for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
  160. v = v.Elem()
  161. }
  162. return v.Interface()
  163. }
  164. func ToStringE(i interface{}) (string, error) {
  165. i = indirectToStringerOrError(i)
  166. jww.DEBUG.Println("ToStringE called on type:", reflect.TypeOf(i))
  167. switch s := i.(type) {
  168. case string:
  169. return s, nil
  170. case float64:
  171. return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil
  172. case int:
  173. return strconv.FormatInt(int64(i.(int)), 10), nil
  174. case []byte:
  175. return string(s), nil
  176. case template.HTML:
  177. return string(s), nil
  178. case nil:
  179. return "", nil
  180. case fmt.Stringer:
  181. return s.String(), nil
  182. case error:
  183. return s.Error(), nil
  184. default:
  185. return "", fmt.Errorf("Unable to Cast %#v to string", i)
  186. }
  187. }
  188. func ToStringMapStringE(i interface{}) (map[string]string, error) {
  189. jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i))
  190. var m = map[string]string{}
  191. switch v := i.(type) {
  192. case map[interface{}]interface{}:
  193. for k, val := range v {
  194. m[ToString(k)] = ToString(val)
  195. }
  196. return m, nil
  197. case map[string]interface{}:
  198. for k, val := range v {
  199. m[ToString(k)] = ToString(val)
  200. }
  201. return m, nil
  202. case map[string]string:
  203. return v, nil
  204. default:
  205. return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
  206. }
  207. return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
  208. }
  209. func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
  210. jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i))
  211. var m = map[string]bool{}
  212. switch v := i.(type) {
  213. case map[interface{}]interface{}:
  214. for k, val := range v {
  215. m[ToString(k)] = ToBool(val)
  216. }
  217. return m, nil
  218. case map[string]interface{}:
  219. for k, val := range v {
  220. m[ToString(k)] = ToBool(val)
  221. }
  222. return m, nil
  223. case map[string]bool:
  224. return v, nil
  225. default:
  226. return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
  227. }
  228. return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
  229. }
  230. func ToStringMapE(i interface{}) (map[string]interface{}, error) {
  231. jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i))
  232. var m = map[string]interface{}{}
  233. switch v := i.(type) {
  234. case map[interface{}]interface{}:
  235. for k, val := range v {
  236. m[ToString(k)] = val
  237. }
  238. return m, nil
  239. case map[string]interface{}:
  240. return v, nil
  241. default:
  242. return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
  243. }
  244. return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
  245. }
  246. func ToSliceE(i interface{}) ([]interface{}, error) {
  247. jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i))
  248. var s []interface{}
  249. switch v := i.(type) {
  250. case []interface{}:
  251. for _, u := range v {
  252. s = append(s, u)
  253. }
  254. return s, nil
  255. case []map[string]interface{}:
  256. for _, u := range v {
  257. s = append(s, u)
  258. }
  259. return s, nil
  260. default:
  261. return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i))
  262. }
  263. return s, fmt.Errorf("Unable to Cast %#v to []interface{}", i)
  264. }
  265. func ToStringSliceE(i interface{}) ([]string, error) {
  266. jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i))
  267. var a []string
  268. switch v := i.(type) {
  269. case []interface{}:
  270. for _, u := range v {
  271. a = append(a, ToString(u))
  272. }
  273. return a, nil
  274. case []string:
  275. return v, nil
  276. case string:
  277. return strings.Fields(v), nil
  278. default:
  279. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  280. }
  281. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  282. }
  283. func StringToDate(s string) (time.Time, error) {
  284. return parseDateWith(s, []string{
  285. time.RFC3339,
  286. "2006-01-02T15:04:05", // iso8601 without timezone
  287. time.RFC1123Z,
  288. time.RFC1123,
  289. time.RFC822Z,
  290. time.RFC822,
  291. time.ANSIC,
  292. time.UnixDate,
  293. time.RubyDate,
  294. "2006-01-02 15:04:05Z07:00",
  295. "02 Jan 06 15:04 MST",
  296. "2006-01-02",
  297. "02 Jan 2006",
  298. })
  299. }
  300. func parseDateWith(s string, dates []string) (d time.Time, e error) {
  301. for _, dateType := range dates {
  302. if d, e = time.Parse(dateType, s); e == nil {
  303. return
  304. }
  305. }
  306. return d, errors.New(fmt.Sprintf("Unable to parse date: %s", s))
  307. }