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

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