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) e.buf = append(e.buf, b)
} }
func (e *Encoder) Encode(v interface{}) ([]byte, error) { type rtype struct{}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr { type interfaceHeader struct {
newV := reflect.New(rv.Type()) typ *rtype
newV.Elem().Set(rv) ptr unsafe.Pointer
rv = newV
}
return e.encode(rv)
} }
func (e *Encoder) encode(v reflect.Value) ([]byte, error) { func (e *Encoder) Encode(v interface{}) ([]byte, error) {
name := v.Type().String() 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 { if op, exists := cachedEncodeOp[name]; exists {
op(e, v.Pointer()) op(e, uintptr(ptr))
copied := make([]byte, len(e.buf)) copied := make([]byte, len(e.buf))
copy(copied, e.buf) copy(copied, e.buf)
return copied, nil 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 { if err != nil {
return nil, err return nil, err
} }
if name != "" { if name != "" {
cachedEncodeOp[name] = op cachedEncodeOp[name] = op
} }
op(e, v.Pointer()) op(e, uintptr(ptr))
copied := make([]byte, len(e.buf)) copied := make([]byte, len(e.buf))
copy(copied, e.buf) copy(copied, e.buf)
return copied, nil return copied, nil