forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 0
/
example3.go
83 lines (71 loc) · 2.06 KB
/
example3.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
// https://play.golang.org/p/bWQ6hiVECQ
// https://github.com/goinggo/mapstructure
// Sample code provided by Mitchell Hashimoto
// Sample program to show how to use reflection to decode an integer.
package main
import (
"fmt"
"reflect"
"strconv"
)
// main is the entry point for the application.
func main() {
var number int
decodeInt("10", &number)
fmt.Println("number:", number)
var age int
decodeInt(45, &age)
fmt.Println("age:", age)
}
// decodeInt accepts a value of any type and will decode
// that value to an integer.
func decodeInt(data interface{}, number *int) error {
// Retrieve the value that the interface contains or points to.
val := reflect.ValueOf(number).Elem()
// Retrieve meta-data for the value to decode.
dataVal := reflect.ValueOf(data)
dataKind := getKind(dataVal)
// Based on the kind of data to decode, perform the
// specific logic.
switch {
case dataKind == reflect.Int:
val.SetInt(dataVal.Int())
case dataKind == reflect.Uint:
val.SetInt(int64(dataVal.Uint()))
case dataKind == reflect.Float32:
val.SetInt(int64(dataVal.Float()))
case dataKind == reflect.Bool:
if dataVal.Bool() {
val.SetInt(1)
} else {
val.SetInt(0)
}
case dataKind == reflect.String:
i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits())
if err == nil {
val.SetInt(i)
} else {
return fmt.Errorf("cannot parse as int: %s", err)
}
default:
return fmt.Errorf("expected type '%s', got unconvertible type '%s'", val.Type(), dataVal.Type())
}
return nil
}
// getKind provides support for identifying predeclared numeric
// types with implementation-specific sizes.
func getKind(val reflect.Value) reflect.Kind {
kind := val.Kind()
switch {
case kind >= reflect.Int && kind <= reflect.Int64:
return reflect.Int
case kind >= reflect.Uint && kind <= reflect.Uint64:
return reflect.Uint
case kind >= reflect.Float32 && kind <= reflect.Float64:
return reflect.Float32
default:
return kind
}
}