package  runtimeimport  (	"internal/abi" 	"unsafe" )type  nameOff  = abi .NameOff type  typeOff  = abi .TypeOff type  textOff  = abi .TextOff type  _type  = abi .Type type  rtype  struct  {	*abi .Type  }func  (t  rtype ) string string  {	s  := t .nameOff (t .Str ).Name ()	if  t .TFlag &abi .TFlagExtraStar  != 0  {		return  s [1 :]	}	return  s }func  (t  rtype ) uncommon uncommontype  {	return  t .Uncommon ()}func  (t  rtype ) name string  {	if  t .TFlag &abi .TFlagNamed  == 0  {		return  "" 	}	s  := t .string ()	i  := len (s ) - 1 	sqBrackets  := 0 	for  i  >= 0  && (s [i ] != '.'  || sqBrackets  != 0 ) {		switch  s [i ] {		case  ']' :			sqBrackets ++		case  '[' :			sqBrackets --		}		i --	}	return  s [i +1 :]}func  (t  rtype ) pkgpath string  {	if  u  := t .uncommon (); u  != nil  {		return  t .nameOff (u .PkgPath ).Name ()	}	switch  t .Kind_  & abi .KindMask  {	case  abi .Struct :		st  := (*structtype )(unsafe .Pointer (t .Type ))		return  st .PkgPath .Name ()	case  abi .Interface :		it  := (*interfacetype )(unsafe .Pointer (t .Type ))		return  it .PkgPath .Name ()	}	return  "" }var  reflectOffs  struct  {	lock mutex 	next int32 	m    map [int32 ]unsafe .Pointer 	minv map [unsafe .Pointer ]int32 }func  reflectOffsLock 	lock (&reflectOffs .lock )	if  raceenabled  {		raceacquire (unsafe .Pointer (&reflectOffs .lock ))	}}func  reflectOffsUnlock 	if  raceenabled  {		racerelease (unsafe .Pointer (&reflectOffs .lock ))	}	unlock (&reflectOffs .lock )}func  resolveNameOff ptrInModule  unsafe .Pointer , off  nameOff ) name  {	if  off  == 0  {		return  name {}	}	base  := uintptr (ptrInModule )	for  md  := &firstmoduledata ; md  != nil ; md  = md .next  {		if  base  >= md .types  && base  < md .etypes  {			res  := md .types  + uintptr (off )			if  res  > md .etypes  {				println ("runtime: nameOff" , hex (off ), "out of range" , hex (md .types ), "-" , hex (md .etypes ))				throw ("runtime: name offset out of range" )			}			return  name {Bytes : (*byte )(unsafe .Pointer (res ))}		}	}		reflectOffsLock ()	res , found  := reflectOffs .m [int32 (off )]	reflectOffsUnlock ()	if  !found  {		println ("runtime: nameOff" , hex (off ), "base" , hex (base ), "not in ranges:" )		for  next  := &firstmoduledata ; next  != nil ; next  = next .next  {			println ("\ttypes" , hex (next .types ), "etypes" , hex (next .etypes ))		}		throw ("runtime: name offset base pointer out of range" )	}	return  name {Bytes : (*byte )(res )}}func  (t  rtype ) nameOff off  nameOff ) name  {	return  resolveNameOff (unsafe .Pointer (t .Type ), off )}func  resolveTypeOff ptrInModule  unsafe .Pointer , off  typeOff ) *_type  {	if  off  == 0  || off  == -1  {				return  nil 	}	base  := uintptr (ptrInModule )	var  md  *moduledata 	for  next  := &firstmoduledata ; next  != nil ; next  = next .next  {		if  base  >= next .types  && base  < next .etypes  {			md  = next 			break 		}	}	if  md  == nil  {		reflectOffsLock ()		res  := reflectOffs .m [int32 (off )]		reflectOffsUnlock ()		if  res  == nil  {			println ("runtime: typeOff" , hex (off ), "base" , hex (base ), "not in ranges:" )			for  next  := &firstmoduledata ; next  != nil ; next  = next .next  {				println ("\ttypes" , hex (next .types ), "etypes" , hex (next .etypes ))			}			throw ("runtime: type offset base pointer out of range" )		}		return  (*_type )(res )	}	if  t  := md .typemap [off ]; t  != nil  {		return  t 	}	res  := md .types  + uintptr (off )	if  res  > md .etypes  {		println ("runtime: typeOff" , hex (off ), "out of range" , hex (md .types ), "-" , hex (md .etypes ))		throw ("runtime: type offset out of range" )	}	return  (*_type )(unsafe .Pointer (res ))}func  (t  rtype ) typeOff off  typeOff ) *_type  {	return  resolveTypeOff (unsafe .Pointer (t .Type ), off )}func  (t  rtype ) textOff off  textOff ) unsafe .Pointer  {	if  off  == -1  {				return  unsafe .Pointer (abi .FuncPCABIInternal (unreachableMethod ))	}	base  := uintptr (unsafe .Pointer (t .Type ))	var  md  *moduledata 	for  next  := &firstmoduledata ; next  != nil ; next  = next .next  {		if  base  >= next .types  && base  < next .etypes  {			md  = next 			break 		}	}	if  md  == nil  {		reflectOffsLock ()		res  := reflectOffs .m [int32 (off )]		reflectOffsUnlock ()		if  res  == nil  {			println ("runtime: textOff" , hex (off ), "base" , hex (base ), "not in ranges:" )			for  next  := &firstmoduledata ; next  != nil ; next  = next .next  {				println ("\ttypes" , hex (next .types ), "etypes" , hex (next .etypes ))			}			throw ("runtime: text offset base pointer out of range" )		}		return  res 	}	res  := md .textAddr (uint32 (off ))	return  unsafe .Pointer (res )}type  uncommontype  = abi .UncommonType type  interfacetype  = abi .InterfaceType type  maptype  = abi .MapType type  arraytype  = abi .ArrayType type  chantype  = abi .ChanType type  slicetype  = abi .SliceType type  functype  = abi .FuncType type  ptrtype  = abi .PtrType type  name  = abi .Name type  structtype  = abi .StructType func  pkgPath n  name ) string  {	if  n .Bytes  == nil  || *n .Data (0 )&(1 <<2 ) == 0  {		return  "" 	}	i , l  := n .ReadVarint (1 )	off  := 1  + i  + l 	if  *n .Data (0 )&(1 <<1 ) != 0  {		i2 , l2  := n .ReadVarint (off )		off  += i2  + l2 	}	var  nameOff  nameOff 	copy ((*[4 ]byte )(unsafe .Pointer (&nameOff ))[:], (*[4 ]byte )(unsafe .Pointer (n .Data (off )))[:])	pkgPathName  := resolveNameOff (unsafe .Pointer (n .Bytes ), nameOff )	return  pkgPathName .Name ()}func  typelinksinit 	if  firstmoduledata .next  == nil  {		return 	}	typehash  := make (map [uint32 ][]*_type , len (firstmoduledata .typelinks ))	modules  := activeModules ()	prev  := modules [0 ]	for  _ , md  := range  modules [1 :] {			collect :		for  _ , tl  := range  prev .typelinks  {			var  t  *_type 			if  prev .typemap  == nil  {				t  = (*_type )(unsafe .Pointer (prev .types  + uintptr (tl )))			} else  {				t  = prev .typemap [typeOff (tl )]			}						tlist  := typehash [t .Hash ]			for  _ , tcur  := range  tlist  {				if  tcur  == t  {					continue  collect 				}			}			typehash [t .Hash ] = append (tlist , t )		}		if  md .typemap  == nil  {						tm  := make (map [typeOff ]*_type , len (md .typelinks ))			pinnedTypemaps  = append (pinnedTypemaps , tm )			md .typemap  = tm 			for  _ , tl  := range  md .typelinks  {				t  := (*_type )(unsafe .Pointer (md .types  + uintptr (tl )))				for  _ , candidate  := range  typehash [t .Hash ] {					seen  := map [_typePair ]struct {}{}					if  typesEqual (t , candidate , seen ) {						t  = candidate 						break 					}				}				md .typemap [typeOff (tl )] = t 			}		}		prev  = md 	}}type  _typePair  struct  {	t1  *_type 	t2  *_type }func  toRType t  *abi .Type ) rtype  {	return  rtype {t }}func  typesEqual t , v  *_type , seen  map [_typePair ]struct {}) bool  {	tp  := _typePair {t , v }	if  _ , ok  := seen [tp ]; ok  {		return  true 	}		seen [tp ] = struct {}{}	if  t  == v  {		return  true 	}	kind  := t .Kind_  & abi .KindMask 	if  kind  != v .Kind_ &abi .KindMask  {		return  false 	}	rt , rv  := toRType (t ), toRType (v )	if  rt .string () != rv .string () {		return  false 	}	ut  := t .Uncommon ()	uv  := v .Uncommon ()	if  ut  != nil  || uv  != nil  {		if  ut  == nil  || uv  == nil  {			return  false 		}		pkgpatht  := rt .nameOff (ut .PkgPath ).Name ()		pkgpathv  := rv .nameOff (uv .PkgPath ).Name ()		if  pkgpatht  != pkgpathv  {			return  false 		}	}	if  abi .Bool  <= kind  && kind  <= abi .Complex128  {		return  true 	}	switch  kind  {	case  abi .String , abi .UnsafePointer :		return  true 	case  abi .Array :		at  := (*arraytype )(unsafe .Pointer (t ))		av  := (*arraytype )(unsafe .Pointer (v ))		return  typesEqual (at .Elem , av .Elem , seen ) && at .Len  == av .Len 	case  abi .Chan :		ct  := (*chantype )(unsafe .Pointer (t ))		cv  := (*chantype )(unsafe .Pointer (v ))		return  ct .Dir  == cv .Dir  && typesEqual (ct .Elem , cv .Elem , seen )	case  abi .Func :		ft  := (*functype )(unsafe .Pointer (t ))		fv  := (*functype )(unsafe .Pointer (v ))		if  ft .OutCount  != fv .OutCount  || ft .InCount  != fv .InCount  {			return  false 		}		tin , vin  := ft .InSlice (), fv .InSlice ()		for  i  := 0 ; i  < len (tin ); i ++ {			if  !typesEqual (tin [i ], vin [i ], seen ) {				return  false 			}		}		tout , vout  := ft .OutSlice (), fv .OutSlice ()		for  i  := 0 ; i  < len (tout ); i ++ {			if  !typesEqual (tout [i ], vout [i ], seen ) {				return  false 			}		}		return  true 	case  abi .Interface :		it  := (*interfacetype )(unsafe .Pointer (t ))		iv  := (*interfacetype )(unsafe .Pointer (v ))		if  it .PkgPath .Name () != iv .PkgPath .Name () {			return  false 		}		if  len (it .Methods ) != len (iv .Methods ) {			return  false 		}		for  i  := range  it .Methods  {			tm  := &it .Methods [i ]			vm  := &iv .Methods [i ]						tname  := resolveNameOff (unsafe .Pointer (tm ), tm .Name )			vname  := resolveNameOff (unsafe .Pointer (vm ), vm .Name )			if  tname .Name () != vname .Name () {				return  false 			}			if  pkgPath (tname ) != pkgPath (vname ) {				return  false 			}			tityp  := resolveTypeOff (unsafe .Pointer (tm ), tm .Typ )			vityp  := resolveTypeOff (unsafe .Pointer (vm ), vm .Typ )			if  !typesEqual (tityp , vityp , seen ) {				return  false 			}		}		return  true 	case  abi .Map :		mt  := (*maptype )(unsafe .Pointer (t ))		mv  := (*maptype )(unsafe .Pointer (v ))		return  typesEqual (mt .Key , mv .Key , seen ) && typesEqual (mt .Elem , mv .Elem , seen )	case  abi .Pointer :		pt  := (*ptrtype )(unsafe .Pointer (t ))		pv  := (*ptrtype )(unsafe .Pointer (v ))		return  typesEqual (pt .Elem , pv .Elem , seen )	case  abi .Slice :		st  := (*slicetype )(unsafe .Pointer (t ))		sv  := (*slicetype )(unsafe .Pointer (v ))		return  typesEqual (st .Elem , sv .Elem , seen )	case  abi .Struct :		st  := (*structtype )(unsafe .Pointer (t ))		sv  := (*structtype )(unsafe .Pointer (v ))		if  len (st .Fields ) != len (sv .Fields ) {			return  false 		}		if  st .PkgPath .Name () != sv .PkgPath .Name () {			return  false 		}		for  i  := range  st .Fields  {			tf  := &st .Fields [i ]			vf  := &sv .Fields [i ]			if  tf .Name .Name () != vf .Name .Name () {				return  false 			}			if  !typesEqual (tf .Typ , vf .Typ , seen ) {				return  false 			}			if  tf .Name .Tag () != vf .Name .Tag () {				return  false 			}			if  tf .Offset  != vf .Offset  {				return  false 			}			if  tf .Name .IsEmbedded () != vf .Name .IsEmbedded () {				return  false 			}		}		return  true 	default :		println ("runtime: impossible type kind" , kind )		throw ("runtime: impossible type kind" )		return  false 	}} The pages are generated with Golds v0.7.6 . (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 @zigo_101  (reachable from the left QR code) to get the latest news of Golds .