reflect: add support for non-named basic types
Этот коммит содержится в:
		
							родитель
							
								
									222c4c75b1
								
							
						
					
					
						коммит
						fb23e9c212
					
				
					 7 изменённых файлов: 397 добавлений и 26 удалений
				
			
		|  | @ -104,15 +104,6 @@ func (t *typeInfo) getMethod(signature *signatureInfo) *methodInfo { | ||||||
| 	panic("could not find method") | 	panic("could not find method") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // id returns the fully-qualified type name including import path, removing the |  | ||||||
| // $type suffix. |  | ||||||
| func (t *typeInfo) id() string { |  | ||||||
| 	if !strings.HasSuffix(t.name, "$type") { |  | ||||||
| 		panic("concrete type does not have $type suffix: " + t.name) |  | ||||||
| 	} |  | ||||||
| 	return t.name[:len(t.name)-len("$type")] |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // typeInfoSlice implements sort.Slice, sorting the most commonly used types | // typeInfoSlice implements sort.Slice, sorting the most commonly used types | ||||||
| // first. | // first. | ||||||
| type typeInfoSlice []*typeInfo | type typeInfoSlice []*typeInfo | ||||||
|  | @ -423,9 +414,7 @@ func (p *lowerInterfacesPass) run() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Assign a type code for each type. | 	// Assign a type code for each type. | ||||||
| 	for i, t := range typeSlice { | 	p.assignTypeCodes(typeSlice) | ||||||
| 		t.num = uint64(i + 1) |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	// Replace each call to runtime.makeInterface with the constant type code. | 	// Replace each call to runtime.makeInterface with the constant type code. | ||||||
| 	for _, use := range makeInterfaceUses { | 	for _, use := range makeInterfaceUses { | ||||||
|  | @ -691,7 +680,7 @@ func (p *lowerInterfacesPass) createInterfaceMethodFunc(itf *interfaceInfo, sign | ||||||
| 
 | 
 | ||||||
| 	// Define all possible functions that can be called. | 	// Define all possible functions that can be called. | ||||||
| 	for _, typ := range itf.types { | 	for _, typ := range itf.types { | ||||||
| 		bb := llvm.AddBasicBlock(fn, typ.id()) | 		bb := llvm.AddBasicBlock(fn, typ.name) | ||||||
| 		sw.AddCase(llvm.ConstInt(p.uintptrType, typ.num, false), bb) | 		sw.AddCase(llvm.ConstInt(p.uintptrType, typ.num, false), bb) | ||||||
| 
 | 
 | ||||||
| 		// The function we will redirect to when the interface has this type. | 		// The function we will redirect to when the interface has this type. | ||||||
|  |  | ||||||
|  | @ -79,9 +79,58 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, global str | ||||||
| // It returns a pointer to an external global which should be replaced with the | // It returns a pointer to an external global which should be replaced with the | ||||||
| // real type in the interface lowering pass. | // real type in the interface lowering pass. | ||||||
| func (c *Compiler) getTypeCode(typ types.Type) llvm.Value { | func (c *Compiler) getTypeCode(typ types.Type) llvm.Value { | ||||||
| 	global := c.mod.NamedGlobal(typ.String() + "$type") | 	var globalName string | ||||||
|  | 	switch typ := typ.(type) { | ||||||
|  | 	case *types.Basic: | ||||||
|  | 		var name string | ||||||
|  | 		switch typ.Kind() { | ||||||
|  | 		case types.Bool: | ||||||
|  | 			name = "bool" | ||||||
|  | 		case types.Int: | ||||||
|  | 			name = "int" | ||||||
|  | 		case types.Int8: | ||||||
|  | 			name = "int8" | ||||||
|  | 		case types.Int16: | ||||||
|  | 			name = "int16" | ||||||
|  | 		case types.Int32: | ||||||
|  | 			name = "int32" | ||||||
|  | 		case types.Int64: | ||||||
|  | 			name = "int64" | ||||||
|  | 		case types.Uint: | ||||||
|  | 			name = "uint" | ||||||
|  | 		case types.Uint8: | ||||||
|  | 			name = "uint8" | ||||||
|  | 		case types.Uint16: | ||||||
|  | 			name = "uint16" | ||||||
|  | 		case types.Uint32: | ||||||
|  | 			name = "uint32" | ||||||
|  | 		case types.Uint64: | ||||||
|  | 			name = "uint64" | ||||||
|  | 		case types.Uintptr: | ||||||
|  | 			name = "uintptr" | ||||||
|  | 		case types.Float32: | ||||||
|  | 			name = "float32" | ||||||
|  | 		case types.Float64: | ||||||
|  | 			name = "float64" | ||||||
|  | 		case types.Complex64: | ||||||
|  | 			name = "complex64" | ||||||
|  | 		case types.Complex128: | ||||||
|  | 			name = "complex128" | ||||||
|  | 		case types.String: | ||||||
|  | 			name = "string" | ||||||
|  | 		case types.UnsafePointer: | ||||||
|  | 			name = "unsafeptr" | ||||||
|  | 		default: | ||||||
|  | 			panic("unknown basic type: " + typ.Name()) | ||||||
|  | 		} | ||||||
|  | 		globalName = "type:basic:" + name | ||||||
|  | 	default: | ||||||
|  | 		// Unknown type, fall back to the .String() method for identification. | ||||||
|  | 		globalName = "type:other:" + typ.String() | ||||||
|  | 	} | ||||||
|  | 	global := c.mod.NamedGlobal(globalName) | ||||||
| 	if global.IsNil() { | 	if global.IsNil() { | ||||||
| 		global = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), typ.String()+"$type") | 		global = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), globalName) | ||||||
| 		global.SetGlobalConstant(true) | 		global.SetGlobalConstant(true) | ||||||
| 	} | 	} | ||||||
| 	return global | 	return global | ||||||
|  |  | ||||||
							
								
								
									
										55
									
								
								compiler/reflect.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										55
									
								
								compiler/reflect.go
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | package compiler | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var basicTypes = map[string]uint64{ | ||||||
|  | 	"bool":       1, | ||||||
|  | 	"int":        2, | ||||||
|  | 	"int8":       3, | ||||||
|  | 	"int16":      4, | ||||||
|  | 	"int32":      5, | ||||||
|  | 	"int64":      6, | ||||||
|  | 	"uint":       7, | ||||||
|  | 	"uint8":      8, | ||||||
|  | 	"uint16":     9, | ||||||
|  | 	"uint32":     10, | ||||||
|  | 	"uint64":     11, | ||||||
|  | 	"uintptr":    12, | ||||||
|  | 	"float32":    13, | ||||||
|  | 	"float64":    14, | ||||||
|  | 	"complex64":  15, | ||||||
|  | 	"complex128": 16, | ||||||
|  | 	"string":     17, | ||||||
|  | 	"unsafeptr":  18, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (c *Compiler) assignTypeCodes(typeSlice typeInfoSlice) { | ||||||
|  | 	fn := c.mod.NamedFunction("reflect.ValueOf") | ||||||
|  | 	if fn.IsNil() { | ||||||
|  | 		// reflect.ValueOf is never used, so we can use the most efficient | ||||||
|  | 		// encoding possible. | ||||||
|  | 		for i, t := range typeSlice { | ||||||
|  | 			t.num = uint64(i + 1) | ||||||
|  | 		} | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Assign typecodes the way the reflect package expects. | ||||||
|  | 	fallbackIndex := 1 | ||||||
|  | 	for _, t := range typeSlice { | ||||||
|  | 		if strings.HasPrefix(t.name, "type:basic:") { | ||||||
|  | 			// Basic types have a typecode with the lowest bit set to 0. | ||||||
|  | 			num, ok := basicTypes[t.name[len("type:basic:"):]] | ||||||
|  | 			if !ok { | ||||||
|  | 				panic("invalid basic type: " + t.name) | ||||||
|  | 			} | ||||||
|  | 			t.num = num<<1 | 0 | ||||||
|  | 		} else { | ||||||
|  | 			// Fallback types have a typecode with the lowest bit set to 1. | ||||||
|  | 			t.num = uint64(fallbackIndex<<1 | 1) | ||||||
|  | 			fallbackIndex++ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -26,6 +26,8 @@ const ( | ||||||
| 	Float64 | 	Float64 | ||||||
| 	Complex64 | 	Complex64 | ||||||
| 	Complex128 | 	Complex128 | ||||||
|  | 	String | ||||||
|  | 	UnsafePointer | ||||||
| 	Array | 	Array | ||||||
| 	Chan | 	Chan | ||||||
| 	Func | 	Func | ||||||
|  | @ -33,11 +35,52 @@ const ( | ||||||
| 	Map | 	Map | ||||||
| 	Ptr | 	Ptr | ||||||
| 	Slice | 	Slice | ||||||
| 	String |  | ||||||
| 	Struct | 	Struct | ||||||
| 	UnsafePointer |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func (k Kind) String() string { | ||||||
|  | 	switch k { | ||||||
|  | 	case Bool: | ||||||
|  | 		return "bool" | ||||||
|  | 	case Int: | ||||||
|  | 		return "int" | ||||||
|  | 	case Int8: | ||||||
|  | 		return "int8" | ||||||
|  | 	case Int16: | ||||||
|  | 		return "int16" | ||||||
|  | 	case Int32: | ||||||
|  | 		return "int32" | ||||||
|  | 	case Int64: | ||||||
|  | 		return "int64" | ||||||
|  | 	case Uint: | ||||||
|  | 		return "uint" | ||||||
|  | 	case Uint8: | ||||||
|  | 		return "uint8" | ||||||
|  | 	case Uint16: | ||||||
|  | 		return "uint16" | ||||||
|  | 	case Uint32: | ||||||
|  | 		return "uint32" | ||||||
|  | 	case Uint64: | ||||||
|  | 		return "uint64" | ||||||
|  | 	case Uintptr: | ||||||
|  | 		return "uintptr" | ||||||
|  | 	case Float32: | ||||||
|  | 		return "float32" | ||||||
|  | 	case Float64: | ||||||
|  | 		return "float64" | ||||||
|  | 	case Complex64: | ||||||
|  | 		return "complex64" | ||||||
|  | 	case Complex128: | ||||||
|  | 		return "complex128" | ||||||
|  | 	case String: | ||||||
|  | 		return "string" | ||||||
|  | 	case UnsafePointer: | ||||||
|  | 		return "unsafe.Pointer" | ||||||
|  | 	default: | ||||||
|  | 		return "T" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // The typecode as used in an interface{}. | // The typecode as used in an interface{}. | ||||||
| type Type uintptr | type Type uintptr | ||||||
| 
 | 
 | ||||||
|  | @ -50,8 +93,13 @@ func (t Type) String() string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t Type) Kind() Kind { | func (t Type) Kind() Kind { | ||||||
|  | 	if t & 1 == 0 { | ||||||
|  | 		// Basic type | ||||||
|  | 		return Kind(t >> 1) | ||||||
|  | 	} else { | ||||||
| 		return Invalid // TODO | 		return Invalid // TODO | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| func (t Type) Elem() Type { | func (t Type) Elem() Type { | ||||||
| 	panic("unimplemented: (reflect.Type).Elem()") | 	panic("unimplemented: (reflect.Type).Elem()") | ||||||
|  |  | ||||||
|  | @ -33,7 +33,14 @@ func (v Value) IsNil() bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Pointer() uintptr { | func (v Value) Pointer() uintptr { | ||||||
|  | 	switch v.Type().Kind() { | ||||||
|  | 	case UnsafePointer: | ||||||
|  | 		return uintptr(v.value) | ||||||
|  | 	case Chan, Func, Map, Ptr, Slice: | ||||||
| 		panic("unimplemented: (reflect.Value).Pointer()") | 		panic("unimplemented: (reflect.Value).Pointer()") | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Pointer"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) IsValid() bool { | func (v Value) IsValid() bool { | ||||||
|  | @ -57,27 +64,132 @@ func (v Value) CanSet() bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Bool() bool { | func (v Value) Bool() bool { | ||||||
| 	panic("unimplemented: (reflect.Value).Bool()") | 	switch v.Type().Kind() { | ||||||
|  | 	case Bool: | ||||||
|  | 		return uintptr(v.value) != 0 | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Bool"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Int() int64 { | func (v Value) Int() int64 { | ||||||
| 	panic("unimplemented: (reflect.Value).Int()") | 	switch v.Type().Kind() { | ||||||
|  | 	case Int: | ||||||
|  | 		if unsafe.Sizeof(int(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			return int64(int(uintptr(v.value))) | ||||||
|  | 		} else { | ||||||
|  | 			return int64(*(*int)(v.value)) | ||||||
|  | 		} | ||||||
|  | 	case Int8: | ||||||
|  | 		return int64(int8(uintptr(v.value))) | ||||||
|  | 	case Int16: | ||||||
|  | 		return int64(int16(uintptr(v.value))) | ||||||
|  | 	case Int32: | ||||||
|  | 		if unsafe.Sizeof(int32(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			return int64(int32(uintptr(v.value))) | ||||||
|  | 		} else { | ||||||
|  | 			return int64(*(*int32)(v.value)) | ||||||
|  | 		} | ||||||
|  | 		return int64(uintptr(v.value)) | ||||||
|  | 	case Int64: | ||||||
|  | 		if unsafe.Sizeof(int64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			return int64(uintptr(v.value)) | ||||||
|  | 		} else { | ||||||
|  | 			return *(*int64)(v.value) | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Int"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Uint() uint64 { | func (v Value) Uint() uint64 { | ||||||
| 	panic("unimplemented: (reflect.Value).Uint()") | 	switch v.Type().Kind() { | ||||||
|  | 	case Uintptr, Uint8, Uint16: | ||||||
|  | 		return uint64(uintptr(v.value)) | ||||||
|  | 	case Uint: | ||||||
|  | 		if unsafe.Sizeof(uint(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			return uint64(uintptr(v.value)) | ||||||
|  | 		} else { | ||||||
|  | 			// For systems with 16-bit pointers. | ||||||
|  | 			return uint64(*(*uint)(v.value)) | ||||||
|  | 		} | ||||||
|  | 	case Uint32: | ||||||
|  | 		if 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)) | ||||||
|  | 		} | ||||||
|  | 	case Uint64: | ||||||
|  | 		if unsafe.Sizeof(uint64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			return uint64(uintptr(v.value)) | ||||||
|  | 		} else { | ||||||
|  | 			// For systems with 16-bit or 32-bit pointers. | ||||||
|  | 			return *(*uint64)(v.value) | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Uint"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Float() float64 { | func (v Value) Float() float64 { | ||||||
| 	panic("unimplemented: (reflect.Value).Float()") | 	switch v.Type().Kind() { | ||||||
|  | 	case Float32: | ||||||
|  | 		if 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 | ||||||
|  | 			// pointers. | ||||||
|  | 			return float64(*(*float32)(v.value)) | ||||||
|  | 		} | ||||||
|  | 	case Float64: | ||||||
|  | 		if unsafe.Sizeof(float64(0)) <= unsafe.Sizeof(uintptr(0)) { | ||||||
|  | 			// The float is directly stored in the interface value on systems | ||||||
|  | 			// with 64-bit pointers. | ||||||
|  | 			return *(*float64)(unsafe.Pointer(&v.value)) | ||||||
|  | 		} else { | ||||||
|  | 			// For systems with 16-bit and 32-bit pointers. | ||||||
|  | 			return *(*float64)(v.value) | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Float"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Complex() complex128 { | func (v Value) Complex() complex128 { | ||||||
| 	panic("unimplemented: (reflect.Value).Complex()") | 	switch v.Type().Kind() { | ||||||
|  | 	case Complex64: | ||||||
|  | 		if 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 | ||||||
|  | 			// 16-bit and 32-bit pointers. | ||||||
|  | 			return complex128(*(*complex64)(v.value)) | ||||||
|  | 		} | ||||||
|  | 	case Complex128: | ||||||
|  | 		// This is a 128-bit value, which is always stored as an external value. | ||||||
|  | 		// It may be stored in the pointer directly on very uncommon | ||||||
|  | 		// architectures with 128-bit pointers, however. | ||||||
|  | 		return *(*complex128)(v.value) | ||||||
|  | 	default: | ||||||
|  | 		panic(&ValueError{"Complex"}) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) String() string { | func (v Value) String() string { | ||||||
| 	panic("unimplemented: (reflect.Value).String()") | 	switch v.Type().Kind() { | ||||||
|  | 	case String: | ||||||
|  | 		// A string value is always bigger than a pointer as it is made of a | ||||||
|  | 		// pointer and a length. | ||||||
|  | 		return *(*string)(v.value) | ||||||
|  | 	default: | ||||||
|  | 		// Special case because of the special treatment of .String() in Go. | ||||||
|  | 		return "<T>" | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (v Value) Bytes() []byte { | func (v Value) Bytes() []byte { | ||||||
|  | @ -147,3 +259,11 @@ func (v Value) SetString(x string) { | ||||||
| func MakeSlice(typ Type, len, cap int) Value { | func MakeSlice(typ Type, len, cap int) Value { | ||||||
| 	panic("unimplemented: reflect.MakeSlice()") | 	panic("unimplemented: reflect.MakeSlice()") | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type ValueError struct { | ||||||
|  | 	Method string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *ValueError) Error() string { | ||||||
|  | 	return "reflect: call of reflect.Value." + e.Method + " on invalid type" | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								testdata/reflect.go
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										62
									
								
								testdata/reflect.go
									
										
									
									
										предоставленный
									
									
								
							|  | @ -1,6 +1,9 @@ | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import "reflect" | import ( | ||||||
|  | 	"reflect" | ||||||
|  | 	"unsafe" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| type myint int | type myint int | ||||||
| 
 | 
 | ||||||
|  | @ -9,4 +12,61 @@ func main() { | ||||||
| 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(int(5))) | 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(int(5))) | ||||||
| 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(uint(5))) | 	println(reflect.TypeOf(int(3)) == reflect.TypeOf(uint(5))) | ||||||
| 	println(reflect.TypeOf(myint(3)) == reflect.TypeOf(int(5))) | 	println(reflect.TypeOf(myint(3)) == reflect.TypeOf(int(5))) | ||||||
|  | 
 | ||||||
|  | 	println("\nvalues of interfaces") | ||||||
|  | 	for _, v := range []interface{}{ | ||||||
|  | 		true, | ||||||
|  | 		false, | ||||||
|  | 		int(2000), | ||||||
|  | 		int(-2000), | ||||||
|  | 		uint(2000), | ||||||
|  | 		int8(-3), | ||||||
|  | 		int8(3), | ||||||
|  | 		uint8(200), | ||||||
|  | 		int16(-300), | ||||||
|  | 		int16(300), | ||||||
|  | 		uint16(50000), | ||||||
|  | 		int32(7 << 20), | ||||||
|  | 		int32(-7 << 20), | ||||||
|  | 		uint32(7 << 20), | ||||||
|  | 		int64(9 << 40), | ||||||
|  | 		int64(-9 << 40), | ||||||
|  | 		uint64(9 << 40), | ||||||
|  | 		uintptr(12345), | ||||||
|  | 		float32(3.14), | ||||||
|  | 		float64(3.14), | ||||||
|  | 		complex64(1.2 + 0.3i), | ||||||
|  | 		complex128(1.3 + 0.4i), | ||||||
|  | 		"foo", | ||||||
|  | 		unsafe.Pointer(new(int)), | ||||||
|  | 	} { | ||||||
|  | 		showValue(v) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func showValue(v interface{}) { | ||||||
|  | 	rv := reflect.ValueOf(v) | ||||||
|  | 	rt := rv.Type() | ||||||
|  | 	if reflect.TypeOf(v) != rt { | ||||||
|  | 		panic("direct TypeOf() is different from ValueOf().Type()") | ||||||
|  | 	} | ||||||
|  | 	println("reflect type:", rt.Kind().String()) | ||||||
|  | 	switch rt.Kind() { | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		println("  bool:", rv.Bool()) | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		println("  int:", rv.Int()) | ||||||
|  | 	case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||||
|  | 		println("  uint:", rv.Uint()) | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		println("  float:", rv.Float()) | ||||||
|  | 	case reflect.Complex64, reflect.Complex128: | ||||||
|  | 		println("  complex:", rv.Complex()) | ||||||
|  | 	case reflect.String: | ||||||
|  | 		println("  string:", rv.String()) | ||||||
|  | 	case reflect.UnsafePointer: | ||||||
|  | 		println("  pointer:", rv.Pointer() != 0) | ||||||
|  | 	default: | ||||||
|  | 		println("  unknown type kind!") | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								testdata/reflect.txt
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										50
									
								
								testdata/reflect.txt
									
										
									
									
										предоставленный
									
									
								
							|  | @ -2,3 +2,53 @@ matching types | ||||||
| true | true | ||||||
| false | false | ||||||
| false | false | ||||||
|  | 
 | ||||||
|  | values of interfaces | ||||||
|  | reflect type: bool | ||||||
|  |   bool: true | ||||||
|  | reflect type: bool | ||||||
|  |   bool: false | ||||||
|  | reflect type: int | ||||||
|  |   int: 2000 | ||||||
|  | reflect type: int | ||||||
|  |   int: -2000 | ||||||
|  | reflect type: uint | ||||||
|  |   uint: 2000 | ||||||
|  | reflect type: int8 | ||||||
|  |   int: -3 | ||||||
|  | reflect type: int8 | ||||||
|  |   int: 3 | ||||||
|  | reflect type: uint8 | ||||||
|  |   uint: 200 | ||||||
|  | reflect type: int16 | ||||||
|  |   int: -300 | ||||||
|  | reflect type: int16 | ||||||
|  |   int: 300 | ||||||
|  | reflect type: uint16 | ||||||
|  |   uint: 50000 | ||||||
|  | reflect type: int32 | ||||||
|  |   int: 7340032 | ||||||
|  | reflect type: int32 | ||||||
|  |   int: -7340032 | ||||||
|  | reflect type: uint32 | ||||||
|  |   uint: 7340032 | ||||||
|  | reflect type: int64 | ||||||
|  |   int: 9895604649984 | ||||||
|  | reflect type: int64 | ||||||
|  |   int: -9895604649984 | ||||||
|  | reflect type: uint64 | ||||||
|  |   uint: 9895604649984 | ||||||
|  | reflect type: uintptr | ||||||
|  |   uint: 12345 | ||||||
|  | reflect type: float32 | ||||||
|  |   float: +3.140000e+000 | ||||||
|  | reflect type: float64 | ||||||
|  |   float: +3.140000e+000 | ||||||
|  | reflect type: complex64 | ||||||
|  |   complex: (+1.200000e+000+3.000000e-001i) | ||||||
|  | reflect type: complex128 | ||||||
|  |   complex: (+1.300000e+000+4.000000e-001i) | ||||||
|  | reflect type: string | ||||||
|  |   string: foo | ||||||
|  | reflect type: unsafe.Pointer | ||||||
|  |   pointer: true | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Ayke van Laethem
						Ayke van Laethem