-
-
Save KirinDave/75b27a5a4b162d69ce6658475ce770df to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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