github.com/leromarinvit/typist@v0.0.0-20170209001249-15cee4975bef/from_string.go (about) 1 // Package typist gets a reflect.Type for a type specified by a string. 2 package typist 3 4 import ( 5 "fmt" 6 "reflect" 7 "unsafe" 8 ) 9 10 //go:linkname typesByString reflect.typesByString 11 func typesByString(s string) []unsafe.Pointer 12 13 /* 14 TypeByString tries to find a reflect.Type corresponding to the type specified by 15 s. 16 17 It calls the unexported `reflect.typesByString` to do so. It will fail if 18 the type can't be found or if more than one type with the given name exist. 19 20 This relies on the following assumptions: 21 * The signature of `reflect.typesByString` must not change 22 * The value returned by `reflect.TypeOf(0)` is a `*reflect.rtype` 23 * The `reflect.Value` struct contains a `ptr` field of type `unsafe.Pointer` 24 */ 25 func TypeByString(s string) (reflect.Type, error) { 26 types := typesByString(s) 27 28 if len(types) == 0 { 29 return nil, fmt.Errorf("Type '%s' not found", s) 30 } 31 if len(types) > 1 { 32 return nil, fmt.Errorf("Type '%s' is ambiguous", s) 33 } 34 35 t := types[0] 36 37 pRtypeType := reflect.ValueOf(reflect.TypeOf(0)).Type() 38 rtype := reflect.New(pRtypeType).Elem() 39 40 ptr := unsafe.Pointer(reflect.ValueOf(rtype).FieldByName("ptr").Pointer()) 41 *(*unsafe.Pointer)(ptr) = t 42 43 typ := rtype.Interface().(reflect.Type) 44 return typ, nil 45 }