reflect: implement Value.Set*() for basic types
Этот коммит содержится в:
родитель
e6720d7ddc
коммит
003211b4ff
4 изменённых файлов: 409 добавлений и 93 удалений
|
@ -199,8 +199,7 @@ func (t Type) Size() uintptr {
|
||||||
case Slice:
|
case Slice:
|
||||||
return unsafe.Sizeof(SliceHeader{})
|
return unsafe.Sizeof(SliceHeader{})
|
||||||
default:
|
default:
|
||||||
// Size unknown.
|
panic("unimplemented: size of type")
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,22 +4,42 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the same thing as an interface{}.
|
|
||||||
type Value struct {
|
type Value struct {
|
||||||
typecode Type
|
typecode Type
|
||||||
value unsafe.Pointer
|
value unsafe.Pointer
|
||||||
|
indirect bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Indirect(v Value) Value {
|
func Indirect(v Value) Value {
|
||||||
return v
|
if v.Kind() != Ptr {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return v.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValueOf(i interface{}) Value {
|
func ValueOf(i interface{}) Value {
|
||||||
return *(*Value)(unsafe.Pointer(&i))
|
v := (*interfaceHeader)(unsafe.Pointer(&i))
|
||||||
|
return Value{
|
||||||
|
typecode: v.typecode,
|
||||||
|
value: v.value,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Interface() interface{} {
|
func (v Value) Interface() interface{} {
|
||||||
return *(*interface{})(unsafe.Pointer(&v))
|
i := interfaceHeader{
|
||||||
|
typecode: v.typecode,
|
||||||
|
value: v.value,
|
||||||
|
}
|
||||||
|
if v.indirect && v.Type().Size() <= unsafe.Sizeof(uintptr(0)) {
|
||||||
|
// Value was indirect but must be put back directly in the interface
|
||||||
|
// value.
|
||||||
|
var value uintptr
|
||||||
|
for j := v.Type().Size(); j != 0; j-- {
|
||||||
|
value = (value << 8) | uintptr(*(*uint8)(unsafe.Pointer(uintptr(v.value) + j - 1)))
|
||||||
|
}
|
||||||
|
i.value = unsafe.Pointer(value)
|
||||||
|
}
|
||||||
|
return *(*interface{})(unsafe.Pointer(&i))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Type() Type {
|
func (v Value) Type() Type {
|
||||||
|
@ -47,7 +67,11 @@ func (v Value) IsNil() bool {
|
||||||
slice := (*SliceHeader)(v.value)
|
slice := (*SliceHeader)(v.value)
|
||||||
return slice.Data == 0
|
return slice.Data == 0
|
||||||
case Interface:
|
case Interface:
|
||||||
panic("unimplemented: (reflect.Value).IsNil()")
|
if v.value == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
itf := (*interfaceHeader)(v.value)
|
||||||
|
return itf.value == nil
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"IsNil"})
|
panic(&ValueError{"IsNil"})
|
||||||
}
|
}
|
||||||
|
@ -85,13 +109,17 @@ func (v Value) Addr() Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) CanSet() bool {
|
func (v Value) CanSet() bool {
|
||||||
panic("unimplemented: (reflect.Value).CanSet()")
|
return v.indirect
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Bool() bool {
|
func (v Value) Bool() bool {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Bool:
|
case Bool:
|
||||||
return uintptr(v.value) != 0
|
if v.indirect {
|
||||||
|
return *((*bool)(v.value))
|
||||||
|
} else {
|
||||||
|
return uintptr(v.value) != 0
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Bool"})
|
panic(&ValueError{"Bool"})
|
||||||
}
|
}
|
||||||
|
@ -100,27 +128,34 @@ func (v Value) Bool() bool {
|
||||||
func (v Value) Int() int64 {
|
func (v Value) Int() int64 {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Int:
|
case Int:
|
||||||
if unsafe.Sizeof(int(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(int(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
return int64(int(uintptr(v.value)))
|
|
||||||
} else {
|
|
||||||
return int64(*(*int)(v.value))
|
return int64(*(*int)(v.value))
|
||||||
|
} else {
|
||||||
|
return int64(int(uintptr(v.value)))
|
||||||
}
|
}
|
||||||
case Int8:
|
case Int8:
|
||||||
return int64(int8(uintptr(v.value)))
|
if v.indirect {
|
||||||
case Int16:
|
return int64(*(*int8)(v.value))
|
||||||
return int64(int16(uintptr(v.value)))
|
|
||||||
case Int32:
|
|
||||||
if unsafe.Sizeof(int32(0)) <= unsafe.Sizeof(uintptr(0)) {
|
|
||||||
return int64(int32(uintptr(v.value)))
|
|
||||||
} else {
|
} else {
|
||||||
return int64(*(*int32)(v.value))
|
return int64(int8(uintptr(v.value)))
|
||||||
}
|
}
|
||||||
return int64(uintptr(v.value))
|
case Int16:
|
||||||
case Int64:
|
if v.indirect {
|
||||||
if unsafe.Sizeof(int64(0)) <= unsafe.Sizeof(uintptr(0)) {
|
return int64(*(*int16)(v.value))
|
||||||
return int64(uintptr(v.value))
|
|
||||||
} else {
|
} else {
|
||||||
return *(*int64)(v.value)
|
return int64(int16(uintptr(v.value)))
|
||||||
|
}
|
||||||
|
case Int32:
|
||||||
|
if v.indirect || unsafe.Sizeof(int32(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
|
return int64(*(*int32)(v.value))
|
||||||
|
} else {
|
||||||
|
return int64(int32(uintptr(v.value)))
|
||||||
|
}
|
||||||
|
case Int64:
|
||||||
|
if v.indirect || unsafe.Sizeof(int64(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
|
return int64(*(*int64)(v.value))
|
||||||
|
} else {
|
||||||
|
return int64(int64(uintptr(v.value)))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Int"})
|
panic(&ValueError{"Int"})
|
||||||
|
@ -129,28 +164,41 @@ func (v Value) Int() int64 {
|
||||||
|
|
||||||
func (v Value) Uint() uint64 {
|
func (v Value) Uint() uint64 {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Uintptr, Uint8, Uint16:
|
case Uintptr:
|
||||||
return uint64(uintptr(v.value))
|
if v.indirect {
|
||||||
case Uint:
|
return uint64(*(*uintptr)(v.value))
|
||||||
if unsafe.Sizeof(uint(0)) <= unsafe.Sizeof(uintptr(0)) {
|
|
||||||
return uint64(uintptr(v.value))
|
|
||||||
} else {
|
} else {
|
||||||
// For systems with 16-bit pointers.
|
return uint64(uintptr(v.value))
|
||||||
|
}
|
||||||
|
case Uint8:
|
||||||
|
if v.indirect {
|
||||||
|
return uint64(*(*uint8)(v.value))
|
||||||
|
} else {
|
||||||
|
return uint64(uintptr(v.value))
|
||||||
|
}
|
||||||
|
case Uint16:
|
||||||
|
if v.indirect {
|
||||||
|
return uint64(*(*uint16)(v.value))
|
||||||
|
} else {
|
||||||
|
return uint64(uintptr(v.value))
|
||||||
|
}
|
||||||
|
case Uint:
|
||||||
|
if v.indirect || unsafe.Sizeof(uint(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
return uint64(*(*uint)(v.value))
|
return uint64(*(*uint)(v.value))
|
||||||
|
} else {
|
||||||
|
return uint64(uintptr(v.value))
|
||||||
}
|
}
|
||||||
case Uint32:
|
case Uint32:
|
||||||
if unsafe.Sizeof(uint32(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(uint32(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
return uint64(uintptr(v.value))
|
|
||||||
} else {
|
|
||||||
// For systems with 16-bit pointers.
|
|
||||||
return uint64(*(*uint32)(v.value))
|
return uint64(*(*uint32)(v.value))
|
||||||
|
} else {
|
||||||
|
return uint64(uintptr(v.value))
|
||||||
}
|
}
|
||||||
case Uint64:
|
case Uint64:
|
||||||
if unsafe.Sizeof(uint64(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(uint64(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
return uint64(uintptr(v.value))
|
return uint64(*(*uint64)(v.value))
|
||||||
} else {
|
} else {
|
||||||
// For systems with 16-bit or 32-bit pointers.
|
return uint64(uintptr(v.value))
|
||||||
return *(*uint64)(v.value)
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Uint"})
|
panic(&ValueError{"Uint"})
|
||||||
|
@ -160,23 +208,23 @@ func (v Value) Uint() uint64 {
|
||||||
func (v Value) Float() float64 {
|
func (v Value) Float() float64 {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Float32:
|
case Float32:
|
||||||
if unsafe.Sizeof(float32(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(float32(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
// The float is directly stored in the interface value on systems
|
|
||||||
// with 32-bit and 64-bit pointers.
|
|
||||||
return float64(*(*float32)(unsafe.Pointer(&v.value)))
|
|
||||||
} else {
|
|
||||||
// The float is stored as an external value on systems with 16-bit
|
// The float is stored as an external value on systems with 16-bit
|
||||||
// pointers.
|
// pointers.
|
||||||
return float64(*(*float32)(v.value))
|
return float64(*(*float32)(v.value))
|
||||||
|
} else {
|
||||||
|
// The float is directly stored in the interface value on systems
|
||||||
|
// with 32-bit and 64-bit pointers.
|
||||||
|
return float64(*(*float32)(unsafe.Pointer(&v.value)))
|
||||||
}
|
}
|
||||||
case Float64:
|
case Float64:
|
||||||
if unsafe.Sizeof(float64(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(float64(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
|
// For systems with 16-bit and 32-bit pointers.
|
||||||
|
return *(*float64)(v.value)
|
||||||
|
} else {
|
||||||
// The float is directly stored in the interface value on systems
|
// The float is directly stored in the interface value on systems
|
||||||
// with 64-bit pointers.
|
// with 64-bit pointers.
|
||||||
return *(*float64)(unsafe.Pointer(&v.value))
|
return *(*float64)(unsafe.Pointer(&v.value))
|
||||||
} else {
|
|
||||||
// For systems with 16-bit and 32-bit pointers.
|
|
||||||
return *(*float64)(v.value)
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"Float"})
|
panic(&ValueError{"Float"})
|
||||||
|
@ -186,14 +234,14 @@ func (v Value) Float() float64 {
|
||||||
func (v Value) Complex() complex128 {
|
func (v Value) Complex() complex128 {
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case Complex64:
|
case Complex64:
|
||||||
if unsafe.Sizeof(complex64(0)) <= unsafe.Sizeof(uintptr(0)) {
|
if v.indirect || unsafe.Sizeof(complex64(0)) > unsafe.Sizeof(uintptr(0)) {
|
||||||
// The complex number is directly stored in the interface value on
|
|
||||||
// systems with 64-bit pointers.
|
|
||||||
return complex128(*(*complex64)(unsafe.Pointer(&v.value)))
|
|
||||||
} else {
|
|
||||||
// The complex number is stored as an external value on systems with
|
// The complex number is stored as an external value on systems with
|
||||||
// 16-bit and 32-bit pointers.
|
// 16-bit and 32-bit pointers.
|
||||||
return complex128(*(*complex64)(v.value))
|
return complex128(*(*complex64)(v.value))
|
||||||
|
} else {
|
||||||
|
// The complex number is directly stored in the interface value on
|
||||||
|
// systems with 64-bit pointers.
|
||||||
|
return complex128(*(*complex64)(unsafe.Pointer(&v.value)))
|
||||||
}
|
}
|
||||||
case Complex128:
|
case Complex128:
|
||||||
// This is a 128-bit value, which is always stored as an external value.
|
// This is a 128-bit value, which is always stored as an external value.
|
||||||
|
@ -252,7 +300,23 @@ func (v Value) NumField() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Elem() Value {
|
func (v Value) Elem() Value {
|
||||||
panic("unimplemented: (reflect.Value).Elem()")
|
switch v.Kind() {
|
||||||
|
case Ptr:
|
||||||
|
ptr := v.value
|
||||||
|
if v.indirect {
|
||||||
|
ptr = *(*unsafe.Pointer)(ptr)
|
||||||
|
}
|
||||||
|
if ptr == nil {
|
||||||
|
return Value{}
|
||||||
|
}
|
||||||
|
return Value{
|
||||||
|
typecode: v.Type().Elem(),
|
||||||
|
value: ptr,
|
||||||
|
indirect: true,
|
||||||
|
}
|
||||||
|
default: // not implemented: Interface
|
||||||
|
panic(&ValueError{"Elem"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Field(i int) Value {
|
func (v Value) Field(i int) Value {
|
||||||
|
@ -269,21 +333,10 @@ func (v Value) Index(i int) Value {
|
||||||
}
|
}
|
||||||
elem := Value{
|
elem := Value{
|
||||||
typecode: v.Type().Elem(),
|
typecode: v.Type().Elem(),
|
||||||
|
indirect: true,
|
||||||
}
|
}
|
||||||
addr := uintptr(slice.Data) + elem.Type().Size() * uintptr(i) // pointer to new value
|
addr := uintptr(slice.Data) + elem.Type().Size() * uintptr(i) // pointer to new value
|
||||||
if elem.Type().Size() <= unsafe.Sizeof(uintptr(0)) {
|
elem.value = unsafe.Pointer(addr)
|
||||||
// Value fits inside interface value.
|
|
||||||
// Make sure to copy it from the slice to the interface value.
|
|
||||||
var value uintptr
|
|
||||||
for j := elem.Type().Size(); j != 0; j-- {
|
|
||||||
value = (value << 8) | uintptr(*(*uint8)(unsafe.Pointer(addr + j - 1)))
|
|
||||||
}
|
|
||||||
elem.value = unsafe.Pointer(value)
|
|
||||||
} else {
|
|
||||||
// Value doesn't fit in the interface.
|
|
||||||
// Store a pointer to the element in the interface.
|
|
||||||
elem.value = unsafe.Pointer(addr)
|
|
||||||
}
|
|
||||||
return elem
|
return elem
|
||||||
case String:
|
case String:
|
||||||
// Extract a character from a string.
|
// Extract a character from a string.
|
||||||
|
@ -313,31 +366,117 @@ func (v Value) MapIndex(key Value) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) Set(x Value) {
|
func (v Value) Set(x Value) {
|
||||||
panic("unimplemented: (reflect.Value).Set()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
if v.Type() != x.Type() {
|
||||||
|
if v.Kind() == Interface {
|
||||||
|
panic("reflect: unimplemented: assigning to interface of different type")
|
||||||
|
} else {
|
||||||
|
panic("reflect: cannot assign")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size := v.Type().Size()
|
||||||
|
xptr := x.value
|
||||||
|
if size <= unsafe.Sizeof(uintptr(0)) && !x.indirect {
|
||||||
|
value := x.value
|
||||||
|
xptr = unsafe.Pointer(&value)
|
||||||
|
}
|
||||||
|
memcpy(v.value, xptr, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetBool(x bool) {
|
func (v Value) SetBool(x bool) {
|
||||||
panic("unimplemented: (reflect.Value).SetBool()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Bool:
|
||||||
|
*(*bool)(v.value) = x
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetBool"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetInt(x int64) {
|
func (v Value) SetInt(x int64) {
|
||||||
panic("unimplemented: (reflect.Value).SetInt()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Int:
|
||||||
|
*(*int)(v.value) = int(x)
|
||||||
|
case Int8:
|
||||||
|
*(*int8)(v.value) = int8(x)
|
||||||
|
case Int16:
|
||||||
|
*(*int16)(v.value) = int16(x)
|
||||||
|
case Int32:
|
||||||
|
*(*int32)(v.value) = int32(x)
|
||||||
|
case Int64:
|
||||||
|
*(*int64)(v.value) = x
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetInt"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetUint(x uint64) {
|
func (v Value) SetUint(x uint64) {
|
||||||
panic("unimplemented: (reflect.Value).SetUint()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Uint:
|
||||||
|
*(*uint)(v.value) = uint(x)
|
||||||
|
case Uint8:
|
||||||
|
*(*uint8)(v.value) = uint8(x)
|
||||||
|
case Uint16:
|
||||||
|
*(*uint16)(v.value) = uint16(x)
|
||||||
|
case Uint32:
|
||||||
|
*(*uint32)(v.value) = uint32(x)
|
||||||
|
case Uint64:
|
||||||
|
*(*uint64)(v.value) = x
|
||||||
|
case Uintptr:
|
||||||
|
*(*uintptr)(v.value) = uintptr(x)
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetUint"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetFloat(x float64) {
|
func (v Value) SetFloat(x float64) {
|
||||||
panic("unimplemented: (reflect.Value).SetFloat()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Float32:
|
||||||
|
*(*float32)(v.value) = float32(x)
|
||||||
|
case Float64:
|
||||||
|
*(*float64)(v.value) = x
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetFloat"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetComplex(x complex128) {
|
func (v Value) SetComplex(x complex128) {
|
||||||
panic("unimplemented: (reflect.Value).SetComplex()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case Complex64:
|
||||||
|
*(*complex64)(v.value) = complex64(x)
|
||||||
|
case Complex128:
|
||||||
|
*(*complex128)(v.value) = x
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetComplex"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) SetString(x string) {
|
func (v Value) SetString(x string) {
|
||||||
panic("unimplemented: (reflect.Value).SetString()")
|
if !v.indirect {
|
||||||
|
panic("reflect: value is not addressable")
|
||||||
|
}
|
||||||
|
switch v.Kind() {
|
||||||
|
case String:
|
||||||
|
*(*string)(v.value) = x
|
||||||
|
default:
|
||||||
|
panic(&ValueError{"SetString"})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeSlice(typ Type, len, cap int) Value {
|
func MakeSlice(typ Type, len, cap int) Value {
|
||||||
|
@ -349,6 +488,12 @@ type funcHeader struct {
|
||||||
Code unsafe.Pointer
|
Code unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the same thing as an interface{}.
|
||||||
|
type interfaceHeader struct {
|
||||||
|
typecode Type
|
||||||
|
value unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
type SliceHeader struct {
|
type SliceHeader struct {
|
||||||
Data uintptr
|
Data uintptr
|
||||||
Len uintptr
|
Len uintptr
|
||||||
|
@ -367,3 +512,6 @@ type ValueError struct {
|
||||||
func (e *ValueError) Error() string {
|
func (e *ValueError) Error() string {
|
||||||
return "reflect: call of reflect.Value." + e.Method + " on invalid type"
|
return "reflect: call of reflect.Value." + e.Method + " on invalid type"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname memcpy runtime.memcpy
|
||||||
|
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
144
testdata/reflect.go
предоставленный
144
testdata/reflect.go
предоставленный
|
@ -66,6 +66,10 @@ func main() {
|
||||||
[]string{"xyz", "Z"},
|
[]string{"xyz", "Z"},
|
||||||
zeroSlice,
|
zeroSlice,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
[]float32{1, 1.32},
|
||||||
|
[]float64{1, 1.64},
|
||||||
|
[]complex64{1, 1.64 + 0.3i},
|
||||||
|
[]complex128{1, 1.128 + 0.4i},
|
||||||
// array
|
// array
|
||||||
[4]int{1, 2, 3, 4},
|
[4]int{1, 2, 3, 4},
|
||||||
// functions
|
// functions
|
||||||
|
@ -78,7 +82,7 @@ func main() {
|
||||||
struct{}{},
|
struct{}{},
|
||||||
struct{ error }{},
|
struct{ error }{},
|
||||||
} {
|
} {
|
||||||
showValue(v, "")
|
showValue(reflect.ValueOf(v), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// test sizes
|
// test sizes
|
||||||
|
@ -98,24 +102,136 @@ func main() {
|
||||||
assertSize(reflect.TypeOf(uintptr(0)).Size() == unsafe.Sizeof(uintptr(0)), "uintptr")
|
assertSize(reflect.TypeOf(uintptr(0)).Size() == unsafe.Sizeof(uintptr(0)), "uintptr")
|
||||||
assertSize(reflect.TypeOf("").Size() == unsafe.Sizeof(""), "string")
|
assertSize(reflect.TypeOf("").Size() == unsafe.Sizeof(""), "string")
|
||||||
assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int")
|
assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int")
|
||||||
|
|
||||||
|
// SetBool
|
||||||
|
rv := reflect.ValueOf(new(bool)).Elem()
|
||||||
|
rv.SetBool(true)
|
||||||
|
if rv.Bool() != true {
|
||||||
|
panic("could not set bool with SetBool()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInt
|
||||||
|
for _, v := range []interface{}{
|
||||||
|
new(int),
|
||||||
|
new(int8),
|
||||||
|
new(int16),
|
||||||
|
new(int32),
|
||||||
|
new(int64),
|
||||||
|
} {
|
||||||
|
rv := reflect.ValueOf(v).Elem()
|
||||||
|
rv.SetInt(99)
|
||||||
|
if rv.Int() != 99 {
|
||||||
|
panic("could not set integer with SetInt()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUint
|
||||||
|
for _, v := range []interface{}{
|
||||||
|
new(uint),
|
||||||
|
new(uint8),
|
||||||
|
new(uint16),
|
||||||
|
new(uint32),
|
||||||
|
new(uint64),
|
||||||
|
new(uintptr),
|
||||||
|
} {
|
||||||
|
rv := reflect.ValueOf(v).Elem()
|
||||||
|
rv.SetUint(99)
|
||||||
|
if rv.Uint() != 99 {
|
||||||
|
panic("could not set integer with SetUint()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFloat
|
||||||
|
for _, v := range []interface{}{
|
||||||
|
new(float32),
|
||||||
|
new(float64),
|
||||||
|
} {
|
||||||
|
rv := reflect.ValueOf(v).Elem()
|
||||||
|
rv.SetFloat(2.25)
|
||||||
|
if rv.Float() != 2.25 {
|
||||||
|
panic("could not set float with SetFloat()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetComplex
|
||||||
|
for _, v := range []interface{}{
|
||||||
|
new(complex64),
|
||||||
|
new(complex128),
|
||||||
|
} {
|
||||||
|
rv := reflect.ValueOf(v).Elem()
|
||||||
|
rv.SetComplex(3 + 2i)
|
||||||
|
if rv.Complex() != 3+2i {
|
||||||
|
panic("could not set complex with SetComplex()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetString
|
||||||
|
rv = reflect.ValueOf(new(string)).Elem()
|
||||||
|
rv.SetString("foo")
|
||||||
|
if rv.String() != "foo" {
|
||||||
|
panic("could not set string with SetString()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set int
|
||||||
|
rv = reflect.ValueOf(new(int)).Elem()
|
||||||
|
rv.SetInt(33)
|
||||||
|
rv.Set(reflect.ValueOf(22))
|
||||||
|
if rv.Int() != 22 {
|
||||||
|
panic("could not set int with Set()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set uint8
|
||||||
|
rv = reflect.ValueOf(new(uint8)).Elem()
|
||||||
|
rv.SetUint(33)
|
||||||
|
rv.Set(reflect.ValueOf(uint8(22)))
|
||||||
|
if rv.Uint() != 22 {
|
||||||
|
panic("could not set uint8 with Set()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set string
|
||||||
|
rv = reflect.ValueOf(new(string)).Elem()
|
||||||
|
rv.SetString("foo")
|
||||||
|
rv.Set(reflect.ValueOf("bar"))
|
||||||
|
if rv.String() != "bar" {
|
||||||
|
panic("could not set string with Set()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set complex128
|
||||||
|
rv = reflect.ValueOf(new(complex128)).Elem()
|
||||||
|
rv.SetComplex(3 + 2i)
|
||||||
|
rv.Set(reflect.ValueOf(4 + 8i))
|
||||||
|
if rv.Complex() != 4+8i {
|
||||||
|
panic("could not set complex128 with Set()")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to slice
|
||||||
|
rv = reflect.ValueOf([]int{3, 5})
|
||||||
|
rv.Index(1).SetInt(7)
|
||||||
|
if rv.Index(1).Int() != 7 {
|
||||||
|
panic("could not set int in slice")
|
||||||
|
}
|
||||||
|
rv.Index(1).Set(reflect.ValueOf(8))
|
||||||
|
if rv.Index(1).Int() != 8 {
|
||||||
|
panic("could not set int in slice")
|
||||||
|
}
|
||||||
|
if rv.Len() != 2 || rv.Index(0).Int() != 3 {
|
||||||
|
panic("slice was changed while setting part of it")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func emptyFunc() {
|
func emptyFunc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showValue(v interface{}, indent string) {
|
func showValue(rv reflect.Value, indent string) {
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
rt := rv.Type()
|
rt := rv.Type()
|
||||||
if reflect.TypeOf(v) != rt {
|
|
||||||
panic("direct TypeOf() is different from ValueOf().Type()")
|
|
||||||
}
|
|
||||||
if rt.Kind() != rv.Kind() {
|
if rt.Kind() != rv.Kind() {
|
||||||
panic("type kind is different from value kind")
|
panic("type kind is different from value kind")
|
||||||
}
|
}
|
||||||
if reflect.ValueOf(rv.Interface()) != rv {
|
print(indent+"reflect type: ", rt.Kind().String())
|
||||||
panic("reflect.ValueOf(Value.Interface()) did not return the same value")
|
if rv.CanSet() {
|
||||||
|
print(" settable=", rv.CanSet())
|
||||||
}
|
}
|
||||||
println(indent+"reflect type:", rt.Kind().String())
|
println()
|
||||||
switch rt.Kind() {
|
switch rt.Kind() {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
println(indent+" bool:", rv.Bool())
|
println(indent+" bool:", rv.Bool())
|
||||||
|
@ -130,7 +246,7 @@ func showValue(v interface{}, indent string) {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
println(indent+" string:", rv.String(), rv.Len())
|
println(indent+" string:", rv.String(), rv.Len())
|
||||||
for i := 0; i < rv.Len(); i++ {
|
for i := 0; i < rv.Len(); i++ {
|
||||||
showValue(rv.Index(i).Interface(), indent+" ")
|
showValue(rv.Index(i), indent+" ")
|
||||||
}
|
}
|
||||||
case reflect.UnsafePointer:
|
case reflect.UnsafePointer:
|
||||||
println(indent+" pointer:", rv.Pointer() != 0)
|
println(indent+" pointer:", rv.Pointer() != 0)
|
||||||
|
@ -142,19 +258,25 @@ func showValue(v interface{}, indent string) {
|
||||||
case reflect.Func:
|
case reflect.Func:
|
||||||
println(indent + " func")
|
println(indent + " func")
|
||||||
println(indent+" nil:", rv.IsNil())
|
println(indent+" nil:", rv.IsNil())
|
||||||
|
case reflect.Interface:
|
||||||
|
println(indent + " interface")
|
||||||
|
println(indent+" nil:", rv.IsNil())
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
println(indent + " map")
|
println(indent + " map")
|
||||||
println(indent+" nil:", rv.IsNil())
|
println(indent+" nil:", rv.IsNil())
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
println(indent+" pointer:", rv.Pointer() != 0, rt.Elem().Kind().String())
|
println(indent+" pointer:", rv.Pointer() != 0, rt.Elem().Kind().String())
|
||||||
println(indent+" nil:", rv.IsNil())
|
println(indent+" nil:", rv.IsNil())
|
||||||
|
if !rv.IsNil() {
|
||||||
|
showValue(rv.Elem(), indent+" ")
|
||||||
|
}
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
println(indent+" slice:", rt.Elem().Kind().String(), rv.Len(), rv.Cap())
|
println(indent+" slice:", rt.Elem().Kind().String(), rv.Len(), rv.Cap())
|
||||||
println(indent+" pointer:", rv.Pointer() != 0)
|
println(indent+" pointer:", rv.Pointer() != 0)
|
||||||
println(indent+" nil:", rv.IsNil())
|
println(indent+" nil:", rv.IsNil())
|
||||||
for i := 0; i < rv.Len(); i++ {
|
for i := 0; i < rv.Len(); i++ {
|
||||||
println(indent+" indexing:", i)
|
println(indent+" indexing:", i)
|
||||||
showValue(rv.Index(i).Interface(), indent+" ")
|
showValue(rv.Index(i), indent+" ")
|
||||||
}
|
}
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
println(indent + " struct")
|
println(indent + " struct")
|
||||||
|
|
65
testdata/reflect.txt
предоставленный
65
testdata/reflect.txt
предоставленный
|
@ -69,51 +69,58 @@ reflect type: chan
|
||||||
reflect type: ptr
|
reflect type: ptr
|
||||||
pointer: true int
|
pointer: true int
|
||||||
nil: false
|
nil: false
|
||||||
|
reflect type: int settable=true
|
||||||
|
int: 0
|
||||||
reflect type: ptr
|
reflect type: ptr
|
||||||
pointer: true interface
|
pointer: true interface
|
||||||
nil: false
|
nil: false
|
||||||
|
reflect type: interface settable=true
|
||||||
|
interface
|
||||||
|
nil: true
|
||||||
reflect type: ptr
|
reflect type: ptr
|
||||||
pointer: true int
|
pointer: true int
|
||||||
nil: false
|
nil: false
|
||||||
|
reflect type: int settable=true
|
||||||
|
int: 42
|
||||||
reflect type: slice
|
reflect type: slice
|
||||||
slice: uint8 3 3
|
slice: uint8 3 3
|
||||||
pointer: true
|
pointer: true
|
||||||
nil: false
|
nil: false
|
||||||
indexing: 0
|
indexing: 0
|
||||||
reflect type: uint8
|
reflect type: uint8 settable=true
|
||||||
uint: 1
|
uint: 1
|
||||||
indexing: 1
|
indexing: 1
|
||||||
reflect type: uint8
|
reflect type: uint8 settable=true
|
||||||
uint: 2
|
uint: 2
|
||||||
indexing: 2
|
indexing: 2
|
||||||
reflect type: uint8
|
reflect type: uint8 settable=true
|
||||||
uint: 3
|
uint: 3
|
||||||
reflect type: slice
|
reflect type: slice
|
||||||
slice: uint8 2 5
|
slice: uint8 2 5
|
||||||
pointer: true
|
pointer: true
|
||||||
nil: false
|
nil: false
|
||||||
indexing: 0
|
indexing: 0
|
||||||
reflect type: uint8
|
reflect type: uint8 settable=true
|
||||||
uint: 0
|
uint: 0
|
||||||
indexing: 1
|
indexing: 1
|
||||||
reflect type: uint8
|
reflect type: uint8 settable=true
|
||||||
uint: 0
|
uint: 0
|
||||||
reflect type: slice
|
reflect type: slice
|
||||||
slice: int32 2 2
|
slice: int32 2 2
|
||||||
pointer: true
|
pointer: true
|
||||||
nil: false
|
nil: false
|
||||||
indexing: 0
|
indexing: 0
|
||||||
reflect type: int32
|
reflect type: int32 settable=true
|
||||||
int: 3
|
int: 3
|
||||||
indexing: 1
|
indexing: 1
|
||||||
reflect type: int32
|
reflect type: int32 settable=true
|
||||||
int: 5
|
int: 5
|
||||||
reflect type: slice
|
reflect type: slice
|
||||||
slice: string 2 2
|
slice: string 2 2
|
||||||
pointer: true
|
pointer: true
|
||||||
nil: false
|
nil: false
|
||||||
indexing: 0
|
indexing: 0
|
||||||
reflect type: string
|
reflect type: string settable=true
|
||||||
string: xyz 3
|
string: xyz 3
|
||||||
reflect type: uint8
|
reflect type: uint8
|
||||||
uint: 120
|
uint: 120
|
||||||
|
@ -122,7 +129,7 @@ reflect type: slice
|
||||||
reflect type: uint8
|
reflect type: uint8
|
||||||
uint: 122
|
uint: 122
|
||||||
indexing: 1
|
indexing: 1
|
||||||
reflect type: string
|
reflect type: string settable=true
|
||||||
string: Z 1
|
string: Z 1
|
||||||
reflect type: uint8
|
reflect type: uint8
|
||||||
uint: 90
|
uint: 90
|
||||||
|
@ -134,6 +141,46 @@ reflect type: slice
|
||||||
slice: uint8 0 0
|
slice: uint8 0 0
|
||||||
pointer: true
|
pointer: true
|
||||||
nil: false
|
nil: false
|
||||||
|
reflect type: slice
|
||||||
|
slice: float32 2 2
|
||||||
|
pointer: true
|
||||||
|
nil: false
|
||||||
|
indexing: 0
|
||||||
|
reflect type: float32 settable=true
|
||||||
|
float: +1.000000e+000
|
||||||
|
indexing: 1
|
||||||
|
reflect type: float32 settable=true
|
||||||
|
float: +1.320000e+000
|
||||||
|
reflect type: slice
|
||||||
|
slice: float64 2 2
|
||||||
|
pointer: true
|
||||||
|
nil: false
|
||||||
|
indexing: 0
|
||||||
|
reflect type: float64 settable=true
|
||||||
|
float: +1.000000e+000
|
||||||
|
indexing: 1
|
||||||
|
reflect type: float64 settable=true
|
||||||
|
float: +1.640000e+000
|
||||||
|
reflect type: slice
|
||||||
|
slice: complex64 2 2
|
||||||
|
pointer: true
|
||||||
|
nil: false
|
||||||
|
indexing: 0
|
||||||
|
reflect type: complex64 settable=true
|
||||||
|
complex: (+1.000000e+000+0.000000e+000i)
|
||||||
|
indexing: 1
|
||||||
|
reflect type: complex64 settable=true
|
||||||
|
complex: (+1.640000e+000+3.000000e-001i)
|
||||||
|
reflect type: slice
|
||||||
|
slice: complex128 2 2
|
||||||
|
pointer: true
|
||||||
|
nil: false
|
||||||
|
indexing: 0
|
||||||
|
reflect type: complex128 settable=true
|
||||||
|
complex: (+1.000000e+000+0.000000e+000i)
|
||||||
|
indexing: 1
|
||||||
|
reflect type: complex128 settable=true
|
||||||
|
complex: (+1.128000e+000+4.000000e-001i)
|
||||||
reflect type: array
|
reflect type: array
|
||||||
array
|
array
|
||||||
reflect type: func
|
reflect type: func
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче