// Copyright 2023 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package abiimport ()// Type is the runtime representation of a Go type.//// Type is also referenced implicitly// (in the form of expressions involving constants and arch.PtrSize)// in cmd/compile/internal/reflectdata/reflect.go// and cmd/link/internal/ld/decodesym.go// (e.g. data[2*arch.PtrSize+4] references the TFlag field)// unsafe.OffsetOf(Type{}.TFlag) cannot be used directly in those// places because it varies with cross compilation and experiments.typeTypestruct {Size_uintptrPtrBytesuintptr// number of (prefix) bytes in the type that can contain pointersHashuint32// hash of type; avoids computation in hash tablesTFlagTFlag// extra type information flagsAlign_uint8// alignment of variable with this typeFieldAlign_uint8// alignment of struct field with this typeKind_uint8// enumeration for C// function for comparing objects of this type // (ptr to object A, ptr to object B) -> ==?Equalfunc(unsafe.Pointer, unsafe.Pointer) bool// GCData stores the GC type data for the garbage collector. // If the KindGCProg bit is set in kind, GCData is a GC program. // Otherwise it is a ptrmask bitmap. See mbitmap.go for details.GCData *byteStrNameOff// string formPtrToThisTypeOff// type for pointer to this type, may be zero}// A Kind represents the specific kind of type that a Type represents.// The zero Kind is not a valid kind.typeKinduintconst (InvalidKind = iotaBoolIntInt8Int16Int32Int64UintUint8Uint16Uint32Uint64UintptrFloat32Float64Complex64Complex128ArrayChanFuncInterfaceMapPointerSliceStringStructUnsafePointer)const (// TODO (khr, drchase) why aren't these in TFlag? Investigate, fix if possible.KindDirectIface = 1 << 5KindGCProg = 1 << 6// Type.gc points to GC programKindMask = (1 << 5) - 1)// TFlag is used by a Type to signal what extra type information is// available in the memory directly following the Type value.typeTFlaguint8const (// TFlagUncommon means that there is a data with a type, UncommonType, // just beyond the shared-per-type common data. That is, the data // for struct types will store their UncommonType at one offset, the // data for interface types will store their UncommonType at a different // offset. UncommonType is always accessed via a pointer that is computed // using trust-us-we-are-the-implementors pointer arithmetic. // // For example, if t.Kind() == Struct and t.tflag&TFlagUncommon != 0, // then t has UncommonType data and it can be accessed as: // // type structTypeUncommon struct { // structType // u UncommonType // } // u := &(*structTypeUncommon)(unsafe.Pointer(t)).uTFlagUncommonTFlag = 1 << 0// TFlagExtraStar means the name in the str field has an // extraneous '*' prefix. This is because for most types T in // a program, the type *T also exists and reusing the str data // saves binary size.TFlagExtraStarTFlag = 1 << 1// TFlagNamed means the type has a name.TFlagNamedTFlag = 1 << 2// TFlagRegularMemory means that equal and hash functions can treat // this type as a single region of t.size bytes.TFlagRegularMemoryTFlag = 1 << 3)// NameOff is the offset to a name from moduledata.types. See resolveNameOff in runtime.typeNameOffint32// TypeOff is the offset to a type from moduledata.types. See resolveTypeOff in runtime.typeTypeOffint32// TextOff is an offset from the top of a text section. See (rtype).textOff in runtime.typeTextOffint32// String returns the name of k.func ( Kind) () string {ifint() < len(kindNames) {returnkindNames[] }returnkindNames[0]}varkindNames = []string{Invalid: "invalid",Bool: "bool",Int: "int",Int8: "int8",Int16: "int16",Int32: "int32",Int64: "int64",Uint: "uint",Uint8: "uint8",Uint16: "uint16",Uint32: "uint32",Uint64: "uint64",Uintptr: "uintptr",Float32: "float32",Float64: "float64",Complex64: "complex64",Complex128: "complex128",Array: "array",Chan: "chan",Func: "func",Interface: "interface",Map: "map",Pointer: "ptr",Slice: "slice",String: "string",Struct: "struct",UnsafePointer: "unsafe.Pointer",}func ( *Type) () Kind { returnKind(.Kind_ & KindMask) }func ( *Type) () bool {return .TFlag&TFlagNamed != 0}func ( *Type) () bool { return .PtrBytes != 0 }// IfaceIndir reports whether t is stored indirectly in an interface value.func ( *Type) () bool {return .Kind_&KindDirectIface == 0}// isDirectIface reports whether t is stored directly in an interface value.func ( *Type) () bool {return .Kind_&KindDirectIface != 0}func ( *Type) (, uintptr) []byte {returnunsafeSliceFor(.GCData, int())[:]}// Method on non-interface typetypeMethodstruct {NameNameOff// name of methodMtypTypeOff// method type (without receiver)IfnTextOff// fn used in interface call (one-word receiver)TfnTextOff// fn used for normal method call}// UncommonType is present only for defined types or types with methods// (if T is a defined type, the uncommonTypes for T and *T have methods).// Using a pointer to this struct reduces the overall size required// to describe a non-defined type with no methods.typeUncommonTypestruct {PkgPathNameOff// import path; empty for built-in types like int, stringMcountuint16// number of methodsXcountuint16// number of exported methodsMoffuint32// offset from this uncommontype to [mcount]Method _ uint32// unused}func ( *UncommonType) () []Method {if .Mcount == 0 {returnnil }return (*[1 << 16]Method)(addChecked(unsafe.Pointer(), uintptr(.Moff), "t.mcount > 0"))[:.Mcount:.Mcount]}func ( *UncommonType) () []Method {if .Xcount == 0 {returnnil }return (*[1 << 16]Method)(addChecked(unsafe.Pointer(), uintptr(.Moff), "t.xcount > 0"))[:.Xcount:.Xcount]}// addChecked returns p+x.//// The whySafe string is ignored, so that the function still inlines// as efficiently as p+x, but all call sites should use the string to// record why the addition is safe, which is to say why the addition// does not cause x to advance to the very end of p's allocation// and therefore point incorrectly at the next block in memory.func ( unsafe.Pointer, uintptr, string) unsafe.Pointer {returnunsafe.Pointer(uintptr() + )}// Imethod represents a method on an interface typetypeImethodstruct {NameNameOff// name of methodTypTypeOff// .(*FuncType) underneath}// ArrayType represents a fixed array type.typeArrayTypestruct {TypeElem *Type// array element typeSlice *Type// slice typeLenuintptr}// Len returns the length of t if t is an array type, otherwise 0func ( *Type) () int {if .Kind() == Array {returnint((*ArrayType)(unsafe.Pointer()).Len) }return0}func ( *Type) () *Type {return}typeChanDirintconst (RecvDirChanDir = 1 << iota// <-chanSendDir// chan<-BothDir = RecvDir | SendDir// chanInvalidDirChanDir = 0)// ChanType represents a channel typetypeChanTypestruct {TypeElem *TypeDirChanDir}typestructTypeUncommonstruct {StructTypeuUncommonType}// ChanDir returns the direction of t if t is a channel type, otherwise InvalidDir (0).func ( *Type) () ChanDir {if .Kind() == Chan { := (*ChanType)(unsafe.Pointer())return .Dir }returnInvalidDir}// Uncommon returns a pointer to T's "uncommon" data if there is any, otherwise nilfunc ( *Type) () *UncommonType {if .TFlag&TFlagUncommon == 0 {returnnil }switch .Kind() {caseStruct:return &(*structTypeUncommon)(unsafe.Pointer()).ucasePointer:typestruct {PtrTypeUncommonType }return &(*)(unsafe.Pointer()).caseFunc:typestruct {FuncTypeUncommonType }return &(*)(unsafe.Pointer()).caseSlice:typestruct {SliceTypeUncommonType }return &(*)(unsafe.Pointer()).caseArray:typestruct {ArrayTypeUncommonType }return &(*)(unsafe.Pointer()).caseChan:typestruct {ChanTypeUncommonType }return &(*)(unsafe.Pointer()).caseMap:typestruct {MapTypeUncommonType }return &(*)(unsafe.Pointer()).caseInterface:typestruct {InterfaceTypeUncommonType }return &(*)(unsafe.Pointer()).default:typestruct {TypeUncommonType }return &(*)(unsafe.Pointer()). }}// Elem returns the element type for t if t is an array, channel, map, pointer, or slice, otherwise nil.func ( *Type) () *Type {switch .Kind() {caseArray: := (*ArrayType)(unsafe.Pointer())return .ElemcaseChan: := (*ChanType)(unsafe.Pointer())return .ElemcaseMap: := (*MapType)(unsafe.Pointer())return .ElemcasePointer: := (*PtrType)(unsafe.Pointer())return .ElemcaseSlice: := (*SliceType)(unsafe.Pointer())return .Elem }returnnil}// StructType returns t cast to a *StructType, or nil if its tag does not match.func ( *Type) () *StructType {if .Kind() != Struct {returnnil }return (*StructType)(unsafe.Pointer())}// MapType returns t cast to a *MapType, or nil if its tag does not match.func ( *Type) () *MapType {if .Kind() != Map {returnnil }return (*MapType)(unsafe.Pointer())}// ArrayType returns t cast to a *ArrayType, or nil if its tag does not match.func ( *Type) () *ArrayType {if .Kind() != Array {returnnil }return (*ArrayType)(unsafe.Pointer())}// FuncType returns t cast to a *FuncType, or nil if its tag does not match.func ( *Type) () *FuncType {if .Kind() != Func {returnnil }return (*FuncType)(unsafe.Pointer())}// InterfaceType returns t cast to a *InterfaceType, or nil if its tag does not match.func ( *Type) () *InterfaceType {if .Kind() != Interface {returnnil }return (*InterfaceType)(unsafe.Pointer())}// Size returns the size of data with type t.func ( *Type) () uintptr { return .Size_ }// Align returns the alignment of data with type t.func ( *Type) () int { returnint(.Align_) }func ( *Type) () int { returnint(.FieldAlign_) }typeInterfaceTypestruct {TypePkgPathName// import pathMethods []Imethod// sorted by hash}func ( *Type) () []Method { := .Uncommon()if == nil {returnnil }return .ExportedMethods()}func ( *Type) () int {if .Kind() == Interface { := (*InterfaceType)(unsafe.Pointer())return .NumMethod() }returnlen(.ExportedMethods())}// NumMethod returns the number of interface methods in the type's method set.func ( *InterfaceType) () int { returnlen(.Methods) }typeMapTypestruct {TypeKey *TypeElem *TypeBucket *Type// internal type representing a hash bucket// function for hashing keys (ptr to key, seed) -> hashHasherfunc(unsafe.Pointer, uintptr) uintptrKeySizeuint8// size of key slotValueSizeuint8// size of elem slotBucketSizeuint16// size of bucketFlagsuint32}// Note: flag values must match those used in the TMAP case// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.func ( *MapType) () bool { // store ptr to key instead of key itselfreturn .Flags&1 != 0}func ( *MapType) () bool { // store ptr to elem instead of elem itselfreturn .Flags&2 != 0}func ( *MapType) () bool { // true if k==k for all keysreturn .Flags&4 != 0}func ( *MapType) () bool { // true if we need to update key on an overwritereturn .Flags&8 != 0}func ( *MapType) () bool { // true if hash function might panicreturn .Flags&16 != 0}func ( *Type) () *Type {if .Kind() == Map {return (*MapType)(unsafe.Pointer()).Key }returnnil}typeSliceTypestruct {TypeElem *Type// slice element type}// funcType represents a function type.//// A *Type for each in and out parameter is stored in an array that// directly follows the funcType (and possibly its uncommonType). So// a function type with one method, one input, and one output is://// struct {// funcType// uncommonType// [2]*rtype // [0] is in, [1] is out// }typeFuncTypestruct {TypeInCountuint16OutCountuint16// top bit is set if last input parameter is ...}func ( *FuncType) ( int) *Type {return .InSlice()[]}func ( *FuncType) () int {returnint(.InCount)}func ( *FuncType) () int {returnint(.OutCount & (1<<15 - 1))}func ( *FuncType) ( int) *Type {return (.OutSlice()[])}func ( *FuncType) () []*Type { := unsafe.Sizeof(*)if .TFlag&TFlagUncommon != 0 { += unsafe.Sizeof(UncommonType{}) }if .InCount == 0 {returnnil }return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(), , "t.inCount > 0"))[:.InCount:.InCount]}func ( *FuncType) () []*Type { := uint16(.NumOut())if == 0 {returnnil } := unsafe.Sizeof(*)if .TFlag&TFlagUncommon != 0 { += unsafe.Sizeof(UncommonType{}) }return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(), , "outCount > 0"))[.InCount : .InCount+ : .InCount+]}func ( *FuncType) () bool {return .OutCount&(1<<15) != 0}typePtrTypestruct {TypeElem *Type// pointer element (pointed at) type}typeStructFieldstruct {NameName// name is always non-emptyTyp *Type// type of fieldOffsetuintptr// byte offset of field}func ( *StructField) () bool {return .Name.IsEmbedded()}typeStructTypestruct {TypePkgPathNameFields []StructField}// Name is an encoded type Name with optional extra data.//// The first byte is a bit field containing://// 1<<0 the name is exported// 1<<1 tag data follows the name// 1<<2 pkgPath nameOff follows the name and tag// 1<<3 the name is of an embedded (a.k.a. anonymous) field//// Following that, there is a varint-encoded length of the name,// followed by the name itself.//// If tag data is present, it also has a varint-encoded length// followed by the tag itself.//// If the import path follows, then 4 bytes at the end of// the data form a nameOff. The import path is only set for concrete// methods that are defined in a different package than their type.//// If a name starts with "*", then the exported bit represents// whether the pointed to type is exported.//// Note: this encoding must match here and in:// cmd/compile/internal/reflectdata/reflect.go// cmd/link/internal/ld/decodesym.gotypeNamestruct {Bytes *byte}// DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to// be safe for the reason in whySafe (which can appear in a backtrace, etc.)func ( Name) ( int, string) *byte {return (*byte)(addChecked(unsafe.Pointer(.Bytes), uintptr(), ))}// Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to// be safe because the runtime made the call (other packages use DataChecked)func ( Name) ( int) *byte {return (*byte)(addChecked(unsafe.Pointer(.Bytes), uintptr(), "the runtime doesn't need to give you a reason"))}// IsExported returns "is n exported?"func ( Name) () bool {return (*.Bytes)&(1<<0) != 0}// HasTag returns true iff there is tag data following this namefunc ( Name) () bool {return (*.Bytes)&(1<<1) != 0}// IsEmbedded returns true iff n is embedded (an anonymous field).func ( Name) () bool {return (*.Bytes)&(1<<3) != 0}// ReadVarint parses a varint as encoded by encoding/binary.// It returns the number of encoded bytes and the encoded value.func ( Name) ( int) (int, int) { := 0for := 0; ; ++ { := *.DataChecked(+, "read varint") += int(&0x7f) << (7 * )if &0x80 == 0 {return + 1, } }}// IsBlank indicates whether n is "_".func ( Name) () bool {if .Bytes == nil {returnfalse } , := .ReadVarint(1)return == 1 && *.Data(2) == '_'}// writeVarint writes n to buf in varint form. Returns the// number of bytes written. n must be nonnegative.// Writes at most 10 bytes.func ( []byte, int) int {for := 0; ; ++ { := byte( & 0x7f) >>= 7if == 0 { [] = return + 1 } [] = | 0x80 }}// Name returns the tag string for n, or empty if there is none.func ( Name) () string {if .Bytes == nil {return"" } , := .ReadVarint(1)returnunsafeStringFor(.DataChecked(1+, "non-empty string"), )}// Tag returns the tag string for n, or empty if there is none.func ( Name) () string {if !.HasTag() {return"" } , := .ReadVarint(1) , := .ReadVarint(1 + + )returnunsafeStringFor(.DataChecked(1+++, "non-empty string"), )}func (, string, , bool) Name {iflen() >= 1<<29 {panic("abi.NewName: name too long: " + [:1024] + "...") }iflen() >= 1<<29 {panic("abi.NewName: tag too long: " + [:1024] + "...") }var [10]bytevar [10]byte := writeVarint([:], len()) := writeVarint([:], len())varbyte := 1 + + len()if { |= 1 << 0 }iflen() > 0 { += + len() |= 1 << 1 }if { |= 1 << 3 } := make([]byte, ) [0] = copy([1:], [:])copy([1+:], )iflen() > 0 { := [1++len():]copy(, [:])copy([:], ) }returnName{Bytes: &[0]}}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.