Skip to content

Instantly share code, notes, and snippets.

@rbranson
Created April 28, 2018 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rbranson/1d0bc8ccae75afd91fc633381084b149 to your computer and use it in GitHub Desktop.
Save rbranson/1d0bc8ccae75afd91fc633381084b149 to your computer and use it in GitHub Desktop.
package stupid
import (
"fmt"
"reflect"
"unsafe"
)
type iptr struct {
itab uintptr
ptr uintptr
}
func (p iptr) String() string {
return fmt.Sprintf("itab=0x%x, ptr=0x%x", p.itab, p.ptr)
}
func (p iptr) Interface() interface{} {
return *(*interface{})(unsafe.Pointer(&p))
}
type interfaceFactory struct {
ptritab unsafe.Pointer
}
func newInterfaceFactory(t reflect.Type) interfaceFactory {
// Need something valid to point at, just a throwaway
tmp := struct{}{}
ptr := unsafe.Pointer(&tmp)
// Construct a pointer of type *t that points at tmp
ptrPtrVal := reflect.NewAt(t, ptr)
// Build interface{*t, ptrPtrVal=>tmp}
ptrPtrIface := ptrPtrVal.Interface()
// Coerce the above interface{} into a touchable struct
ptrPtrIptr := *(*iptr)(unsafe.Pointer(&ptrPtrIface))
// All we care about is the itab field, which contains the
// type information to copy onto factory-created interface{}s
itabPtr := unsafe.Pointer(ptrPtrIptr.itab)
return interfaceFactory{
ptritab: itabPtr,
}
}
// takes interface{Struct, ptr=>struct}, returns interface{*FieldType, ptr=>&struct.field}
func (f *interfaceFactory) PtrToStructField(any interface{}, field reflect.StructField) interface{} {
// creates an iptr struct out of the 'any' interface
anyIptr := *(*iptr)(unsafe.Pointer(&any))
// construct the new pointer (&struct.field) that will be returned
interptr := unsafe.Pointer(anyIptr.ptr + field.Offset)
// construct the interface{} with cached type information, pointing at &struct.field
newIptr := iptr{
itab: uintptr(f.ptritab),
ptr: uintptr(interptr),
}
return newIptr.Interface()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment