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

443 lines
10 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 template.URL:
  179. return string(s), nil
  180. case nil:
  181. return "", nil
  182. case fmt.Stringer:
  183. return s.String(), nil
  184. case error:
  185. return s.Error(), nil
  186. default:
  187. return "", fmt.Errorf("Unable to Cast %#v to string", i)
  188. }
  189. }
  190. func ToStringMapStringE(i interface{}) (map[string]string, error) {
  191. jww.DEBUG.Println("ToStringMapStringE called on type:", reflect.TypeOf(i))
  192. var m = map[string]string{}
  193. switch v := i.(type) {
  194. case map[string]string:
  195. return v, nil
  196. case map[string]interface{}:
  197. for k, val := range v {
  198. m[ToString(k)] = ToString(val)
  199. }
  200. return m, nil
  201. case map[interface{}]string:
  202. for k, val := range v {
  203. m[ToString(k)] = ToString(val)
  204. }
  205. return m, nil
  206. case map[interface{}]interface{}:
  207. for k, val := range v {
  208. m[ToString(k)] = ToString(val)
  209. }
  210. return m, nil
  211. default:
  212. return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
  213. }
  214. return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i)
  215. }
  216. func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
  217. jww.DEBUG.Println("ToStringMapStringSliceE called on type:", reflect.TypeOf(i))
  218. var m = map[string][]string{}
  219. switch v := i.(type) {
  220. case map[string][]string:
  221. return v, nil
  222. case map[string][]interface{}:
  223. for k, val := range v {
  224. m[ToString(k)] = ToStringSlice(val)
  225. }
  226. return m, nil
  227. case map[string]string:
  228. for k, val := range v {
  229. m[ToString(k)] = []string{val}
  230. }
  231. case map[string]interface{}:
  232. for k, val := range v {
  233. m[ToString(k)] = []string{ToString(val)}
  234. }
  235. return m, nil
  236. case map[interface{}][]string:
  237. for k, val := range v {
  238. m[ToString(k)] = ToStringSlice(val)
  239. }
  240. return m, nil
  241. case map[interface{}]string:
  242. for k, val := range v {
  243. m[ToString(k)] = ToStringSlice(val)
  244. }
  245. return m, nil
  246. case map[interface{}][]interface{}:
  247. for k, val := range v {
  248. m[ToString(k)] = ToStringSlice(val)
  249. }
  250. return m, nil
  251. case map[interface{}]interface{}:
  252. for k, val := range v {
  253. key, err := ToStringE(k)
  254. if err != nil {
  255. return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
  256. }
  257. value, err := ToStringSliceE(val)
  258. if err != nil {
  259. return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i)
  260. }
  261. m[key] = value
  262. }
  263. }
  264. return m, nil
  265. }
  266. func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
  267. jww.DEBUG.Println("ToStringMapBoolE called on type:", reflect.TypeOf(i))
  268. var m = map[string]bool{}
  269. switch v := i.(type) {
  270. case map[interface{}]interface{}:
  271. for k, val := range v {
  272. m[ToString(k)] = ToBool(val)
  273. }
  274. return m, nil
  275. case map[string]interface{}:
  276. for k, val := range v {
  277. m[ToString(k)] = ToBool(val)
  278. }
  279. return m, nil
  280. case map[string]bool:
  281. return v, nil
  282. default:
  283. return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
  284. }
  285. return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i)
  286. }
  287. func ToStringMapE(i interface{}) (map[string]interface{}, error) {
  288. jww.DEBUG.Println("ToStringMapE called on type:", reflect.TypeOf(i))
  289. var m = map[string]interface{}{}
  290. switch v := i.(type) {
  291. case map[interface{}]interface{}:
  292. for k, val := range v {
  293. m[ToString(k)] = val
  294. }
  295. return m, nil
  296. case map[string]interface{}:
  297. return v, nil
  298. default:
  299. return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
  300. }
  301. return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i)
  302. }
  303. func ToSliceE(i interface{}) ([]interface{}, error) {
  304. jww.DEBUG.Println("ToSliceE called on type:", reflect.TypeOf(i))
  305. var s []interface{}
  306. switch v := i.(type) {
  307. case []interface{}:
  308. for _, u := range v {
  309. s = append(s, u)
  310. }
  311. return s, nil
  312. case []map[string]interface{}:
  313. for _, u := range v {
  314. s = append(s, u)
  315. }
  316. return s, nil
  317. default:
  318. return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i))
  319. }
  320. return s, fmt.Errorf("Unable to Cast %#v to []interface{}", i)
  321. }
  322. func ToStringSliceE(i interface{}) ([]string, error) {
  323. jww.DEBUG.Println("ToStringSliceE called on type:", reflect.TypeOf(i))
  324. var a []string
  325. switch v := i.(type) {
  326. case []interface{}:
  327. for _, u := range v {
  328. a = append(a, ToString(u))
  329. }
  330. return a, nil
  331. case []string:
  332. return v, nil
  333. case string:
  334. return strings.Fields(v), nil
  335. default:
  336. str, err := ToStringE(v)
  337. if err != nil {
  338. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  339. }
  340. return []string{str}, nil
  341. }
  342. return a, fmt.Errorf("Unable to Cast %#v to []string", i)
  343. }
  344. func ToIntSliceE(i interface{}) ([]int, error) {
  345. jww.DEBUG.Println("ToIntSliceE called on type:", reflect.TypeOf(i))
  346. if i == nil {
  347. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  348. }
  349. switch v := i.(type) {
  350. case []int:
  351. return v, nil
  352. }
  353. kind := reflect.TypeOf(i).Kind()
  354. switch kind {
  355. case reflect.Slice, reflect.Array:
  356. s := reflect.ValueOf(i)
  357. a := make([]int, s.Len())
  358. for j := 0; j < s.Len(); j++ {
  359. val, err := ToIntE(s.Index(j).Interface())
  360. if err != nil {
  361. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  362. }
  363. a[j] = val
  364. }
  365. return a, nil
  366. default:
  367. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  368. }
  369. return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i)
  370. }
  371. func StringToDate(s string) (time.Time, error) {
  372. return parseDateWith(s, []string{
  373. time.RFC3339,
  374. "2006-01-02T15:04:05", // iso8601 without timezone
  375. time.RFC1123Z,
  376. time.RFC1123,
  377. time.RFC822Z,
  378. time.RFC822,
  379. time.ANSIC,
  380. time.UnixDate,
  381. time.RubyDate,
  382. "2006-01-02 15:04:05Z07:00",
  383. "02 Jan 06 15:04 MST",
  384. "2006-01-02",
  385. "02 Jan 2006",
  386. })
  387. }
  388. func parseDateWith(s string, dates []string) (d time.Time, e error) {
  389. for _, dateType := range dates {
  390. if d, e = time.Parse(dateType, s); e == nil {
  391. return
  392. }
  393. }
  394. return d, errors.New(fmt.Sprintf("Unable to parse date: %s", s))
  395. }