From f1ad87fd712b9f70ffa0f97b25dc55a3b61d7999 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 20 Apr 2020 17:13:03 +0900 Subject: [PATCH] Get pointer from interface{} (FYI: https://golang.org/src/reflect/value.go ) --- encode.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/encode.go b/encode.go index 9c574c4..fa4b588 100644 --- a/encode.go +++ b/encode.go @@ -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