Get pointer from interface{} (FYI: https://golang.org/src/reflect/value.go )

This commit is contained in:
Masaaki Goshima 2020-04-20 17:13:03 +09:00
parent c515899c6d
commit f1ad87fd71
1 changed files with 18 additions and 13 deletions

View File

@ -114,32 +114,37 @@ func (e *Encoder) EncodeByte(b byte) {
e.buf = append(e.buf, b)
}
func (e *Encoder) Encode(v interface{}) ([]byte, error) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
newV := reflect.New(rv.Type())
newV.Elem().Set(rv)
rv = newV
}
return e.encode(rv)
type rtype struct{}
type interfaceHeader struct {
typ *rtype
ptr unsafe.Pointer
}
func (e *Encoder) encode(v reflect.Value) ([]byte, error) {
name := v.Type().String()
func (e *Encoder) Encode(v interface{}) ([]byte, error) {
header := (*interfaceHeader)(unsafe.Pointer(&v))
return e.encode(reflect.TypeOf(v), header.ptr)
}
func (e *Encoder) encode(typ reflect.Type, ptr unsafe.Pointer) ([]byte, error) {
name := typ.String()
if op, exists := cachedEncodeOp[name]; exists {
op(e, v.Pointer())
op(e, uintptr(ptr))
copied := make([]byte, len(e.buf))
copy(copied, e.buf)
return copied, nil
}
op, err := e.compile(v.Elem().Type())
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
op, err := e.compile(typ)
if err != nil {
return nil, err
}
if name != "" {
cachedEncodeOp[name] = op
}
op(e, v.Pointer())
op(e, uintptr(ptr))
copied := make([]byte, len(e.buf))
copy(copied, e.buf)
return copied, nil