package reflect2
import (
"reflect"
"runtime"
"sync"
"unsafe"
)
type Type interface {
Kind () reflect .Kind
New () interface {}
UnsafeNew () unsafe .Pointer
PackEFace (ptr unsafe .Pointer ) interface {}
Indirect (obj interface {}) interface {}
UnsafeIndirect (ptr unsafe .Pointer ) interface {}
Type1 () reflect .Type
Implements (thatType Type ) bool
String () string
RType () uintptr
LikePtr () bool
IsNullable () bool
IsNil (obj interface {}) bool
UnsafeIsNil (ptr unsafe .Pointer ) bool
Set (obj interface {}, val interface {})
UnsafeSet (ptr unsafe .Pointer , val unsafe .Pointer )
AssignableTo (anotherType Type ) bool
}
type ListType interface {
Type
Elem () Type
SetIndex (obj interface {}, index int , elem interface {})
UnsafeSetIndex (obj unsafe .Pointer , index int , elem unsafe .Pointer )
GetIndex (obj interface {}, index int ) interface {}
UnsafeGetIndex (obj unsafe .Pointer , index int ) unsafe .Pointer
}
type ArrayType interface {
ListType
Len () int
}
type SliceType interface {
ListType
MakeSlice (length int , cap int ) interface {}
UnsafeMakeSlice (length int , cap int ) unsafe .Pointer
Grow (obj interface {}, newLength int )
UnsafeGrow (ptr unsafe .Pointer , newLength int )
Append (obj interface {}, elem interface {})
UnsafeAppend (obj unsafe .Pointer , elem unsafe .Pointer )
LengthOf (obj interface {}) int
UnsafeLengthOf (ptr unsafe .Pointer ) int
SetNil (obj interface {})
UnsafeSetNil (ptr unsafe .Pointer )
Cap (obj interface {}) int
UnsafeCap (ptr unsafe .Pointer ) int
}
type StructType interface {
Type
NumField () int
Field (i int ) StructField
FieldByName (name string ) StructField
FieldByIndex (index []int ) StructField
FieldByNameFunc (match func (string ) bool ) StructField
}
type StructField interface {
Offset () uintptr
Name () string
PkgPath () string
Type () Type
Tag () reflect .StructTag
Index () []int
Anonymous () bool
Set (obj interface {}, value interface {})
UnsafeSet (obj unsafe .Pointer , value unsafe .Pointer )
Get (obj interface {}) interface {}
UnsafeGet (obj unsafe .Pointer ) unsafe .Pointer
}
type MapType interface {
Type
Key () Type
Elem () Type
MakeMap (cap int ) interface {}
UnsafeMakeMap (cap int ) unsafe .Pointer
SetIndex (obj interface {}, key interface {}, elem interface {})
UnsafeSetIndex (obj unsafe .Pointer , key unsafe .Pointer , elem unsafe .Pointer )
TryGetIndex (obj interface {}, key interface {}) (interface {}, bool )
GetIndex (obj interface {}, key interface {}) interface {}
UnsafeGetIndex (obj unsafe .Pointer , key unsafe .Pointer ) unsafe .Pointer
Iterate (obj interface {}) MapIterator
UnsafeIterate (obj unsafe .Pointer ) MapIterator
}
type MapIterator interface {
HasNext () bool
Next () (key interface {}, elem interface {})
UnsafeNext () (key unsafe .Pointer , elem unsafe .Pointer )
}
type PtrType interface {
Type
Elem () Type
}
type InterfaceType interface {
NumMethod () int
}
type Config struct {
UseSafeImplementation bool
}
type API interface {
TypeOf (obj interface {}) Type
Type2 (type1 reflect .Type ) Type
}
var ConfigUnsafe = Config {UseSafeImplementation : false }.Froze ()
var ConfigSafe = Config {UseSafeImplementation : true }.Froze ()
type frozenConfig struct {
useSafeImplementation bool
cache *sync .Map
}
func (cfg Config ) Froze () *frozenConfig {
return &frozenConfig {
useSafeImplementation : cfg .UseSafeImplementation ,
cache : new (sync .Map ),
}
}
func (cfg *frozenConfig ) TypeOf (obj interface {}) Type {
cacheKey := uintptr (unpackEFace (obj ).rtype )
typeObj , found := cfg .cache .Load (cacheKey )
if found {
return typeObj .(Type )
}
return cfg .Type2 (reflect .TypeOf (obj ))
}
func (cfg *frozenConfig ) Type2 (type1 reflect .Type ) Type {
if type1 == nil {
return nil
}
cacheKey := uintptr (unpackEFace (type1 ).data )
typeObj , found := cfg .cache .Load (cacheKey )
if found {
return typeObj .(Type )
}
type2 := cfg .wrapType (type1 )
cfg .cache .Store (cacheKey , type2 )
return type2
}
func (cfg *frozenConfig ) wrapType (type1 reflect .Type ) Type {
safeType := safeType {Type : type1 , cfg : cfg }
switch type1 .Kind () {
case reflect .Struct :
if cfg .useSafeImplementation {
return &safeStructType {safeType }
}
return newUnsafeStructType (cfg , type1 )
case reflect .Array :
if cfg .useSafeImplementation {
return &safeSliceType {safeType }
}
return newUnsafeArrayType (cfg , type1 )
case reflect .Slice :
if cfg .useSafeImplementation {
return &safeSliceType {safeType }
}
return newUnsafeSliceType (cfg , type1 )
case reflect .Map :
if cfg .useSafeImplementation {
return &safeMapType {safeType }
}
return newUnsafeMapType (cfg , type1 )
case reflect .Ptr , reflect .Chan , reflect .Func :
if cfg .useSafeImplementation {
return &safeMapType {safeType }
}
return newUnsafePtrType (cfg , type1 )
case reflect .Interface :
if cfg .useSafeImplementation {
return &safeMapType {safeType }
}
if type1 .NumMethod () == 0 {
return newUnsafeEFaceType (cfg , type1 )
}
return newUnsafeIFaceType (cfg , type1 )
default :
if cfg .useSafeImplementation {
return &safeType
}
return newUnsafeType (cfg , type1 )
}
}
func TypeOf (obj interface {}) Type {
return ConfigUnsafe .TypeOf (obj )
}
func TypeOfPtr (obj interface {}) PtrType {
return TypeOf (obj ).(PtrType )
}
func Type2 (type1 reflect .Type ) Type {
if type1 == nil {
return nil
}
return ConfigUnsafe .Type2 (type1 )
}
func PtrTo (typ Type ) Type {
return Type2 (reflect .PtrTo (typ .Type1 ()))
}
func PtrOf (obj interface {}) unsafe .Pointer {
return unpackEFace (obj ).data
}
func RTypeOf (obj interface {}) uintptr {
return uintptr (unpackEFace (obj ).rtype )
}
func IsNil (obj interface {}) bool {
if obj == nil {
return true
}
return unpackEFace (obj ).data == nil
}
func IsNullable (kind reflect .Kind ) bool {
switch kind {
case reflect .Ptr , reflect .Map , reflect .Chan , reflect .Func , reflect .Slice , reflect .Interface :
return true
}
return false
}
func likePtrKind(kind reflect .Kind ) bool {
switch kind {
case reflect .Ptr , reflect .Map , reflect .Chan , reflect .Func :
return true
}
return false
}
func likePtrType(typ reflect .Type ) bool {
if likePtrKind (typ .Kind ()) {
return true
}
if typ .Kind () == reflect .Struct {
if typ .NumField () != 1 {
return false
}
return likePtrType (typ .Field (0 ).Type )
}
if typ .Kind () == reflect .Array {
if typ .Len () != 1 {
return false
}
return likePtrType (typ .Elem ())
}
return false
}
func NoEscape (p unsafe .Pointer ) unsafe .Pointer {
x := uintptr (p )
return unsafe .Pointer (x ^ 0 )
}
func UnsafeCastString (str string ) []byte {
bytes := make ([]byte , 0 )
stringHeader := (*reflect .StringHeader )(unsafe .Pointer (&str ))
sliceHeader := (*reflect .SliceHeader )(unsafe .Pointer (&bytes ))
sliceHeader .Data = stringHeader .Data
sliceHeader .Cap = stringHeader .Len
sliceHeader .Len = stringHeader .Len
runtime .KeepAlive (str )
return bytes
}
The pages are generated with Golds v0.8.2 . (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 .