Repository: apache/dubbo-go-hessian2
Pull request #289 (2021-11-15 06:42:10)

convert pointer to encode
<!--  Thanks for sending a pull request! 
-->

**What this PR does**:

When a user implements custom POJOs and uses non-pointer POJOs to encode, the encoding fails to transfer pojos forcibly. As a result, the program execution fails to meet expectations

![image](https://user-images.githubusercontent.com/28588342/141734262-63f2dc67-fa32-42f1-be55-3d6eeba2a020.png)



When non-pointer structures are encoded, they are uniformly converted to Pointers for encoding

、
**Which issue(s) this PR fixes**:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".
-->
```release-note

```
Benchmark: 分别在struct以及pointer场景下 用串行以及8c并行 对当前pr与master进行对比。

// Benchmark_Struct_Encode  	 2231869	       506.8 ns/op	     560 B/op	       7 allocs/op
// Benchmark_Struct_Encode-master  	713761	      1549 ns/op	     560 B/op	       8 allocs/op

// Benchmark_Pointer_Encode   	 2565778	       476.1 ns/op	     560 B/op	       7 allocs/op
// Benchmark_Pointer_Encode-master   	 2328867	       511.4 ns/op	     576 B/op	       8 allocs/op

// Benchmark_Struct_Encode_8   	 2307214	       519.4 ns/op	     560 B/op	       7 allocs/op
// Benchmark_Struct_Encode_8-master   	 3104438	       387.6 ns/op	     560 B/op	       8 allocs/op

// Benchmark_Pointer_Encode_8   	 2460842	       476.7 ns/op	     560 B/op	       7 allocs/op
// Benchmark_Pointer_Encode_8-master   	 2254734	       514.9 ns/op	     576 B/op	       8 allocs/op

当前master 对于struct 是非指针并且receiver是指针的情况下 性能和当前pr差距较大，其他的情况差距都还好。

codecov-commenter: # [Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
> Merging [#289](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (146bb9b) into [master](https://codecov.io/gh/apache/dubbo-go-hessian2/commit/3a4ef0be57cec0ab889e3a0b22e546df24e2e6a8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (3a4ef0b) will **decrease** coverage by `0.09%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/graphs/tree.svg?width=650&height=150&src=pr&token=Yh82j7lS1W&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)

```diff
@@            Coverage Diff             @@
##           master     #289      +/-   ##
==========================================
- Coverage   70.26%   70.16%   -0.10%     
==========================================
  Files          27       27              
  Lines        3033     3040       +7     
==========================================
+ Hits         2131     2133       +2     
- Misses        677      681       +4     
- Partials      225      226       +1     
```


| [Impacted Files](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
|---|---|---|
| [codec.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-Y29kZWMuZ28=) | `69.51% <100.00%> (+0.50%)` | :arrow_up: |
| [encode.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-ZW5jb2RlLmdv) | `78.26% <100.00%> (+0.58%)` | :arrow_up: |
| [serialize.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c2VyaWFsaXplLmdv) | `66.66% <100.00%> (ø)` | |
| [java\_sql\_time.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-amF2YV9zcWxfdGltZS5nbw==) | `63.88% <0.00%> (-2.78%)` | :arrow_down: |
| [ref.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-cmVmLmdv) | `83.78% <0.00%> (-2.71%)` | :arrow_down: |
| [pojo.go](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-cG9qby5nbw==) | `63.46% <0.00%> (-0.49%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Last update [3a4ef0b...146bb9b](https://codecov.io/gh/apache/dubbo-go-hessian2/pull/289?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation).

wongoo: @sanxun0325 I think it definition issue, if define `JavaClassName` on struct pointer , then not encode the non-pointer struct instance.   

If u want encode the non-pointer struct instance, define  `JavaClassName` on the struct directly.

Patch:
diff --git a/codec.go b/codec.go
index 5087efa..425468c 100644
--- a/codec.go
+++ b/codec.go
@@ -476,3 +476,10 @@ func ConvertSliceValueType(destTyp reflect.Type, v reflect.Value) (reflect.Value
 
 	return sl, nil
 }
+
+//PackPtrInterface pack struct interface to pointer interface
+func PackPtrInterface(s interface{}, value reflect.Value) interface{} {
+	vv := reflect.New(reflect.TypeOf(s))
+	vv.Elem().Set(value)
+	return vv.Interface()
+}
diff --git a/encode.go b/encode.go
index c26832e..0daf3e0 100644
--- a/encode.go
+++ b/encode.go
@@ -160,7 +160,11 @@ func (e *Encoder) Encode(v interface{}) error {
 		switch t.Kind() {
 		case reflect.Struct:
 			vv := reflect.ValueOf(v)
-			vv = UnpackPtr(vv)
+			if vv.Kind() != reflect.Ptr {
+				v = PackPtrInterface(v, vv)
+			} else {
+				vv = UnpackPtr(vv)
+			}
 			if !vv.IsValid() {
 				e.buffer = EncNull(e.buffer)
 				return nil
diff --git a/serialize.go b/serialize.go
index b57702b..ca738ea 100644
--- a/serialize.go
+++ b/serialize.go
@@ -69,7 +69,7 @@ func (IntegerSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo)
 }
 
 func (IntegerSerializer) EncObject(e *Encoder, v POJO) error {
-	bigInt, ok := v.(bigInteger)
+	bigInt, ok := v.(*bigInteger)
 	if !ok {
 		return e.encObject(v)
 	}
@@ -80,7 +80,7 @@ func (IntegerSerializer) EncObject(e *Encoder, v POJO) error {
 type DecimalSerializer struct{}
 
 func (DecimalSerializer) EncObject(e *Encoder, v POJO) error {
-	decimal, ok := v.(big.Decimal)
+	decimal, ok := v.(*big.Decimal)
 	if !ok {
 		return e.encObject(v)
 	}


Test patch:
diff --git a/codec_test.go b/codec_test.go
index a4cdd1b..b2dd937 100644
--- a/codec_test.go
+++ b/codec_test.go
@@ -18,9 +18,14 @@
 package hessian
 
 import (
+	"reflect"
 	"testing"
 )
 
+import (
+	"github.com/stretchr/testify/assert"
+)
+
 // go test -v -run TestPackUint16
 func TestPackUint16(t *testing.T) {
 	// var arr []byte
@@ -57,3 +62,11 @@ func TestPackInt64(t *testing.T) {
 		t.Fatalf("v:0X%d, pack-unpack value:0X%x\n", v, r)
 	}
 }
+
+func TestPackPtrInterface(t *testing.T) {
+	v := "struct"
+	vv := reflect.ValueOf(v)
+	sPointer, ok := PackPtrInterface(v, vv).(*string)
+	assert.True(t, ok)
+	assert.True(t, *sPointer == "struct")
+}
diff --git a/encode_test.go b/encode_test.go
index 543452f..6db3a98 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -87,3 +87,53 @@ func testSimpleEncode(t *testing.T, v interface{}) {
 	err := e.Encode(v)
 	assert.Nil(t, err)
 }
+
+type BenchData struct {
+	name string
+}
+
+func (b *BenchData) JavaClassName() string {
+	return "test.bench.BenchData"
+}
+
+// Benchmark_Struct_Encode  	 2231869	       506.8 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Struct_Encode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		NewEncoder().Encode(BenchData{})
+	}
+}
+
+// Benchmark_Pointer_Encode   	 2565778	       476.1 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Pointer_Encode(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		NewEncoder().Encode(&BenchData{})
+	}
+}
+
+// Benchmark_Struct_Encode_8   	 2307214	       519.4 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Struct_Encode_8(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	b.SetParallelism(8)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			NewEncoder().Encode(BenchData{})
+		}
+	})
+}
+
+// Benchmark_Pointer_Encode_8   	 2460842	       476.7 ns/op	     560 B/op	       7 allocs/op
+func Benchmark_Pointer_Encode_8(b *testing.B) {
+	b.ReportAllocs()
+	b.ResetTimer()
+	b.SetParallelism(8)
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			NewEncoder().Encode(&BenchData{})
+		}
+	})
+}