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

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