英文:
Why map type's kind is reported as 53 instead of 21?
问题
这是一个Go语言的代码片段,它定义了一些类型和常量。其中,p._type.typ.kind
的值为53,表示map[int]int
类型的kind值为53。但是在src/runtime/typekind.go
中,kindMap
的值为21,而不是53。同样地,kindChan
的值为50,而不是18。这是因为在Go语言的运行时库中,类型的kind值可能与常量定义的值不完全一致,这取决于具体的实现和版本。因此,在不同的环境中,kind值可能会有所不同。
英文:
show code:
package main
import (
"fmt"
"unsafe"
)
// copy form src/runtime/type.go
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
fieldAlign uint8
kind uint8
equal func(unsafe.Pointer, unsafe.Pointer) bool
gcdata *byte
str nameOff
ptrToThis typeOff
}
type tflag uint8
type nameOff int32
type typeOff int32
// copy form src/runtime/runtime2.go
type eface struct {
_type *maptype
data unsafe.Pointer
}
// copy form src/runtime/type.go
type maptype struct {
typ _type
key *_type
elem *_type
bucket *_type // internal type representing a hash bucket
// function for hashing keys (ptr to key, seed) -> hash
hasher func(unsafe.Pointer, uintptr) uintptr
keysize uint8 // size of key slot
elemsize uint8 // size of elem slot
bucketsize uint16 // size of bucket
flags uint32
}
func main() {
var t interface{} = map[int]int{1: 1}
p := (*eface)(unsafe.Pointer(&t))
fmt.Println(p._type.typ.kind) // 53
}
print 53,
but you can find in src/runtime/typekind.go
const (
kindBool = 1 + iota
kindInt
kindInt8
kindInt16
kindInt32
kindInt64
kindUint
kindUint8
kindUint16
kindUint32
kindUint64
kindUintptr
kindFloat32
kindFloat64
kindComplex64
kindComplex128
kindArray
kindChan
kindFunc
kindInterface
kindMap // 21
kindPtr
kindSlice
kindString
kindStruct
kindUnsafePointer
kindDirectIface = 1 << 5
kindGCProg = 1 << 6
kindMask = (1 << 5) - 1
)
the map type is const 21. Similarly, chan is 50 instead of kindChan(18). Why?
答案1
得分: 2
如果你查看src/runtime/typekind.go,你会发现有一个函数用于检查值是否直接存储在接口值中,这适用于你的情况,因为你创建了一个类型为interface{}
的变量t
,但将一个映射类型存储到其中。
// isDirectIface报告t是否直接存储在接口值中。
func isDirectIface(t *_type) bool {
return t.kind&kindDirectIface != 0
}
当你将其应用于p
的值,即isDirectIface(&p._type.typ)
,它返回true
,因为与接口类型对应的底层位值被设置为1 (kindDirectIface = 1 << 5
,32)。
因此,实际上,值53表示(十进制21+32),一个映射类型21(kindMap
)存储为一个接口类型32(kindDirectIface
)。
英文:
If you look at the src/runtime/typekind.go, there is a function to check if the value is stored directly in an interface value, which applies to your case, as you are creating t
of interface{}
but storing a map type to it.
// isDirectIface reports whether t is stored directly in an interface value.
func isDirectIface(t *_type) bool {
return t.kind&kindDirectIface != 0
}
When using that on your value of p
as isDirectIface(&p._type.typ)
it returns true
, because of the underlying bit value corresponding to interface type is set (kindDirectIface = 1 << 5
, 32)
So in effect, the value 53 represents (decimal 21+32) a map type 21 (kindMap
) stored as an interface type 32 (kindDirectIface
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论