github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/encoding/gob/type.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gob 6 7 import ( 8 "errors" 9 "fmt" 10 "os" 11 "reflect" 12 "sync" 13 "unicode" 14 "unicode/utf8" 15 ) 16 17 // userTypeInfo stores the information associated with a type the user has handed 18 // to the package. It's computed once and stored in a map keyed by reflection 19 // type. 20 type userTypeInfo struct { 21 user reflect.Type // the type the user handed us 22 base reflect.Type // the base type after all indirections 23 indir int // number of indirections to reach the base type 24 isGobEncoder bool // does the type implement GobEncoder? 25 isGobDecoder bool // does the type implement GobDecoder? 26 encIndir int8 // number of indirections to reach the receiver type; may be negative 27 decIndir int8 // number of indirections to reach the receiver type; may be negative 28 } 29 30 var ( 31 // Protected by an RWMutex because we read it a lot and write 32 // it only when we see a new type, typically when compiling. 33 userTypeLock sync.RWMutex 34 userTypeCache = make(map[reflect.Type]*userTypeInfo) 35 ) 36 37 // validType returns, and saves, the information associated with user-provided type rt. 38 // If the user type is not valid, err will be non-nil. To be used when the error handler 39 // is not set up. 40 func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) { 41 userTypeLock.RLock() 42 ut = userTypeCache[rt] 43 userTypeLock.RUnlock() 44 if ut != nil { 45 return 46 } 47 // Now set the value under the write lock. 48 userTypeLock.Lock() 49 defer userTypeLock.Unlock() 50 if ut = userTypeCache[rt]; ut != nil { 51 // Lost the race; not a problem. 52 return 53 } 54 ut = new(userTypeInfo) 55 ut.base = rt 56 ut.user = rt 57 // A type that is just a cycle of pointers (such as type T *T) cannot 58 // be represented in gobs, which need some concrete data. We use a 59 // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, 60 // pp 539-540. As we step through indirections, run another type at 61 // half speed. If they meet up, there's a cycle. 62 slowpoke := ut.base // walks half as fast as ut.base 63 for { 64 pt := ut.base 65 if pt.Kind() != reflect.Ptr { 66 break 67 } 68 ut.base = pt.Elem() 69 if ut.base == slowpoke { // ut.base lapped slowpoke 70 // recursive pointer type. 71 return nil, errors.New("can't represent recursive pointer type " + ut.base.String()) 72 } 73 if ut.indir%2 == 0 { 74 slowpoke = slowpoke.Elem() 75 } 76 ut.indir++ 77 } 78 ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType) 79 ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType) 80 userTypeCache[rt] = ut 81 return 82 } 83 84 var ( 85 gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem() 86 gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem() 87 ) 88 89 // implementsInterface reports whether the type implements the 90 // gobEncoder/gobDecoder interface. 91 // It also returns the number of indirections required to get to the 92 // implementation. 93 func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) { 94 if typ == nil { 95 return 96 } 97 rt := typ 98 // The type might be a pointer and we need to keep 99 // dereferencing to the base type until we find an implementation. 100 for { 101 if rt.Implements(gobEncDecType) { 102 return true, indir 103 } 104 if p := rt; p.Kind() == reflect.Ptr { 105 indir++ 106 if indir > 100 { // insane number of indirections 107 return false, 0 108 } 109 rt = p.Elem() 110 continue 111 } 112 break 113 } 114 // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. 115 if typ.Kind() != reflect.Ptr { 116 // Not a pointer, but does the pointer work? 117 if reflect.PtrTo(typ).Implements(gobEncDecType) { 118 return true, -1 119 } 120 } 121 return false, 0 122 } 123 124 // userType returns, and saves, the information associated with user-provided type rt. 125 // If the user type is not valid, it calls error. 126 func userType(rt reflect.Type) *userTypeInfo { 127 ut, err := validUserType(rt) 128 if err != nil { 129 error_(err) 130 } 131 return ut 132 } 133 134 // A typeId represents a gob Type as an integer that can be passed on the wire. 135 // Internally, typeIds are used as keys to a map to recover the underlying type info. 136 type typeId int32 137 138 var nextId typeId // incremented for each new type we build 139 var typeLock sync.Mutex // set while building a type 140 const firstUserId = 64 // lowest id number granted to user 141 142 type gobType interface { 143 id() typeId 144 setId(id typeId) 145 name() string 146 string() string // not public; only for debugging 147 safeString(seen map[typeId]bool) string 148 } 149 150 var types = make(map[reflect.Type]gobType) 151 var idToType = make(map[typeId]gobType) 152 var builtinIdToType map[typeId]gobType // set in init() after builtins are established 153 154 func setTypeId(typ gobType) { 155 // When building recursive types, someone may get there before us. 156 if typ.id() != 0 { 157 return 158 } 159 nextId++ 160 typ.setId(nextId) 161 idToType[nextId] = typ 162 } 163 164 func (t typeId) gobType() gobType { 165 if t == 0 { 166 return nil 167 } 168 return idToType[t] 169 } 170 171 // string returns the string representation of the type associated with the typeId. 172 func (t typeId) string() string { 173 if t.gobType() == nil { 174 return "<nil>" 175 } 176 return t.gobType().string() 177 } 178 179 // Name returns the name of the type associated with the typeId. 180 func (t typeId) name() string { 181 if t.gobType() == nil { 182 return "<nil>" 183 } 184 return t.gobType().name() 185 } 186 187 // CommonType holds elements of all types. 188 // It is a historical artifact, kept for binary compatibility and exported 189 // only for the benefit of the package's encoding of type descriptors. It is 190 // not intended for direct use by clients. 191 type CommonType struct { 192 Name string 193 Id typeId 194 } 195 196 func (t *CommonType) id() typeId { return t.Id } 197 198 func (t *CommonType) setId(id typeId) { t.Id = id } 199 200 func (t *CommonType) string() string { return t.Name } 201 202 func (t *CommonType) safeString(seen map[typeId]bool) string { 203 return t.Name 204 } 205 206 func (t *CommonType) name() string { return t.Name } 207 208 // Create and check predefined types 209 // The string for tBytes is "bytes" not "[]byte" to signify its specialness. 210 211 var ( 212 // Primordial types, needed during initialization. 213 // Always passed as pointers so the interface{} type 214 // goes through without losing its interfaceness. 215 tBool = bootstrapType("bool", (*bool)(nil), 1) 216 tInt = bootstrapType("int", (*int)(nil), 2) 217 tUint = bootstrapType("uint", (*uint)(nil), 3) 218 tFloat = bootstrapType("float", (*float64)(nil), 4) 219 tBytes = bootstrapType("bytes", (*[]byte)(nil), 5) 220 tString = bootstrapType("string", (*string)(nil), 6) 221 tComplex = bootstrapType("complex", (*complex128)(nil), 7) 222 tInterface = bootstrapType("interface", (*interface{})(nil), 8) 223 // Reserve some Ids for compatible expansion 224 tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil), 9) 225 tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil), 10) 226 tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil), 11) 227 tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil), 12) 228 tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil), 13) 229 tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil), 14) 230 tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil), 15) 231 ) 232 233 // Predefined because it's needed by the Decoder 234 var tWireType = mustGetTypeInfo(reflect.TypeOf(wireType{})).id 235 var wireTypeUserInfo *userTypeInfo // userTypeInfo of (*wireType) 236 237 func init() { 238 // Some magic numbers to make sure there are no surprises. 239 checkId(16, tWireType) 240 checkId(17, mustGetTypeInfo(reflect.TypeOf(arrayType{})).id) 241 checkId(18, mustGetTypeInfo(reflect.TypeOf(CommonType{})).id) 242 checkId(19, mustGetTypeInfo(reflect.TypeOf(sliceType{})).id) 243 checkId(20, mustGetTypeInfo(reflect.TypeOf(structType{})).id) 244 checkId(21, mustGetTypeInfo(reflect.TypeOf(fieldType{})).id) 245 checkId(23, mustGetTypeInfo(reflect.TypeOf(mapType{})).id) 246 247 builtinIdToType = make(map[typeId]gobType) 248 for k, v := range idToType { 249 builtinIdToType[k] = v 250 } 251 252 // Move the id space upwards to allow for growth in the predefined world 253 // without breaking existing files. 254 if nextId > firstUserId { 255 panic(fmt.Sprintln("nextId too large:", nextId)) 256 } 257 nextId = firstUserId 258 registerBasics() 259 wireTypeUserInfo = userType(reflect.TypeOf((*wireType)(nil))) 260 } 261 262 // Array type 263 type arrayType struct { 264 CommonType 265 Elem typeId 266 Len int 267 } 268 269 func newArrayType(name string) *arrayType { 270 a := &arrayType{CommonType{Name: name}, 0, 0} 271 return a 272 } 273 274 func (a *arrayType) init(elem gobType, len int) { 275 // Set our type id before evaluating the element's, in case it's our own. 276 setTypeId(a) 277 a.Elem = elem.id() 278 a.Len = len 279 } 280 281 func (a *arrayType) safeString(seen map[typeId]bool) string { 282 if seen[a.Id] { 283 return a.Name 284 } 285 seen[a.Id] = true 286 return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) 287 } 288 289 func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } 290 291 // GobEncoder type (something that implements the GobEncoder interface) 292 type gobEncoderType struct { 293 CommonType 294 } 295 296 func newGobEncoderType(name string) *gobEncoderType { 297 g := &gobEncoderType{CommonType{Name: name}} 298 setTypeId(g) 299 return g 300 } 301 302 func (g *gobEncoderType) safeString(seen map[typeId]bool) string { 303 return g.Name 304 } 305 306 func (g *gobEncoderType) string() string { return g.Name } 307 308 // Map type 309 type mapType struct { 310 CommonType 311 Key typeId 312 Elem typeId 313 } 314 315 func newMapType(name string) *mapType { 316 m := &mapType{CommonType{Name: name}, 0, 0} 317 return m 318 } 319 320 func (m *mapType) init(key, elem gobType) { 321 // Set our type id before evaluating the element's, in case it's our own. 322 setTypeId(m) 323 m.Key = key.id() 324 m.Elem = elem.id() 325 } 326 327 func (m *mapType) safeString(seen map[typeId]bool) string { 328 if seen[m.Id] { 329 return m.Name 330 } 331 seen[m.Id] = true 332 key := m.Key.gobType().safeString(seen) 333 elem := m.Elem.gobType().safeString(seen) 334 return fmt.Sprintf("map[%s]%s", key, elem) 335 } 336 337 func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } 338 339 // Slice type 340 type sliceType struct { 341 CommonType 342 Elem typeId 343 } 344 345 func newSliceType(name string) *sliceType { 346 s := &sliceType{CommonType{Name: name}, 0} 347 return s 348 } 349 350 func (s *sliceType) init(elem gobType) { 351 // Set our type id before evaluating the element's, in case it's our own. 352 setTypeId(s) 353 // See the comments about ids in newTypeObject. Only slices and 354 // structs have mutual recursion. 355 if elem.id() == 0 { 356 setTypeId(elem) 357 } 358 s.Elem = elem.id() 359 } 360 361 func (s *sliceType) safeString(seen map[typeId]bool) string { 362 if seen[s.Id] { 363 return s.Name 364 } 365 seen[s.Id] = true 366 return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) 367 } 368 369 func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } 370 371 // Struct type 372 type fieldType struct { 373 Name string 374 Id typeId 375 } 376 377 type structType struct { 378 CommonType 379 Field []*fieldType 380 } 381 382 func (s *structType) safeString(seen map[typeId]bool) string { 383 if s == nil { 384 return "<nil>" 385 } 386 if _, ok := seen[s.Id]; ok { 387 return s.Name 388 } 389 seen[s.Id] = true 390 str := s.Name + " = struct { " 391 for _, f := range s.Field { 392 str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) 393 } 394 str += "}" 395 return str 396 } 397 398 func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } 399 400 func newStructType(name string) *structType { 401 s := &structType{CommonType{Name: name}, nil} 402 // For historical reasons we set the id here rather than init. 403 // See the comment in newTypeObject for details. 404 setTypeId(s) 405 return s 406 } 407 408 // newTypeObject allocates a gobType for the reflection type rt. 409 // Unless ut represents a GobEncoder, rt should be the base type 410 // of ut. 411 // This is only called from the encoding side. The decoding side 412 // works through typeIds and userTypeInfos alone. 413 func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { 414 // Does this type implement GobEncoder? 415 if ut.isGobEncoder { 416 return newGobEncoderType(name), nil 417 } 418 var err error 419 var type0, type1 gobType 420 defer func() { 421 if err != nil { 422 delete(types, rt) 423 } 424 }() 425 // Install the top-level type before the subtypes (e.g. struct before 426 // fields) so recursive types can be constructed safely. 427 switch t := rt; t.Kind() { 428 // All basic types are easy: they are predefined. 429 case reflect.Bool: 430 return tBool.gobType(), nil 431 432 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 433 return tInt.gobType(), nil 434 435 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 436 return tUint.gobType(), nil 437 438 case reflect.Float32, reflect.Float64: 439 return tFloat.gobType(), nil 440 441 case reflect.Complex64, reflect.Complex128: 442 return tComplex.gobType(), nil 443 444 case reflect.String: 445 return tString.gobType(), nil 446 447 case reflect.Interface: 448 return tInterface.gobType(), nil 449 450 case reflect.Array: 451 at := newArrayType(name) 452 types[rt] = at 453 type0, err = getBaseType("", t.Elem()) 454 if err != nil { 455 return nil, err 456 } 457 // Historical aside: 458 // For arrays, maps, and slices, we set the type id after the elements 459 // are constructed. This is to retain the order of type id allocation after 460 // a fix made to handle recursive types, which changed the order in 461 // which types are built. Delaying the setting in this way preserves 462 // type ids while allowing recursive types to be described. Structs, 463 // done below, were already handling recursion correctly so they 464 // assign the top-level id before those of the field. 465 at.init(type0, t.Len()) 466 return at, nil 467 468 case reflect.Map: 469 mt := newMapType(name) 470 types[rt] = mt 471 type0, err = getBaseType("", t.Key()) 472 if err != nil { 473 return nil, err 474 } 475 type1, err = getBaseType("", t.Elem()) 476 if err != nil { 477 return nil, err 478 } 479 mt.init(type0, type1) 480 return mt, nil 481 482 case reflect.Slice: 483 // []byte == []uint8 is a special case 484 if t.Elem().Kind() == reflect.Uint8 { 485 return tBytes.gobType(), nil 486 } 487 st := newSliceType(name) 488 types[rt] = st 489 type0, err = getBaseType(t.Elem().Name(), t.Elem()) 490 if err != nil { 491 return nil, err 492 } 493 st.init(type0) 494 return st, nil 495 496 case reflect.Struct: 497 st := newStructType(name) 498 types[rt] = st 499 idToType[st.id()] = st 500 for i := 0; i < t.NumField(); i++ { 501 f := t.Field(i) 502 if !isExported(f.Name) { 503 continue 504 } 505 typ := userType(f.Type).base 506 tname := typ.Name() 507 if tname == "" { 508 t := userType(f.Type).base 509 tname = t.String() 510 } 511 gt, err := getBaseType(tname, f.Type) 512 if err != nil { 513 return nil, err 514 } 515 // Some mutually recursive types can cause us to be here while 516 // still defining the element. Fix the element type id here. 517 // We could do this more neatly by setting the id at the start of 518 // building every type, but that would break binary compatibility. 519 if gt.id() == 0 { 520 setTypeId(gt) 521 } 522 st.Field = append(st.Field, &fieldType{f.Name, gt.id()}) 523 } 524 return st, nil 525 526 default: 527 return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String()) 528 } 529 } 530 531 // isExported reports whether this is an exported - upper case - name. 532 func isExported(name string) bool { 533 rune, _ := utf8.DecodeRuneInString(name) 534 return unicode.IsUpper(rune) 535 } 536 537 // getBaseType returns the Gob type describing the given reflect.Type's base type. 538 // typeLock must be held. 539 func getBaseType(name string, rt reflect.Type) (gobType, error) { 540 ut := userType(rt) 541 return getType(name, ut, ut.base) 542 } 543 544 // getType returns the Gob type describing the given reflect.Type. 545 // Should be called only when handling GobEncoders/Decoders, 546 // which may be pointers. All other types are handled through the 547 // base type, never a pointer. 548 // typeLock must be held. 549 func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { 550 typ, present := types[rt] 551 if present { 552 return typ, nil 553 } 554 typ, err := newTypeObject(name, ut, rt) 555 if err == nil { 556 types[rt] = typ 557 } 558 return typ, err 559 } 560 561 func checkId(want, got typeId) { 562 if want != got { 563 fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) 564 panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) 565 } 566 } 567 568 // used for building the basic types; called only from init(). the incoming 569 // interface always refers to a pointer. 570 func bootstrapType(name string, e interface{}, expect typeId) typeId { 571 rt := reflect.TypeOf(e).Elem() 572 _, present := types[rt] 573 if present { 574 panic("bootstrap type already present: " + name + ", " + rt.String()) 575 } 576 typ := &CommonType{Name: name} 577 types[rt] = typ 578 setTypeId(typ) 579 checkId(expect, nextId) 580 userType(rt) // might as well cache it now 581 return nextId 582 } 583 584 // Representation of the information we send and receive about this type. 585 // Each value we send is preceded by its type definition: an encoded int. 586 // However, the very first time we send the value, we first send the pair 587 // (-id, wireType). 588 // For bootstrapping purposes, we assume that the recipient knows how 589 // to decode a wireType; it is exactly the wireType struct here, interpreted 590 // using the gob rules for sending a structure, except that we assume the 591 // ids for wireType and structType etc. are known. The relevant pieces 592 // are built in encode.go's init() function. 593 // To maintain binary compatibility, if you extend this type, always put 594 // the new fields last. 595 type wireType struct { 596 ArrayT *arrayType 597 SliceT *sliceType 598 StructT *structType 599 MapT *mapType 600 GobEncoderT *gobEncoderType 601 } 602 603 func (w *wireType) string() string { 604 const unknown = "unknown type" 605 if w == nil { 606 return unknown 607 } 608 switch { 609 case w.ArrayT != nil: 610 return w.ArrayT.Name 611 case w.SliceT != nil: 612 return w.SliceT.Name 613 case w.StructT != nil: 614 return w.StructT.Name 615 case w.MapT != nil: 616 return w.MapT.Name 617 case w.GobEncoderT != nil: 618 return w.GobEncoderT.Name 619 } 620 return unknown 621 } 622 623 type typeInfo struct { 624 id typeId 625 encoder *encEngine 626 wire *wireType 627 } 628 629 var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock 630 631 // typeLock must be held. 632 func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { 633 rt := ut.base 634 if ut.isGobEncoder { 635 // We want the user type, not the base type. 636 rt = ut.user 637 } 638 info, ok := typeInfoMap[rt] 639 if ok { 640 return info, nil 641 } 642 info = new(typeInfo) 643 gt, err := getBaseType(rt.Name(), rt) 644 if err != nil { 645 return nil, err 646 } 647 info.id = gt.id() 648 649 if ut.isGobEncoder { 650 userType, err := getType(rt.Name(), ut, rt) 651 if err != nil { 652 return nil, err 653 } 654 info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)} 655 typeInfoMap[ut.user] = info 656 return info, nil 657 } 658 659 t := info.id.gobType() 660 switch typ := rt; typ.Kind() { 661 case reflect.Array: 662 info.wire = &wireType{ArrayT: t.(*arrayType)} 663 case reflect.Map: 664 info.wire = &wireType{MapT: t.(*mapType)} 665 case reflect.Slice: 666 // []byte == []uint8 is a special case handled separately 667 if typ.Elem().Kind() != reflect.Uint8 { 668 info.wire = &wireType{SliceT: t.(*sliceType)} 669 } 670 case reflect.Struct: 671 info.wire = &wireType{StructT: t.(*structType)} 672 } 673 typeInfoMap[rt] = info 674 return info, nil 675 } 676 677 // Called only when a panic is acceptable and unexpected. 678 func mustGetTypeInfo(rt reflect.Type) *typeInfo { 679 t, err := getTypeInfo(userType(rt)) 680 if err != nil { 681 panic("getTypeInfo: " + err.Error()) 682 } 683 return t 684 } 685 686 // GobEncoder is the interface describing data that provides its own 687 // representation for encoding values for transmission to a GobDecoder. 688 // A type that implements GobEncoder and GobDecoder has complete 689 // control over the representation of its data and may therefore 690 // contain things such as private fields, channels, and functions, 691 // which are not usually transmissible in gob streams. 692 // 693 // Note: Since gobs can be stored permanently, It is good design 694 // to guarantee the encoding used by a GobEncoder is stable as the 695 // software evolves. For instance, it might make sense for GobEncode 696 // to include a version number in the encoding. 697 type GobEncoder interface { 698 // GobEncode returns a byte slice representing the encoding of the 699 // receiver for transmission to a GobDecoder, usually of the same 700 // concrete type. 701 GobEncode() ([]byte, error) 702 } 703 704 // GobDecoder is the interface describing data that provides its own 705 // routine for decoding transmitted values sent by a GobEncoder. 706 type GobDecoder interface { 707 // GobDecode overwrites the receiver, which must be a pointer, 708 // with the value represented by the byte slice, which was written 709 // by GobEncode, usually for the same concrete type. 710 GobDecode([]byte) error 711 } 712 713 var ( 714 registerLock sync.RWMutex 715 nameToConcreteType = make(map[string]reflect.Type) 716 concreteTypeToName = make(map[reflect.Type]string) 717 ) 718 719 // RegisterName is like Register but uses the provided name rather than the 720 // type's default. 721 func RegisterName(name string, value interface{}) { 722 if name == "" { 723 // reserved for nil 724 panic("attempt to register empty name") 725 } 726 registerLock.Lock() 727 defer registerLock.Unlock() 728 ut := userType(reflect.TypeOf(value)) 729 // Check for incompatible duplicates. The name must refer to the 730 // same user type, and vice versa. 731 if t, ok := nameToConcreteType[name]; ok && t != ut.user { 732 panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user)) 733 } 734 if n, ok := concreteTypeToName[ut.base]; ok && n != name { 735 panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name)) 736 } 737 // Store the name and type provided by the user.... 738 nameToConcreteType[name] = reflect.TypeOf(value) 739 // but the flattened type in the type table, since that's what decode needs. 740 concreteTypeToName[ut.base] = name 741 } 742 743 // Register records a type, identified by a value for that type, under its 744 // internal type name. That name will identify the concrete type of a value 745 // sent or received as an interface variable. Only types that will be 746 // transferred as implementations of interface values need to be registered. 747 // Expecting to be used only during initialization, it panics if the mapping 748 // between types and names is not a bijection. 749 func Register(value interface{}) { 750 // Default to printed representation for unnamed types 751 rt := reflect.TypeOf(value) 752 name := rt.String() 753 754 // But for named types (or pointers to them), qualify with import path (but see inner comment). 755 // Dereference one pointer looking for a named type. 756 star := "" 757 if rt.Name() == "" { 758 if pt := rt; pt.Kind() == reflect.Ptr { 759 star = "*" 760 // NOTE: The following line should be rt = pt.Elem() to implement 761 // what the comment above claims, but fixing it would break compatibility 762 // with existing gobs. 763 // 764 // Given package p imported as "full/p" with these definitions: 765 // package p 766 // type T1 struct { ... } 767 // this table shows the intended and actual strings used by gob to 768 // name the types: 769 // 770 // Type Correct string Actual string 771 // 772 // T1 full/p.T1 full/p.T1 773 // *T1 *full/p.T1 *p.T1 774 // 775 // The missing full path cannot be fixed without breaking existing gob decoders. 776 rt = pt 777 } 778 } 779 if rt.Name() != "" { 780 if rt.PkgPath() == "" { 781 name = star + rt.Name() 782 } else { 783 name = star + rt.PkgPath() + "." + rt.Name() 784 } 785 } 786 787 RegisterName(name, value) 788 } 789 790 func registerBasics() { 791 Register(int(0)) 792 Register(int8(0)) 793 Register(int16(0)) 794 Register(int32(0)) 795 Register(int64(0)) 796 Register(uint(0)) 797 Register(uint8(0)) 798 Register(uint16(0)) 799 Register(uint32(0)) 800 Register(uint64(0)) 801 Register(float32(0)) 802 Register(float64(0)) 803 Register(complex64(0i)) 804 Register(complex128(0i)) 805 Register(uintptr(0)) 806 Register(false) 807 Register("") 808 Register([]byte(nil)) 809 Register([]int(nil)) 810 Register([]int8(nil)) 811 Register([]int16(nil)) 812 Register([]int32(nil)) 813 Register([]int64(nil)) 814 Register([]uint(nil)) 815 Register([]uint8(nil)) 816 Register([]uint16(nil)) 817 Register([]uint32(nil)) 818 Register([]uint64(nil)) 819 Register([]float32(nil)) 820 Register([]float64(nil)) 821 Register([]complex64(nil)) 822 Register([]complex128(nil)) 823 Register([]uintptr(nil)) 824 Register([]bool(nil)) 825 Register([]string(nil)) 826 }