在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.
 
 
 

457 lines
11 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. "fmt"
  8. "html/template"
  9. "reflect"
  10. "strconv"
  11. "strings"
  12. "time"
  13. jww "github.com/spf13/jwalterweatherman"
  14. )
  15. // ToTimeE casts an empty interface to time.Time.
  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. // ToDurationE casts an empty interface to time.Duration.
  33. func ToDurationE(i interface{}) (d time.Duration, err error) {
  34. i = indirect(i)
  35. jww.DEBUG.Println("ToDurationE called on type:", reflect.TypeOf(i))
  36. switch s := i.(type) {
  37. case time.Duration:
  38. return s, nil
  39. case int64:
  40. d = time.Duration(s)
  41. return
  42. case float64:
  43. d = time.Duration(s)
  44. return
  45. case string:
  46. d, err = time.ParseDuration(s)
  47. return
  48. default:
  49. err = fmt.Errorf("Unable to Cast %#v to Duration\n", i)
  50. return
  51. }
  52. }
  53. // ToBoolE casts an empty interface to a bool.
  54. func ToBoolE(i interface{}) (bool, error) {
  55. i = indirect(i)
  56. jww.DEBUG.Println("ToBoolE called on type:", reflect.TypeOf(i))
  57. switch b := i.(type) {
  58. case bool:
  59. return b, nil
  60. case nil:
  61. return false, nil
  62. case int:
  63. if i.(int) != 0 {
  64. return true, nil
  65. }
  66. return false, nil
  67. case string:
  68. return strconv.ParseBool(i.(string))
  69. default:
  70. return false, fmt.Errorf("Unable to Cast %#v to bool", i)
  71. }
  72. }
  73. // ToFloat64E casts an empty interface to a float64.
  74. func ToFloat64E(i interface{}) (float64, error) {
  75. i = indirect(i)
  76. jww.DEBUG.Println("ToFloat64E called on type:", reflect.TypeOf(i))
  77. switch s := i.(type) {
  78. case float64:
  79. return s, nil
  80. case float32:
  81. return float64(s), nil
  82. case int64:
  83. return float64(s), nil
  84. case int32:
  85. return float64(s), nil
  86. case int16:
  87. return float64(s), nil
  88. case int8:
  89. return float64(s), nil
  90. case int:
  91. return float64(s), nil
  92. case string:
  93. v, err := strconv.ParseFloat(s, 64)
  94. if err == nil {
  95. return float64(v), nil
  96. }
  97. return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
  98. default:
  99. return 0.0, fmt.Errorf("Unable to Cast %#v to float", i)
  100. }
  101. }
  102. // ToIntE casts an empty interface to an int.
  103. func ToIntE(i interface{}) (int, error) {
  104. i = indirect(i)
  105. jww.DEBUG.Println("ToIntE called on type:", reflect.TypeOf(i))
  106. switch s := i.(type) {
  107. case int:
  108. return s, nil
  109. case int64:
  110. return int(s), nil
  111. case int32:
  112. return int(s), nil
  113. case int16:
  114. return int(s), nil
  115. case int8:
  116. return int(s), nil
  117. case string:
  118. v, err := strconv.ParseInt(s, 0, 0)
  119. if err == nil {
  120. return int(v), nil
  121. }
  122. return 0, fmt.Errorf("Unable to Cast %#v to int", i)
  123. case float64:
  124. return int(s), nil
  125. case bool:
  126. if bool(s) {
  127. return 1, nil
  128. }
  129. return 0, nil
  130. case nil:
  131. return 0, nil
  132. default:
  133. return 0, fmt.Errorf("Unable to Cast %#v to int", i)
  134. }
  135. }
  136. // From html/template/content.go
  137. // Copyright 2011 The Go Authors. All rights reserved.
  138. // indirect returns the value, after dereferencing as many times
  139. // as necessary to reach the base type (or nil).
  140. func indirect(a interface{}) interface{} {
  141. if a == nil {
  142. return nil
  143. }
  144. if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
  145. // Avoid creating a reflect.Value if it's not a pointer.
  146. return a
  147. }
  148. v := reflect.ValueOf(a)
  149. for v.Kind() == reflect.Ptr && !v.IsNil() {
  150. v = v.Elem()
  151. }
  152. return v.Interface()
  153. }
  154. // From html/template/content.go
  155. // Copyright 2011 The Go Authors. All rights reserved.
  156. // indirectToStringerOrError returns the value, after dereferencing as many times
  157. // as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
  158. // or error,
  159. func indirectToStringerOrError(a interface{}) interface{} {
  160. if a == nil {
  161. return nil
  162. }
  163. var errorType = reflect.TypeOf((*error)(nil)).Elem()
  164. var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
  165. v := reflect.ValueOf(a)
  166. for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
  167. v = v.Elem()
  168. }
  169. return v.Interface()
  170. }
  171. // ToStringE casts an empty interface to a string.
  172. func ToStringE(i interface{}) (string, error) {
  173. i = indirectToStringerOrError(i)
  174. jww.DEBUG.Println("ToStringE called on type:", reflect.TypeOf(i))
  175. switch s := i.(type) {
  176. case string:
  177. return s, nil
  178. case bool:
  179. return strconv.FormatBool(s), nil
  180. case float64:
  181. return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil
  182. case int:
  183. return strconv.FormatInt(int64(i.(int)), 10), nil
  184. case []byte:
  185. return string(s), nil
  186. case template.HTML:
  187. return string(s), nil
  188. case template.URL:
  189. return string(s), nil
  190. case nil:
  191. return "", nil
  192. case fmt.Stringer:
  193. return s.String(), nil
  194. case error:
  195. return s.Error(), nil
  196. default:
  197. return "", fmt.Errorf("Unable to Cast %#v to string", i)
  198. }
  199. }
  200. // ToStringMapStringE casts an empty interface to a map[string]string.
  201. func ToStringMapStringE(i interface{}) (map[string]string, error) {
  202. jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i))
  203. var m = map[string]string{}
  204. switch v := i.(type) {
  205. case map[string]string:
  206. return v, nil
  207. case map[string]interface{}:
  208. for k, val := range v {
  209. m[ToString(k)] = ToString(val)
  210. }
  211. return m, nil
  212. case map[interface{}]string:
  213. for k, val := range v {
  214. m[ToString(k)] = ToString(val)
  215. }
  216. return m, nil
  217. case map[interface{}]interface{}:
  218. for k, val := range v {
  219. m[ToString(k)] = ToString(val)
  220. }
  221. return m, nil
  222. default:
  223. return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
  224. }
  225. }
  226. // ToStringMapStringSliceE casts an empty interface to a map[string][]string.
  227. func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
  228. jww.DEBUG.Println("ToStringMapStringSliceE called on type:", reflect.TypeOf(i))
  229. var m = map[string][]string{}
  230. switch v := i.(type) {
  231. case map[string][]string:
  232. return v, nil
  233. case map[string][]interface{}:
  234. for k, val := range v {
  235. m[ToString(k)] = ToStringSlice(val)
  236. }
  237. return m, nil
  238. case map[string]string:
  239. for k, val := range v {
  240. m[ToString(k)] = []string{val}
  241. }
  242. case map[string]interface{}:
  243. for k, val := range v {
  244. m[ToString(k)] = []string{ToString(val)}
  245. }
  246. return m, nil
  247. case map[interface{}][]string:
  248. for k, val := range v {
  249. m[ToString(k)] = ToStringSlice(val)
  250. }
  251. return m, nil
  252. case map[interface{}]string:
  253. for k, val := range v {
  254. m[ToString(k)] = ToStringSlice(val)
  255. }
  256. return m, nil
  257. case map[interface{}][]interface{}:
  258. for k, val := range v {
  259. m[ToString(k)] = ToStringSlice(val)
  260. }
  261. return m, nil
  262. case map[interface{}]interface{}:
  263. for k, val := range v {
  264. key, err := ToStringE(k)
  265. if err != nil {
  266. return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
  267. }
  268. value, err := ToStringSliceE(val)
  269. if err != nil {
  270. return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
  271. }
  272. m[key] = value
  273. }
  274. default:
  275. return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
  276. }
  277. return m, nil
  278. }
  279. // ToStringMapBoolE casts an empty interface to a map[string]bool.
  280. func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
  281. jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i))
  282. var m = map[string]bool{}
  283. switch v := i.(type) {
  284. case map[interface{}]interface{}:
  285. for k, val := range v {
  286. m[ToString(k)] = ToBool(val)
  287. }
  288. return m, nil
  289. case map[string]interface{}:
  290. for k, val := range v {
  291. m[ToString(k)] = ToBool(val)
  292. }
  293. return m, nil
  294. case map[string]bool:
  295. return v, nil
  296. default:
  297. return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
  298. }
  299. }
  300. // ToStringMapE casts an empty interface to a map[string]interface{}.
  301. func ToStringMapE(i interface{}) (map[string]interface{}, error) {
  302. jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i))
  303. var m = map[string]interface{}{}
  304. switch v := i.(type) {
  305. case map[interface{}]interface{}:
  306. for k, val := range v {
  307. m[ToString(k)] = val
  308. }
  309. return m, nil
  310. case map[string]interface{}:
  311. return v, nil
  312. default:
  313. return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
  314. }
  315. }
  316. // ToSliceE casts an empty interface to a []interface{}.
  317. func ToSliceE(i interface{}) ([]interface{}, error) {
  318. jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i))
  319. var s []interface{}
  320. switch v := i.(type) {
  321. case []interface{}:
  322. for _, u := range v {
  323. s = append(s, u)
  324. }
  325. return s, nil
  326. case []map[string]interface{}:
  327. for _, u := range v {
  328. s = append(s, u)
  329. }
  330. return s, nil
  331. default:
  332. return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i))
  333. }
  334. }
  335. // ToStringSliceE casts an empty interface to a []string.
  336. func ToStringSliceE(i interface{}) ([]string, error) {
  337. jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i))
  338. var a []string
  339. switch v := i.(type) {
  340. case []interface{}:
  341. for _, u := range v {
  342. a = append(a, ToString(u))
  343. }
  344. return a, nil
  345. case []string:
  346. return v, nil
  347. case string:
  348. return strings.Fields(v), nil
  349. case interface{}:
  350. str, err := ToStringE(v)
  351. if err != nil {
  352. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  353. }
  354. return []string{str}, nil
  355. default:
  356. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  357. }
  358. }
  359. // ToIntSliceE casts an empty interface to a []int.
  360. func ToIntSliceE(i interface{}) ([]int, error) {
  361. jww.DEBUG.Println("ToIntSliceE called on type:", reflect.TypeOf(i))
  362. if i == nil {
  363. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  364. }
  365. switch v := i.(type) {
  366. case []int:
  367. return v, nil
  368. }
  369. kind := reflect.TypeOf(i).Kind()
  370. switch kind {
  371. case reflect.Slice, reflect.Array:
  372. s := reflect.ValueOf(i)
  373. a := make([]int, s.Len())
  374. for j := 0; j < s.Len(); j++ {
  375. val, err := ToIntE(s.Index(j).Interface())
  376. if err != nil {
  377. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  378. }
  379. a[j] = val
  380. }
  381. return a, nil
  382. default:
  383. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  384. }
  385. }
  386. // StringToDate casts an empty interface to a time.Time.
  387. func StringToDate(s string) (time.Time, error) {
  388. return parseDateWith(s, []string{
  389. time.RFC3339,
  390. "2006-01-02T15:04:05", // iso8601 without timezone
  391. time.RFC1123Z,
  392. time.RFC1123,
  393. time.RFC822Z,
  394. time.RFC822,
  395. time.ANSIC,
  396. time.UnixDate,
  397. time.RubyDate,
  398. "2006-01-02 15:04:05Z07:00",
  399. "02 Jan 06 15:04 MST",
  400. "2006-01-02",
  401. "02 Jan 2006",
  402. "2006-01-02 15:04:05 -07:00",
  403. "2006-01-02 15:04:05 -0700",
  404. })
  405. }
  406. func parseDateWith(s string, dates []string) (d time.Time, e error) {
  407. for _, dateType := range dates {
  408. if d, e = time.Parse(dateType, s); e == nil {
  409. return
  410. }
  411. }
  412. return d, fmt.Errorf("Unable to parse date: %s", s)
  413. }