optimize exception bug
diff --git a/.gitignore b/.gitignore
index 1363720..fc62e8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 .idea
+vendor
 coverage.txt
diff --git a/CHANGE.md b/CHANGE.md
index a3f32e4..492220c 100644
--- a/CHANGE.md
+++ b/CHANGE.md
@@ -1,5 +1,18 @@
 # Release Notes
 
+## v1.6.0
+
+### New Features
+- ignore non-exist fields when decoding. [#201](https://github.com/apache/dubbo-go-hessian2/pull/201)
+
+### Enhancement
+- add cache in reflection to improve performance. [#179](https://github.com/apache/dubbo-go-hessian2/pull/179)
+- string decode performance improvement. [#188](https://github.com/apache/dubbo-go-hessian2/pull/188)
+
+### Bugfixes
+- fix attachment lost for nil value. [#191](https://github.com/apache/dubbo-go-hessian2/pull/191)
+- fix float32 accuracy issue. [#196](https://github.com/apache/dubbo-go-hessian2/pull/196)
+
 ## v1.5.0
 
 ### New Features
diff --git a/README.md b/README.md
index 9c12941..6bc9b78 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,15 @@
 
 ---
 
+> **Notice: When decoding, the java version of hessian will default skip and ignore non-exist fields.**
+> **From the version of v1.6.0 , dubbo-go-hessian2 will skip non-exist fields too, while that before v1.6.0 will return errors.**
+
 It's a golang hessian library used by [Apache/dubbo-go](https://github.com/apache/dubbo-go).
 
+There is a big performance improvement, and some bugs fix for v1.6.0, 
+thanks to [micln](https://github.com/micln), [pantianying](https://github.com/pantianying), [zonghaishang](https://github.com/zonghaishang),
+ [willson-chen](https://github.com/willson-chen), [champly](https://github.com/champly).
+
 ## Feature List
 
 * [All JDK Exceptions](https://github.com/apache/dubbo-go-hessian2/issues/59)
diff --git a/binary_test.go b/binary_test.go
index dafda34..c145e13 100644
--- a/binary_test.go
+++ b/binary_test.go
@@ -20,8 +20,6 @@
 import (
 	"bytes"
 	"fmt"
-
-	// "fmt"
 	"testing"
 )
 
diff --git a/double.go b/double.go
index d70c682..376a1f4 100644
--- a/double.go
+++ b/double.go
@@ -20,6 +20,7 @@
 import (
 	"encoding/binary"
 	"math"
+	"strconv"
 )
 
 import (
@@ -62,6 +63,38 @@
 		byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits))
 }
 
+func encFloat32(b []byte, v float32) []byte {
+	fv := float32(int32(v))
+	if fv == v {
+		iv := int32(v)
+		switch iv {
+		case 0:
+			return encByte(b, BC_DOUBLE_ZERO)
+		case 1:
+			return encByte(b, BC_DOUBLE_ONE)
+		}
+		if iv >= -0x80 && iv < 0x80 {
+			return encByte(b, BC_DOUBLE_BYTE, byte(iv))
+		} else if iv >= -0x8000 && iv < 0x8000 {
+			return encByte(b, BC_DOUBLE_SHORT, byte(iv>>8), byte(iv))
+		}
+
+		goto END
+	}
+
+END:
+	if float32(int32(v*1000)) == v*1000 {
+		iv := int32(v * 1000)
+		return encByte(b, BC_DOUBLE_MILL, byte(iv>>24), byte(iv>>16), byte(iv>>8), byte(iv))
+	} else {
+		str := strconv.FormatFloat(float64(v), 'f', -1, 32)
+		d, _ := strconv.ParseFloat(str, 64)
+		bits := math.Float64bits(d)
+		return encByte(b, BC_DOUBLE, byte(bits>>56), byte(bits>>48), byte(bits>>40),
+			byte(bits>>32), byte(bits>>24), byte(bits>>16), byte(bits>>8), byte(bits))
+	}
+}
+
 /////////////////////////////////////////
 // Double
 /////////////////////////////////////////
diff --git a/double_test.go b/double_test.go
index 111124b..43e9391 100644
--- a/double_test.go
+++ b/double_test.go
@@ -42,6 +42,33 @@
 	t.Logf("decode(%v) = %v, %v\n", v, res, err)
 }
 
+func TestIssue181(t *testing.T) {
+	var (
+		v   float32
+		err error
+		e   *Encoder
+		d   *Decoder
+		res interface{}
+	)
+
+	e = NewEncoder()
+	v = 99.8
+	e.Encode(v)
+	if len(e.Buffer()) == 0 {
+		t.Fail()
+	}
+
+	// res would be '99.800003' without patches in PR #196
+	d = NewDecoder(e.Buffer())
+	res, err = d.Decode()
+	f := res.(float64)
+	if float32(f) != v {
+		t.Errorf("decode(%v) = %v, %v\n", v, res, err)
+		return
+	}
+	t.Logf("decode(%v) = %v\n", v, res)
+}
+
 func TestDouble(t *testing.T) {
 	testDecodeFramework(t, "replyDouble_0_0", 0.0)
 	testDecodeFramework(t, "replyDouble_0_001", 0.001)
diff --git a/encode.go b/encode.go
index fbeae99..ad9d5c6 100644
--- a/encode.go
+++ b/encode.go
@@ -112,7 +112,7 @@
 		}
 
 	case float32:
-		e.buffer = encFloat(e.buffer, float64(val))
+		e.buffer = encFloat32(e.buffer, val)
 
 	case float64:
 		e.buffer = encFloat(e.buffer, val)
diff --git a/int_test.go b/int_test.go
index 726a11f..082f399 100644
--- a/int_test.go
+++ b/int_test.go
@@ -18,10 +18,13 @@
 package hessian
 
 import (
-	"github.com/stretchr/testify/assert"
 	"testing"
 )
 
+import (
+	"github.com/stretchr/testify/assert"
+)
+
 func TestEncInt32Len1B(t *testing.T) {
 	var (
 		v   int32
diff --git a/object.go b/object.go
index 72353de..2a86820 100644
--- a/object.go
+++ b/object.go
@@ -380,7 +380,6 @@
 			// skip field
 			d.DecodeValue()
 			continue
-			//return nil, perrors.Errorf("can not find field %s", fieldName)
 		}
 
 		// skip unexported anonymous field
@@ -398,8 +397,8 @@
 
 		// unpack pointer to enable value setting
 		fldRawValue := UnpackPtrValue(field)
-
 		kind := fldTyp.Kind()
+
 		switch kind {
 		case reflect.String:
 			str, err := d.decString(TAG_READ)
diff --git a/object_test.go b/object_test.go
index 76654c7..db66596 100644
--- a/object_test.go
+++ b/object_test.go
@@ -25,6 +25,10 @@
 	"time"
 )
 
+import (
+	"github.com/stretchr/testify/assert"
+)
+
 type Department struct {
 	Name string
 }
@@ -749,3 +753,18 @@
 		}
 	}
 }
+
+type Person183 struct {
+	Name string
+}
+
+func (Person183) JavaClassName() string {
+	return `test.Person183`
+}
+
+func TestIssue183_DecodeExcessStructField(t *testing.T) {
+	RegisterPOJO(&Person183{})
+	got, err := decodeJavaResponse(`customReplyPerson183`, ``, false)
+	assert.NoError(t, err)
+	t.Logf("%T %+v", got, got)
+}
diff --git a/string.go b/string.go
index 6a217c5..a2a24ce 100644
--- a/string.go
+++ b/string.go
@@ -218,10 +218,7 @@
 // ::= [x00-x1f] <utf8-data>         # string of length 0-31
 // ::= [x30-x34] <utf8-data>         # string of length 0-1023
 func (d *Decoder) getStringLength(tag byte) (int, error) {
-	var (
-		err    error
-		length int
-	)
+	var length int
 
 	switch {
 	case tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX:
@@ -251,16 +248,15 @@
 		return length, nil
 
 	default:
-		return -1, perrors.WithStack(err)
+		return -1, perrors.Errorf("string decode: unknown tag %b", tag)
 	}
 }
 
 func (d *Decoder) decString(flag int32) (string, error) {
 	var (
-		tag      byte
-		chunkLen int
-		last     bool
-		s        string
+		tag  byte
+		last bool
+		s    string
 	)
 
 	if flag != TAG_READ {
@@ -315,11 +311,10 @@
 			last = true
 		}
 
-		charLen, err := d.getStringLength(tag)
+		chunkLen, err := d.getStringLength(tag)
 		if err != nil {
 			return s, perrors.WithStack(err)
 		}
-		chunkLen = charLen
 		bytesBuf := make([]byte, chunkLen<<2)
 		offset := 0
 
@@ -342,20 +337,11 @@
 						last = true
 					}
 
-					charLen, err = d.getStringLength(b)
+					chunkLen, err = d.getStringLength(b)
 					if err != nil {
 						return s, perrors.WithStack(err)
 					}
-
-					if chunkLen < 0 {
-						chunkLen = 0
-					}
-					if charLen < 0 {
-						charLen = 0
-					}
-
-					chunkLen += charLen
-					remain, cap := len(bytesBuf)-offset, charLen<<2
+					remain, cap := len(bytesBuf)-offset, chunkLen<<2
 					if remain < cap {
 						grow := len(bytesBuf) + cap
 						bs := make([]byte, grow)
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index 4586e24..12fc411 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -425,6 +425,18 @@
         output.flush();
     }
 
+    public void customReplyPerson183() throws Exception {
+        Person183 p = new Person183();
+        p.name = "pname";
+        p.age = 13;
+        InnerPerson innerPerson = new InnerPerson();
+        innerPerson.name = "pname2";
+        innerPerson.age = 132;
+        p.innerPerson = innerPerson;
+        output.writeObject(p);
+        output.flush();
+    }
+
     public void customReplyComplexString() throws Exception {
         output.writeObject(TestString.getComplexString());
         output.flush();
@@ -491,3 +503,14 @@
     }
 
 }
+
+class Person183 implements Serializable {
+    public String name;
+    public Integer age;
+    public InnerPerson innerPerson;
+}
+
+class InnerPerson implements Serializable {
+    public String name;
+    public Integer age;
+}
diff --git a/test_hessian/src/main/java/test/TestString.java b/test_hessian/src/main/java/test/TestString.java
index a19cb73..c026796 100644
--- a/test_hessian/src/main/java/test/TestString.java
+++ b/test_hessian/src/main/java/test/TestString.java
@@ -30,8 +30,8 @@
         return s + ",max" + maxUnicode;
     }
 
-        public static String getComplexString() {
-            String s = "킐\u0088中国你好!\u0088\u0088\u0088\u0088\u0088\u0088";
-            return s;
-        }
+    public static String getComplexString() {
+        String s = "킐\u0088中国你好!\u0088\u0088\u0088\u0088\u0088\u0088";
+        return s;
+    }
 }