reflect: add limited support for all type kinds

This commit makes sure all Go types can be encoded in the interface type
code, so that Type.Kind() always returns a proper type kind for any
non-nil interface.
This commit is contained in:
Ayke van Laethem
2019-01-20 17:30:27 +01:00
parent 101f2e519b
commit dfef168139
6 changed files with 377 additions and 66 deletions
+80 -1
View File
@@ -5,16 +5,29 @@ import (
"unsafe"
)
type myint int
type (
myint int
myslice []byte
myslice2 []myint
)
func main() {
println("matching types")
println(reflect.TypeOf(int(3)) == reflect.TypeOf(int(5)))
println(reflect.TypeOf(int(3)) == reflect.TypeOf(uint(5)))
println(reflect.TypeOf(myint(3)) == reflect.TypeOf(int(5)))
println(reflect.TypeOf(myslice{}) == reflect.TypeOf([]byte{}))
println(reflect.TypeOf(myslice2{}) == reflect.TypeOf([]myint{}))
println(reflect.TypeOf(myslice2{}) == reflect.TypeOf([]int{}))
println("\nvalues of interfaces")
var zeroSlice []byte
var zeroFunc func()
var zeroMap map[string]int
var zeroChan chan int
n := 42
for _, v := range []interface{}{
// basic types
true,
false,
int(2000),
@@ -37,15 +50,57 @@ func main() {
float64(3.14),
complex64(1.2 + 0.3i),
complex128(1.3 + 0.4i),
myint(32),
"foo",
unsafe.Pointer(new(int)),
// channels
zeroChan,
// pointers
new(int),
new(error),
&n,
// slices
[]byte{1, 2, 3},
make([]uint8, 2, 5),
[]rune{3, 5},
[]string{"xyz", "Z"},
zeroSlice,
[]byte{},
// array
[4]int{1, 2, 3, 4},
// functions
zeroFunc,
emptyFunc,
// maps
zeroMap,
map[string]int{},
// structs
struct{}{},
struct{ error }{},
} {
showValue(v, "")
}
// test sizes
println("\nsizes:")
println("int8", int(reflect.TypeOf(int8(0)).Size()))
println("int16", int(reflect.TypeOf(int16(0)).Size()))
println("int32", int(reflect.TypeOf(int32(0)).Size()))
println("int64", int(reflect.TypeOf(int64(0)).Size()))
println("uint8", int(reflect.TypeOf(uint8(0)).Size()))
println("uint16", int(reflect.TypeOf(uint16(0)).Size()))
println("uint32", int(reflect.TypeOf(uint32(0)).Size()))
println("uint64", int(reflect.TypeOf(uint64(0)).Size()))
println("float32", int(reflect.TypeOf(float32(0)).Size()))
println("float64", int(reflect.TypeOf(float64(0)).Size()))
println("complex64", int(reflect.TypeOf(complex64(0)).Size()))
println("complex128", int(reflect.TypeOf(complex128(0)).Size()))
assertSize(reflect.TypeOf(uintptr(0)).Size() == unsafe.Sizeof(uintptr(0)), "uintptr")
assertSize(reflect.TypeOf("").Size() == unsafe.Sizeof(""), "string")
assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int")
}
func emptyFunc() {
}
func showValue(v interface{}, indent string) {
@@ -79,13 +134,37 @@ func showValue(v interface{}, indent string) {
}
case reflect.UnsafePointer:
println(indent+" pointer:", rv.Pointer() != 0)
case reflect.Array:
println(indent + " array")
case reflect.Chan:
println(indent+" chan:", rt.Elem().Kind().String())
println(indent+" nil:", rv.IsNil())
case reflect.Func:
println(indent + " func")
println(indent+" nil:", rv.IsNil())
case reflect.Map:
println(indent + " map")
println(indent+" nil:", rv.IsNil())
case reflect.Ptr:
println(indent+" pointer:", rv.Pointer() != 0, rt.Elem().Kind().String())
println(indent+" nil:", rv.IsNil())
case reflect.Slice:
println(indent+" slice:", rt.Elem().Kind().String(), rv.Len(), rv.Cap())
println(indent+" pointer:", rv.Pointer() != 0)
println(indent+" nil:", rv.IsNil())
for i := 0; i < rv.Len(); i++ {
println(indent+" indexing:", i)
showValue(rv.Index(i).Interface(), indent+" ")
}
case reflect.Struct:
println(indent + " struct")
default:
println(indent + " unknown type kind!")
}
}
func assertSize(ok bool, typ string) {
if !ok {
panic("size mismatch for type " + typ)
}
}
+65
View File
@@ -2,6 +2,9 @@ matching types
true
false
false
false
false
false
values of interfaces
reflect type: bool
@@ -48,6 +51,8 @@ reflect type: complex64
complex: (+1.200000e+000+3.000000e-001i)
reflect type: complex128
complex: (+1.300000e+000+4.000000e-001i)
reflect type: int
int: 32
reflect type: string
string: foo 3
reflect type: uint8
@@ -58,8 +63,22 @@ reflect type: string
uint: 111
reflect type: unsafe.Pointer
pointer: true
reflect type: chan
chan: int
nil: true
reflect type: ptr
pointer: true int
nil: false
reflect type: ptr
pointer: true interface
nil: false
reflect type: ptr
pointer: true int
nil: false
reflect type: slice
slice: uint8 3 3
pointer: true
nil: false
indexing: 0
reflect type: uint8
uint: 1
@@ -71,6 +90,8 @@ reflect type: slice
uint: 3
reflect type: slice
slice: uint8 2 5
pointer: true
nil: false
indexing: 0
reflect type: uint8
uint: 0
@@ -79,6 +100,8 @@ reflect type: slice
uint: 0
reflect type: slice
slice: int32 2 2
pointer: true
nil: false
indexing: 0
reflect type: int32
int: 3
@@ -87,6 +110,8 @@ reflect type: slice
int: 5
reflect type: slice
slice: string 2 2
pointer: true
nil: false
indexing: 0
reflect type: string
string: xyz 3
@@ -101,3 +126,43 @@ reflect type: slice
string: Z 1
reflect type: uint8
uint: 90
reflect type: slice
slice: uint8 0 0
pointer: false
nil: true
reflect type: slice
slice: uint8 0 0
pointer: true
nil: false
reflect type: array
array
reflect type: func
func
nil: true
reflect type: func
func
nil: false
reflect type: map
map
nil: true
reflect type: map
map
nil: false
reflect type: struct
struct
reflect type: struct
struct
sizes:
int8 1
int16 2
int32 4
int64 8
uint8 1
uint16 2
uint32 4
uint64 8
float32 4
float64 8
complex64 8
complex128 16