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

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