code: func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
  	tinfoLock.RLock()
  	tinfo, ok := tinfoMap[typ]
  	tinfoLock.RUnlock()
  	if ok {
  		return tinfo, nil
  	}
  	tinfo = &typeInfo{}
  	if typ.Kind() == reflect.Struct && typ != nameType {
  		n := typ.NumField()
  		for i := 0; i < n; i++ {
  			f := typ.Field(i)
  			if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
  				continue // Private field
  			}
  
  			// For embedded structs, embed its fields.
  			if f.Anonymous {
  				t := f.Type
  				if t.Kind() == reflect.Ptr {
  					t = t.Elem()
  				}
  				if t.Kind() == reflect.Struct {
  					inner, err := getTypeInfo(t)
  					if err != nil {
  						return nil, err
  					}
  					if tinfo.xmlname == nil {
  						tinfo.xmlname = inner.xmlname
  					}
  					for _, finfo := range inner.fields {
  						finfo.idx = append([]int{i}, finfo.idx...)
  						if err := addFieldInfo(typ, tinfo, &finfo); err != nil {
  							return nil, err
  						}
  					}
  					continue
  				}
  			}
  
  			finfo, err := structFieldInfo(typ, &f)
  			if err != nil {
  				return nil, err
  			}
  
  			if f.Name == "XMLName" {
  				tinfo.xmlname = finfo
  				continue
  			}
  
  			// Add the field if it doesn't conflict with other fields.
  			if err := addFieldInfo(typ, tinfo, finfo); err != nil {
  				return nil, err
  			}
  		}
  	}
  	tinfoLock.Lock()
  	tinfoMap[typ] = tinfo
  	tinfoLock.Unlock()
  	return tinfo, nil
  }
docs: // getTypeInfo returns the typeInfo structure with details necessary
  // for marshalling and unmarshalling typ.