forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 0
/
integer.go
96 lines (72 loc) · 1.98 KB
/
integer.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
84
85
86
87
88
89
90
91
92
93
94
95
96
// All material is licensed under the Apache License Version 2.0, January 2016
// http://www.apache.org/licenses/LICENSE-2.0
// Example shows how to use reflection to decode an integer.
package main
import (
"fmt"
"reflect"
"strconv"
)
func main() {
// Decode the string into the integer variable.
var number int
decodeInt("10", &number)
fmt.Println("number:", number)
// Decode the integer into the integer variable.
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(v interface{}, number *int) error {
// Inspect the concrete type value that is passed in.
rv := reflect.ValueOf(v)
// Retrieve the value that the integer pointer points to.
val := reflect.ValueOf(number).Elem()
// Based on the kind of data to decode, perform the specific logic.
switch getKind(rv) {
case reflect.Int:
val.SetInt(rv.Int())
return nil
case reflect.Uint:
val.SetInt(int64(rv.Uint()))
return nil
case reflect.Float32:
val.SetInt(int64(rv.Float()))
return nil
case reflect.Bool:
if rv.Bool() {
val.SetInt(1)
return nil
}
val.SetInt(0)
return nil
case reflect.String:
i, err := strconv.ParseInt(rv.String(), 0, val.Type().Bits())
if err != nil {
return fmt.Errorf("cannot parse as int: %s", err)
}
val.SetInt(i)
return nil
default:
return fmt.Errorf("expected type '%s', got unconvertible type '%s'", val.Type(), rv.Type())
}
}
// getKind provides support for identifying predeclared numeric
// types with implementation-specific sizes.
func getKind(val reflect.Value) reflect.Kind {
// Capture the value's Kind.
kind := val.Kind()
// Check each condition until a case is true.
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
}
}