Source File
type.go
Belonging Package
encoding/gob
package gob
import (
)
type userTypeInfo struct {
user reflect.Type // the type the user handed us
base reflect.Type // the base type after all indirections
indir int // number of indirections to reach the base type
externalEnc int // xGob, xBinary, or xText
externalDec int // xGob, xBinary or xText
encIndir int8 // number of indirections to reach the receiver type; may be negative
decIndir int8 // number of indirections to reach the receiver type; may be negative
}
func ( reflect.Type) (*userTypeInfo, error) {
if , := userTypeCache.Load(); {
return .(*userTypeInfo), nil
}
:= new(userTypeInfo)
.base =
return nil, errors.New("can't represent recursive pointer type " + .base.String())
}
if .indir%2 == 0 {
= .Elem()
}
.indir++
}
if , := implementsInterface(.user, gobEncoderInterfaceType); {
.externalEnc, .encIndir = xGob,
} else if , := implementsInterface(.user, binaryMarshalerInterfaceType); {
.externalEnc, .encIndir = xBinary,
}
if , := implementsInterface(.user, gobDecoderInterfaceType); {
.externalDec, .decIndir = xGob,
} else if , := implementsInterface(.user, binaryUnmarshalerInterfaceType); {
.externalDec, .decIndir = xBinary,
}
, := userTypeCache.LoadOrStore(, )
return .(*userTypeInfo), nil
}
var (
gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
binaryMarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
textMarshalerInterfaceType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerInterfaceType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
if reflect.PtrTo().Implements() {
return true, -1
}
}
return false, 0
}
func ( reflect.Type) *userTypeInfo {
, := validUserType()
if != nil {
error_()
}
return
}
type typeId int32
var nextId typeId // incremented for each new type we build
var typeLock sync.Mutex // set while building a type
const firstUserId = 64 // lowest id number granted to user
type gobType interface {
id() typeId
setId(id typeId)
name() string
string() string // not public; only for debugging
safeString(seen map[typeId]bool) string
}
var types = make(map[reflect.Type]gobType)
var idToType = make(map[typeId]gobType)
var builtinIdToType map[typeId]gobType // set in init() after builtins are established
type CommonType struct {
Name string
Id typeId
}
func ( *CommonType) () typeId { return .Id }
func ( *CommonType) ( typeId) { .Id = }
func ( *CommonType) () string { return .Name }
func ( *CommonType) ( map[typeId]bool) string {
return .Name
}
func ( *CommonType) () string { return .Name }
tBool = bootstrapType("bool", (*bool)(nil), 1)
tInt = bootstrapType("int", (*int)(nil), 2)
tUint = bootstrapType("uint", (*uint)(nil), 3)
tFloat = bootstrapType("float", (*float64)(nil), 4)
tBytes = bootstrapType("bytes", (*[]byte)(nil), 5)
tString = bootstrapType("string", (*string)(nil), 6)
tComplex = bootstrapType("complex", (*complex128)(nil), 7)
tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9)
tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10)
tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11)
tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12)
tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13)
tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14)
tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15)
)
var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id
var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType)
checkId(16, tWireType)
checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id)
checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id)
checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id)
checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id)
checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id)
checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id)
builtinIdToType = make(map[typeId]gobType)
for , := range idToType {
builtinIdToType[] =
}
if nextId > firstUserId {
panic(fmt.Sprintln("nextId too large:", nextId))
}
nextId = firstUserId
registerBasics()
wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil)))
}
type gobEncoderType struct {
CommonType
}
func ( string) *gobEncoderType {
:= &gobEncoderType{CommonType{Name: }}
setTypeId()
return
}
func ( *gobEncoderType) ( map[typeId]bool) string {
return .Name
}
func ( *gobEncoderType) () string { return .Name }
type sliceType struct {
CommonType
Elem typeId
}
func ( string) *sliceType {
:= &sliceType{CommonType{Name: }, 0}
return
}
type fieldType struct {
Name string
Id typeId
}
type structType struct {
CommonType
Field []*fieldType
}
func ( *structType) ( map[typeId]bool) string {
if == nil {
return "<nil>"
}
if , := [.Id]; {
return .Name
}
[.Id] = true
:= .Name + " = struct { "
for , := range .Field {
+= fmt.Sprintf("%s %s; ", .Name, .Id.gobType().safeString())
}
+= "}"
return
}
func ( *structType) () string { return .safeString(make(map[typeId]bool)) }
func ( string) *structType {
setTypeId()
return
}
if .externalEnc != 0 {
return newGobEncoderType(), nil
}
var error
var , gobType
defer func() {
if != nil {
delete(types, )
}
case reflect.Bool:
return tBool.gobType(), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return tInt.gobType(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return tUint.gobType(), nil
case reflect.Float32, reflect.Float64:
return tFloat.gobType(), nil
case reflect.Complex64, reflect.Complex128:
return tComplex.gobType(), nil
case reflect.String:
return tString.gobType(), nil
case reflect.Interface:
return tInterface.gobType(), nil
case reflect.Array:
:= newArrayType()
types[] =
, = getBaseType("", .Elem())
if != nil {
return nil,
if .Elem().Kind() == reflect.Uint8 {
return tBytes.gobType(), nil
}
:= newSliceType()
types[] =
, = getBaseType(.Elem().Name(), .Elem())
if != nil {
return nil,
}
.init()
return , nil
case reflect.Struct:
:= newStructType()
types[] =
idToType[.id()] =
for := 0; < .NumField(); ++ {
:= .Field()
if !isSent(&) {
continue
}
:= userType(.Type).base
:= .Name()
if == "" {
:= userType(.Type).base
= .String()
}
, := getBaseType(, .Type)
if != nil {
return nil,
func ( *reflect.StructField) bool {
if !isExported(.Name) {
return false
func ( string, *userTypeInfo, reflect.Type) (gobType, error) {
, := types[]
if {
return , nil
}
, := newTypeObject(, , )
if == nil {
types[] =
}
return ,
}
func (, typeId) {
if != {
fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(), int())
panic("bootstrap type wrong id: " + .name() + " " + .string() + " not " + .string())
}
}
type wireType struct {
ArrayT *arrayType
SliceT *sliceType
StructT *structType
MapT *mapType
GobEncoderT *gobEncoderType
BinaryMarshalerT *gobEncoderType
TextMarshalerT *gobEncoderType
}
func ( *wireType) () string {
const = "unknown type"
if == nil {
return
}
switch {
case .ArrayT != nil:
return .ArrayT.Name
case .SliceT != nil:
return .SliceT.Name
case .StructT != nil:
return .StructT.Name
case .MapT != nil:
return .MapT.Name
case .GobEncoderT != nil:
return .GobEncoderT.Name
case .BinaryMarshalerT != nil:
return .BinaryMarshalerT.Name
case .TextMarshalerT != nil:
return .TextMarshalerT.Name
}
return
}
type typeInfo struct {
id typeId
encInit sync.Mutex // protects creation of encoder
encoder atomic.Value // *encEngine
wire *wireType
}
var typeInfoMap atomic.Value
func ( reflect.Type) *typeInfo {
, := typeInfoMap.Load().(map[reflect.Type]*typeInfo)
return []
}
func ( *userTypeInfo) (*typeInfo, error) {
:= .base
= .user
}
if := lookupTypeInfo(); != nil {
return , nil
}
return buildTypeInfo(, )
}
func ( *userTypeInfo, reflect.Type) (*typeInfo, error) {
typeLock.Lock()
defer typeLock.Unlock()
if := lookupTypeInfo(); != nil {
return , nil
}
, := getBaseType(.Name(), )
if != nil {
return nil,
}
:= &typeInfo{id: .id()}
if .externalEnc != 0 {
, := getType(.Name(), , )
if != nil {
return nil,
}
:= .id().gobType().(*gobEncoderType)
switch .externalEnc {
case xGob:
.wire = &wireType{GobEncoderT: }
case xBinary:
.wire = &wireType{BinaryMarshalerT: }
case xText:
.wire = &wireType{TextMarshalerT: }
}
= .user
} else {
:= .id.gobType()
switch := ; .Kind() {
case reflect.Array:
.wire = &wireType{ArrayT: .(*arrayType)}
case reflect.Map:
.wire = &wireType{MapT: .(*mapType)}
GobDecode([]byte) error
}
var (
nameToConcreteType sync.Map // map[string]reflect.Type
concreteTypeToName sync.Map // map[reflect.Type]string
)
func ( string, interface{}) {
if , := nameToConcreteType.LoadOrStore(, reflect.TypeOf()); && != .user {
panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", , , .user))
}
if , := concreteTypeToName.LoadOrStore(.base, ); && != {
nameToConcreteType.Delete()
panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", .user, , ))
}
}
=
}
}
if .Name() != "" {
if .PkgPath() == "" {
= + .Name()
} else {
= + .PkgPath() + "." + .Name()
}
}
RegisterName(, )
}
func () {
Register(int(0))
Register(int8(0))
Register(int16(0))
Register(int32(0))
Register(int64(0))
Register(uint(0))
Register(uint8(0))
Register(uint16(0))
Register(uint32(0))
Register(uint64(0))
Register(float32(0))
Register(float64(0))
Register(complex64(0i))
Register(complex128(0i))
Register(uintptr(0))
Register(false)
Register("")
Register([]byte(nil))
Register([]int(nil))
Register([]int8(nil))
Register([]int16(nil))
Register([]int32(nil))
Register([]int64(nil))
Register([]uint(nil))
Register([]uint8(nil))
Register([]uint16(nil))
Register([]uint32(nil))
Register([]uint64(nil))
Register([]float32(nil))
Register([]float64(nil))
Register([]complex64(nil))
Register([]complex128(nil))
Register([]uintptr(nil))
Register([]bool(nil))
Register([]string(nil))
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin 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. |