[ROCKETMQ-282]RocketMQ-SDK go implementation producer ready

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..989c7a4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,28 @@
+matrix:
+#  include:
+#    language: go
+#    go:
+#     - 1.7.x
+#    go_import_path: apache/incubator-rocketmq-externals/rocketmq-go
+#    before_script:
+#      - cd rocketmq-go
+#    script:
+#     - go test -v ./...
+
+
+  include:
+    - language: java
+      os: linux
+      env: CUSTOM_JDK="oraclejdk7"
+      before_script:
+        - cd rocketmq-console
+      script:
+        - travis_retry mvn -B clean
+        - travis_retry mvn -B package findbugs:findbugs jacoco:report coveralls:report
+
+notifications:
+  email:
+    recipients:
+      - styletang.me@gmail.com
+  on_success: change
+  on_failure: always
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7f77f44
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (properties) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
\ No newline at end of file
diff --git a/rocketmq-console/README.md b/rocketmq-console/README.md
index 30dd67c..2857f91 100644
--- a/rocketmq-console/README.md
+++ b/rocketmq-console/README.md
@@ -1,4 +1,4 @@
-## RocketMQ-Console-Ng[![Build Status](https://travis-ci.org/rocketmq/rocketmq-console-ng.svg?branch=master)](https://travis-ci.org/rocketmq/rocketmq-console-ng) [![Coverage Status](https://coveralls.io/repos/github/rocketmq/rocketmq-console-ng/badge.svg?branch=master)](https://coveralls.io/github/rocketmq/rocketmq-console-ng?branch=master)
+## RocketMQ-Console-Ng[![Build Status](https://travis-ci.org/StyleTang/incubator-rocketmq-externals.svg?branch=master)](https://travis-ci.org/StyleTang/incubator-rocketmq-externals) [![Coverage Status](https://coveralls.io/repos/github/StyleTang/incubator-rocketmq-externals/badge.svg?branch=master)](https://coveralls.io/github/StyleTang/incubator-rocketmq-externals?branch=master)
 [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
 ## How To Install
 
diff --git a/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ConsumerServiceImplTest.java b/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ConsumerServiceImplTest.java
index 8979391..a0e55cb 100644
--- a/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ConsumerServiceImplTest.java
+++ b/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ConsumerServiceImplTest.java
@@ -19,6 +19,7 @@
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -64,6 +65,16 @@
     public void queryGroupList() throws Exception {
         List<GroupConsumeInfo> consumeInfoList = consumerService.queryGroupList();
         Assert.assertTrue(CollectionUtils.isNotEmpty(consumeInfoList));
+        GroupConsumeInfo consumeInfo1 = new GroupConsumeInfo();
+        consumeInfo1.setCount(1);
+        consumeInfo1.setDiffTotal(1);
+        GroupConsumeInfo consumeInfo2 = new GroupConsumeInfo();
+        consumeInfo2.setCount(2);
+        consumeInfo2.setDiffTotal(2);
+        List<GroupConsumeInfo> consumeInfoListTestCompare = Lists.newArrayList(consumeInfo1,consumeInfo2);
+        Collections.sort(consumeInfoListTestCompare);
+        Assert.assertEquals(consumeInfoListTestCompare.get(0),consumeInfo2);
+
     }
 
     @Test
diff --git a/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ProducerServiceImplTest.java b/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ProducerServiceImplTest.java
index 1baa433..48a3945 100644
--- a/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ProducerServiceImplTest.java
+++ b/rocketmq-console/src/test/java/org/apache/rocketmq/console/service/impl/ProducerServiceImplTest.java
@@ -25,11 +25,16 @@
 import org.apache.rocketmq.console.service.ProducerService;
 import org.apache.rocketmq.console.testbase.RocketMQConsoleTestBase;
 import org.apache.rocketmq.console.testbase.TestConstant;
+import org.apache.rocketmq.remoting.exception.RemotingException;
+import org.apache.rocketmq.tools.admin.MQAdminExt;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit4.SpringRunner;
@@ -68,4 +73,17 @@
 
     }
 
+
+    @Mock
+    private MQAdminExt mqAdminExt;
+
+    @InjectMocks
+    private ProducerService producerServiceMock = new ProducerServiceImpl();
+
+    @Test(expected = RuntimeException.class)
+    public void getProducerConnectionException() throws Exception {
+        Mockito.when(mqAdminExt.examineProducerConnectionInfo(Mockito.anyString(),Mockito.anyString())).thenThrow(new RemotingException("test-RemotingException"));
+        producerServiceMock.getProducerConnection(TEST_PRODUCER_GROUP,TEST_CONSOLE_TOPIC);
+    }
+
 }
\ No newline at end of file
diff --git a/rocketmq-go/LICENSE b/rocketmq-go/LICENSE
index b67d909..7f77f44 100644
--- a/rocketmq-go/LICENSE
+++ b/rocketmq-go/LICENSE
@@ -1,4 +1,4 @@
-Apache License
+                                 Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
 
@@ -15,7 +15,7 @@
       "Legal Entity" shall mean the union of the acting entity and all
       other entities that control, are controlled by, or are under common
       control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
+      "control" means (properties) the power, direct or indirect, to cause the
       direction or management of such entity, whether by contract or
       otherwise, or (ii) ownership of fifty percent (50%) or more of the
       outstanding shares, or (iii) beneficial ownership of such entity.
@@ -178,7 +178,7 @@
    APPENDIX: How to apply the Apache License to your work.
 
       To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "{}"
+      boilerplate notice, with the fields enclosed by brackets "[]"
       replaced with your own identifying information. (Don't include
       the brackets!)  The text should be enclosed in the appropriate
       comment syntax for the file format. We also recommend that a
@@ -186,7 +186,7 @@
       same "printed page" as the copyright notice for easier
       identification within third-party archives.
 
-   Copyright {}
+   Copyright [yyyy] [name of copyright owner]
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -198,4 +198,4 @@
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
-   limitations under the License.
+   limitations under the License.
\ No newline at end of file
diff --git a/rocketmq-go/README.md b/rocketmq-go/README.md
index 900e918..f85a8e9 100644
--- a/rocketmq-go/README.md
+++ b/rocketmq-go/README.md
@@ -1,4 +1,94 @@
-# RocketMQ Go SDK
-some code refer to below repos:
-* https://github.com/didapinchegit/go_rocket_mq
-* https://github.com/sevennt/go_rocket_mq/
\ No newline at end of file
+# RocketMQ Go SDK Millstone1 Detail Design[![Go Report Card](https://goreportcard.com/badge/github.com/StyleTang/incubator-rocketmq-externals)](https://goreportcard.com/report/github.com/StyleTang/incubator-rocketmq-externals)
+
+## How to Use
+examples:
+* rocketmq-go/example/producer_consumer.go
+* rocketmq-go/example/simple_consumer.go
+* rocketmq-go/example/simple_producer_consumer.go
+
+# Go RocketMQ Client's Arch
+
+![Go RocketMQ Client's Arch](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/package.puml)
+
+# Go RocketMQ Client's Roadmap
+ [Go RocketMQ Client's Roadmap](https://github.com/StyleTang/incubator-rocketmq-externals/blob/master/rocketmq-go/docs/roadmap.md)
+
+# How Go RocketMQ Client Works
+
+
+1. create a new rocketMqMange instance(nameServerAddr ...)
+
+2. create a new consumer instance(topic/tag/listener ...)(now only support cluster/concurrent)
+
+3. consumer register to rocketMqMange
+ 
+4. rocketMqMange start
+
+* register ClientRequestProcessor
+  * CHECK_TRANSACTION_STATE
+  * NOTIFY_CONSUMER_IDS_CHANGED
+  * RESET_CONSUMER_CLIENT_OFFSET
+  * GET_CONSUMER_STATUS_FROM_CLIENT
+  * GET_CONSUMER_RUNNING_INFO
+  * CONSUME_MESSAGE_DIRECTLY
+ 
+* Start All Task
+    * updateTopicRouteInfo
+    * heartbeat
+    * rebalance
+    * pullMessage
+    * cleanExpireMsg (Non-major)
+
+## All Tasks
+
+ ### updateTopicRouteInfo
+ 
+ update Topic Route Info by consumer subscription data (topic route info data get from name server) 
+ 
+ put them into local memory(BrokerAddrTable/TopicPublishInfoTable/TopicSubscribeInfoTable/TopicRouteTable)
+
+![update-topic-routeInfo-timing-diagram](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/update-topic-routeInfo-timing-diagram.puml)
+
+ ### heartbeat:
+ 
+ prepare heartbeat data(all consumer and producer data in this client)
+ 
+ send it to all brokers.(broker data is from BrokerAddrTable) 
+  
+ (only broker know the distribution of the consumers we can rebalance)
+
+![heartbeat-timing-diagram](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/heartbeat-timing-diagram.puml)
+
+ ### rebalance
+ 
+ for each MqClientManager.ClientFactory's consumers,invoke consumer.rebalance's DoRebalance method
+ 
+ (after rebalance we can know the (topic/consumer group) should consume from which broker which queue)
+ 
+  put them into local memory(processQueueTable)
+  
+  enqueue pull message request (chan *model.PullRequest)
+  
+ ![rebalance-timing-diagram](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/rebalance-timing-diagram.puml)
+  
+ ### pullMessage
+ 
+ dequeue pull message request and pull message from broker,when get messages to consume,
+ put them into consume request,consume request handler will call the listener consume the message
+ 
+ enqueue a new pull message request and commit our consume offset to broker
+ 
+ #### pullMessage
+ 
+ ![pull-message-timing-diagram](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/pull-message-timing-diagram.puml)
+ 
+ #### consumeMessage(submitConsumeRequest)
+ 
+ ![consume-message-activity](http://www.plantuml.com/plantuml/proxy?fmt=svg&src=https://raw.githubusercontent.com/StyleTang/incubator-rocketmq-externals/master/rocketmq-go/docs/consume-message-activity.puml)
+   
+ ### cleanExpireMsg (Non-major)
+
+when message cost too many time,we will drop this message(send message back) (for example 30 mins)
+
+
+
diff --git a/rocketmq-go/api/model/message.go b/rocketmq-go/api/model/message.go
new file mode 100644
index 0000000..a2b51c8
--- /dev/null
+++ b/rocketmq-go/api/model/message.go
@@ -0,0 +1,51 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+
+// Message rocketmq message
+// topic: the topic of this message
+// tag: the topic of this message, one topic may have no tag or different tag
+// key: key makes this message easy to search by console (https://github.com/apache/incubator-rocketmq-externals/rocketmq-console)
+// body: the message's user content
+// see MessageImpl
+type Message interface {
+	//Topic Topic get topic
+	Topic() (topic string)
+	//SetTopic set message topic
+	SetTopic(tag string)
+
+	//SetTag set message tag
+	SetTag(tag string)
+	//Tag get message tag
+	Tag() (tag string)
+	//SetKeys set message key
+	SetKeys(keys []string)
+
+	//SetDelayTimeLevel set delay time level
+	SetDelayTimeLevel(delayTimeLevel int)
+	//SetBody set body
+	SetBody([]byte)
+}
+
+// NewMessage create a message instance
+func NewMessage() (msg Message) {
+	msg = message.NewMessageImpl()
+	return
+}
diff --git a/rocketmq-go/api/model/message_ext.go b/rocketmq-go/api/model/message_ext.go
new file mode 100644
index 0000000..de19bdb
--- /dev/null
+++ b/rocketmq-go/api/model/message_ext.go
@@ -0,0 +1,31 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+//MessageExt see MessageExtImpl
+type MessageExt interface {
+	//Topic get message topic
+	Topic() (tag string)
+	//Tag get message tag
+	Tag() (tag string)
+
+	//Body get body
+	Body() []byte
+	//MsgId get messageId
+	MsgId() string
+}
diff --git a/rocketmq-go/api/model/message_listener.go b/rocketmq-go/api/model/message_listener.go
new file mode 100644
index 0000000..18d5cf2
--- /dev/null
+++ b/rocketmq-go/api/model/message_listener.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+// ConsumeStatus message consume status
+type ConsumeStatus int
+
+const (
+	//CONSUME_SUCCESS consume success
+	CONSUME_SUCCESS ConsumeStatus = iota
+	//RECONSUME_LATER consume fail, consume again later
+	RECONSUME_LATER
+)
+
+// ConsumeConcurrentlyResult message consume result
+type ConsumeConcurrentlyResult struct {
+	// consume status
+	ConsumeConcurrentlyStatus ConsumeStatus
+	//success ack index, from 0 to n-1
+	AckIndex int
+}
+
+// MessageListener mqConsumer.RegisterMessageListener
+type MessageListener func(msgs []MessageExt) ConsumeConcurrentlyResult
diff --git a/rocketmq-go/api/model/message_queue.go b/rocketmq-go/api/model/message_queue.go
new file mode 100644
index 0000000..9b944dc
--- /dev/null
+++ b/rocketmq-go/api/model/message_queue.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+//MessageQueue message queue
+type MessageQueue struct {
+	Topic      string `json:"topic"`
+	BrokerName string `json:"brokerName"`
+	QueueId    int32  `json:"queueId"`
+}
+
+//Equals judge messageQueue is the same
+func (m MessageQueue) Equals(messageQueue *MessageQueue) bool {
+	if m.QueueId != messageQueue.QueueId {
+		return false
+	}
+	if m.Topic != messageQueue.Topic {
+		return false
+	}
+	if m.BrokerName != messageQueue.BrokerName {
+		return false
+	}
+	return true
+}
diff --git a/rocketmq-go/api/model/mq_client_config.go b/rocketmq-go/api/model/mq_client_config.go
new file mode 100644
index 0000000..9af5746
--- /dev/null
+++ b/rocketmq-go/api/model/mq_client_config.go
@@ -0,0 +1,45 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+//SerializeType default serialize type is JSON_SERIALIZE, but ROCKETMQ_SERIALIZE(need version >= ?) is faster
+type SerializeType byte
+
+const (
+	//JSON_SERIALIZE see json_serializable.go
+	JSON_SERIALIZE SerializeType = iota
+	//ROCKETMQ_SERIALIZE see rocketmq_serializable.go
+	ROCKETMQ_SERIALIZE
+)
+
+//MqClientConfig MqClientConfig
+type MqClientConfig struct {
+	// NameServerAddress split by ;
+	NameServerAddress string
+	//this client use which serialize type
+	ClientSerializeType SerializeType
+}
+
+//NewMqClientConfig create a MqClientConfig instance
+func NewMqClientConfig(nameServerAddress string) (mqClientConfig *MqClientConfig) {
+	mqClientConfig = &MqClientConfig{
+		NameServerAddress:   nameServerAddress,
+		ClientSerializeType: JSON_SERIALIZE,
+	}
+	return
+}
diff --git a/rocketmq-go/api/model/mq_consumer_config.go b/rocketmq-go/api/model/mq_consumer_config.go
new file mode 100644
index 0000000..fdb386c
--- /dev/null
+++ b/rocketmq-go/api/model/mq_consumer_config.go
@@ -0,0 +1,124 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+import "time"
+
+//PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION Delay some time when exception occur
+const PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION int64 = 3000
+
+//PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL Flow control interval
+const PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL int64 = 50
+
+//ConsumeFromWhere consume from where
+type ConsumeFromWhere int
+
+//first consume from the last offset
+const (
+	//CONSUME_FROM_LAST_OFFSET first consume from the last offset
+	CONSUME_FROM_LAST_OFFSET ConsumeFromWhere = iota
+
+	//CONSUME_FROM_FIRST_OFFSET first consume from the first offset
+	CONSUME_FROM_FIRST_OFFSET
+
+	//CONSUME_FROM_TIMESTAMP first consume from the time
+	CONSUME_FROM_TIMESTAMP
+)
+
+//MqConsumerConfig MqConsumerConfig
+type MqConsumerConfig struct {
+
+	//consume from where
+	ConsumeFromWhere ConsumeFromWhere
+
+	//Concurrently max span offset.it has no effect on sequential consumption
+	ConsumeConcurrentlyMaxSpan int // = 2000;
+
+	//Flow control threshold
+	PullThresholdForQueue int //= 1000;
+
+	//Message pull Interval
+	PullInterval int64 //= 0;
+
+	//Batch consumption size
+	ConsumeMessageBatchMaxSize int //= 1;
+
+	//Batch pull size
+	PullBatchSize int //= 32;
+
+	//Whether update subscription relationship when every pull
+	PostSubscriptionWhenPull bool //= false; //get subExpression
+
+	/**
+	 * Whether the unit of subscription group
+	 */
+	UnitMode                      bool  // = false;
+	MaxReconsumeTimes             int   //= 16;
+	SuspendCurrentQueueTimeMillis int64 //= 1000;
+	ConsumeTimeout                int64 //= 15 //minutes
+
+	//=========can not change
+	/**
+	 * Delay some time when exception occur
+	 */
+	PullTimeDelayMillsWhenException int64 //= 3000;
+	/**
+	 * Flow control interval
+	 */
+	PullTimeDelayMillsWhenFlowControl int64 //= 50;
+	/**
+	 * Delay some time when suspend pull service
+	 */
+	PullTimeDelayMillsWhenSuspend    int64 //= 1000;
+	BrokerSuspendMaxTimeMillis       int64 //1000 * 15;
+	ConsumerTimeoutMillisWhenSuspend int64 //= 1000 * 30;
+
+	/**
+	* Backtracking consumption time with second precision.time format is
+	* 20131223171201
+	* Implying Seventeen twelve and 01 seconds on December 23, 2013 year
+	* Default backtracking consumption time Half an hour ago
+	 */
+	ConsumeTimestamp time.Time //when use CONSUME_FROM_TIMESTAMP
+}
+
+//NewRocketMqConsumerConfig create a MqConsumerConfig instance
+func NewRocketMqConsumerConfig() (consumerConfig *MqConsumerConfig) {
+	consumerConfig = &MqConsumerConfig{
+		ConsumeFromWhere:              CONSUME_FROM_LAST_OFFSET,
+		ConsumeConcurrentlyMaxSpan:    2000,
+		PullThresholdForQueue:         1000,
+		PullInterval:                  0,
+		ConsumeMessageBatchMaxSize:    1,
+		PullBatchSize:                 32,
+		PostSubscriptionWhenPull:      false,
+		UnitMode:                      false,
+		MaxReconsumeTimes:             16,
+		SuspendCurrentQueueTimeMillis: 1000,
+		ConsumeTimeout:                15,
+		ConsumeTimestamp:              time.Now().Add(-30 * time.Minute),
+
+		// use custom or constants.don't suggest to change
+		PullTimeDelayMillsWhenException:   PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION,
+		PullTimeDelayMillsWhenFlowControl: PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL,
+		PullTimeDelayMillsWhenSuspend:     1000,
+		BrokerSuspendMaxTimeMillis:        1000 * 15,
+		ConsumerTimeoutMillisWhenSuspend:  1000 * 30,
+	}
+	return
+}
diff --git a/rocketmq-go/api/model/mq_producer_config.go b/rocketmq-go/api/model/mq_producer_config.go
new file mode 100644
index 0000000..1e8067e
--- /dev/null
+++ b/rocketmq-go/api/model/mq_producer_config.go
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+//MqProducerConfig MqProducerConfig
+type MqProducerConfig struct {
+	// SendMsgTimeout for this producer
+	SendMsgTimeout int64
+	// CompressMsgBodyOverHowMuch
+	CompressMsgBodyOverHowMuch int
+	// ZipCompressLevel
+	ZipCompressLevel                 int
+	RetryTimesWhenSendFailed         int
+	RetryTimesWhenSendAsyncFailed    int
+	RetryAnotherBrokerWhenNotStoreOK bool
+	MaxMessageSize                   int
+	SendLatencyFaultEnable           bool
+	LatencyMax                       []int64
+	NotAvailableDuration             []int64
+}
+
+//NewProducerConfig create a MqProducerConfig instance
+func NewProducerConfig() (producerConfig *MqProducerConfig) {
+	producerConfig = &MqProducerConfig{
+		SendMsgTimeout:             3000,
+		CompressMsgBodyOverHowMuch: 1024 * 4,
+		ZipCompressLevel:           5,
+		MaxMessageSize:             1024 * 1024 * 4, // 4M
+
+		RetryTimesWhenSendFailed:         2,
+		RetryTimesWhenSendAsyncFailed:    2,
+		RetryAnotherBrokerWhenNotStoreOK: false,
+		SendLatencyFaultEnable:           false,
+		LatencyMax:                       []int64{50, 100, 550, 1000, 2000, 3000, 15000},
+		NotAvailableDuration:             []int64{0, 0, 30000, 60000, 120000, 180000, 600000},
+	}
+	return
+}
diff --git a/rocketmq-go/api/model/send_result.go b/rocketmq-go/api/model/send_result.go
new file mode 100644
index 0000000..a817f57
--- /dev/null
+++ b/rocketmq-go/api/model/send_result.go
@@ -0,0 +1,129 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmqm
+
+import (
+	"fmt"
+)
+
+//SendStatus message send result
+type SendStatus int
+
+const (
+	//SendOK message send success
+	SendOK SendStatus = iota
+	//FlushDiskTimeout FlushDiskTimeout
+	FlushDiskTimeout
+	//FlushSlaveTimeout FlushSlaveTimeout
+	FlushSlaveTimeout
+	//SlaveNotAvaliable SlaveNotAvaliable
+	SlaveNotAvaliable
+)
+
+//SendResult rocketmq send result
+type SendResult struct {
+	sendStatus    SendStatus
+	msgID         string
+	messageQueue  MessageQueue
+	queueOffset   int64
+	transactionID string
+	offsetMsgID   string
+	regionID      string
+	traceOn       bool
+}
+
+//TraceOn TraceOn
+func (result *SendResult) TraceOn() bool {
+	return result.traceOn
+}
+
+//SetTraceOn SetTraceOn
+func (result *SendResult) SetTraceOn(b bool) {
+	result.traceOn = b
+}
+
+//SetRegionID SetRegionID
+func (result *SendResult) SetRegionID(s string) {
+	result.regionID = s
+}
+
+//MsgID get rocketmq message id
+func (result *SendResult) MsgID() string {
+	return result.msgID
+}
+
+//SetMsgID set rocketmq message id
+func (result *SendResult) SetMsgID(s string) {
+	result.msgID = s
+}
+
+//SendStatus SendStatus
+func (result *SendResult) SendStatus() SendStatus {
+	return result.sendStatus
+}
+
+//SetSendStatus SetSendStatus
+func (result *SendResult) SetSendStatus(status SendStatus) {
+	result.sendStatus = status
+}
+
+//MessageQueue this message send to which message queue
+func (result *SendResult) MessageQueue() MessageQueue {
+	return result.messageQueue
+}
+
+//SetMessageQueue SetMessageQueue
+func (result *SendResult) SetMessageQueue(queue MessageQueue) {
+	result.messageQueue = queue
+}
+
+//QueueOffset this message in this message queue's offset
+func (result *SendResult) QueueOffset() int64 {
+	return result.queueOffset
+}
+
+//SetQueueOffset SetQueueOffset
+func (result *SendResult) SetQueueOffset(offset int64) {
+	result.queueOffset = offset
+}
+
+//TransactionID no use,because not support transaction message
+func (result *SendResult) TransactionID() string {
+	return result.transactionID
+}
+
+//SetTransactionID no use,because not support transaction message
+func (result *SendResult) SetTransactionID(s string) {
+	result.transactionID = s
+}
+
+//OffsetMsgID OffsetMsgID
+func (result *SendResult) OffsetMsgID() string {
+	return result.offsetMsgID
+}
+
+//SetOffsetMsgID SetOffsetMsgID
+func (result *SendResult) SetOffsetMsgID(s string) {
+	result.offsetMsgID = s
+}
+
+//SendResult send message result to string(detail result)
+func (result *SendResult) String() string {
+	return fmt.Sprintf("SendResult [sendStatus=%d, msgId=%s, offsetMsgId=%s, messageQueue.BrokerName=%s, messageQueue.QueueId=%d, queueOffset=%d]",
+		result.sendStatus, result.msgID, result.offsetMsgID, result.messageQueue.BrokerName, result.messageQueue.QueueId, result.queueOffset)
+}
diff --git a/rocketmq-go/api/rocketmq_clent_instance.go b/rocketmq-go/api/rocketmq_clent_instance.go
new file mode 100644
index 0000000..f3eecbd
--- /dev/null
+++ b/rocketmq-go/api/rocketmq_clent_instance.go
@@ -0,0 +1,65 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmq
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel"
+)
+
+//MQClientInstance MQClientInstance
+type MQClientInstance interface {
+	//Register rocketmq producer to this client instance
+	RegisterProducer(producer MQProducer)
+	//Register rocketmq consumer to this client instance
+	RegisterConsumer(consumer MQConsumer)
+	// start this client instance. (register should before start)
+	Start()
+}
+
+//ClientInstanceImpl MQClientInstance's implement
+type ClientInstanceImpl struct {
+	rocketMqManager *kernel.MqClientManager
+}
+
+//InitRocketMQClientInstance create a MQClientInstance instance
+func InitRocketMQClientInstance(nameServerAddress string) (rocketMQClientInstance MQClientInstance) {
+	mqClientConfig := rocketmqm.NewMqClientConfig(nameServerAddress)
+	return InitRocketMQClientInstanceWithCustomClientConfig(mqClientConfig)
+}
+
+//InitRocketMQClientInstanceWithCustomClientConfig create a MQClientInstance instance with custom client config
+func InitRocketMQClientInstanceWithCustomClientConfig(mqClientConfig *rocketmqm.MqClientConfig) (rocketMQClientInstance MQClientInstance) {
+	rocketMQClientInstance = &ClientInstanceImpl{rocketMqManager: kernel.MqClientManagerInit(mqClientConfig)}
+	return
+}
+
+//RegisterProducer register producer to this client instance
+func (r *ClientInstanceImpl) RegisterProducer(producer MQProducer) {
+	r.rocketMqManager.RegisterProducer(producer.(*kernel.DefaultMQProducer))
+}
+
+//RegisterConsumer register consumer to this client instance
+func (r *ClientInstanceImpl) RegisterConsumer(consumer MQConsumer) {
+	r.rocketMqManager.RegisterConsumer(consumer.(*kernel.DefaultMQPushConsumer))
+}
+
+//Start start this client instance. (register should before start)
+func (r *ClientInstanceImpl) Start() {
+	r.rocketMqManager.Start()
+}
diff --git a/rocketmq-go/api/rocketmq_consumer.go b/rocketmq-go/api/rocketmq_consumer.go
new file mode 100644
index 0000000..ef59b46
--- /dev/null
+++ b/rocketmq-go/api/rocketmq_consumer.go
@@ -0,0 +1,48 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmq
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel"
+)
+
+//MQConsumer rocketmq consumer
+type MQConsumer interface {
+	// register custom's message listener to this consumer
+	RegisterMessageListener(listener rocketmqm.MessageListener)
+
+	// this consumer subscribe which topic, filter tags with subExpression
+	// subExpression is split by |
+	// for example.
+	// consume topic "TestTopic1",consume all message tag
+	// mqConsumer.Subscribe("TestTopic1","*")
+	// consume topic "TestTopic2",consume message with tag1 or tag2
+	// mqConsumer.Subscribe("TestTopic2","tag1|tag2")
+	Subscribe(topic string, subExpression string)
+}
+
+//NewDefaultMQPushConsumer Concurrently(no order) CLUSTERING mq consumer with default config
+func NewDefaultMQPushConsumer(producerGroup string) (r MQConsumer) {
+	return NewDefaultMQPushConsumerWithCustomConfig(producerGroup, rocketmqm.NewRocketMqConsumerConfig())
+}
+
+//NewDefaultMQPushConsumerWithCustomConfig Concurrently(no order) CLUSTERING mq consumer with custom config
+func NewDefaultMQPushConsumerWithCustomConfig(producerGroup string, consumerConfig *rocketmqm.MqConsumerConfig) (r MQConsumer) {
+	return kernel.NewDefaultMQPushConsumer(producerGroup, consumerConfig)
+}
diff --git a/rocketmq-go/api/rocketmq_producer.go b/rocketmq-go/api/rocketmq_producer.go
new file mode 100644
index 0000000..b95c703
--- /dev/null
+++ b/rocketmq-go/api/rocketmq_producer.go
@@ -0,0 +1,41 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package rocketmq
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel"
+)
+
+//MQProducer rocketmq producer
+type MQProducer interface {
+	//send message,default timeout is 3000
+	Send(message rocketmqm.Message) (sendResult *rocketmqm.SendResult, err error)
+	//send message with custom timeout
+	SendWithTimeout(message rocketmqm.Message, timeout int64) (sendResult *rocketmqm.SendResult, err error)
+}
+
+//NewDefaultMQProducer mq producer with default config
+func NewDefaultMQProducer(producerGroup string) (r MQProducer) {
+	return NewDefaultMQProducerWithCustomConfig(producerGroup, rocketmqm.NewProducerConfig())
+}
+
+//NewDefaultMQProducerWithCustomConfig mq producer with custom config
+func NewDefaultMQProducerWithCustomConfig(producerGroup string, producerConfig *rocketmqm.MqProducerConfig) (r MQProducer) {
+	return kernel.NewDefaultMQProducer(producerGroup, producerConfig)
+}
diff --git a/rocketmq-go/clean_expire_msg_controller.go b/rocketmq-go/clean_expire_msg_controller.go
deleted file mode 100644
index 73bb35b..0000000
--- a/rocketmq-go/clean_expire_msg_controller.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-	"time"
-)
-
-type CleanExpireMsgController struct {
-	mqClient      service.RocketMqClient
-	clientFactory *ClientFactory
-}
-
-func NewCleanExpireMsgController(mqClient service.RocketMqClient, clientFactory *ClientFactory) *CleanExpireMsgController {
-	return &CleanExpireMsgController{
-		mqClient:      mqClient,
-		clientFactory: clientFactory,
-	}
-}
-
-func (self *CleanExpireMsgController) Start() {
-	for _, consumer := range self.clientFactory.ConsumerTable {
-		go func() {
-			cleanExpireMsgTimer := time.NewTimer(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * 1000 * 60 * time.Millisecond)
-			//cleanExpireMsgTimer := time.NewTimer(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * time.Millisecond)
-			for {
-				<-cleanExpireMsgTimer.C
-				consumer.CleanExpireMsg()
-				cleanExpireMsgTimer.Reset(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * 1000 * 60 * time.Millisecond)
-				//cleanExpireMsgTimer.Reset(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * time.Millisecond)
-			}
-		}()
-	}
-}
diff --git a/rocketmq-go/docs/checklist.md b/rocketmq-go/docs/checklist.md
index 0412f86..a5ae9a3 100644
--- a/rocketmq-go/docs/checklist.md
+++ b/rocketmq-go/docs/checklist.md
@@ -1 +1,3 @@
 # Test Check List
+
+## todo
\ No newline at end of file
diff --git a/rocketmq-go/docs/consume-message-activity.puml b/rocketmq-go/docs/consume-message-activity.puml
new file mode 100644
index 0000000..12756e5
--- /dev/null
+++ b/rocketmq-go/docs/consume-message-activity.puml
@@ -0,0 +1,26 @@
+@startuml
+
+start
+:messageList = transformMessageToConsume;
+:ret = MessageListener(messageList);
+if (ret.ConsumeStatus == 'CONSUME_SUCCESS'?) then (yes)
+  :ackIndex = ret.AckIndex;
+else (no)
+  :ackIndex = -1;
+endif
+:successMessages = msgs[:ackIndex + 1];
+: i = ackIndex+1;
+while (i < msgs.length?)
+  :sendBackResult = sendMessageBack(msgs[i]);
+  if(sendBackResult?) then (yes)
+        :successMessages.append(msgs[i]);
+  else
+        :failedMessages.append(msgs[i]);
+  endif
+endwhile
+:commitOffset = removeSuccessMessage(successMessages);
+:submitConsumeRequest(failedMessages);
+:updateOffsetInLocalMemory(commitOffset);
+stop
+@enduml
+
diff --git a/rocketmq-go/docs/heartbeat-timing-diagram.puml b/rocketmq-go/docs/heartbeat-timing-diagram.puml
new file mode 100644
index 0000000..a8341b5
--- /dev/null
+++ b/rocketmq-go/docs/heartbeat-timing-diagram.puml
@@ -0,0 +1,7 @@
+@startuml
+MqClientManager ->ClientFactory:prepareHeartbeatData(producer/consumer info of this client)
+MqClientManager->MqClient:SendHeartbeatToAllBroker
+
+@enduml
+
+
diff --git a/rocketmq-go/docs/package.puml b/rocketmq-go/docs/package.puml
index f34dd38..ebeacdf 100644
--- a/rocketmq-go/docs/package.puml
+++ b/rocketmq-go/docs/package.puml
@@ -1,26 +1,45 @@
 @startuml
-
-
-class rocketmq_go.MqClientManager{
-serviceState
-}
-class rocketmq_go.PullMessageController{
+interface api.MQProducer{
 
 }
-class rocketmq_go.ClientFactory{
+interface api.MQConsumer{
+
+}
+interface api.MQClientInstance{
+
+       
+}
+
+namespace api{
+    MQClientInstance o-- kernel.MqClientManager
+    MQProducer o-- kernel.DefaultMQProducer
+    MQConsumer o-- kernel.DefaultMQPushConsumer
+    MQConsumer o-- kernel.DefaultMQPullConsumer
+}
+
+class kernel.MqClientManager{
+kernelState
+}
+class kernel.PullMessageController{
+
+}
+class kernel.AllocateMessageQueueStrategy{
+}
+class kernel.ClientFactory{
 mqConsumerTable
 mqProducerTable
 }
-class service.MqConsumer{
-serviceState
-offsetStore
+class kernel.DefaultMQPushConsumer{
 }
-class service.MqProducer{
-serviceState
+class kernel.DefaultMQPullConsumer{
+    to be done
+}
+class kernel.DefaultMQProducer{
  }
- class service.MqClient{
+ class kernel.MqClient{
 
-
+ }
+ class kernel.MessageListener{
  }
   class remoting.RemotingClient{
    invokeSync
@@ -49,27 +68,34 @@
     }
 
 
-namespace service{
+namespace kernel{
 
 
-rocketmq_go.PullMessageController *-- rocketmq_go.ClientFactory:contains
-rocketmq_go.ClientFactory *-- MqProducer:contains
-rocketmq_go.ClientFactory *-- MqConsumer:contains
-MqProducer *-- service.MqClient :contains
-MqConsumer *-- service.MqClient : contains
-MqConsumer *-- service.OffsetStore : contains
-MqConsumer *-- service.Rebalance : contains
-MqConsumer *-- service.ConsumeMessageService : contains
+kernel.PullMessageController *-- kernel.ClientFactory:contains
+    MqClientManager o-- PullMessageController
+    MqClientManager o-- ClientFactory
+    kernel.ClientFactory *-- DefaultMQPushConsumer:contains
+    kernel.ClientFactory *-- DefaultMQPullConsumer:contains
+    DefaultMQPushConsumer *-- kernel.MqClient : contains
+    DefaultMQPushConsumer *-- kernel.OffsetStore : contains
+    DefaultMQPushConsumer *-- kernel.Rebalance : contains
+    DefaultMQPushConsumer *-- kernel.ConsumeMessageService : contains
+    kernel.ClientFactory *-- DefaultMQProducer:contains
+
+    DefaultMQProducer *-- kernel.MqClient :contains
+
 
 }
 
-namespace service{
+namespace kernel{
     MqClient o-- remoting.RemotingClient:contains
     OffsetStore o-- MqClient
     Rebalance o-- MqClient
     Rebalance o-- OffsetStore
-    ConsumeMessageService o-- SendMessageBackProducerService
+    Rebalance o-- AllocateMessageQueueStrategy
+    ConsumeMessageService o-- SendMessageBackProducerkernel
     ConsumeMessageService o-- OffsetStore
+    ConsumeMessageService o-- MessageListener
 }
 
 namespace remoting {
@@ -81,13 +107,9 @@
 
 }
 
-namespace rocketmq_go{
-    MqClientManager o-- PullMessageController
-    MqClientManager o-- ClientFactory
-}
 
 
 note top of remoting.RemotingClient :(sync|aysc|oneWay)
 note top of remoting :net,serialize,connect,request response
-note top of service.MqClient :mq common method
+
 @enduml
\ No newline at end of file
diff --git a/rocketmq-go/docs/pull-message-timing-diagram.puml b/rocketmq-go/docs/pull-message-timing-diagram.puml
new file mode 100644
index 0000000..6ae4ba2
--- /dev/null
+++ b/rocketmq-go/docs/pull-message-timing-diagram.puml
@@ -0,0 +1,21 @@
+@startuml
+Rebalance ->Rebalance:after rebalance we get a Map<MessageQueue,ProcessQueue>
+Rebalance -> PullRequestController :  buid a pullRequest and put to pullRequestQueue
+PullRequestController -> PullRequestController : while loop take the item of pullRequestQueue then pullMessage
+PullRequestController->Broker:do something about flow control/message drop... if ok,async pull message from broker
+Broker ->PullRequestController:pull message call back.
+alt FOUND
+PullRequestController->PullRequestController:put Message into processQueue
+PullRequestController->ConsumeMessageService:submitConsumeRequest
+else NO_NEW_MSG
+PullRequestController->PullRequestController
+else NO_MATCHED_MSG
+PullRequestController->PullRequestController
+else OFFSET_ILLEGAL
+PullRequestController->PullRequestController
+end
+PullRequestController->PullRequestController:executeNextPullRequest
+
+@enduml
+
+
diff --git a/rocketmq-go/docs/rebalance-timing-diagram.puml b/rocketmq-go/docs/rebalance-timing-diagram.puml
new file mode 100644
index 0000000..15a4041
--- /dev/null
+++ b/rocketmq-go/docs/rebalance-timing-diagram.puml
@@ -0,0 +1,16 @@
+@startuml
+Rebalance ->Rebalance:for each topic in Subscription
+Rebalance->MqClient:findConsumerIdList(topic,group)
+Rebalance->MqClient:GetTopicSubscribeInfo(topic)
+Rebalance->AllocateMessageQueueStrategy:allocate with all consumer client List and all queue info
+Rebalance->Rebalance:updateProcessQueueTableInRebalance
+alt allocate a new queue belong this consumer
+Rebalance->OffsetStore:computePullFromWhere
+OffsetStore->MqClient:read offset
+Rebalance->MqClient:enqueue pull message request
+else find a queue not belong this consumer
+Rebalance->Rebalance:delete this processQueue
+end
+@enduml
+
+
diff --git a/rocketmq-go/docs/roadmap.md b/rocketmq-go/docs/roadmap.md
index a69c561..3f00e44 100644
--- a/rocketmq-go/docs/roadmap.md
+++ b/rocketmq-go/docs/roadmap.md
@@ -1,97 +1,22 @@
 # RoadMap-Milestone1
-
-## Consumer
-- [x] ConsumerType
-    - [x] PushConsumer
-- [x] MessageListener
-    - [x] Concurrently
-- [x] MessageModel
-    - [x] CLUSTERING
-- [x] OffsetStore
-    - [x] RemoteBrokerOffsetStore
-- [x] RebalanceService
-- [x] PullMessageService
-- [x] ConsumeMessageService
-- [x] AllocateMessageQueueStrategy
-    - [x] AllocateMessageQueueAveragely
-- [x] Other
-    - [x] Config
-    - [x] ZIP
-    - [x] ConsumeFromWhere
-        - [x] CONSUME_FROM_LAST_OFFSET
-        - [x] CONSUME_FROM_FIRST_OFFSET
-        - [x] CONSUME_FROM_TIMESTAMP
-    - [x] Retry(sendMessageBack)
-    - [x] TimeOut(clearExpiredMessage)
-    - [x] ACK(partSuccess)
-    - [x] FlowControl(messageCanNotConsume)
-    
 ## Producer
 - [x] ProducerType
     - [x] DefaultProducer
-- [x] API
-    - [x] Send
+- [ ] API
+    - [ ] Send
         - [x] Sync
-- [x] Other
+        - [ ] Async
+        - [ ] OneWay
+- [ ] Other
     - [x] DelayMessage
     - [x] Config
     - [x] MessageId Generate
     - [x] CompressMsg
     - [x] TimeOut
     - [x] LoadBalance
-    - [x] DefaultTopic
-    - [x] VipChannel
-    - [x] MQFaultStrategy
-
-## Manager
-- [x] Controller
-    - [x] PullMessageController
-- [x] Task
-    - [x] UpdateTopicRouteInfo
-    - [x] Heartbeat
-    - [x] Rebalance
-    - [x] PullMessage
-    - [x] CleanExpireMsg
-- [x] ClientRemotingProcessor
-    - [x] CHECK_TRANSACTION_STATE
-    - [x] NOTIFY_CONSUMER_IDS_CHANGED
-    - [x] RESET_CONSUMER_CLIENT_OFFSET
-    - [x] GET_CONSUMER_STATUS_FROM_CLIENT
-    - [x] GET_CONSUMER_RUNNING_INFO
-    - [x] CONSUME_MESSAGE_DIRECTLY
-
-## Remoting
-- [x] MqClientRequest
-    - [x] InvokeSync
-    - [x] InvokeAsync
-    - [x] InvokeOneWay
-- [x] Serialize
-    - [x] JSON
-    - [x] ROCKETMQ
-- [x] NamesrvAddrChoosed(HA)
-
-
-# RoadMap-ALL
-
-## Producer
-- [ ] ProducerType
-    - [ ] DefaultProducer
-    - [ ] TransactionProducer
-- [ ] API
-    - [ ] Send
-        - [ ] Sync
-        - [ ] Async
-        - [ ] OneWay
-- [ ] Other
-    - [ ] DelayMessage
-    - [ ] Config
-    - [ ] MessageId Generate
-    - [ ] CompressMsg
-    - [ ] TimeOut
-    - [ ] LoadBalance
     - [ ] DefaultTopic
     - [ ] VipChannel
-    - [ ] Retry
+    - [x] Retry
     - [ ] SendMessageHook
     - [ ] CheckRequestQueue
     - [ ] CheckForbiddenHookList
@@ -101,67 +26,67 @@
 
 ## Consumer
 - [ ] ConsumerType
-    - [ ] PushConsumer
+    - [x] PushConsumer
     - [ ] PullConsumer
 - [ ] MessageListener
-    - [ ] Concurrently
+    - [x] Concurrently
     - [ ] Orderly
 - [ ] MessageModel
-    - [ ] CLUSTERING
+    - [x] CLUSTERING
     - [ ] BROADCASTING
 - [ ] OffsetStore
-    - [ ] RemoteBrokerOffsetStore
-        - [ ] many actions
+    - [x] RemoteBrokerOffsetStore
     - [ ] LocalFileOffsetStore
-- [ ] RebalanceService
-- [ ] PullMessageService
-- [ ] ConsumeMessageService
+- [x] RebalanceService
+- [x] PullMessageService
+- [x] ConsumeMessageService
 - [ ] AllocateMessageQueueStrategy
-    - [ ] AllocateMessageQueueAveragely
+    - [x] AllocateMessageQueueAveragely
     - [ ] AllocateMessageQueueAveragelyByCircle
     - [ ] AllocateMessageQueueByConfig
     - [ ] AllocateMessageQueueByMachineRoom
 - [ ] Other
-    - [ ] Config
-    - [ ] ZIP
+    - [x] Config
+    - [x] ZIP
     - [ ] AllocateMessageQueueStrategy
-    - [ ] ConsumeFromWhere
-        - [ ] CONSUME_FROM_LAST_OFFSET
-        - [ ] CONSUME_FROM_FIRST_OFFSET
-        - [ ] CONSUME_FROM_TIMESTAMP
-    - [ ] Retry(sendMessageBack)
-    - [ ] TimeOut(clearExpiredMessage)
-    - [ ] ACK(partSuccess)
-    - [ ] FlowControl(messageCanNotConsume)
+    - [x] ConsumeFromWhere
+        - [x] CONSUME_FROM_LAST_OFFSET
+        - [x] CONSUME_FROM_FIRST_OFFSET
+        - [x] CONSUME_FROM_TIMESTAMP
+    - [x] Retry(sendMessageBack)
+    - [x] TimeOut(clearExpiredMessage)
+    - [x] ACK(partSuccess)
+    - [x] FlowControl(messageCanNotConsume)
     - [ ] ConsumeMessageHook
     - [ ] filterMessageHookList
 
-## Manager
-- [ ] Controller
-    - [ ] RebalanceController
-    - [ ] PullMessageController
+## Kernel
+- [x] Controller
+    - [x] RebalanceController
+    - [x] PullMessageController
 - [ ] Task
-    - [ ] UpdateTopicRouteInfo
-    - [ ] Heartbeat
-    - [ ] Rebalance
-    - [ ] PullMessage
-    - [ ] CleanExpireMsg
-- [ ] ClientRemotingProcessor
+    - [x] Heartbeat
+    - [x] UpdateTopicRouteInfoFromNameServer
+    - [ ] CleanOfflineBroker
+    - [x] PersistAllConsumerOffset
+    - [x] ClearExpiredMessage(form consumer consumeMessageService)
+    - [ ] UploadFilterClassSource(FromHeartBeat/But Golang Not Easy To do this(Java Source))
+- [x] ClientRemotingProcessor
     - [ ] CHECK_TRANSACTION_STATE
-    - [ ] NOTIFY_CONSUMER_IDS_CHANGED
-    - [ ] RESET_CONSUMER_CLIENT_OFFSET
-    - [ ] GET_CONSUMER_STATUS_FROM_CLIENT
-    - [ ] GET_CONSUMER_RUNNING_INFO
-    - [ ] CONSUME_MESSAGE_DIRECTLY
+    - [x] NOTIFY_CONSUMER_IDS_CHANGED
+    - [x] RESET_CONSUMER_CLIENT_OFFSET
+    - [x] GET_CONSUMER_STATUS_FROM_CLIENT
+    - [x] GET_CONSUMER_RUNNING_INFO
+    - [x] CONSUME_MESSAGE_DIRECTLY
 ## Remoting
-- [ ] MqClientRequest
-    - [ ] InvokeSync
-    - [ ] InvokeAsync
-    - [ ] InvokeOneWay
-- [ ] Serialize
-    - [ ] JSON
-    - [ ] ROCKETMQ
-- [ ] NamesrvAddrChoosed(HA)
+- [x] MqClientRequest
+    - [x] InvokeSync
+    - [x] InvokeAsync
+    - [x] InvokeOneWay
+- [x] Serialize
+    - [x] JSON
+    - [x] ROCKETMQ
+- [x] NamesrvAddrChoosed(HA)
 - [ ] Other
     - [ ] VIPChannel
     - [ ] RPCHook
diff --git a/rocketmq-go/docs/update-topic-routeInfo-timing-diagram.puml b/rocketmq-go/docs/update-topic-routeInfo-timing-diagram.puml
new file mode 100644
index 0000000..df26aa0
--- /dev/null
+++ b/rocketmq-go/docs/update-topic-routeInfo-timing-diagram.puml
@@ -0,0 +1,10 @@
+@startuml
+MqClientManager ->ClientFactory:get all topics from consumer.subscription
+MqClientManager -> MqClient:all topics from topic publish info
+MqClientManager -> MqClient:for each topic,UpdateTopicRouteInfoFromNameServer
+MqClient -> RemotingClient:GetTopicRouteInfoFromNameServer
+MqClient -> MqClient:updateTopicRouteInfoLocal \nBrokerAddrTable\nTopicPublishInfoTable\nTopicSubscribeInfoTable\nTopicRouteTable
+
+@enduml
+
+
diff --git a/rocketmq-go/example/consumer_example.go b/rocketmq-go/example/consumer_example.go
deleted file mode 100644
index 7c94e58..0000000
--- a/rocketmq-go/example/consumer_example.go
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package main
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/golang/glog"
-	"time"
-)
-
-func main() {
-
-	var (
-		testTopic = "GoLang"
-	)
-	var comsumer1 = rocketmq.NewDefaultMQPushConsumer(testTopic + "-StyleTang")
-	comsumer1.ConsumerConfig.PullInterval = 0
-	comsumer1.ConsumerConfig.ConsumeTimeout = 1
-	comsumer1.ConsumerConfig.ConsumeMessageBatchMaxSize = 16
-	comsumer1.ConsumerConfig.ConsumeFromWhere = "CONSUME_FROM_TIMESTAMP"
-	comsumer1.ConsumerConfig.ConsumeTimestamp = time.Now()
-	comsumer1.Subscribe(testTopic, "*")
-	comsumer1.RegisterMessageListener(func(msgs []model.MessageExt) model.ConsumeConcurrentlyResult {
-		for _, msg := range msgs {
-			glog.Info(msg.BornTimestamp)
-		}
-		glog.Info("look message len ", len(msgs))
-		return model.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: model.CONSUME_SUCCESS, AckIndex: len(msgs)}
-	})
-	var clienConfig = &config.ClientConfig{}
-	clienConfig.SetNameServerAddress("120.55.113.35:9876")
-	rocketMqManager := rocketmq.MqClientManagerInit(clienConfig)
-	rocketMqManager.RegistConsumer(comsumer1)
-	rocketMqManager.Start()
-	select {}
-	rocketMqManager.ShutDown()
-}
diff --git a/rocketmq-go/example/producer_consumer_example.go b/rocketmq-go/example/producer_consumer_example.go
deleted file mode 100644
index 0d8e455..0000000
--- a/rocketmq-go/example/producer_consumer_example.go
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package main
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go" //todo todo  I want only import this
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"github.com/golang/glog"
-	"net/http"
-	_ "net/http/pprof"
-	"time"
-)
-
-func main() {
-	go func() {
-		http.ListenAndServe("localhost:6060", nil)
-	}()
-	var (
-		testTopic = "GoLang"
-	)
-	var producer1 = rocketmq.NewDefaultMQProducer("Test1")
-	producer1.ProducerConfig.CompressMsgBodyOverHowMuch = 1
-	var producer2 = rocketmq.NewDefaultMQProducer("Test2")
-	var comsumer1 = rocketmq.NewDefaultMQPushConsumer(testTopic + "-StyleTang")
-	comsumer1.ConsumerConfig.PullInterval = 0
-	comsumer1.ConsumerConfig.ConsumeTimeout = 1
-	comsumer1.ConsumerConfig.ConsumeMessageBatchMaxSize = 16
-	comsumer1.ConsumerConfig.ConsumeFromWhere = "CONSUME_FROM_TIMESTAMP"
-	comsumer1.ConsumerConfig.ConsumeTimestamp = time.Now()
-	comsumer1.Subscribe(testTopic, "*")
-	comsumer1.RegisterMessageListener(func(msgs []model.MessageExt) model.ConsumeConcurrentlyResult {
-		for _, msg := range msgs {
-			glog.Info(msg.BornTimestamp)
-		}
-		glog.Info("look message len ", len(msgs))
-		return model.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: model.CONSUME_SUCCESS, AckIndex: len(msgs)}
-	})
-	var clienConfig = &config.ClientConfig{}
-	clienConfig.SetNameServerAddress("120.55.113.35:9876")
-	rocketMqManager := rocketmq.MqClientManagerInit(clienConfig)
-	rocketMqManager.RegistProducer(producer1)
-	rocketMqManager.RegistProducer(producer2)
-	rocketMqManager.RegistConsumer(comsumer1)
-	rocketMqManager.Start()
-	for i := 0; i < 10000000; i++ {
-		var message = &model.Message{}
-		message.Topic = testTopic
-		message.SetKeys([]string{"xxx"})
-		message.SetTag("1122")
-		message.Body = []byte("hellAXXWord" + util.IntToString(i))
-
-		xx, ee := producer1.Send(message)
-		if ee != nil {
-			glog.Error(ee)
-			continue
-		}
-		glog.V(0).Infof("sendMessageResutl messageId[%s] err[%s]", xx.MsgID(), ee)
-	}
-	select {}
-	rocketMqManager.ShutDown()
-}
diff --git a/rocketmq-go/example/producer_example.go b/rocketmq-go/example/producer_example.go
deleted file mode 100644
index acc2011..0000000
--- a/rocketmq-go/example/producer_example.go
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package main
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"github.com/golang/glog"
-	_ "net/http/pprof"
-)
-
-func main() {
-	var (
-		testTopic = "GoLang"
-	)
-	var producer1 = rocketmq.NewDefaultMQProducer("Test1")
-	producer1.ProducerConfig.CompressMsgBodyOverHowMuch = 1
-	var producer2 = rocketmq.NewDefaultMQProducer("Test2")
-	var clienConfig = &config.ClientConfig{}
-	clienConfig.SetNameServerAddress("120.55.113.35:9876")
-	rocketMqManager := rocketmq.MqClientManagerInit(clienConfig)
-	rocketMqManager.RegistProducer(producer1)
-	rocketMqManager.RegistProducer(producer2)
-	rocketMqManager.Start()
-	for i := 0; i < 1000; i++ {
-		var message = &model.Message{}
-		message.Topic = testTopic
-		message.SetKeys([]string{"xxx"})
-		message.SetTag("1122")
-		message.Body = []byte("hellAXXWord" + util.IntToString(i))
-
-		xx, ee := producer1.Send(message)
-		if ee != nil {
-			glog.Error(ee)
-			continue
-		}
-		glog.V(0).Infof("sendMessageResutl messageId[%s] err[%s]", xx.MsgID(), ee)
-	}
-	select {}
-	rocketMqManager.ShutDown()
-}
diff --git a/rocketmq-go/example/rocketmq_client_example.go b/rocketmq-go/example/rocketmq_client_example.go
deleted file mode 100644
index c6828c8..0000000
--- a/rocketmq-go/example/rocketmq_client_example.go
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package main
-
-import (
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-)
-
-func main() {
-
-	var clienConfig = config.NewClientConfig()
-	clienConfig.SetNameServerAddress("120.55.113.35:9876")
-
-	//use json serializer
-	var mqClient = service.MqClientInit(clienConfig, nil)
-	fmt.Println(mqClient.TryToFindTopicPublishInfo("GoLang"))
-	//&{false true [{GoLang broker-a 0} {GoLang broker-a 1} {GoLang broker-a 2} {GoLang broker-a 3}] 0xc420016800 0} <nil>
-
-	//use rocketmq serializer
-	constant.USE_HEADER_SERIALIZETYPE = constant.ROCKETMQ_SERIALIZE
-	var mqClient2 = service.MqClientInit(clienConfig, nil)
-	fmt.Println(mqClient2.TryToFindTopicPublishInfo("GoLang"))
-}
diff --git a/rocketmq-go/example/simple_consumer.go b/rocketmq-go/example/simple_consumer.go
new file mode 100644
index 0000000..2dcec45
--- /dev/null
+++ b/rocketmq-go/example/simple_consumer.go
@@ -0,0 +1,53 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+)
+
+func main() {
+	var (
+		nameServerAddress = "127.0.0.1:9876" //address split by ;  (for example 192.168.1.1:9876;192.168.1.2:9876)
+		testTopic         = "GoLangRocketMQ"
+		testConsumerGroup = "TestConsumerGroup"
+	)
+	// init rocketMQClientInstance
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	// 1.init rocketMQConsumer
+	// 2.subscribe topic and register our function to message listener
+	// 3.register it
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, "*")
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			glog.Infof("test receiveMessage messageId=[%s] messageBody=[%s]", msg.MsgId(), string(msg.Body()))
+			// call your function
+			successIndex = index
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+
+	// start rocketMQ client instance
+	rocketMQClientInstance.Start()
+	select {}
+}
diff --git a/rocketmq-go/example/simple_producer.go b/rocketmq-go/example/simple_producer.go
new file mode 100644
index 0000000..84f4b2d
--- /dev/null
+++ b/rocketmq-go/example/simple_producer.go
@@ -0,0 +1,47 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+)
+
+func main() {
+	var (
+		nameServerAddress = "127.0.0.1:9876" //address split by ;  (for example 192.168.1.1:9876;192.168.1.2:9876)
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestProducerGroup"
+	)
+	// init rocketMQClientInstance
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	// init rocketMQProducer and register it
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+
+	// start rocketMQ client instance
+	rocketMQClientInstance.Start()
+
+	//start send test message
+	var message = rocketmqm.NewMessage()
+	message.SetTopic(testTopic)
+	message.SetBody([]byte("hello World"))
+	result, err := producer.Send(message)
+	glog.Infof("test sendMessageResult result=[%s] err=[%s]", result.String(), err)
+}
diff --git a/rocketmq-go/example/simple_producer_consumer.go b/rocketmq-go/example/simple_producer_consumer.go
new file mode 100644
index 0000000..052d7c6
--- /dev/null
+++ b/rocketmq-go/example/simple_producer_consumer.go
@@ -0,0 +1,66 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+)
+
+func main() {
+	var (
+		nameServerAddress = "127.0.0.1:9876" //address split by ;  (for example 192.168.1.1:9876;192.168.1.2:9876)
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestProducerGroup"
+		testConsumerGroup = "TestConsumerGroup"
+	)
+	// init rocketMQClientInstance
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	// init rocketMQProducer and register it
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+
+	// 1.init rocketMQConsumer
+	// 2.subscribe topic and register our function to message listener
+	// 3.register it
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, "*")
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			glog.Infof("test receiveMessage messageId=[%s] messageBody=[%s]", msg.MsgId(), string(msg.Body()))
+			// call your function
+			successIndex = index
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+
+	// start rocketMQ client instance
+	rocketMQClientInstance.Start()
+
+	//start send test message
+	for {
+		var message = rocketmqm.NewMessage()
+		message.SetTopic(testTopic)
+		message.SetBody([]byte("hello World"))
+		result, err := producer.Send(message)
+		glog.Infof("test sendMessageResult result=[%s] err=[%s]", result.String(), err)
+	}
+}
diff --git a/rocketmq-go/kernel/allocate/allocate_message_averagely.go b/rocketmq-go/kernel/allocate/allocate_message_averagely.go
new file mode 100644
index 0000000..48cc050
--- /dev/null
+++ b/rocketmq-go/kernel/allocate/allocate_message_averagely.go
@@ -0,0 +1,83 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package allocate
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+)
+
+//allocateMessageQueueAveragely allocateMessageQueueAveragely
+type allocateMessageQueueAveragely struct{}
+
+//Allocate message queue
+func (a *allocateMessageQueueAveragely) Allocate(consumerGroup string, currentCID string, mqAll []*rocketmqm.MessageQueue, cidAll []string) ([]rocketmqm.MessageQueue, error) {
+
+	if currentCID == "" {
+		return nil, errors.New("currentCID is empty")
+	}
+
+	if mqAll == nil || len(mqAll) == 0 {
+		return nil, errors.New("mqAll is nil or mqAll empty")
+	}
+
+	if cidAll == nil || len(cidAll) == 0 {
+		return nil, errors.New("cidAll is nil or cidAll empty")
+	}
+
+	result := make([]rocketmqm.MessageQueue, 0)
+	for i, cid := range cidAll {
+		if cid == currentCID {
+			mqLen := len(mqAll)
+			cidLen := len(cidAll)
+			mod := mqLen % cidLen
+			var averageSize int
+			if mqLen < cidLen {
+				averageSize = 1
+			} else {
+				if mod > 0 && i < mod {
+					averageSize = mqLen/cidLen + 1
+				} else {
+					averageSize = mqLen / cidLen
+				}
+			}
+
+			var startIndex int
+			if mod > 0 && i < mod {
+				startIndex = i * averageSize
+			} else {
+				startIndex = i*averageSize + mod
+			}
+
+			var min int
+			if averageSize > mqLen-startIndex {
+				min = mqLen - startIndex
+			} else {
+				min = averageSize
+			}
+
+			for j := 0; j < min; j++ {
+				result = append(result, *mqAll[(startIndex+j)%mqLen])
+			}
+			return result, nil
+
+		}
+	}
+
+	return nil, errors.New("cant't find currentCID")
+}
diff --git a/rocketmq-go/kernel/allocate/allocate_message_averagely_by_circle.go b/rocketmq-go/kernel/allocate/allocate_message_averagely_by_circle.go
new file mode 100644
index 0000000..369d59f
--- /dev/null
+++ b/rocketmq-go/kernel/allocate/allocate_message_averagely_by_circle.go
@@ -0,0 +1,82 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package allocate
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+)
+
+//AllocateMessageQueueAveragelyByCircle AllocateMessageQueueAveragelyByCircle
+type AllocateMessageQueueAveragelyByCircle struct{}
+
+//Allocate message queue
+func (a *AllocateMessageQueueAveragelyByCircle) Allocate(consumerGroup string, currentCID string, mqAll []*rocketmqm.MessageQueue, cidAll []string) ([]rocketmqm.MessageQueue, error) {
+	if currentCID == "" {
+		return nil, errors.New("currentCID is empty")
+	}
+
+	if mqAll == nil || len(mqAll) == 0 {
+		return nil, errors.New("mqAll is nil or mqAll empty")
+	}
+
+	if cidAll == nil || len(cidAll) == 0 {
+		return nil, errors.New("cidAll is nil or cidAll empty")
+	}
+
+	result := make([]rocketmqm.MessageQueue, 0)
+	for i, cid := range cidAll {
+		if cid == currentCID {
+			mqLen := len(mqAll)
+			cidLen := len(cidAll)
+			mod := mqLen % cidLen
+			var averageSize int
+			if mqLen < cidLen {
+				averageSize = 1
+			} else {
+				if mod > 0 && i < mod {
+					averageSize = mqLen/cidLen + 1
+				} else {
+					averageSize = mqLen / cidLen
+				}
+			}
+
+			var startIndex int
+			if mod > 0 && i < mod {
+				startIndex = i * averageSize
+			} else {
+				startIndex = i*averageSize + mod
+			}
+
+			var min int
+			if averageSize > mqLen-startIndex {
+				min = mqLen - startIndex
+			} else {
+				min = averageSize
+			}
+
+			for j := 0; j < min; j++ {
+				result = append(result, *mqAll[(startIndex+j)%mqLen])
+			}
+			return result, nil
+
+		}
+	}
+
+	return nil, errors.New("cant't find currentCID")
+}
diff --git a/rocketmq-go/kernel/allocate/allocate_message_by_config.go b/rocketmq-go/kernel/allocate/allocate_message_by_config.go
new file mode 100644
index 0000000..d392e67
--- /dev/null
+++ b/rocketmq-go/kernel/allocate/allocate_message_by_config.go
@@ -0,0 +1,32 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package allocate
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+)
+
+//AllocateMessageQueueByConfig AllocateMessageQueueByConfig
+type AllocateMessageQueueByConfig struct {
+	messageQueueList []rocketmqm.MessageQueue
+}
+
+//Allocate message queue
+func (a *AllocateMessageQueueByConfig) Allocate(consumerGroup string, currentCID string, mqAll []*rocketmqm.MessageQueue, cidAll []string) ([]rocketmqm.MessageQueue, error) {
+	return a.messageQueueList, nil
+}
diff --git a/rocketmq-go/kernel/allocate/allocate_message_by_machine_room.go b/rocketmq-go/kernel/allocate/allocate_message_by_machine_room.go
new file mode 100644
index 0000000..cae3cd8
--- /dev/null
+++ b/rocketmq-go/kernel/allocate/allocate_message_by_machine_room.go
@@ -0,0 +1,83 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package allocate
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+)
+
+//allocateMessageQueueByMachineRoom allocateMessageQueueByMachineRoom
+type allocateMessageQueueByMachineRoom struct {
+}
+
+//Allocate Allocate message queue by machine room
+func (a *allocateMessageQueueByMachineRoom) Allocate(consumerGroup string, currentCID string, mqAll []*rocketmqm.MessageQueue, cidAll []string) ([]rocketmqm.MessageQueue, error) {
+	if currentCID == "" {
+		return nil, errors.New("currentCID is empty")
+	}
+
+	if mqAll == nil || len(mqAll) == 0 {
+		return nil, errors.New("mqAll is nil or mqAll empty")
+	}
+
+	if cidAll == nil || len(cidAll) == 0 {
+		return nil, errors.New("cidAll is nil or cidAll empty")
+	}
+
+	result := make([]rocketmqm.MessageQueue, 0)
+	for i, cid := range cidAll {
+		if cid == currentCID {
+			mqLen := len(mqAll)
+			cidLen := len(cidAll)
+			mod := mqLen % cidLen
+			var averageSize int
+			if mqLen < cidLen {
+				averageSize = 1
+			} else {
+				if mod > 0 && i < mod {
+					averageSize = mqLen/cidLen + 1
+				} else {
+					averageSize = mqLen / cidLen
+				}
+			}
+
+			var startIndex int
+			if mod > 0 && i < mod {
+				startIndex = i * averageSize
+			} else {
+				startIndex = i*averageSize + mod
+			}
+
+			var min int
+			if averageSize > mqLen-startIndex {
+				min = mqLen - startIndex
+			} else {
+				min = averageSize
+			}
+
+			for j := 0; j < min; j++ {
+				result = append(result, *mqAll[(startIndex+j)%mqLen])
+			}
+			return result, nil
+
+		}
+	}
+
+	return nil, errors.New("cant't find currentCID")
+}
diff --git a/rocketmq-go/kernel/allocate/allocate_message_queue_strategy.go b/rocketmq-go/kernel/allocate/allocate_message_queue_strategy.go
new file mode 100644
index 0000000..10bb6a7
--- /dev/null
+++ b/rocketmq-go/kernel/allocate/allocate_message_queue_strategy.go
@@ -0,0 +1,30 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package allocate
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+//AllocateMessageQueueStrategy Allocate message queue
+type AllocateMessageQueueStrategy interface {
+	Allocate(consumerGroup string, currentCID string, mqAll []*rocketmqm.MessageQueue, cidAll []string) ([]rocketmqm.MessageQueue, error)
+}
+
+//GetAllocateMessageQueueStrategyByConfig get allocate message queue strategy by config
+func GetAllocateMessageQueueStrategyByConfig(allocateMessageQueueStrategy string) AllocateMessageQueueStrategy {
+	return new(allocateMessageQueueAveragely)
+}
diff --git a/rocketmq-go/kernel/clean_expire_msg_controller.go b/rocketmq-go/kernel/clean_expire_msg_controller.go
new file mode 100644
index 0000000..d155126
--- /dev/null
+++ b/rocketmq-go/kernel/clean_expire_msg_controller.go
@@ -0,0 +1,49 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"time"
+)
+
+type cleanExpireMsgController struct {
+	mqClient      RocketMqClient
+	clientFactory *clientFactory
+}
+
+func newCleanExpireMsgController(mqClient RocketMqClient, clientFactory *clientFactory) *cleanExpireMsgController {
+	return &cleanExpireMsgController{
+		mqClient:      mqClient,
+		clientFactory: clientFactory,
+	}
+}
+
+func (c *cleanExpireMsgController) start() {
+	for _, consumer := range c.clientFactory.consumerTable {
+		go func(currentConsumer *DefaultMQPushConsumer) {
+			cleanExpireMsgTimer := time.NewTimer(time.Duration(currentConsumer.ConsumerConfig.ConsumeTimeout) * 1000 * 60 * time.Millisecond)
+			//cleanExpireMsgTimer := time.NewTimer(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * time.Millisecond)
+			for {
+				<-cleanExpireMsgTimer.C
+				currentConsumer.CleanExpireMsg()
+				cleanExpireMsgTimer.Reset(time.Duration(currentConsumer.ConsumerConfig.ConsumeTimeout) * 1000 * 60 * time.Millisecond)
+				//cleanExpireMsgTimer.Reset(time.Duration(consumer.ConsumerConfig.ConsumeTimeout) * time.Millisecond)
+			}
+		}(consumer)
+	}
+}
diff --git a/rocketmq-go/kernel/consume_message_service.go b/rocketmq-go/kernel/consume_message_service.go
new file mode 100644
index 0000000..f34991e
--- /dev/null
+++ b/rocketmq-go/kernel/consume_message_service.go
@@ -0,0 +1,162 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+)
+
+type consumeMessageService interface {
+	init(consumerGroup string, mqClient RocketMqClient, offsetStore OffsetStore, defaultProducerService *DefaultProducerService, consumerConfig *rocketmqm.MqConsumerConfig)
+	submitConsumeRequest(msgs []message.MessageExtImpl, processQueue *model.ProcessQueue,
+		messageQueue *rocketmqm.MessageQueue, dispathToConsume bool)
+	sendMessageBack(messageExt *message.MessageExtImpl, delayLayLevel int, brokerName string) (err error)
+	consumeMessageDirectly(messageExt *message.MessageExtImpl, brokerName string) (consumeMessageDirectlyResult model.ConsumeMessageDirectlyResult, err error)
+}
+
+type consumeMessageConcurrentlyServiceImpl struct {
+	consumerGroup                  string
+	messageListener                rocketmqm.MessageListener
+	sendMessageBackProducerService sendMessageBackProducerService //for send retry MessageImpl
+	offsetStore                    OffsetStore
+	consumerConfig                 *rocketmqm.MqConsumerConfig
+}
+
+func newConsumeMessageConcurrentlyServiceImpl(messageListener rocketmqm.MessageListener) (consumeService consumeMessageService) {
+	consumeService = &consumeMessageConcurrentlyServiceImpl{messageListener: messageListener, sendMessageBackProducerService: &sendMessageBackProducerServiceImpl{}}
+	return
+}
+
+func (c *consumeMessageConcurrentlyServiceImpl) init(consumerGroup string, mqClient RocketMqClient, offsetStore OffsetStore, defaultProducerService *DefaultProducerService, consumerConfig *rocketmqm.MqConsumerConfig) {
+	c.consumerGroup = consumerGroup
+	c.offsetStore = offsetStore
+	c.sendMessageBackProducerService.initSendMessageBackProducerService(consumerGroup, mqClient, defaultProducerService, consumerConfig)
+	c.consumerConfig = consumerConfig
+}
+
+func (c *consumeMessageConcurrentlyServiceImpl) submitConsumeRequest(msgs []message.MessageExtImpl, processQueue *model.ProcessQueue, messageQueue *rocketmqm.MessageQueue, dispathToConsume bool) {
+	msgsLen := len(msgs)
+	for i := 0; i < msgsLen; {
+		begin := i
+		end := i + c.consumerConfig.ConsumeMessageBatchMaxSize
+		if end > msgsLen {
+			end = msgsLen
+		}
+		go func() {
+			glog.V(2).Infof("look slice begin %d end %d msgsLen %d", begin, end, msgsLen)
+			batchMsgs := transformMessageToConsume(c.consumerGroup, msgs[begin:end])
+
+			consumeState := c.messageListener(c.convert2ConsumeType(batchMsgs))
+			c.processConsumeResult(consumeState, batchMsgs, messageQueue, processQueue)
+		}()
+		i = end
+	}
+	return
+}
+func (c *consumeMessageConcurrentlyServiceImpl) convert2ConsumeType(msgs []message.MessageExtImpl) (ret []rocketmqm.MessageExt) {
+	msgLen := len(msgs)
+	ret = make([]rocketmqm.MessageExt, msgLen)
+
+	for i := 0; i < msgLen; i++ {
+		ret[i] = rocketmqm.MessageExt(&msgs[i])
+	}
+	return
+}
+
+func (c *consumeMessageConcurrentlyServiceImpl) sendMessageBack(messageExt *message.MessageExtImpl, delayLayLevel int, brokerName string) (err error) {
+	err = c.sendMessageBackProducerService.sendMessageBack(messageExt, 0, brokerName)
+	return
+}
+
+func (c *consumeMessageConcurrentlyServiceImpl) consumeMessageDirectly(messageExt *message.MessageExtImpl, brokerName string) (consumeMessageDirectlyResult model.ConsumeMessageDirectlyResult, err error) {
+	start := util.CurrentTimeMillisInt64()
+	consumeResult := c.messageListener(c.convert2ConsumeType([]message.MessageExtImpl{*messageExt}))
+	consumeMessageDirectlyResult.AutoCommit = true
+	consumeMessageDirectlyResult.Order = false
+	consumeMessageDirectlyResult.SpentTimeMills = util.CurrentTimeMillisInt64() - start
+	if consumeResult.ConsumeConcurrentlyStatus == rocketmqm.CONSUME_SUCCESS && consumeResult.AckIndex >= 0 {
+		consumeMessageDirectlyResult.ConsumeResult = model.CR_SUCCESS
+	} else {
+		consumeMessageDirectlyResult.ConsumeResult = model.CR_THROW_EXCEPTION
+	}
+	return
+}
+
+func (c *consumeMessageConcurrentlyServiceImpl) processConsumeResult(result rocketmqm.ConsumeConcurrentlyResult, msgs []message.MessageExtImpl, messageQueue *rocketmqm.MessageQueue, processQueue *model.ProcessQueue) {
+	if processQueue.IsDropped() {
+		glog.Warning("processQueue is dropped without process consume result. ", msgs)
+		return
+	}
+	if len(msgs) == 0 {
+		return
+	}
+	ackIndex := result.AckIndex
+	if rocketmqm.CONSUME_SUCCESS == result.ConsumeConcurrentlyStatus {
+		if ackIndex >= len(msgs) {
+			ackIndex = len(msgs) - 1
+		} else {
+			if result.AckIndex < 0 {
+				ackIndex = -1
+			}
+		}
+	}
+	var failedMessages []message.MessageExtImpl
+	successMessages := []message.MessageExtImpl{}
+	if ackIndex >= 0 {
+		successMessages = msgs[:ackIndex+1]
+	}
+	for i := ackIndex + 1; i < len(msgs); i++ {
+		err := c.sendMessageBack(&msgs[i], 0, messageQueue.BrokerName)
+		if err != nil {
+			msgs[i].ReconsumeTimes = msgs[i].ReconsumeTimes + 1
+			failedMessages = append(failedMessages, msgs[i])
+		} else {
+			successMessages = append(successMessages, msgs[i])
+		}
+	}
+	if len(failedMessages) > 0 {
+		c.submitConsumeRequest(failedMessages, processQueue, messageQueue, true)
+	}
+	commitOffset := processQueue.RemoveMessage(successMessages)
+	if commitOffset > 0 && !processQueue.IsDropped() {
+		c.offsetStore.updateOffset(messageQueue, commitOffset, true)
+	}
+
+}
+
+func transformMessageToConsume(consumerGroup string, msgs []message.MessageExtImpl) []message.MessageExtImpl {
+	retryTopicName := constant.RETRY_GROUP_TOPIC_PREFIX + consumerGroup
+
+	for _, msg := range msgs {
+		//reset retry topic name
+		if msg.MessageImpl.Topic() == retryTopicName {
+			retryTopic := msg.PropertiesKeyValue(constant.PROPERTY_RETRY_TOPIC)
+			if len(retryTopic) > 0 {
+				msg.MessageImpl.SetTopic(retryTopic)
+			}
+		}
+		//set consume start time
+		msg.SetConsumeStartTime()
+	}
+	return msgs
+}
diff --git a/rocketmq-go/kernel/header/consume_message_directly_result_request_header.go b/rocketmq-go/kernel/header/consume_message_directly_result_request_header.go
new file mode 100644
index 0000000..989d826
--- /dev/null
+++ b/rocketmq-go/kernel/header/consume_message_directly_result_request_header.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//ConsumeMessageDirectlyResultRequestHeader of CustomerHeader
+type ConsumeMessageDirectlyResultRequestHeader struct {
+	//ConsumerGroup
+	ConsumerGroup string `json:"consumerGroup"`
+	//ClientId
+	ClientId string `json:"clientId"`
+	//MsgId
+	MsgId string `json:"msgId"`
+	//BrokerName
+	BrokerName string `json:"brokerName"`
+}
+
+//FromMap convert map[string]interface to struct
+func (c *ConsumeMessageDirectlyResultRequestHeader) FromMap(headerMap map[string]interface{}) {
+	c.ConsumerGroup = headerMap["consumerGroup"].(string)
+	c.ClientId = headerMap["clientId"].(string)
+	c.MsgId = headerMap["msgId"].(string)
+	c.BrokerName = headerMap["brokerName"].(string)
+	return
+}
diff --git a/rocketmq-go/kernel/header/consumer_send_msg_back_request_header.go b/rocketmq-go/kernel/header/consumer_send_msg_back_request_header.go
new file mode 100644
index 0000000..07c57c9
--- /dev/null
+++ b/rocketmq-go/kernel/header/consumer_send_msg_back_request_header.go
@@ -0,0 +1,34 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//ConsumerSendMsgBackRequestHeader of CustomerHeader
+type ConsumerSendMsgBackRequestHeader struct {
+	Offset            int64
+	Group             string
+	DelayLevel        int32
+	OriginMsgId       string
+	OriginTopic       string
+	UnitMode          bool
+	MaxReconsumeTimes int32
+}
+
+//FromMap convert map[string]interface to struct
+func (c *ConsumerSendMsgBackRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/get_consumer_list_by_group.go b/rocketmq-go/kernel/header/get_consumer_list_by_group.go
new file mode 100644
index 0000000..ef72edd
--- /dev/null
+++ b/rocketmq-go/kernel/header/get_consumer_list_by_group.go
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//GetConsumerListByGroupRequestHeader of CustomerHeader
+type GetConsumerListByGroupRequestHeader struct {
+	ConsumerGroup string `json:"consumerGroup"`
+}
+
+//FromMap convert map[string]interface to struct
+func (g *GetConsumerListByGroupRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
+
+//GetConsumerListByGroupResponseBody of CustomerHeader
+type GetConsumerListByGroupResponseBody struct {
+	ConsumerIdList []string
+}
+
+//FromMap convert map[string]interface to struct
+func (g *GetConsumerListByGroupResponseBody) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/get_consumer_running_info_request_header.go b/rocketmq-go/kernel/header/get_consumer_running_info_request_header.go
new file mode 100644
index 0000000..5e04e27
--- /dev/null
+++ b/rocketmq-go/kernel/header/get_consumer_running_info_request_header.go
@@ -0,0 +1,32 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//GetConsumerRunningInfoRequestHeader of CustomerHeader
+type GetConsumerRunningInfoRequestHeader struct {
+	ConsumerGroup string `json:"consumerGroup"`
+	ClientId      string `json:"clientId"`
+	JstackEnable  bool   `json:"jstackEnable"`
+}
+
+//FromMap convert map[string]interface to struct
+func (g *GetConsumerRunningInfoRequestHeader) FromMap(headerMap map[string]interface{}) {
+	g.ConsumerGroup = headerMap["consumerGroup"].(string)
+	g.ClientId = headerMap["clientId"].(string)
+	return
+}
diff --git a/rocketmq-go/kernel/header/get_max_offset_request_header.go b/rocketmq-go/kernel/header/get_max_offset_request_header.go
new file mode 100644
index 0000000..df09f7a
--- /dev/null
+++ b/rocketmq-go/kernel/header/get_max_offset_request_header.go
@@ -0,0 +1,29 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//GetMaxOffsetRequestHeader of CustomerHeader
+type GetMaxOffsetRequestHeader struct {
+	Topic   string `json:"topic"`
+	QueueId int32  `json:"queueId"`
+}
+
+//FromMap convert map[string]interface to struct
+func (g *GetMaxOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/get_max_offset_response_header.go b/rocketmq-go/kernel/header/get_max_offset_response_header.go
new file mode 100644
index 0000000..d50a1a6
--- /dev/null
+++ b/rocketmq-go/kernel/header/get_max_offset_response_header.go
@@ -0,0 +1,31 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+
+//QueryOffsetResponseHeader of CustomerHeader
+type QueryOffsetResponseHeader struct {
+	Offset int64 `json:"offset"`
+}
+
+//FromMap convert map[string]interface to struct
+func (q *QueryOffsetResponseHeader) FromMap(headerMap map[string]interface{}) {
+	q.Offset = util.StrToInt64WithDefaultValue(headerMap["offset"].(string), -1)
+	return
+}
diff --git a/rocketmq-go/kernel/header/get_route_info_request_header.go b/rocketmq-go/kernel/header/get_route_info_request_header.go
new file mode 100644
index 0000000..6a8391b
--- /dev/null
+++ b/rocketmq-go/kernel/header/get_route_info_request_header.go
@@ -0,0 +1,28 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//GetRouteInfoRequestHeader of CustomerHeader
+type GetRouteInfoRequestHeader struct {
+	Topic string `json:"topic"`
+}
+
+//FromMap convert map[string]interface to struct
+func (g *GetRouteInfoRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/pull_message_request_header.go b/rocketmq-go/kernel/header/pull_message_request_header.go
new file mode 100644
index 0000000..a26b2db
--- /dev/null
+++ b/rocketmq-go/kernel/header/pull_message_request_header.go
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//PullMessageRequestHeader of CustomerHeader
+type PullMessageRequestHeader struct {
+	ConsumerGroup        string `json:"consumerGroup"`
+	Topic                string `json:"topic"`
+	QueueId              int32  `json:"queueId"`
+	QueueOffset          int64  `json:"queueOffset"`
+	MaxMsgNums           int32  `json:"maxMsgNums"`
+	SysFlag              int32  `json:"sysFlag"`
+	CommitOffset         int64  `json:"commitOffset"`
+	SuspendTimeoutMillis int64  `json:"suspendTimeoutMillis"`
+	Subscription         string `json:"subscription"`
+	SubVersion           int64  `json:"subVersion"`
+}
+
+//FromMap convert map[string]interface to struct
+func (p *PullMessageRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/query_consumer_offset_request_header.go b/rocketmq-go/kernel/header/query_consumer_offset_request_header.go
new file mode 100644
index 0000000..75c456f
--- /dev/null
+++ b/rocketmq-go/kernel/header/query_consumer_offset_request_header.go
@@ -0,0 +1,30 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//QueryConsumerOffsetRequestHeader of CustomerHeader
+type QueryConsumerOffsetRequestHeader struct {
+	ConsumerGroup string `json:"consumerGroup"`
+	Topic         string `json:"topic"`
+	QueueId       int32  `json:"queueId"`
+}
+
+//FromMap convert map[string]interface to struct
+func (q *QueryConsumerOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/reset_offset_request_header.go b/rocketmq-go/kernel/header/reset_offset_request_header.go
new file mode 100644
index 0000000..0cb2346
--- /dev/null
+++ b/rocketmq-go/kernel/header/reset_offset_request_header.go
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"strconv"
+)
+
+//ResetOffsetRequestHeader of CustomerHeader
+type ResetOffsetRequestHeader struct {
+	Topic     string `json:"topic"`
+	Group     string `json:"group"`
+	Timestamp int64  `json:"timestamp"`
+	IsForce   bool   `json:"isForce"`
+}
+
+//FromMap convert map[string]interface to struct
+func (r *ResetOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
+	r.Group = headerMap["group"].(string)
+	r.Topic = headerMap["topic"].(string)
+	r.Timestamp = util.StrToInt64WithDefaultValue(headerMap["timestamp"].(string), -1)
+	r.IsForce, _ = strconv.ParseBool(headerMap["isForce"].(string))
+	return
+}
diff --git a/rocketmq-go/kernel/header/search_offset_request_header.go b/rocketmq-go/kernel/header/search_offset_request_header.go
new file mode 100644
index 0000000..7170f0a
--- /dev/null
+++ b/rocketmq-go/kernel/header/search_offset_request_header.go
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+)
+
+//SearchOffsetRequestHeader of CustomerHeader
+type SearchOffsetRequestHeader struct {
+	Topic     string `json:"topic"`
+	QueueId   int32  `json:"queueId"`
+	Timestamp int64  `json:"timestamp"`
+}
+
+//FromMap convert map[string]interface to struct
+func (s *SearchOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
+	s.Topic = headerMap["topic"].(string)
+	s.Topic = headerMap["queueId"].(string)
+	s.Timestamp = util.StrToInt64WithDefaultValue(headerMap["timestamp"].(string), -1)
+	return
+}
diff --git a/rocketmq-go/kernel/header/send_message_request_header.go b/rocketmq-go/kernel/header/send_message_request_header.go
new file mode 100644
index 0000000..9109e1f
--- /dev/null
+++ b/rocketmq-go/kernel/header/send_message_request_header.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+//SendMessageRequestHeader of CustomerHeader
+type SendMessageRequestHeader struct {
+	ProducerGroup         string `json:"producerGroup"`
+	Topic                 string `json:"topic"`
+	DefaultTopic          string `json:"defaultTopic"`
+	DefaultTopicQueueNums int    `json:"defaultTopicQueueNums"`
+	QueueId               int32  `json:"queueId"`
+	SysFlag               int    `json:"sysFlag"`
+	BornTimestamp         int64  `json:"bornTimestamp"`
+	Flag                  int    `json:"flag"`
+	Properties            string `json:"properties"`
+	ReconsumeTimes        int    `json:"reconsumeTimes"`
+	UnitMode              bool   `json:"unitMode"`
+	MaxReconsumeTimes     int    `json:"maxReconsumeTimes"`
+}
+
+//FromMap to SendMessageRequestHeader
+func (s *SendMessageRequestHeader) FromMap(headerMap map[string]interface{}) {
+	return
+}
diff --git a/rocketmq-go/kernel/header/send_message_response_header.go b/rocketmq-go/kernel/header/send_message_response_header.go
new file mode 100644
index 0000000..32fd1eb
--- /dev/null
+++ b/rocketmq-go/kernel/header/send_message_response_header.go
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+
+//SendMessageResponseHeader of CustomerHeader
+type SendMessageResponseHeader struct {
+	MsgId         string
+	QueueId       int32
+	QueueOffset   int64
+	TransactionId string
+	MsgRegion     string
+}
+
+//FromMap convert map[string]interface to struct
+func (s *SendMessageResponseHeader) FromMap(headerMap map[string]interface{}) {
+	s.MsgId = headerMap["msgId"].(string)
+	s.QueueId = util.StrToInt32WithDefaultValue(headerMap["queueId"].(string), -1)
+	s.QueueOffset = util.StrToInt64WithDefaultValue(headerMap["queueOffset"].(string), -1)
+	transactionId := headerMap["transactionId"]
+	if transactionId != nil {
+		s.TransactionId = headerMap["transactionId"].(string)
+	}
+	msgRegion := headerMap["MSG_REGION"]
+	if msgRegion != nil {
+		s.MsgRegion = headerMap["MSG_REGION"].(string)
+	}
+
+	return
+}
+
+//for example
+
+/**
+{
+    "MSG_REGION": "DefaultRegion",
+    "TRACE_ON": "true",
+    "msgId": "C0A8000200002A9F0000000039FA93B5",
+    "queueId": "3",
+    "queueOffset": "1254671"
+}
+*/
diff --git a/rocketmq-go/kernel/header/update_consumer_offset_request_header.go b/rocketmq-go/kernel/header/update_consumer_offset_request_header.go
new file mode 100644
index 0000000..b7b5d44
--- /dev/null
+++ b/rocketmq-go/kernel/header/update_consumer_offset_request_header.go
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package header
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+
+//UpdateConsumerOffsetRequestHeader of CustomerHeader
+type UpdateConsumerOffsetRequestHeader struct {
+	ConsumerGroup string `json:"consumerGroup"`
+	Topic         string `json:"topic"`
+	QueueId       int32  `json:"queueId"`
+	CommitOffset  int64  `json:"commitOffset"`
+}
+
+//FromMap convert map[string]interface to struct
+func (u *UpdateConsumerOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
+	u.ConsumerGroup = headerMap["consumerGroup"].(string)
+	u.QueueId = util.StrToInt32WithDefaultValue(util.ReadString(headerMap["queueId"]), 0)
+	u.CommitOffset = util.StrToInt64WithDefaultValue(headerMap["commitOffset"].(string), -1)
+	u.Topic = util.ReadString(headerMap["topic"])
+	return
+}
diff --git a/rocketmq-go/kernel/mq_client.go b/rocketmq-go/kernel/mq_client.go
new file mode 100644
index 0000000..07ac0ab
--- /dev/null
+++ b/rocketmq-go/kernel/mq_client.go
@@ -0,0 +1,362 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+//RocketMqClient this struct is for something common,for example
+//1.brokerInfo
+//2.routerInfo
+//3.subscribeInfo
+//4.heartbeat
+type RocketMqClient interface {
+	//get mqClient's clientId ip@pid
+	getClientId() (clientId string)
+	//get remoting client in mqClient
+	getRemotingClient() (remotingClient *remoting.DefaultRemotingClient)
+	//get topic subscribe info
+	getTopicSubscribeInfo(topic string) (messageQueueList []*rocketmqm.MessageQueue)
+	//getPublishTopicList
+	getPublishTopicList() []string
+	fetchMasterBrokerAddress(brokerName string) (masterAddress string)
+	enqueuePullMessageRequest(pullRequest *model.PullRequest)
+	dequeuePullMessageRequest() (pullRequest *model.PullRequest)
+	findBrokerAddressInSubscribe(brokerName string, brokerId int, onlyThisBroker bool) (brokerAddr string, slave bool, found bool)
+	tryToFindTopicPublishInfo(topic string) (topicPublicInfo *model.TopicPublishInfo, err error)
+	findBrokerAddrByTopic(topic string) (addr string, ok bool)
+	updateTopicRouteInfoFromNameServer(topic string) (err error)
+	updateTopicRouteInfoFromNameServerUseDefaultTopic(topic string) (err error)
+	sendHeartbeatToAllBroker(heartBeatData *model.HeartbeatData) (err error)
+	clearExpireResponse()
+	getMaxOffset(mq *rocketmqm.MessageQueue) int64
+	searchOffset(mq *rocketmqm.MessageQueue, time time.Time) int64
+}
+
+//DEFAULT_TIMEOUT rocketmq client's default timeout
+var DEFAULT_TIMEOUT int64 = 3000
+
+//MqClientImpl RocketMqClient
+type MqClientImpl struct {
+	clientId                string
+	remotingClient          *remoting.DefaultRemotingClient
+	topicRouteTable         util.ConcurrentMap // map[string]*model.TopicRouteData   //topic | topicRoteData
+	brokerAddrTable         util.ConcurrentMap //map[string]map[int]string          //brokerName | map[brokerId]address
+	topicPublishInfoTable   util.ConcurrentMap //map[string]*model.TopicPublishInfo //topic | TopicPublishInfo //all use this
+	topicSubscribeInfoTable util.ConcurrentMap //map[string][]*rocketmqm.MessageQueue   //topic | MessageQueue
+	pullRequestQueue        chan *model.PullRequest
+}
+
+//mqClientInit create a mqClientInit instance
+func mqClientInit(clientConfig *rocketmqm.MqClientConfig, clientRequestProcessor remoting.ClientRequestProcessor) (mqClientImpl *MqClientImpl) {
+	mqClientImpl = &MqClientImpl{}
+	mqClientImpl.clientId = buildMqClientImplId()
+	mqClientImpl.topicRouteTable = util.NewConcurrentMap() // make(map[string]*model.TopicRouteData)
+	mqClientImpl.brokerAddrTable = util.NewConcurrentMap() //make(map[string]map[int]string)
+	mqClientImpl.remotingClient = remoting.RemotingClientInit(clientConfig, clientRequestProcessor)
+	mqClientImpl.topicPublishInfoTable = util.NewConcurrentMap()   //make(map[string]*model.TopicPublishInfo)
+	mqClientImpl.topicSubscribeInfoTable = util.NewConcurrentMap() //make(map[string][]*rocketmqm.MessageQueue)
+	mqClientImpl.pullRequestQueue = make(chan *model.PullRequest, 1024)
+	return
+}
+
+//getTopicSubscribeInfo
+func (m *MqClientImpl) getTopicSubscribeInfo(topic string) (messageQueueList []*rocketmqm.MessageQueue) {
+	value, ok := m.topicSubscribeInfoTable.Get(topic)
+	if ok {
+		messageQueueList = value.([]*rocketmqm.MessageQueue)
+	}
+	return
+}
+func (m *MqClientImpl) getMaxOffset(mq *rocketmqm.MessageQueue) int64 {
+	brokerAddr := m.fetchMasterBrokerAddress(mq.BrokerName)
+	if len(brokerAddr) == 0 {
+		m.tryToFindTopicPublishInfo(mq.Topic)
+		brokerAddr = m.fetchMasterBrokerAddress(mq.BrokerName)
+	}
+	getMaxOffsetRequestHeader := &header.GetMaxOffsetRequestHeader{Topic: mq.Topic, QueueId: mq.QueueId}
+	remotingCmd := remoting.NewRemotingCommand(remoting.GET_MAX_OFFSET, getMaxOffsetRequestHeader)
+	response, err := m.remotingClient.InvokeSync(brokerAddr, remotingCmd, DEFAULT_TIMEOUT)
+	if err != nil {
+		return -1
+	}
+	queryOffsetResponseHeader := header.QueryOffsetResponseHeader{}
+	queryOffsetResponseHeader.FromMap(response.ExtFields)
+	return queryOffsetResponseHeader.Offset
+}
+func (m *MqClientImpl) searchOffset(mq *rocketmqm.MessageQueue, time time.Time) int64 {
+	brokerAddr := m.fetchMasterBrokerAddress(mq.BrokerName)
+	if len(brokerAddr) == 0 {
+		m.tryToFindTopicPublishInfo(mq.Topic)
+		brokerAddr = m.fetchMasterBrokerAddress(mq.BrokerName)
+	}
+	timeStamp := util.CurrentTimeMillisInt64()
+	searchOffsetRequestHeader := &header.SearchOffsetRequestHeader{Topic: mq.Topic, QueueId: mq.QueueId, Timestamp: timeStamp}
+	remotingCmd := remoting.NewRemotingCommand(remoting.SEARCH_OFFSET_BY_TIMESTAMP, searchOffsetRequestHeader)
+	response, err := m.remotingClient.InvokeSync(brokerAddr, remotingCmd, DEFAULT_TIMEOUT)
+	if err != nil {
+		return -1
+	}
+	queryOffsetResponseHeader := header.QueryOffsetResponseHeader{}
+
+	queryOffsetResponseHeader.FromMap(response.ExtFields)
+	return queryOffsetResponseHeader.Offset
+}
+func (m *MqClientImpl) getClientId() string {
+	return m.clientId
+}
+func (m *MqClientImpl) getPublishTopicList() []string {
+	var publishTopicList []string
+	for _, topic := range m.topicPublishInfoTable.Keys() {
+		publishTopicList = append(publishTopicList, topic)
+	}
+	return publishTopicList
+}
+func (m *MqClientImpl) getRemotingClient() *remoting.DefaultRemotingClient {
+	return m.remotingClient
+}
+
+func (m *MqClientImpl) enqueuePullMessageRequest(pullRequest *model.PullRequest) {
+	m.pullRequestQueue <- pullRequest
+}
+func (m *MqClientImpl) dequeuePullMessageRequest() (pullRequest *model.PullRequest) {
+	pullRequest = <-m.pullRequestQueue
+	return
+}
+
+func (m *MqClientImpl) clearExpireResponse() {
+	m.remotingClient.ClearExpireResponse()
+}
+
+func (m *MqClientImpl) fetchMasterBrokerAddress(brokerName string) (masterAddress string) {
+	value, ok := m.brokerAddrTable.Get(brokerName)
+	if ok {
+		masterAddress = value.(map[string]string)["0"]
+	}
+	return
+}
+func (m *MqClientImpl) tryToFindTopicPublishInfo(topic string) (topicPublicInfo *model.TopicPublishInfo, err error) {
+	value, ok := m.topicPublishInfoTable.Get(topic)
+	if ok {
+		topicPublicInfo = value.(*model.TopicPublishInfo)
+	}
+
+	if topicPublicInfo == nil || !topicPublicInfo.JudgeTopicPublishInfoOk() {
+		m.topicPublishInfoTable.Set(topic, &model.TopicPublishInfo{HaveTopicRouterInfo: false})
+		err = m.updateTopicRouteInfoFromNameServer(topic)
+		if err != nil {
+			glog.Warning(err) // if updateRouteInfo error, maybe we can use the defaultTopic
+		}
+		value, ok := m.topicPublishInfoTable.Get(topic)
+		if ok {
+			topicPublicInfo = value.(*model.TopicPublishInfo)
+		}
+	}
+	if topicPublicInfo.HaveTopicRouterInfo && topicPublicInfo.JudgeTopicPublishInfoOk() {
+		return
+	}
+	//try to use the defaultTopic
+	err = m.updateTopicRouteInfoFromNameServerUseDefaultTopic(topic)
+
+	defaultValue, defaultValueOk := m.topicPublishInfoTable.Get(topic)
+	if defaultValueOk {
+		topicPublicInfo = defaultValue.(*model.TopicPublishInfo)
+	}
+
+	return
+}
+
+func (m MqClientImpl) getTopicRouteInfoFromNameServer(topic string, timeoutMillis int64) (*model.TopicRouteData, error) {
+	requestHeader := &header.GetRouteInfoRequestHeader{
+		Topic: topic,
+	}
+	var remotingCommand = remoting.NewRemotingCommand(remoting.GET_ROUTEINTO_BY_TOPIC, requestHeader)
+	response, err := m.remotingClient.InvokeSync("", remotingCommand, timeoutMillis)
+
+	if err != nil {
+		return nil, err
+	}
+	if response.Code == remoting.SUCCESS {
+		topicRouteData := new(model.TopicRouteData)
+		bodyjson := strings.Replace(string(response.Body), ",0:", ",\"0\":", -1)
+		bodyjson = strings.Replace(bodyjson, ",1:", ",\"1\":", -1) // fastJson key is string todo todo
+		bodyjson = strings.Replace(bodyjson, "{0:", "{\"0\":", -1)
+		bodyjson = strings.Replace(bodyjson, "{1:", "{\"1\":", -1)
+		err = json.Unmarshal([]byte(bodyjson), topicRouteData)
+		if err != nil {
+			glog.Error(err, bodyjson)
+			return nil, err
+		}
+		return topicRouteData, nil
+	}
+	return nil, fmt.Errorf("get topicRouteInfo from nameServer error[code:%d,topic:%s]", response.Code, topic)
+}
+
+func (m MqClientImpl) findBrokerAddressInSubscribe(brokerName string, brokerId int, onlyThisBroker bool) (brokerAddr string, slave bool, found bool) {
+	slave = false
+	found = false
+	value, ok := m.brokerAddrTable.Get(brokerName)
+	if !ok {
+		return
+	}
+	brokerMap := value.(map[string]string)
+	brokerAddr, ok = brokerMap[util.IntToString(brokerId)]
+	slave = (brokerId != 0)
+	found = ok
+
+	if !found && !onlyThisBroker {
+		var id string
+		for id, brokerAddr = range brokerMap {
+			slave = (id != "0")
+			found = true
+			break
+		}
+	}
+	return
+}
+
+func (m MqClientImpl) updateTopicRouteInfoFromNameServer(topic string) (err error) {
+	var (
+		topicRouteData *model.TopicRouteData
+	)
+	//namesvr lock
+	topicRouteData, err = m.getTopicRouteInfoFromNameServer(topic, DEFAULT_TIMEOUT)
+	if err != nil {
+		return
+	}
+	m.updateTopicRouteInfoLocal(topic, topicRouteData)
+	return
+}
+func (m MqClientImpl) updateTopicRouteInfoFromNameServerUseDefaultTopic(topic string) (err error) {
+	var (
+		topicRouteData *model.TopicRouteData
+	)
+	//namesvr lock
+	topicRouteData, err = m.getTopicRouteInfoFromNameServer(constant.DEFAULT_TOPIC, DEFAULT_TIMEOUT)
+	if err != nil {
+		return
+	}
+
+	for _, queueData := range topicRouteData.QueueDatas {
+		defaultQueueData := constant.DEFAULT_TOPIC_QUEUE_NUMS
+		if queueData.ReadQueueNums < defaultQueueData {
+			defaultQueueData = queueData.ReadQueueNums
+		}
+		queueData.ReadQueueNums = defaultQueueData
+		queueData.WriteQueueNums = defaultQueueData
+	}
+	m.updateTopicRouteInfoLocal(topic, topicRouteData)
+	return
+}
+func (m MqClientImpl) updateTopicRouteInfoLocal(topic string, topicRouteData *model.TopicRouteData) (err error) {
+	if topicRouteData == nil {
+		return
+	}
+	// topicRouteData judgeTopicRouteData need update
+	//needUpdate := true
+	//if !needUpdate {
+	//	return
+	//}
+	//update brokerAddrTable
+	for _, brokerData := range topicRouteData.BrokerDatas {
+		m.brokerAddrTable.Set(brokerData.BrokerName, brokerData.BrokerAddrs)
+	}
+
+	//update pubInfo for each
+	topicPublishInfo := model.BuildTopicPublishInfoFromTopicRoteData(topic, topicRouteData)
+	m.topicPublishInfoTable.Set(topic, topicPublishInfo)
+
+	mqList := model.BuildTopicSubscribeInfoFromRoteData(topic, topicRouteData)
+	m.topicSubscribeInfoTable.Set(topic, mqList)
+	m.topicRouteTable.Set(topic, topicRouteData)
+	return
+}
+
+func (m MqClientImpl) findBrokerAddrByTopic(topic string) (addr string, ok bool) {
+	value, findValue := m.topicRouteTable.Get(topic)
+	if !findValue {
+		return "", false
+	}
+	topicRouteData := value.(*model.TopicRouteData)
+	brokers := topicRouteData.BrokerDatas
+	if brokers != nil && len(brokers) > 0 {
+		brokerData := brokers[0]
+		brokerData.BrokerAddrsLock.RLock()
+		addr, ok = brokerData.BrokerAddrs["0"]
+		brokerData.BrokerAddrsLock.RUnlock()
+
+		if ok {
+			return
+		}
+		for _, addr = range brokerData.BrokerAddrs {
+			return addr, ok
+		}
+	}
+	return
+}
+
+func buildMqClientImplId() (clientId string) {
+	clientId = util.GetLocalIp4() + "@" + strconv.Itoa(os.Getpid())
+	return
+}
+
+func (m MqClientImpl) sendHeartBeat(addr string, remotingCommand *remoting.RemotingCommand, timeoutMillis int64) error {
+	remotingCommand, err := m.remotingClient.InvokeSync(addr, remotingCommand, timeoutMillis)
+	if err != nil {
+		glog.Error(err)
+	} else {
+		if remotingCommand == nil || remotingCommand.Code != remoting.SUCCESS {
+			glog.Error("send heartbeat response  error")
+		}
+	}
+	return err
+}
+
+func (m MqClientImpl) sendHeartbeatToAllBroker(heartBeatData *model.HeartbeatData) (err error) {
+	for _, brokerTable := range m.brokerAddrTable.Items() {
+		for brokerId, addr := range brokerTable.(map[string]string) {
+			if len(addr) == 0 || brokerId != "0" {
+				continue
+			}
+			data, err := json.Marshal(heartBeatData)
+			if err != nil {
+				glog.Error(err)
+				return err
+			}
+			glog.V(2).Info("send heartbeat to broker look data[", string(data)+"]")
+			remotingCommand := remoting.NewRemotingCommandWithBody(remoting.HEART_BEAT, nil, data)
+			glog.V(2).Info("send heartbeat to broker[", addr+"]")
+			m.sendHeartBeat(addr, remotingCommand, DEFAULT_TIMEOUT)
+
+		}
+	}
+	return nil
+}
diff --git a/rocketmq-go/kernel/mq_client_manage.go b/rocketmq-go/kernel/mq_client_manage.go
new file mode 100644
index 0000000..f5cd9ef
--- /dev/null
+++ b/rocketmq-go/kernel/mq_client_manage.go
@@ -0,0 +1,248 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+	"strings"
+	"time"
+)
+
+//MqClientManager MqClientManager
+type MqClientManager struct {
+	//rocketMqManagerLock      sync.Mutex
+	BootTimestamp            int64
+	clientFactory            *clientFactory
+	mqClient                 RocketMqClient
+	pullMessageController    *PullMessageController
+	cleanExpireMsgController *cleanExpireMsgController
+	rebalanceControllr       *rebalanceController
+	defaultProducerService   *DefaultProducerService
+}
+
+//MqClientManagerInit create a MqClientManager instance
+func MqClientManagerInit(clientConfig *rocketmqm.MqClientConfig) (rocketMqManager *MqClientManager) {
+	rocketMqManager = &MqClientManager{}
+	rocketMqManager.BootTimestamp = time.Now().Unix()
+	rocketMqManager.clientFactory = clientFactoryInit()
+	rocketMqManager.mqClient = mqClientInit(clientConfig, rocketMqManager.initClientRequestProcessor()) // todo todo todo
+	rocketMqManager.pullMessageController = newPullMessageController(rocketMqManager.mqClient, rocketMqManager.clientFactory)
+	rocketMqManager.cleanExpireMsgController = newCleanExpireMsgController(rocketMqManager.mqClient, rocketMqManager.clientFactory)
+	rocketMqManager.rebalanceControllr = newRebalanceController(rocketMqManager.clientFactory)
+
+	return
+}
+
+//Start start MqClientManager
+func (m *MqClientManager) Start() {
+	//d.sendHeartbeatToAllBrokerWithLock()//we should send heartbeat first todo check
+	m.startAllScheduledTask()
+}
+
+//RegisterProducer register producer to this MqClientManager
+func (m *MqClientManager) RegisterProducer(producer *DefaultMQProducer) {
+	producer.producerService = newDefaultProducerService(producer.producerGroup, producer.ProducerConfig, m.mqClient)
+	m.clientFactory.producerTable[producer.producerGroup] = producer
+	return
+}
+
+//RegisterConsumer register consumer to this MqClientManager
+func (m *MqClientManager) RegisterConsumer(consumer *DefaultMQPushConsumer) {
+	if m.defaultProducerService == nil {
+		m.defaultProducerService = newDefaultProducerService(constant.CLIENT_INNER_PRODUCER_GROUP, rocketmqm.NewProducerConfig(), m.mqClient)
+	}
+	consumer.mqClient = m.mqClient
+	consumer.offsetStore = remoteOffsetStoreInit(consumer.consumerGroup, m.mqClient)
+	m.clientFactory.consumerTable[consumer.consumerGroup] = consumer
+	consumer.rebalance = newRebalance(consumer.consumerGroup, consumer.subscription, consumer.mqClient, consumer.offsetStore, consumer.ConsumerConfig)
+	consumer.consumeMessageService.init(consumer.consumerGroup, m.mqClient, consumer.offsetStore, m.defaultProducerService, consumer.ConsumerConfig)
+	return
+}
+func (m *MqClientManager) initClientRequestProcessor() (clientRequestProcessor remoting.ClientRequestProcessor) {
+	clientRequestProcessor = func(cmd *remoting.RemotingCommand) (response *remoting.RemotingCommand) {
+		switch cmd.Code {
+		case remoting.CHECK_TRANSACTION_STATE:
+			glog.V(2).Info("receive_request_code CHECK_TRANSACTION_STATE")
+			break
+		case remoting.NOTIFY_CONSUMER_IDS_CHANGED:
+			glog.V(2).Info("receive_request_code NOTIFY_CONSUMER_IDS_CHANGED")
+			m.rebalanceControllr.doRebalance()
+			break
+		case remoting.RESET_CONSUMER_CLIENT_OFFSET: //  struct json key supported
+			m.resetConsumerClientOffset(cmd)
+			break
+		case remoting.GET_CONSUMER_STATUS_FROM_CLIENT: // useless we can use GET_CONSUMER_RUNNING_INFO instead
+			glog.V(2).Info("receive_request_code GET_CONSUMER_STATUS_FROM_CLIENT")
+			break
+		case remoting.GET_CONSUMER_RUNNING_INFO:
+			response = m.getConsumerRunningInfo(cmd)
+			break
+		case remoting.CONSUME_MESSAGE_DIRECTLY:
+			response = m.consumeMessageDirectly(cmd)
+			break
+		default:
+			glog.Error("illeage requestCode ", cmd.Code)
+		}
+		return
+	}
+	return
+}
+
+func (m *MqClientManager) consumeMessageDirectly(cmd *remoting.RemotingCommand) (response *remoting.RemotingCommand) {
+	glog.V(2).Info("receive_request_code CONSUME_MESSAGE_DIRECTLY")
+	var consumeMessageDirectlyResultRequestHeader = &header.ConsumeMessageDirectlyResultRequestHeader{}
+	if cmd.ExtFields != nil {
+		consumeMessageDirectlyResultRequestHeader.FromMap(cmd.ExtFields)
+		messageExt := &decodeMessage(cmd.Body)[0]
+		glog.V(2).Info("op=look", messageExt)
+		defaultMQPushConsumer := m.clientFactory.consumerTable[consumeMessageDirectlyResultRequestHeader.ConsumerGroup]
+		consumeResult, err := defaultMQPushConsumer.consumeMessageService.consumeMessageDirectly(messageExt, consumeMessageDirectlyResultRequestHeader.BrokerName)
+		if err != nil {
+			return
+		}
+		jsonByte, err := json.Marshal(consumeResult)
+		if err != nil {
+			glog.Error(err)
+			return
+		}
+		response = remoting.NewRemotingCommandWithBody(remoting.SUCCESS, nil, jsonByte)
+	}
+	return
+}
+
+func (m *MqClientManager) getConsumerRunningInfo(cmd *remoting.RemotingCommand) (response *remoting.RemotingCommand) {
+	glog.V(2).Info("receive_request_code GET_CONSUMER_RUNNING_INFO")
+	var getConsumerRunningInfoRequestHeader = &header.GetConsumerRunningInfoRequestHeader{}
+	if cmd.ExtFields != nil {
+		getConsumerRunningInfoRequestHeader.FromMap(cmd.ExtFields) //change map[string]interface{} into CustomerHeader struct
+		consumerRunningInfo := model.ConsumerRunningInfo{}
+		consumerRunningInfo.Properties = map[string]string{}
+		defaultMQPushConsumer := m.clientFactory.consumerTable[getConsumerRunningInfoRequestHeader.ConsumerGroup]
+		consumerConfigMap := util.Struct2Map(defaultMQPushConsumer.ConsumerConfig)
+		for key, value := range consumerConfigMap {
+			consumerRunningInfo.Properties[key] = fmt.Sprintf("%v", value)
+		}
+
+		consumerRunningInfo.Properties["PROP_NAMESERVER_ADDR"] = strings.Join(defaultMQPushConsumer.mqClient.getRemotingClient().GetNamesrvAddrList(), ";")
+		consumerRunningInfo.MqTable = defaultMQPushConsumer.rebalance.getMqTableInfo()
+
+		glog.V(2).Info("op=look consumerRunningInfo", consumerRunningInfo)
+		jsonByte, err := consumerRunningInfo.Encode()
+		glog.V(2).Info("op=enCode jsonByte", string(jsonByte))
+		if err != nil {
+			glog.Error(err)
+			return
+		}
+		response = remoting.NewRemotingCommandWithBody(remoting.SUCCESS, nil, jsonByte)
+	}
+	return
+}
+func (m *MqClientManager) resetConsumerClientOffset(cmd *remoting.RemotingCommand) {
+	glog.V(2).Info("receive_request_code RESET_CONSUMER_CLIENT_OFFSET")
+	glog.V(2).Info("op=look cmd body", string(cmd.Body))
+	var resetOffsetRequestHeader = &header.ResetOffsetRequestHeader{}
+	if cmd.ExtFields != nil {
+		resetOffsetRequestHeader.FromMap(cmd.ExtFields) //change map[string]interface{} into CustomerHeader struct
+		glog.V(2).Info("op=look ResetOffsetRequestHeader", resetOffsetRequestHeader)
+		resetOffsetBody := &model.ResetOffsetBody{}
+		err := resetOffsetBody.Decode(cmd.Body)
+		if err != nil {
+			return
+		}
+		glog.V(2).Info("op=look resetOffsetBody xxxxx", resetOffsetBody)
+		m.resetConsumerOffset(resetOffsetRequestHeader.Topic, resetOffsetRequestHeader.Group, resetOffsetBody.OffsetTable)
+	}
+}
+
+func (m *MqClientManager) resetConsumerOffset(topic, group string, offsetTable map[rocketmqm.MessageQueue]int64) {
+	consumer := m.clientFactory.consumerTable[group]
+	if consumer == nil {
+		glog.Error("resetConsumerOffset because consumer not online,group=", group)
+		return
+	}
+	consumer.resetOffset(offsetTable)
+}
+
+type clientFactory struct {
+	producerTable map[string]*DefaultMQProducer     //group|RocketMQProducer
+	consumerTable map[string]*DefaultMQPushConsumer //group|Consumer
+}
+
+func clientFactoryInit() (clientFactoryInstance *clientFactory) {
+	clientFactoryInstance = &clientFactory{}
+	clientFactoryInstance.producerTable = make(map[string]*DefaultMQProducer)
+	clientFactoryInstance.consumerTable = make(map[string]*DefaultMQPushConsumer)
+	return
+}
+
+//heart beat
+func (m *MqClientManager) sendHeartbeatToAllBrokerWithLock() error {
+	heartbeatData := m.prepareHeartbeatData()
+	if len(heartbeatData.ConsumerDataSet) == 0 {
+		return errors.New("send heartbeat error")
+	}
+	m.mqClient.sendHeartbeatToAllBroker(heartbeatData)
+	return nil
+}
+
+//routeInfo
+func (m *MqClientManager) updateTopicRouteInfoFromNameServer() {
+	var topicSet []string
+	for _, consumer := range m.clientFactory.consumerTable {
+		for key := range consumer.subscription {
+			topicSet = append(topicSet, key)
+		}
+	}
+	topicSet = append(topicSet, m.mqClient.getPublishTopicList()...)
+	for _, topic := range topicSet {
+		m.mqClient.updateTopicRouteInfoFromNameServer(topic)
+
+	}
+}
+
+func (m *MqClientManager) prepareHeartbeatData() *model.HeartbeatData {
+	heartbeatData := new(model.HeartbeatData)
+	heartbeatData.ClientId = m.mqClient.getClientId()
+	heartbeatData.ConsumerDataSet = make([]*model.ConsumerData, 0)
+	heartbeatData.ProducerDataSet = make([]*model.ProducerData, 0)
+	for group, consumer := range m.clientFactory.consumerTable {
+		consumerData := new(model.ConsumerData)
+		consumerData.GroupName = group
+		consumerData.ConsumeType = consumer.consumeType
+		consumerData.ConsumeFromWhere = consumer.ConsumerConfig.ConsumeFromWhere
+		consumerData.MessageModel = consumer.messageModel
+		consumerData.SubscriptionDataSet = consumer.Subscriptions()
+		consumerData.UnitMode = consumer.unitMode
+		heartbeatData.ConsumerDataSet = append(heartbeatData.ConsumerDataSet, consumerData)
+	}
+	for group := range m.clientFactory.producerTable {
+		producerData := new(model.ProducerData)
+		producerData.GroupName = group
+		heartbeatData.ProducerDataSet = append(heartbeatData.ProducerDataSet, producerData)
+	}
+	return heartbeatData
+}
diff --git a/rocketmq-go/kernel/mq_fault_strategy.go b/rocketmq-go/kernel/mq_fault_strategy.go
new file mode 100644
index 0000000..bca20d6
--- /dev/null
+++ b/rocketmq-go/kernel/mq_fault_strategy.go
@@ -0,0 +1,51 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+)
+
+type mqFaultStrategy struct {
+}
+
+//if first select : random one
+//if has error broker before ,skip the err broker
+func selectOneMessageQueue(topicPublishInfo *model.TopicPublishInfo, lastFailedBroker string) (mqQueue rocketmqm.MessageQueue, err error) {
+	queueIndex := topicPublishInfo.FetchQueueIndex()
+	queues := topicPublishInfo.MessageQueueList
+	if len(lastFailedBroker) == 0 {
+		mqQueue = queues[queueIndex]
+		return
+	}
+	for i := 0; i < len(queues); i++ {
+		nowQueueIndex := queueIndex + i
+		if nowQueueIndex >= len(queues) {
+			nowQueueIndex = nowQueueIndex - len(queues)
+		}
+		if lastFailedBroker == queues[nowQueueIndex].BrokerName {
+			continue
+		}
+		mqQueue = queues[nowQueueIndex]
+		return
+	}
+	err = errors.New("send to [" + lastFailedBroker + "] fail,no other broker")
+	return
+}
diff --git a/rocketmq-go/kernel/mq_producer.go b/rocketmq-go/kernel/mq_producer.go
new file mode 100644
index 0000000..dafa712
--- /dev/null
+++ b/rocketmq-go/kernel/mq_producer.go
@@ -0,0 +1,55 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+)
+
+//DefaultMQProducer use DefaultMQProducer send message
+type DefaultMQProducer struct {
+	producerGroup  string
+	ProducerConfig *rocketmqm.MqProducerConfig
+
+	producerService ProducerService
+}
+
+//NewDefaultMQProducer create a  DefaultMQProducer instance
+// see rocketmq_producer.go
+func NewDefaultMQProducer(producerGroup string, producerConfig *rocketmqm.MqProducerConfig) (rocketMQProducer *DefaultMQProducer) {
+	rocketMQProducer = &DefaultMQProducer{
+		producerGroup:  producerGroup,
+		ProducerConfig: producerConfig,
+	}
+	return
+}
+
+//Send see rocketmq_producer.go
+func (d *DefaultMQProducer) Send(msg rocketmqm.Message) (sendResult *rocketmqm.SendResult, err error) {
+	sendResult, err = d.producerService.sendDefaultImpl(msg.(*message.MessageImpl), constant.COMMUNICATIONMODE_SYNC, "", d.ProducerConfig.SendMsgTimeout)
+	return
+}
+
+//SendWithTimeout see rocketmq_producer.go
+func (d *DefaultMQProducer) SendWithTimeout(msg rocketmqm.Message, timeout int64) (sendResult *rocketmqm.SendResult, err error) {
+	sendResult, err = d.producerService.sendDefaultImpl(msg.(*message.MessageImpl), constant.COMMUNICATIONMODE_SYNC, "", timeout)
+	return
+}
diff --git a/rocketmq-go/kernel/mq_push_consumer.go b/rocketmq-go/kernel/mq_push_consumer.go
new file mode 100644
index 0000000..bc2f1ad
--- /dev/null
+++ b/rocketmq-go/kernel/mq_push_consumer.go
@@ -0,0 +1,155 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+	"strings"
+	"time"
+)
+
+//DefaultMQPushConsumer no order/cluster
+type DefaultMQPushConsumer struct {
+	consumerGroup         string
+	consumeType           string
+	messageModel          string
+	unitMode              bool
+	subscription          map[string]string   //topic|subExpression
+	subscriptionTag       map[string][]string // we use it filter again
+	offsetStore           OffsetStore
+	mqClient              RocketMqClient
+	rebalance             *rebalance
+	pause                 bool
+	consumeMessageService consumeMessageService
+	ConsumerConfig        *rocketmqm.MqConsumerConfig
+}
+
+//NewDefaultMQPushConsumer create a DefaultMQPushConsumer instance
+func NewDefaultMQPushConsumer(consumerGroup string, consumerConfig *rocketmqm.MqConsumerConfig) (defaultMQPushConsumer *DefaultMQPushConsumer) {
+	defaultMQPushConsumer = &DefaultMQPushConsumer{
+		consumerGroup: consumerGroup,
+		consumeType:   "CONSUME_PASSIVELY",
+		messageModel:  "CLUSTERING",
+		pause:         false}
+	defaultMQPushConsumer.subscription = make(map[string]string)
+	defaultMQPushConsumer.subscriptionTag = make(map[string][]string)
+	defaultMQPushConsumer.ConsumerConfig = consumerConfig
+
+	return
+}
+
+//Subscribe subscribe topic, filter by subExpression
+func (d *DefaultMQPushConsumer) Subscribe(topic string, subExpression string) {
+	d.subscription[topic] = subExpression
+	if len(subExpression) == 0 || subExpression == "*" {
+		return
+	}
+	tags := strings.Split(subExpression, "||")
+	tagsList := []string{}
+	for _, tag := range tags {
+		t := strings.TrimSpace(tag)
+		if len(t) == 0 {
+			continue
+		}
+		tagsList = append(tagsList, t)
+	}
+	if len(tagsList) > 0 {
+		d.subscriptionTag[topic] = tagsList
+	}
+}
+
+//RegisterMessageListener register message listener to this consumer
+func (d *DefaultMQPushConsumer) RegisterMessageListener(messageListener rocketmqm.MessageListener) {
+	d.consumeMessageService = newConsumeMessageConcurrentlyServiceImpl(messageListener)
+}
+
+func (d *DefaultMQPushConsumer) resetOffset(offsetTable map[rocketmqm.MessageQueue]int64) {
+	d.pause = true
+	glog.V(2).Info("now we clearProcessQueue 0 ", offsetTable)
+
+	d.rebalance.clearProcessQueue(offsetTable)
+	glog.V(2).Info("now we clearProcessQueue", offsetTable)
+	go func() {
+		waitTime := time.NewTimer(10 * time.Second)
+		<-waitTime.C
+		defer func() {
+			d.pause = false
+			d.rebalance.doRebalance()
+		}()
+
+		for messageQueue, offset := range offsetTable {
+			processQueue := d.rebalance.getProcessQueue(messageQueue)
+			if processQueue == nil || offset < 0 {
+				continue
+			}
+			glog.V(2).Info("now we updateOffset", messageQueue, offset)
+			d.offsetStore.updateOffset(&messageQueue, offset, false)
+			d.rebalance.removeProcessQueue(&messageQueue)
+		}
+	}()
+}
+
+//Subscriptions get this consumer's subscription data
+func (d *DefaultMQPushConsumer) Subscriptions() []*model.SubscriptionData {
+	subscriptions := make([]*model.SubscriptionData, 0)
+	for _, subscription := range d.rebalance.subscriptionInner {
+		subscriptions = append(subscriptions, subscription)
+	}
+	return subscriptions
+}
+
+//CleanExpireMsg cleanExpireMsg
+func (d *DefaultMQPushConsumer) CleanExpireMsg() {
+	nowTime := util.CurrentTimeMillisInt64() //will cause nowTime - consumeStartTime <0 ,but no matter
+	messageQueueList, processQueueList := d.rebalance.getProcessQueueList()
+	for messageQueueIndex, processQueue := range processQueueList {
+		loop := processQueue.GetMsgCount()
+		if loop > 16 {
+			loop = 16
+		}
+		for i := 0; i < loop; i++ {
+			_, message := processQueue.GetMinMessageInTree()
+			if message == nil {
+				break
+			}
+			consumeStartTime := message.GetConsumeStartTime()
+			maxDiffTime := d.ConsumerConfig.ConsumeTimeout * 1000 * 60
+			//maxDiffTime := d.ConsumerConfig.ConsumeTimeout
+			glog.V(2).Info("look message.GetConsumeStartTime()", consumeStartTime)
+			glog.V(2).Infof("look diff %d  %d", nowTime-consumeStartTime, maxDiffTime)
+			//if(nowTime - consumeStartTime <0){
+			//	panic("nowTime - consumeStartTime <0")
+			//}
+			if nowTime-consumeStartTime < maxDiffTime {
+				break
+			}
+			glog.Info("look now we send expire message back", message.Topic(), message.MsgId())
+			err := d.consumeMessageService.sendMessageBack(message, 3, messageQueueList[messageQueueIndex].BrokerName)
+			if err != nil {
+				glog.Error("op=send_expire_message_back_error", err)
+				continue
+			}
+			processQueue.DeleteExpireMsg(int(message.QueueOffset))
+		}
+	}
+	return
+}
diff --git a/rocketmq-go/kernel/offset_store.go b/rocketmq-go/kernel/offset_store.go
new file mode 100644
index 0000000..67e1375
--- /dev/null
+++ b/rocketmq-go/kernel/offset_store.go
@@ -0,0 +1,175 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/golang/glog"
+	"strconv"
+	"sync"
+)
+
+const (
+	//MEMORY_FIRST_THEN_STORE memory first then store
+	MEMORY_FIRST_THEN_STORE = 0
+	//READ_FROM_MEMORY   READ_FROM_MEMORY
+	READ_FROM_MEMORY = 1
+	//READ_FROM_STORE READ_FROM_STORE
+	READ_FROM_STORE = 2
+)
+
+//OffsetStore OffsetStore
+type OffsetStore interface {
+	//update local offsetTable's offset
+	updateOffset(mq *rocketmqm.MessageQueue, offset int64, increaseOnly bool)
+	//read offset,from memory or broker
+	readOffset(mq *rocketmqm.MessageQueue, readType int) int64
+	//update broker's offset
+	persist(mq *rocketmqm.MessageQueue)
+	//remove local offsetTable's offset
+	removeOffset(mq *rocketmqm.MessageQueue)
+}
+
+//RemoteOffsetStore offset store on remote
+type RemoteOffsetStore struct {
+	groupName       string
+	mqClient        RocketMqClient
+	offsetTable     map[rocketmqm.MessageQueue]int64
+	offsetTableLock *sync.RWMutex
+}
+
+func remoteOffsetStoreInit(groupName string, mqClient RocketMqClient) OffsetStore {
+	offsetStore := new(RemoteOffsetStore)
+	offsetStore.groupName = groupName
+	offsetStore.mqClient = mqClient
+	offsetStore.offsetTable = make(map[rocketmqm.MessageQueue]int64)
+	offsetStore.offsetTableLock = new(sync.RWMutex)
+	return offsetStore
+}
+func (r *RemoteOffsetStore) removeOffset(mq *rocketmqm.MessageQueue) {
+	defer r.offsetTableLock.Unlock()
+	r.offsetTableLock.Lock()
+	delete(r.offsetTable, *mq)
+}
+
+func (r *RemoteOffsetStore) persist(mq *rocketmqm.MessageQueue) {
+	brokerAddr := r.mqClient.fetchMasterBrokerAddress(mq.BrokerName)
+	if len(brokerAddr) == 0 {
+		r.mqClient.tryToFindTopicPublishInfo(mq.Topic)
+		brokerAddr = r.mqClient.fetchMasterBrokerAddress(mq.BrokerName)
+	}
+	r.offsetTableLock.RLock()
+	offset := r.offsetTable[*mq]
+	r.offsetTableLock.RUnlock()
+	updateConsumerOffsetRequestHeader := &header.UpdateConsumerOffsetRequestHeader{ConsumerGroup: r.groupName, Topic: mq.Topic, QueueId: mq.QueueId, CommitOffset: offset}
+	requestCommand := remoting.NewRemotingCommand(remoting.UPDATE_CONSUMER_OFFSET, updateConsumerOffsetRequestHeader)
+	r.mqClient.getRemotingClient().InvokeOneWay(brokerAddr, requestCommand, 1000*5)
+}
+
+func (r *RemoteOffsetStore) readOffset(mq *rocketmqm.MessageQueue, readType int) int64 {
+
+	switch readType {
+	case MEMORY_FIRST_THEN_STORE:
+	case READ_FROM_MEMORY:
+		r.offsetTableLock.RLock()
+		offset, ok := r.offsetTable[*mq]
+		r.offsetTableLock.RUnlock()
+		if ok {
+			return offset
+		}
+		return -1
+
+	case READ_FROM_STORE:
+		offset, err := r.fetchConsumeOffsetFromBroker(mq)
+		if err != nil {
+			glog.Error(err)
+			return -1
+		}
+		glog.V(2).Info("READ_FROM_STORE", offset)
+		r.updateOffset(mq, offset, false)
+		return offset
+	}
+
+	return -1
+
+}
+
+func (r *RemoteOffsetStore) fetchConsumeOffsetFromBroker(mq *rocketmqm.MessageQueue) (int64, error) {
+	brokerAddr, _, found := r.mqClient.findBrokerAddressInSubscribe(mq.BrokerName, 0, false)
+
+	if !found {
+		brokerAddr, _, found = r.mqClient.findBrokerAddressInSubscribe(mq.BrokerName, 0, false)
+	}
+
+	if found {
+		requestHeader := &header.QueryConsumerOffsetRequestHeader{}
+		requestHeader.Topic = mq.Topic
+		requestHeader.QueueId = mq.QueueId
+		requestHeader.ConsumerGroup = r.groupName
+		return r.queryConsumerOffset(brokerAddr, requestHeader, 3000)
+	}
+
+	return -1, errors.New("fetch consumer offset error")
+}
+
+func (r RemoteOffsetStore) queryConsumerOffset(addr string, requestHeader *header.QueryConsumerOffsetRequestHeader, timeoutMillis int64) (int64, error) {
+	remotingCommand := remoting.NewRemotingCommand(remoting.QUERY_CONSUMER_OFFSET, requestHeader)
+	response, err := r.mqClient.getRemotingClient().InvokeSync(addr, remotingCommand, timeoutMillis)
+	if err != nil {
+		glog.Error(err)
+		return -1, err
+	}
+
+	if response.Code == remoting.QUERY_NOT_FOUND {
+		return -1, nil
+	}
+
+	if offsetInter, ok := response.ExtFields["offset"]; ok {
+		if offsetStr, ok := offsetInter.(string); ok {
+			offset, err := strconv.ParseInt(offsetStr, 10, 64)
+			if err != nil {
+				glog.Error(err)
+				return -1, err
+			}
+			return offset, nil
+
+		}
+	}
+	glog.Error(requestHeader, response)
+	return -1, errors.New("query offset error")
+}
+
+func (r *RemoteOffsetStore) updateOffset(mq *rocketmqm.MessageQueue, offset int64, increaseOnly bool) {
+	defer r.offsetTableLock.Unlock()
+	r.offsetTableLock.Lock()
+	if mq != nil {
+		if increaseOnly {
+			offsetOld := r.offsetTable[*mq]
+			if offsetOld >= offset {
+				return
+			}
+			r.offsetTable[*mq] = offset
+		} else {
+			r.offsetTable[*mq] = offset
+		}
+
+	}
+}
diff --git a/rocketmq-go/kernel/producer_service.go b/rocketmq-go/kernel/producer_service.go
new file mode 100644
index 0000000..8ad91f0
--- /dev/null
+++ b/rocketmq-go/kernel/producer_service.go
@@ -0,0 +1,247 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+)
+
+//ProducerService producerService, for send message
+type ProducerService interface {
+	checkConfig() (err error)
+	sendDefaultImpl(message *message.MessageImpl, communicationMode string, sendCallback string, timeout int64) (sendResult *rocketmqm.SendResult, err error)
+}
+
+//DefaultProducerService ProducerService's implement
+type DefaultProducerService struct {
+	producerGroup   string
+	producerConfig  *rocketmqm.MqProducerConfig
+	mqClient        RocketMqClient
+	mqFaultStrategy mqFaultStrategy
+}
+
+func newDefaultProducerService(producerGroup string, producerConfig *rocketmqm.MqProducerConfig, mqClient RocketMqClient) (defaultProducerService *DefaultProducerService) {
+	defaultProducerService = &DefaultProducerService{
+		mqClient:       mqClient,
+		producerGroup:  producerGroup,
+		producerConfig: producerConfig,
+	}
+	defaultProducerService.checkConfig()
+	return
+}
+func (d *DefaultProducerService) checkConfig() (err error) {
+	// todo check if not pass panic
+	return
+}
+
+func (d *DefaultProducerService) sendDefaultImpl(message *message.MessageImpl, communicationMode string, sendCallback string, timeout int64) (sendResult *rocketmqm.SendResult, err error) {
+	var (
+		topicPublishInfo *model.TopicPublishInfo
+	)
+	err = d.checkMessage(message)
+	if err != nil {
+		return
+	}
+	topicPublishInfo, err = d.mqClient.tryToFindTopicPublishInfo(message.Topic())
+	if err != nil {
+		return
+	}
+	if topicPublishInfo.JudgeTopicPublishInfoOk() == false {
+		err = errors.New("topicPublishInfo is error,topic=" + message.Topic())
+		return
+	}
+	glog.V(2).Info("op=look topicPublishInfo", topicPublishInfo)
+	//if(!ok) return error
+	sendResult, err = d.sendMsgUseTopicPublishInfo(message, communicationMode, sendCallback, topicPublishInfo, timeout)
+	return
+}
+
+func (d *DefaultProducerService) producerSendMessageRequest(brokerName, brokerAddr string, sendMessageHeader remoting.CustomerHeader, message *message.MessageImpl, timeout int64) (sendResult *rocketmqm.SendResult, err error) {
+	remotingCommand := remoting.NewRemotingCommandWithBody(remoting.SEND_MESSAGE, sendMessageHeader, message.Body())
+	var response *remoting.RemotingCommand
+	response, err = d.mqClient.getRemotingClient().InvokeSync(brokerAddr, remotingCommand, timeout)
+	if err != nil {
+		glog.Error(err)
+		return
+	}
+
+	sendResult, err = processSendResponse(brokerName, message, response)
+	return
+}
+func processSendResponse(brokerName string, message *message.MessageImpl, response *remoting.RemotingCommand) (sendResult *rocketmqm.SendResult, err error) {
+	sendResult = &rocketmqm.SendResult{}
+	switch response.Code {
+	case remoting.FLUSH_DISK_TIMEOUT:
+		{
+			sendResult.SetSendStatus(rocketmqm.FlushDiskTimeout)
+			break
+		}
+	case remoting.FLUSH_SLAVE_TIMEOUT:
+		{
+			sendResult.SetSendStatus(rocketmqm.FlushSlaveTimeout)
+			break
+		}
+	case remoting.SLAVE_NOT_AVAILABLE:
+		{
+			sendResult.SetSendStatus(rocketmqm.SlaveNotAvaliable)
+			break
+		}
+	case remoting.SUCCESS:
+		{
+			sendResult.SetSendStatus(rocketmqm.SendOK)
+			break
+		}
+	default:
+		err = errors.New("response.Code error_code=" + util.IntToString(int(response.Code)))
+		return
+	}
+	var responseHeader = &header.SendMessageResponseHeader{}
+	if response.ExtFields != nil {
+		responseHeader.FromMap(response.ExtFields) //change map[string]interface{} into CustomerHeader struct
+	}
+	sendResult.SetMsgID(message.PropertiesKeyValue(constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX))
+	sendResult.SetOffsetMsgID(responseHeader.MsgId)
+	sendResult.SetQueueOffset(responseHeader.QueueOffset)
+	sendResult.SetTransactionID(responseHeader.TransactionId)
+	messageQueue := rocketmqm.MessageQueue{Topic: message.Topic(), BrokerName: brokerName,
+		QueueId: responseHeader.QueueId}
+	sendResult.SetMessageQueue(messageQueue)
+	var regionId = responseHeader.MsgRegion
+	if len(regionId) == 0 {
+		regionId = "DefaultRegion"
+	}
+	sendResult.SetRegionID(regionId)
+	return
+}
+
+func (d *DefaultProducerService) checkMessage(message *message.MessageImpl) (err error) {
+	if message == nil {
+		err = errors.New("message is nil")
+		return
+	}
+	if len(message.Topic()) == 0 {
+		err = errors.New("topic is empty")
+		return
+	}
+	if message.Topic() == constant.DEFAULT_TOPIC {
+		err = errors.New("the topic[" + message.Topic() + "] is conflict with default topic.")
+		return
+	}
+
+	if len(message.Topic()) > constant.MAX_MESSAGE_TOPIC_SIZE {
+		err = errors.New("the specified topic is longer than topic max length 255.")
+		return
+	}
+
+	if !util.MatchString(message.Topic(), `^[%|a-zA-Z0-9_-]+$`) {
+		err = errors.New("the specified topic[" + message.Topic() + "] contains illegal characters")
+		return
+	}
+	if len(message.Body()) == 0 {
+		err = errors.New("messageBody is empty")
+		return
+	}
+	if len(message.Body()) > d.producerConfig.MaxMessageSize {
+		err = errors.New("messageBody is large than " + util.IntToString(d.producerConfig.MaxMessageSize))
+		return
+	}
+	return
+}
+
+func (d *DefaultProducerService) sendMsgUseTopicPublishInfo(message *message.MessageImpl, communicationMode string, sendCallback string, topicPublishInfo *model.TopicPublishInfo, timeout int64) (sendResult *rocketmqm.SendResult, err error) {
+	var (
+		sendTotalTime int
+		messageQueue  rocketmqm.MessageQueue
+	)
+
+	sendTotalTime = 1
+	var lastFailedBroker = ""
+	//todo transaction
+	// todo retry
+	for i := 0; i < sendTotalTime; i++ {
+		messageQueue, err = selectOneMessageQueue(topicPublishInfo, lastFailedBroker)
+		if err != nil {
+			return
+		}
+		sendResult, err = d.doSendMessage(message, messageQueue, communicationMode, sendCallback, topicPublishInfo, timeout)
+		if err != nil {
+			// todo retry
+			return
+		}
+	}
+	return
+}
+
+func (d *DefaultProducerService) doSendMessage(message *message.MessageImpl, messageQueue rocketmqm.MessageQueue,
+	communicationMode string, sendCallback string,
+	topicPublishInfo *model.TopicPublishInfo,
+	timeout int64) (sendResult *rocketmqm.SendResult, err error) {
+	var (
+		brokerAddr          string
+		sysFlag             int
+		compressMessageFlag int
+	)
+	compressMessageFlag, err = d.tryToCompressMessage(message)
+	if err != nil {
+		return
+	}
+	sysFlag = sysFlag | compressMessageFlag
+	brokerAddr = d.mqClient.fetchMasterBrokerAddress(messageQueue.BrokerName)
+	if len(brokerAddr) == 0 {
+		err = errors.New("The broker[" + messageQueue.BrokerName + "] not exist")
+		return
+	}
+	message.GeneratorMsgUniqueKey()
+	sendMessageHeader := &header.SendMessageRequestHeader{
+		ProducerGroup:         d.producerGroup,
+		Topic:                 message.Topic(),
+		DefaultTopic:          constant.DEFAULT_TOPIC,
+		DefaultTopicQueueNums: 4,
+		QueueId:               messageQueue.QueueId,
+		SysFlag:               sysFlag,
+		BornTimestamp:         util.CurrentTimeMillisInt64(),
+		Flag:                  message.Flag(),
+		Properties:            util.MessageProperties2String(message.Properties()),
+
+		UnitMode:          false,
+		ReconsumeTimes:    message.GetReconsumeTimes(),
+		MaxReconsumeTimes: message.GetMaxReconsumeTimes(),
+	}
+	sendResult, err = d.producerSendMessageRequest(messageQueue.BrokerName, brokerAddr, sendMessageHeader, message, timeout)
+	return
+}
+
+func (d *DefaultProducerService) tryToCompressMessage(message *message.MessageImpl) (compressedFlag int, err error) {
+	if len(message.Body()) < d.producerConfig.CompressMsgBodyOverHowMuch {
+		compressedFlag = 0
+		return
+	}
+	compressedFlag = int(constant.CompressedFlag)
+	var compressBody []byte
+	compressBody, err = util.CompressWithLevel(message.Body(), d.producerConfig.ZipCompressLevel)
+	message.SetBody(compressBody)
+	return
+}
diff --git a/rocketmq-go/kernel/producer_service_for_send_back.go b/rocketmq-go/kernel/producer_service_for_send_back.go
new file mode 100644
index 0000000..f3dafba
--- /dev/null
+++ b/rocketmq-go/kernel/producer_service_for_send_back.go
@@ -0,0 +1,114 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"encoding/json"
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/golang/glog"
+)
+
+type sendMessageBackProducerService interface {
+	sendMessageBack(messageExt *message.MessageExtImpl, delayLayLevel int, brokerName string) (err error)
+	initSendMessageBackProducerService(consumerGroup string, mqClient RocketMqClient, defaultProducerService *DefaultProducerService, consumerConfig *rocketmqm.MqConsumerConfig)
+}
+
+type sendMessageBackProducerServiceImpl struct {
+	mqClient               RocketMqClient
+	defaultProducerService *DefaultProducerService // one namesvr only one
+	consumerGroup          string
+	consumerConfig         *rocketmqm.MqConsumerConfig //one mq group have one
+}
+
+// send to original broker,if fail send a new retry message
+func (s *sendMessageBackProducerServiceImpl) sendMessageBack(messageExt *message.MessageExtImpl, delayLayLevel int, brokerName string) (err error) {
+	glog.V(2).Info("op=look_send_message_back", messageExt.MsgId(), messageExt.Properties(), string(messageExt.Body()))
+	err = s.consumerSendMessageBack(brokerName, messageExt, delayLayLevel)
+	if err == nil {
+		return
+	}
+	glog.Error(err)
+	err = s.sendRetryMessageBack(messageExt)
+	return
+}
+
+func (s *sendMessageBackProducerServiceImpl) sendRetryMessageBack(messageExt *message.MessageExtImpl) error {
+	retryMessage := &message.MessageImpl{}
+	originMessageId := messageExt.GetOriginMessageId()
+	retryMessage.SetProperties(messageExt.Properties())
+	retryMessage.SetOriginMessageId(originMessageId)
+	retryMessage.SetFlag(messageExt.Flag())
+	retryMessage.SetTopic(constant.RETRY_GROUP_TOPIC_PREFIX + s.consumerGroup)
+	retryMessage.SetBody(messageExt.Body())
+	retryMessage.SetRetryTopic(messageExt.Topic())
+	retryMessage.SetReconsumeTime(messageExt.GetReconsumeTimes() + 1)
+	retryMessage.SetMaxReconsumeTimes(s.consumerConfig.MaxReconsumeTimes)
+	retryMessage.SetDelayTimeLevel(3 + messageExt.GetReconsumeTimes())
+	pp, _ := json.Marshal(retryMessage)
+	glog.Info("look retryMessage ", string(pp), string(messageExt.Body()))
+	sendResult, err := s.defaultProducerService.sendDefaultImpl(retryMessage, constant.COMMUNICATIONMODE_SYNC, "", s.defaultProducerService.producerConfig.SendMsgTimeout)
+	if err != nil {
+		glog.Error(err)
+		return err
+	}
+	xx, _ := json.Marshal(sendResult)
+	glog.V(2).Info("look retryMessage result", string(xx))
+	return nil
+
+}
+
+func (s *sendMessageBackProducerServiceImpl) initSendMessageBackProducerService(consumerGroup string, mqClient RocketMqClient, defaultProducerService *DefaultProducerService, consumerConfig *rocketmqm.MqConsumerConfig) {
+	s.mqClient = mqClient
+	s.consumerGroup = consumerGroup
+	s.defaultProducerService = defaultProducerService
+	s.consumerConfig = consumerConfig
+}
+
+func (s *sendMessageBackProducerServiceImpl) consumerSendMessageBack(brokerName string, messageExt *message.MessageExtImpl, delayLayLevel int) (err error) {
+	if len(brokerName) == 0 {
+		err = errors.New("broker can't be empty")
+		glog.Error(err)
+		return
+	}
+	brokerAddr := s.mqClient.fetchMasterBrokerAddress(brokerName)
+	sendMsgBackHeader := &header.ConsumerSendMsgBackRequestHeader{
+		Offset:            messageExt.CommitLogOffset,
+		Group:             s.consumerGroup,
+		DelayLevel:        0, //MessageImpl consume retry strategy<br>-1,no retry,put into DLQ directly<br>0,broker control retry frequency<br>>0,client control retry frequency
+		OriginMsgId:       messageExt.MsgId(),
+		OriginTopic:       messageExt.Topic(),
+		UnitMode:          false,
+		MaxReconsumeTimes: int32(s.consumerConfig.MaxReconsumeTimes),
+	}
+	remotingCommand := remoting.NewRemotingCommand(remoting.CONSUMER_SEND_MSG_BACK, sendMsgBackHeader)
+	response, invokeErr := s.mqClient.getRemotingClient().InvokeSync(brokerAddr, remotingCommand, 5000)
+	if invokeErr != nil {
+		err = invokeErr
+		return
+	}
+	if response == nil || response.Code != remoting.SUCCESS {
+		glog.Error("sendMsgBackRemarkError", response.Remark)
+		err = errors.New("send MessageImpl back error")
+	}
+	return
+}
diff --git a/rocketmq-go/kernel/pull_message_controller.go b/rocketmq-go/kernel/pull_message_controller.go
new file mode 100644
index 0000000..0618842
--- /dev/null
+++ b/rocketmq-go/kernel/pull_message_controller.go
@@ -0,0 +1,328 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+	"strconv"
+	"time"
+)
+
+//PullMessageController put pull message logic here
+type PullMessageController struct {
+	mqClient      RocketMqClient
+	clientFactory *clientFactory
+}
+
+func newPullMessageController(mqClient RocketMqClient, clientFactory *clientFactory) *PullMessageController {
+	return &PullMessageController{
+		mqClient:      mqClient,
+		clientFactory: clientFactory,
+	}
+}
+
+func (p *PullMessageController) start() {
+	go func() {
+		for {
+			pullRequest := p.mqClient.dequeuePullMessageRequest()
+			p.pullMessage(pullRequest)
+		}
+	}()
+}
+
+func (p *PullMessageController) needDelayPullMessage(mqPushConsumer *DefaultMQPushConsumer, pullRequest *model.PullRequest) (needDelayTime int64) {
+	if pullRequest.ProcessQueue.GetMsgCount() > mqPushConsumer.ConsumerConfig.PullThresholdForQueue {
+		return mqPushConsumer.ConsumerConfig.PullTimeDelayMillsWhenFlowControl
+	}
+	if pullRequest.ProcessQueue.GetMaxSpan() > mqPushConsumer.ConsumerConfig.ConsumeConcurrentlyMaxSpan {
+		return mqPushConsumer.ConsumerConfig.PullTimeDelayMillsWhenFlowControl
+	}
+	return
+}
+
+func (p *PullMessageController) pullMessageLater(pullRequest *model.PullRequest, millisecond int64) {
+	go func() {
+		timeoutTimer := time.NewTimer(time.Duration(millisecond) * time.Millisecond)
+		<-timeoutTimer.C
+		p.pullMessage(pullRequest)
+	}()
+	return
+}
+
+func (p *PullMessageController) pullMessage(pullRequest *model.PullRequest) {
+	defaultMQPullConsumer := p.clientFactory.consumerTable[pullRequest.ConsumerGroup]
+	if pullRequest.ProcessQueue.IsDropped() {
+		return
+	}
+	delayPullTime := p.needDelayPullMessage(defaultMQPullConsumer, pullRequest)
+	if delayPullTime > 0 {
+		p.pullMessageLater(pullRequest, delayPullTime)
+		return
+	}
+	commitOffsetValue := defaultMQPullConsumer.offsetStore.readOffset(pullRequest.MessageQueue, READ_FROM_MEMORY)
+
+	subscriptionData, ok := defaultMQPullConsumer.rebalance.subscriptionInner[pullRequest.MessageQueue.Topic]
+	if !ok {
+		p.pullMessageLater(pullRequest, defaultMQPullConsumer.ConsumerConfig.PullTimeDelayMillsWhenException)
+		return
+	}
+
+	var sysFlag int32
+	if commitOffsetValue > 0 {
+		sysFlag |= constant.FLAG_COMMIT_OFFSET
+	}
+	sysFlag |= constant.FLAG_SUSPEND
+	sysFlag |= constant.FLAG_SUBSCRIPTION
+	requestHeader := new(header.PullMessageRequestHeader)
+	requestHeader.ConsumerGroup = pullRequest.ConsumerGroup
+	requestHeader.Topic = pullRequest.MessageQueue.Topic
+	requestHeader.QueueId = pullRequest.MessageQueue.QueueId
+	requestHeader.QueueOffset = pullRequest.NextOffset
+
+	requestHeader.CommitOffset = commitOffsetValue
+	requestHeader.SuspendTimeoutMillis = defaultMQPullConsumer.ConsumerConfig.BrokerSuspendMaxTimeMillis
+	requestHeader.MaxMsgNums = int32(defaultMQPullConsumer.ConsumerConfig.PullBatchSize)
+	requestHeader.SubVersion = subscriptionData.SubVersion
+	requestHeader.Subscription = subscriptionData.SubString
+
+	requestHeader.SysFlag = sysFlag
+
+	pullCallback := func(responseFuture *remoting.ResponseFuture) {
+		var nextBeginOffset int64 = pullRequest.NextOffset
+
+		if responseFuture != nil {
+			responseCommand := responseFuture.ResponseCommand
+			if responseCommand.Code == remoting.SUCCESS && len(responseCommand.Body) > 0 {
+				nextBeginOffset = parseNextBeginOffset(responseCommand)
+				//}
+				msgs := decodeMessage(responseFuture.ResponseCommand.Body)
+				msgs = filterMessageAgainByTags(msgs, defaultMQPullConsumer.subscriptionTag[pullRequest.MessageQueue.Topic])
+				if len(msgs) == 0 {
+					if pullRequest.ProcessQueue.GetMsgCount() == 0 {
+						defaultMQPullConsumer.offsetStore.updateOffset(pullRequest.MessageQueue, nextBeginOffset, true)
+					}
+				}
+				pullRequest.ProcessQueue.PutMessage(msgs)
+				defaultMQPullConsumer.consumeMessageService.submitConsumeRequest(msgs, pullRequest.ProcessQueue, pullRequest.MessageQueue, true)
+			} else {
+				//var err error // change the offset , use nextBeginOffset
+				//pullResult := responseCommand.ExtFields
+				//if ok {
+				//	if nextBeginOffsetInter, ok := pullResult["nextBeginOffset"]; ok {
+				//		if nextBeginOffsetStr, ok := nextBeginOffsetInter.(string); ok {
+				//			nextBeginOffset, err = strconv.ParseInt(nextBeginOffsetStr, 10, 64)
+				//			if err != nil {
+				//				glog.Error(err)
+				//			}
+				//		}
+				//	}
+				nextBeginOffset = parseNextBeginOffset(responseCommand)
+
+				//}
+				if responseCommand.Code == remoting.PULL_NOT_FOUND || responseCommand.Code == remoting.PULL_RETRY_IMMEDIATELY {
+					//NO_NEW_MSG //NO_MATCHED_MSG
+					if pullRequest.ProcessQueue.GetMsgCount() == 0 {
+						defaultMQPullConsumer.offsetStore.updateOffset(pullRequest.MessageQueue, nextBeginOffset, true)
+					}
+					//update offset increase only
+					//failedPullRequest, _ := json.Marshal(pullRequest)
+					//glog.Error("the pull request offset illegal", string(failedPullRequest))
+				} else if responseCommand.Code == remoting.PULL_OFFSET_MOVED {
+					//OFFSET_ILLEGAL
+					glog.Error(fmt.Sprintf("PULL_OFFSET_MOVED,code=%d,body=%s", responseCommand.Code, string(responseCommand.Body)))
+					pullRequest.ProcessQueue.SetDrop(true)
+					go func() {
+						executeTaskLater := time.NewTimer(10 * time.Second)
+						<-executeTaskLater.C
+						defaultMQPullConsumer.offsetStore.updateOffset(pullRequest.MessageQueue, nextBeginOffset, false)
+						defaultMQPullConsumer.rebalance.removeProcessQueue(pullRequest.MessageQueue)
+					}()
+				} else {
+					glog.Errorf("illegal response code. pull message error,code=%d,request=%v OFFSET_ILLEGAL", responseCommand.Code, requestHeader)
+					glog.Error(pullRequest.MessageQueue)
+					time.Sleep(1 * time.Second)
+				}
+			}
+		} else {
+			glog.Error("responseFuture is nil")
+		}
+		p.enqueueNextPullRequest(defaultMQPullConsumer, pullRequest, nextBeginOffset)
+
+	}
+	glog.V(2).Infof("requestHeader look offset %s %s %s %s", requestHeader.QueueOffset, requestHeader.Topic, requestHeader.QueueId, requestHeader.CommitOffset)
+	p.consumerPullMessageAsync(pullRequest.MessageQueue.BrokerName, requestHeader, pullCallback)
+}
+
+//func (p *PullMessageController) updateOffsetIfNeed(msgs []message.MessageExtImpl, pullRequest *model.PullRequest, defaultMQPullConsumer *DefaultMQPushConsumer, nextBeginOffset int64) {
+//	if len(msgs) == 0 {
+//		if pullRequest.ProcessQueue.GetMsgCount() == 0 {
+//			defaultMQPullConsumer.OffsetStore.updateOffset(pullRequest.MessageQueue, nextBeginOffset, true)
+//		}
+//	}
+//}
+func parseNextBeginOffset(responseCommand *remoting.RemotingCommand) (nextBeginOffset int64) {
+	var err error
+	pullResult := responseCommand.ExtFields
+	if nextBeginOffsetInter, ok := pullResult["nextBeginOffset"]; ok {
+		if nextBeginOffsetStr, ok := nextBeginOffsetInter.(string); ok {
+			nextBeginOffset, err = strconv.ParseInt(nextBeginOffsetStr, 10, 64)
+			if err != nil {
+				panic(err)
+			}
+		}
+	}
+	return
+}
+func (p *PullMessageController) enqueueNextPullRequest(defaultMQPullConsumer *DefaultMQPushConsumer, pullRequest *model.PullRequest, nextBeginOffset int64) {
+	if pullRequest.ProcessQueue.IsDropped() {
+		return
+	}
+	nextPullRequest := &model.PullRequest{
+		ConsumerGroup: pullRequest.ConsumerGroup,
+		NextOffset:    nextBeginOffset,
+		MessageQueue:  pullRequest.MessageQueue,
+		ProcessQueue:  pullRequest.ProcessQueue,
+	}
+	if defaultMQPullConsumer.ConsumerConfig.PullInterval > 0 {
+		go func() {
+			nextPullTime := time.NewTimer(time.Duration(defaultMQPullConsumer.ConsumerConfig.PullInterval) * time.Millisecond)
+			<-nextPullTime.C
+			p.mqClient.enqueuePullMessageRequest(nextPullRequest)
+		}()
+	} else {
+		p.mqClient.enqueuePullMessageRequest(nextPullRequest)
+	}
+}
+func filterMessageAgainByTags(msgExts []message.MessageExtImpl, subscriptionTagList []string) (result []message.MessageExtImpl) {
+	result = msgExts
+	if len(subscriptionTagList) == 0 {
+		return
+	}
+	result = []message.MessageExtImpl{}
+	for _, msg := range msgExts {
+		for _, tag := range subscriptionTagList {
+			if tag == msg.Tag() {
+				result = append(result, msg)
+				break
+			}
+		}
+	}
+	return
+}
+
+func (p *PullMessageController) consumerPullMessageAsync(brokerName string, requestHeader remoting.CustomerHeader, invokeCallback remoting.InvokeCallback) {
+	brokerAddr, _, found := p.mqClient.findBrokerAddressInSubscribe(brokerName, 0, false)
+	if found {
+		remotingCommand := remoting.NewRemotingCommand(remoting.PULL_MESSAGE, requestHeader)
+		p.mqClient.getRemotingClient().InvokeAsync(brokerAddr, remotingCommand, 1000, invokeCallback)
+	}
+}
+
+func decodeMessage(data []byte) []message.MessageExtImpl {
+	buf := bytes.NewBuffer(data)
+	var storeSize, magicCode, bodyCRC, queueId, flag, sysFlag, reconsumeTimes, bodyLength, bornPort, storePort int32
+	var queueOffset, physicOffset, preparedTransactionOffset, bornTimeStamp, storeTimestamp int64
+	var topicLen byte
+	var topic, body, properties, bornHost, storeHost []byte
+	var propertiesLength int16
+
+	var propertiesMap = make(map[string]string)
+
+	msgs := []message.MessageExtImpl{}
+	for buf.Len() > 0 {
+		msg := message.MessageExtImpl{MessageImpl: &message.MessageImpl{}}
+		binary.Read(buf, binary.BigEndian, &storeSize)
+		binary.Read(buf, binary.BigEndian, &magicCode)
+		binary.Read(buf, binary.BigEndian, &bodyCRC)
+		binary.Read(buf, binary.BigEndian, &queueId)
+		binary.Read(buf, binary.BigEndian, &flag)
+		binary.Read(buf, binary.BigEndian, &queueOffset)
+		binary.Read(buf, binary.BigEndian, &physicOffset)
+		binary.Read(buf, binary.BigEndian, &sysFlag)
+		binary.Read(buf, binary.BigEndian, &bornTimeStamp)
+		bornHost = make([]byte, 4)
+		binary.Read(buf, binary.BigEndian, &bornHost)
+		binary.Read(buf, binary.BigEndian, &bornPort)
+		binary.Read(buf, binary.BigEndian, &storeTimestamp)
+		storeHost = make([]byte, 4)
+		binary.Read(buf, binary.BigEndian, &storeHost)
+		binary.Read(buf, binary.BigEndian, &storePort)
+		binary.Read(buf, binary.BigEndian, &reconsumeTimes)
+		binary.Read(buf, binary.BigEndian, &preparedTransactionOffset)
+		binary.Read(buf, binary.BigEndian, &bodyLength)
+		if bodyLength > 0 {
+			body = make([]byte, bodyLength)
+			binary.Read(buf, binary.BigEndian, body)
+			if (sysFlag & constant.CompressedFlag) == constant.CompressedFlag {
+				var err error
+				body, err = util.UnCompress(body)
+				if err != nil {
+					glog.Error(err)
+					return nil
+				}
+			}
+		}
+		binary.Read(buf, binary.BigEndian, &topicLen)
+		topic = make([]byte, int(topicLen))
+		binary.Read(buf, binary.BigEndian, &topic)
+		binary.Read(buf, binary.BigEndian, &propertiesLength)
+		if propertiesLength > 0 {
+			properties = make([]byte, propertiesLength)
+			binary.Read(buf, binary.BigEndian, &properties)
+			propertiesMap = util.String2MessageProperties(string(properties))
+		}
+
+		if magicCode != -626843481 {
+			glog.Errorf("magic code is error %d", magicCode)
+			return nil
+		}
+
+		msg.SetTopic(string(topic))
+		msg.QueueId = queueId
+		msg.SysFlag = sysFlag
+		msg.QueueOffset = queueOffset
+		msg.BodyCRC = bodyCRC
+		msg.StoreSize = storeSize
+		msg.BornTimestamp = bornTimeStamp
+		msg.ReconsumeTimes = reconsumeTimes
+		msg.SetFlag(int(flag))
+		msg.CommitLogOffset = physicOffset
+		msg.StoreTimestamp = storeTimestamp
+		msg.PreparedTransactionOffset = preparedTransactionOffset
+		msg.SetBody(body)
+		msg.SetProperties(propertiesMap)
+		//  <  3.5.8 use messageOffsetId
+		//  >= 3.5.8 use clientUniqMsgId
+		msg.SetMsgId(msg.GetMsgUniqueKey())
+		if len(msg.MsgId()) == 0 {
+			msg.SetMsgId(message.GeneratorMessageOffsetId(storeHost, storePort, msg.CommitLogOffset))
+		}
+		msgs = append(msgs, msg)
+	}
+
+	return msgs
+}
diff --git a/rocketmq-go/kernel/rebalance.go b/rocketmq-go/kernel/rebalance.go
new file mode 100644
index 0000000..fefd5b3
--- /dev/null
+++ b/rocketmq-go/kernel/rebalance.go
@@ -0,0 +1,308 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"encoding/json"
+	"errors"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/allocate"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/kernel/header"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"github.com/golang/glog"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+type rebalance struct {
+	groupName                    string
+	messageModel                 string
+	topicSubscribeInfoTableLock  sync.RWMutex
+	subscriptionInner            map[string]*model.SubscriptionData
+	subscriptionInnerLock        sync.RWMutex
+	mqClient                     RocketMqClient
+	allocateMessageQueueStrategy allocate.AllocateMessageQueueStrategy
+	processQueueTable            map[rocketmqm.MessageQueue]*model.ProcessQueue // both subscribe topic and retry group
+	processQueueTableLock        sync.RWMutex
+	mutex                        sync.Mutex
+	offsetStore                  OffsetStore
+	consumerConfig               *rocketmqm.MqConsumerConfig
+}
+
+//when invoke GET_CONSUMER_RUNNING_INFO, getMqTableInfo will return ProcessQueueInfo
+func (r *rebalance) getMqTableInfo() map[rocketmqm.MessageQueue]model.ProcessQueueInfo {
+	defer r.processQueueTableLock.RUnlock()
+	r.processQueueTableLock.RLock()
+	mqTable := map[rocketmqm.MessageQueue]model.ProcessQueueInfo{}
+	for messageQueue, processQueue := range r.processQueueTable {
+		mqTable[messageQueue] = processQueue.ChangeToProcessQueueInfo()
+	}
+	return mqTable
+}
+
+func (r *rebalance) getProcessQueue(messageQueue rocketmqm.MessageQueue) *model.ProcessQueue {
+	defer r.processQueueTableLock.RUnlock()
+	r.processQueueTableLock.RLock()
+	return r.processQueueTable[messageQueue]
+}
+
+func (r *rebalance) clearProcessQueue(offsetTable map[rocketmqm.MessageQueue]int64) {
+	defer r.processQueueTableLock.Unlock()
+	r.processQueueTableLock.Lock()
+	for mq := range offsetTable {
+		processQueue, ok := r.processQueueTable[mq]
+		if !ok {
+			continue
+		}
+		processQueue.Clear()
+	}
+
+}
+
+func (r *rebalance) getProcessQueueList() (messageQueueList []rocketmqm.MessageQueue, processQueueList []*model.ProcessQueue) {
+	defer r.processQueueTableLock.RUnlock()
+	r.processQueueTableLock.RLock()
+	for messageQueue, processQueue := range r.processQueueTable {
+		processQueueList = append(processQueueList, processQueue)
+		messageQueueList = append(messageQueueList, messageQueue)
+	}
+	return
+}
+
+//removeUnnecessaryMessageQueue you should drop it first
+func (r *rebalance) removeProcessQueue(messageQueue *rocketmqm.MessageQueue) {
+	r.offsetStore.persist(messageQueue)
+	r.offsetStore.removeOffset(messageQueue)
+	r.removeMessageQueueFromMap(*messageQueue)
+}
+func (r *rebalance) removeMessageQueueFromMap(messageQueue rocketmqm.MessageQueue) {
+	defer r.processQueueTableLock.Unlock()
+	r.processQueueTableLock.Lock()
+	delete(r.processQueueTable, messageQueue)
+
+}
+
+func newRebalance(groupName string, subscription map[string]string, mqClient RocketMqClient, offsetStore OffsetStore, consumerConfig *rocketmqm.MqConsumerConfig) *rebalance {
+	subscriptionInner := make(map[string]*model.SubscriptionData)
+	for topic, subExpression := range subscription {
+		subData := &model.SubscriptionData{
+			Topic:      topic,
+			SubString:  subExpression,
+			SubVersion: time.Now().Unix(),
+		}
+		subscriptionInner[topic] = subData
+	}
+	// put retry
+	retryTopic := constant.RETRY_GROUP_TOPIC_PREFIX + groupName
+	subscriptionInner[retryTopic] = &model.SubscriptionData{
+		Topic:      retryTopic,
+		SubString:  "*",
+		SubVersion: time.Now().Unix(),
+	}
+	return &rebalance{
+		groupName:                    groupName,
+		mqClient:                     mqClient,
+		offsetStore:                  offsetStore,
+		subscriptionInner:            subscriptionInner,
+		allocateMessageQueueStrategy: allocate.GetAllocateMessageQueueStrategyByConfig("default"),
+		messageModel:                 "CLUSTERING",
+		processQueueTable:            make(map[rocketmqm.MessageQueue]*model.ProcessQueue),
+		consumerConfig:               consumerConfig,
+	}
+}
+
+func (r *rebalance) doRebalance() {
+	r.mutex.Lock()
+	defer r.mutex.Unlock()
+	for topic := range r.subscriptionInner {
+		r.rebalanceByTopic(topic)
+	}
+}
+
+type consumerIdSorter []string
+
+func (c consumerIdSorter) Len() int {
+	return len(c)
+}
+func (c consumerIdSorter) Swap(i, j int) {
+	c[i], c[j] = c[j], c[i]
+}
+func (c consumerIdSorter) Less(i, j int) bool {
+	if c[i] < c[j] {
+		return true
+	}
+	return false
+}
+
+func (r *rebalance) rebalanceByTopic(topic string) error {
+	var cidAll []string
+	cidAll, err := r.findConsumerIdList(topic, r.groupName)
+	if err != nil {
+		glog.Error(err)
+		return err
+	}
+	r.topicSubscribeInfoTableLock.RLock()
+	mqs := r.mqClient.getTopicSubscribeInfo(topic)
+	r.topicSubscribeInfoTableLock.RUnlock()
+	if len(mqs) > 0 && len(cidAll) > 0 {
+		var messageQueues model.MessageQueues = mqs
+		var consumerIdSorter consumerIdSorter = cidAll
+
+		sort.Sort(messageQueues)
+		sort.Sort(consumerIdSorter)
+	}
+	allocateResult, err := r.allocateMessageQueueStrategy.Allocate(r.groupName, r.mqClient.getClientId(), mqs, cidAll)
+
+	if err != nil {
+		glog.Error(err)
+		return err
+	}
+
+	glog.V(2).Infof("rebalance topic[%s]", topic)
+	r.updateProcessQueueTableInRebalance(topic, allocateResult)
+	return nil
+}
+
+func (r *rebalance) updateProcessQueueTableInRebalance(topic string, mqSet []rocketmqm.MessageQueue) {
+	defer r.processQueueTableLock.RUnlock()
+	r.processQueueTableLock.RLock()
+	r.removeTheQueueDontBelongHere(topic, mqSet)
+	r.putTheQueueToProcessQueueTable(topic, mqSet)
+
+}
+func (r *rebalance) removeTheQueueDontBelongHere(topic string, mqSet []rocketmqm.MessageQueue) {
+	// there is n^2 todo improve
+	for key, value := range r.processQueueTable {
+		if topic != key.Topic {
+			continue
+		}
+		needDelete := true
+		for _, messageQueueItem := range mqSet {
+			if key == messageQueueItem {
+				needDelete = false
+				break
+			}
+		}
+		if needDelete {
+			value.SetDrop(true)
+			delete(r.processQueueTable, key)
+		}
+	}
+}
+
+func (r *rebalance) putTheQueueToProcessQueueTable(topic string, mqSet []rocketmqm.MessageQueue) {
+	for index, mq := range mqSet {
+		_, ok := r.processQueueTable[mq]
+		if !ok {
+			pullRequest := new(model.PullRequest)
+			pullRequest.ConsumerGroup = r.groupName
+			pullRequest.MessageQueue = &mqSet[index]
+			pullRequest.NextOffset = r.computePullFromWhere(&mq)
+			pullRequest.ProcessQueue = model.NewProcessQueue()
+			r.processQueueTable[mq] = pullRequest.ProcessQueue
+			r.mqClient.enqueuePullMessageRequest(pullRequest)
+		}
+	}
+
+}
+func (r *rebalance) computePullFromWhere(mq *rocketmqm.MessageQueue) int64 {
+	var result int64 = -1
+	lastOffset := r.offsetStore.readOffset(mq, READ_FROM_STORE)
+	switch r.consumerConfig.ConsumeFromWhere {
+	case rocketmqm.CONSUME_FROM_LAST_OFFSET:
+		if lastOffset >= 0 {
+			result = lastOffset
+		} else {
+			if strings.HasPrefix(mq.Topic, constant.RETRY_GROUP_TOPIC_PREFIX) {
+				result = 0
+			} else {
+				result = r.mqClient.getMaxOffset(mq)
+			}
+		}
+		break
+	case rocketmqm.CONSUME_FROM_FIRST_OFFSET:
+		if lastOffset >= 0 {
+			result = lastOffset
+		} else {
+			result = 0 // use the begin offset
+		}
+		break
+	case rocketmqm.CONSUME_FROM_TIMESTAMP:
+		if lastOffset >= 0 {
+			result = lastOffset
+		} else {
+			if strings.HasPrefix(mq.Topic, constant.RETRY_GROUP_TOPIC_PREFIX) {
+				result = 0
+			} else {
+				result = r.mqClient.searchOffset(mq, r.consumerConfig.ConsumeTimestamp)
+			}
+		}
+		break
+	default:
+
+	}
+
+	return result
+}
+
+func (r *rebalance) findConsumerIdList(topic string, groupName string) ([]string, error) {
+	brokerAddr, ok := r.mqClient.findBrokerAddrByTopic(topic)
+	if !ok {
+		err := r.mqClient.updateTopicRouteInfoFromNameServer(topic)
+		if err != nil {
+			glog.Error(err)
+		}
+		brokerAddr, ok = r.mqClient.findBrokerAddrByTopic(topic)
+	}
+
+	if ok {
+		return r.getConsumerIdListByGroup(brokerAddr, groupName, 3000)
+	}
+
+	return nil, errors.New("can't find broker")
+
+}
+
+func (r *rebalance) getConsumerIdListByGroup(addr string, consumerGroup string, timeoutMillis int64) ([]string, error) {
+	requestHeader := new(header.GetConsumerListByGroupRequestHeader)
+	requestHeader.ConsumerGroup = consumerGroup
+
+	request := remoting.NewRemotingCommand(remoting.GET_CONSUMER_LIST_BY_GROUP, requestHeader)
+
+	response, err := r.mqClient.getRemotingClient().InvokeSync(addr, request, timeoutMillis)
+	if err != nil {
+		glog.Error(err)
+		return nil, err
+	}
+	if response.Code == remoting.SUCCESS {
+		getConsumerListByGroupResponseBody := new(header.GetConsumerListByGroupResponseBody)
+		bodyjson := strings.Replace(string(response.Body), "0:", "\"0\":", -1)
+		bodyjson = strings.Replace(bodyjson, "1:", "\"1\":", -1)
+		err := json.Unmarshal([]byte(bodyjson), getConsumerListByGroupResponseBody)
+		if err != nil {
+			glog.Error(err)
+			return nil, err
+		}
+		return getConsumerListByGroupResponseBody.ConsumerIdList, nil
+	}
+	return nil, errors.New("getConsumerIdListByGroup error=" + response.Remark)
+}
diff --git a/rocketmq-go/kernel/rebalance_controller.go b/rocketmq-go/kernel/rebalance_controller.go
new file mode 100644
index 0000000..093f1a0
--- /dev/null
+++ b/rocketmq-go/kernel/rebalance_controller.go
@@ -0,0 +1,35 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+//rebalanceController rebalanceController
+type rebalanceController struct {
+	clientFactory *clientFactory
+}
+
+func newRebalanceController(clientFactory *clientFactory) *rebalanceController {
+	return &rebalanceController{
+		clientFactory: clientFactory,
+	}
+}
+
+func (r *rebalanceController) doRebalance() {
+	for _, consumer := range r.clientFactory.consumerTable {
+		consumer.rebalance.doRebalance()
+	}
+}
diff --git a/rocketmq-go/kernel/tasks.go b/rocketmq-go/kernel/tasks.go
new file mode 100644
index 0000000..d07bbc2
--- /dev/null
+++ b/rocketmq-go/kernel/tasks.go
@@ -0,0 +1,66 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kernel
+
+import (
+	"math/rand"
+	"time"
+)
+
+func (m *MqClientManager) startAllScheduledTask() {
+	rand.Seed(time.Now().UnixNano())
+	go func() {
+		updateTopicRouteTimer := time.NewTimer(5 * time.Second)
+		for {
+			<-updateTopicRouteTimer.C
+			m.updateTopicRouteInfoFromNameServer()
+			updateTopicRouteTimer.Reset(5 * time.Second)
+		}
+	}()
+
+	go func() {
+		heartbeatTimer := time.NewTimer(10 * time.Second)
+		for {
+			<-heartbeatTimer.C
+			m.sendHeartbeatToAllBrokerWithLock()
+			heartbeatTimer.Reset(5 * time.Second)
+		}
+	}()
+
+	go func() {
+		rebalanceTimer := time.NewTimer(15 * time.Second)
+		for {
+			<-rebalanceTimer.C
+			m.rebalanceControllr.doRebalance()
+			rebalanceTimer.Reset(30 * time.Second)
+		}
+	}()
+
+	go func() {
+		timeoutTimer := time.NewTimer(3 * time.Second)
+		for {
+			<-timeoutTimer.C
+			m.mqClient.clearExpireResponse()
+			timeoutTimer.Reset(time.Second)
+		}
+	}()
+	m.pullMessageController.start()
+
+	//cleanExpireMsg
+	m.cleanExpireMsgController.start()
+}
diff --git a/rocketmq-go/model/config/client_config.go b/rocketmq-go/model/config/client_config.go
deleted file mode 100644
index 8a415d8..0000000
--- a/rocketmq-go/model/config/client_config.go
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package config
-
-import (
-	"bytes"
-	"time"
-)
-
-// client common config
-type ClientConfig struct {
-	nameServerAddress string // only this is in use
-
-	clientIP                      string
-	instanceName                  string
-	clientCallbackExecutorThreads int // TODO: clientCallbackExecutorThreads
-	// Pulling topic information interval from the named server
-	pullNameServerInterval time.Duration // default 30
-	// Heartbeat interval in microseconds with message broker
-	heartbeatBrokerInterval time.Duration // default 30
-	// Offset persistent interval for consumer
-	persistConsumerOffsetInterval time.Duration // default 5
-	unitMode                      bool
-	unitName                      string
-	vipChannelEnabled             bool
-}
-
-func NewClientConfig() *ClientConfig {
-	return &ClientConfig{
-		unitMode:                      false,
-		pullNameServerInterval:        time.Second * 30,
-		heartbeatBrokerInterval:       time.Second * 30,
-		persistConsumerOffsetInterval: time.Second * 30,
-	}
-}
-
-func (config *ClientConfig) BuildMQClientId() string {
-	var buffer bytes.Buffer
-	buffer.WriteString(config.clientIP)
-	buffer.WriteString("@")
-	buffer.WriteString(config.instanceName)
-	if config.unitName != "" {
-		buffer.WriteString("@")
-		buffer.WriteString(config.unitName)
-	}
-	return buffer.String()
-}
-
-func (config *ClientConfig) ChangeInstanceNameToPID() {
-	// TODO
-}
-
-func (config *ClientConfig) ResetClientConfig(cfg *ClientConfig) {
-	// TODO
-}
-
-func (config *ClientConfig) CloneClientConfig() *ClientConfig {
-	return &ClientConfig{
-		nameServerAddress:             config.nameServerAddress,
-		clientIP:                      config.clientIP,
-		instanceName:                  config.instanceName,
-		clientCallbackExecutorThreads: config.clientCallbackExecutorThreads,
-		pullNameServerInterval:        config.pullNameServerInterval,
-		heartbeatBrokerInterval:       config.heartbeatBrokerInterval,
-		persistConsumerOffsetInterval: config.persistConsumerOffsetInterval,
-		unitMode:                      config.unitMode,
-		unitName:                      config.unitName,
-		vipChannelEnabled:             config.vipChannelEnabled,
-	}
-}
-
-func (config *ClientConfig) ClientIP() string {
-	return config.clientIP
-}
-
-func (config *ClientConfig) SetClientIP(s string) {
-	config.clientIP = s
-}
-
-func (config *ClientConfig) InstanceName() string {
-	return config.instanceName
-}
-
-func (config *ClientConfig) SetInstanceName(s string) {
-	config.instanceName = s
-}
-
-func (config *ClientConfig) NameServerAddress() string {
-	return config.nameServerAddress
-}
-
-func (config *ClientConfig) SetNameServerAddress(s string) {
-	config.nameServerAddress = s
-}
-
-func (config *ClientConfig) ClientCallbackExecutorThreads() int {
-	return config.clientCallbackExecutorThreads
-}
-
-func (config *ClientConfig) SetClientCallbackExecutorThreads(threads int) {
-	config.clientCallbackExecutorThreads = threads
-}
-
-func (config *ClientConfig) PullNameServerInteval() time.Duration {
-	return config.pullNameServerInterval
-}
-
-func (config *ClientConfig) SetPullNameServerInteval(interval time.Duration) {
-	config.pullNameServerInterval = interval
-}
-
-func (config *ClientConfig) HeartbeatBrokerInterval() time.Duration {
-	return config.heartbeatBrokerInterval
-}
-
-func (config *ClientConfig) SetHeartbeatBrokerInterval(interval time.Duration) {
-	config.heartbeatBrokerInterval = interval
-}
-
-func (config *ClientConfig) PersistConsumerOffsetInterval() time.Duration {
-	return config.persistConsumerOffsetInterval
-}
-
-func (config *ClientConfig) SetPersistConsumerOffsetInterval(interval time.Duration) {
-	config.persistConsumerOffsetInterval = interval
-}
-
-func (config *ClientConfig) UnitName() string {
-	return config.unitName
-}
-
-func (config *ClientConfig) SetUnitName(name string) {
-	config.unitName = name
-}
-
-func (config *ClientConfig) UnitMode() bool {
-	return config.unitMode
-}
-
-func (config *ClientConfig) SetUnitMode(mode bool) {
-	config.unitMode = mode
-}
-
-func (config *ClientConfig) VipChannelEnabled() bool {
-	return config.vipChannelEnabled
-}
-
-func (config *ClientConfig) SetVipChannelEnabled(enable bool) {
-	config.vipChannelEnabled = enable
-}
-
-func (config *ClientConfig) String() string {
-	//TODO
-	return ""
-}
diff --git a/rocketmq-go/model/config/consumer_config.go b/rocketmq-go/model/config/consumer_config.go
deleted file mode 100644
index b6a6f32..0000000
--- a/rocketmq-go/model/config/consumer_config.go
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package config
-
-import "time"
-
-/**
- * Delay some time when exception occur
- */
-const PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION int64 = 3000
-
-/**
- * Flow control interval
- */
-const PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL int64 = 50
-
-//consume from where
-//first consume from the last offset
-const CONSUME_FROM_LAST_OFFSET string = "CONSUME_FROM_LAST_OFFSET"
-
-//first consume from the first offset
-const CONSUME_FROM_FIRST_OFFSET string = "CONSUME_FROM_FIRST_OFFSET"
-
-//first consume from the time
-const CONSUME_FROM_TIMESTAMP string = "CONSUME_FROM_TIMESTAMP"
-
-//consume from where
-
-type RocketMqConsumerConfig struct {
-	ConsumeFromWhere string
-	/**
-	 * Concurrently max span offset.it has no effect on sequential consumption
-	 */
-	ConsumeConcurrentlyMaxSpan int // = 2000;
-	/**
-	 * Flow control threshold
-	 */
-	PullThresholdForQueue int //= 1000;
-	/**
-	 * Message pull Interval
-	 */
-	PullInterval int64 //= 0;
-	/**
-	 * Batch consumption size
-	 */
-	ConsumeMessageBatchMaxSize int //= 1;
-	/**
-	 * Batch pull size
-	 */
-	PullBatchSize int //= 32;
-
-	/**
-	 * Whether update subscription relationship when every pull
-	 */
-	PostSubscriptionWhenPull bool //= false; //get subExpression
-
-	/**
-	 * Whether the unit of subscription group
-	 */
-	UnitMode                      bool  // = false;
-	MaxReconsumeTimes             int   //= 16;
-	SuspendCurrentQueueTimeMillis int64 //= 1000;
-	ConsumeTimeout                int64 //= 15 //minutes
-
-	//=========can not change
-	/**
-	 * Delay some time when exception occur
-	 */
-	PullTimeDelayMillsWhenException int64 //= 3000;
-	/**
-	 * Flow control interval
-	 */
-	PullTimeDelayMillsWhenFlowControl int64 //= 50;
-	/**
-	 * Delay some time when suspend pull service
-	 */
-	PullTimeDelayMillsWhenSuspend    int64 //= 1000;
-	BrokerSuspendMaxTimeMillis       int64 //1000 * 15;
-	ConsumerTimeoutMillisWhenSuspend int64 //= 1000 * 30;
-
-	/**
-	* Backtracking consumption time with second precision.time format is
-	* 20131223171201
-	* Implying Seventeen twelve and 01 seconds on December 23, 2013 year
-	* Default backtracking consumption time Half an hour ago
-	 */
-	ConsumeTimestamp time.Time //when use CONSUME_FROM_TIMESTAMP
-}
-
-func NewRocketMqConsumerConfig() (consumerConfig *RocketMqConsumerConfig) {
-	consumerConfig = &RocketMqConsumerConfig{
-		ConsumeFromWhere:              CONSUME_FROM_LAST_OFFSET,
-		ConsumeConcurrentlyMaxSpan:    2000,
-		PullThresholdForQueue:         1000,
-		PullInterval:                  0,
-		ConsumeMessageBatchMaxSize:    1,
-		PullBatchSize:                 32,
-		PostSubscriptionWhenPull:      false,
-		UnitMode:                      false,
-		MaxReconsumeTimes:             16,
-		SuspendCurrentQueueTimeMillis: 1000,
-		ConsumeTimeout:                15,
-		ConsumeTimestamp:              time.Now().Add(-30 * time.Minute),
-
-		// use custom or constants.don't suggest to change
-		PullTimeDelayMillsWhenException:   PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION,
-		PullTimeDelayMillsWhenFlowControl: PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL,
-		PullTimeDelayMillsWhenSuspend:     1000,
-		BrokerSuspendMaxTimeMillis:        1000 * 15,
-		ConsumerTimeoutMillisWhenSuspend:  1000 * 30,
-	}
-	return
-}
diff --git a/rocketmq-go/model/config/producer_config.go b/rocketmq-go/model/config/producer_config.go
deleted file mode 100644
index 3bf4844..0000000
--- a/rocketmq-go/model/config/producer_config.go
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package config
-
-type RocketMqProducerConfig struct {
-	SendMsgTimeout int64 //done
-	//private int sendMsgTimeout = 3000;
-	CompressMsgBodyOverHowMuch int //done
-	//private int compressMsgBodyOverHowmuch = 1024 * 4;
-	ZipCompressLevel int //done
-	//private int zipCompressLevel = Integer.parseInt(System.getProperty(MixAll.MESSAGE_COMPRESS_LEVEL, "5"));
-	/**
-	 * Just for testing or demo program
-	 */
-	//	private String createTopicKey = MixAll.DEFAULT_TOPIC;
-
-	//DefaultTopicQueueNums            int
-	////private volatile int defaultTopicQueueNums = 4;
-
-	RetryTimesWhenSendFailed int
-	//private int retryTimesWhenSendFailed = 2;
-	RetryTimesWhenSendAsyncFailed int
-	//private int retryTimesWhenSendAsyncFailed = 2;
-	//
-	RetryAnotherBrokerWhenNotStoreOK bool
-	//private boolean retryAnotherBrokerWhenNotStoreOK = false;
-	MaxMessageSize int
-	//private int maxMessageSize = 1024 * 1024 * 4; // 4M
-
-	//for MQFaultStrategy todo to be done
-	SendLatencyFaultEnable bool    //false
-	LatencyMax             []int64 //=             {50L,   100L,   550L,       1000L,  2000L,      3000L,      15000L};
-	NotAvailableDuration   []int64 //   {0L,    0L,     30000L,     60000L, 120000L,    180000L,    600000L};
-}
-
-//set defaultValue
-func NewProducerConfig() (producerConfig *RocketMqProducerConfig) {
-	producerConfig = &RocketMqProducerConfig{
-		SendMsgTimeout:             3000,
-		CompressMsgBodyOverHowMuch: 1024 * 4,
-		ZipCompressLevel:           5,
-		MaxMessageSize:             1024 * 1024 * 4, // 4M
-
-		RetryTimesWhenSendFailed:         2,
-		RetryTimesWhenSendAsyncFailed:    2, //
-		RetryAnotherBrokerWhenNotStoreOK: false,
-		SendLatencyFaultEnable:           false,
-		LatencyMax:                       []int64{50, 100, 550, 1000, 2000, 3000, 15000},
-		NotAvailableDuration:             []int64{0, 0, 30000, 60000, 120000, 180000, 600000},
-	}
-	return
-}
diff --git a/rocketmq-go/model/constant/config.go b/rocketmq-go/model/constant/config.go
index 5f7f5db..4ba2285 100644
--- a/rocketmq-go/model/constant/config.go
+++ b/rocketmq-go/model/constant/config.go
@@ -1,29 +1,27 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
-//-------SerializeType-------
-var JSON_SERIALIZE byte = 0
-var ROCKETMQ_SERIALIZE byte = 1
-
-//-------SerializeType-------
-
-var USE_HEADER_SERIALIZETYPE = JSON_SERIALIZE
-
+//REMOTING_COMMAND_FLAG  0, REQUEST_COMMAND
 var REMOTING_COMMAND_FLAG = 0
+
+//REMOTING_COMMAND_LANGUAGE org.apache.rocketmq.remoting.protocol.LanguageCode
 var REMOTING_COMMAND_LANGUAGE = "OTHER"
+
+//REMOTING_COMMAND_VERSION org.apache.rocketmq.common.MQVersion.Version.ordinal()
 var REMOTING_COMMAND_VERSION int16 = 213
diff --git a/rocketmq-go/model/constant/message_const.go b/rocketmq-go/model/constant/message_const.go
index 402d328..cff8f08 100644
--- a/rocketmq-go/model/constant/message_const.go
+++ b/rocketmq-go/model/constant/message_const.go
@@ -1,45 +1,70 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
 const (
-	PROPERTY_KEYS                          = "KEYS"
-	PROPERTY_TAGS                          = "TAGS"
-	PROPERTY_WAIT_STORE_MSG_OK             = "WAIT"
-	PROPERTY_DELAY_TIME_LEVEL              = "DELAY"
-	PROPERTY_RETRY_TOPIC                   = "RETRY_TOPIC"
-	PROPERTY_REAL_TOPIC                    = "REAL_TOPIC"
-	PROPERTY_REAL_QUEUE_ID                 = "REAL_QID"
-	PROPERTY_TRANSACTION_PREPARED          = "TRAN_MSG"
-	PROPERTY_PRODUCER_GROUP                = "PGROUP"
-	PROPERTY_MIN_OFFSET                    = "MIN_OFFSET"
-	PROPERTY_MAX_OFFSET                    = "MAX_OFFSET"
-	PROPERTY_BUYER_ID                      = "BUYER_ID"
-	PROPERTY_ORIGIN_MESSAGE_ID             = "ORIGIN_MESSAGE_ID"
-	PROPERTY_TRANSFER_FLAG                 = "TRANSFER_FLAG"
-	PROPERTY_CORRECTION_FLAG               = "CORRECTION_FLAG"
-	PROPERTY_MQ2_FLAG                      = "MQ2_FLAG"
-	PROPERTY_RECONSUME_TIME                = "RECONSUME_TIME"
-	PROPERTY_MSG_REGION                    = "MSG_REGION"
+	//PROPERTY_KEYS property keys in MessageImpl.properties
+	PROPERTY_KEYS = "KEYS"
+	//PROPERTY_TAGS message tags
+	PROPERTY_TAGS = "TAGS"
+	//PROPERTY_WAIT_STORE_MSG_OK             PROPERTY_WAIT_STORE_MSG_OK
+	PROPERTY_WAIT_STORE_MSG_OK = "WAIT"
+	//PROPERTY_DELAY_TIME_LEVEL              PROPERTY_DELAY_TIME_LEVEL
+	PROPERTY_DELAY_TIME_LEVEL = "DELAY"
+	//PROPERTY_RETRY_TOPIC                   PROPERTY_RETRY_TOPIC
+	PROPERTY_RETRY_TOPIC = "RETRY_TOPIC"
+	//PROPERTY_REAL_TOPIC                    PROPERTY_REAL_TOPIC
+	PROPERTY_REAL_TOPIC = "REAL_TOPIC"
+	//PROPERTY_REAL_QUEUE_ID                 PROPERTY_REAL_QUEUE_ID
+	PROPERTY_REAL_QUEUE_ID = "REAL_QID"
+	//PROPERTY_TRANSACTION_PREPARED          PROPERTY_TRANSACTION_PREPARED
+	PROPERTY_TRANSACTION_PREPARED = "TRAN_MSG"
+	//PROPERTY_PRODUCER_GROUP                PROPERTY_PRODUCER_GROUP
+	PROPERTY_PRODUCER_GROUP = "PGROUP"
+	//PROPERTY_MIN_OFFSET                    PROPERTY_MIN_OFFSET
+	PROPERTY_MIN_OFFSET = "MIN_OFFSET"
+	//PROPERTY_MAX_OFFSET                    PROPERTY_MAX_OFFSET
+	PROPERTY_MAX_OFFSET = "MAX_OFFSET"
+	//PROPERTY_BUYER_ID                      PROPERTY_BUYER_ID
+	PROPERTY_BUYER_ID = "BUYER_ID"
+	//PROPERTY_ORIGIN_MESSAGE_ID             PROPERTY_ORIGIN_MESSAGE_ID
+	PROPERTY_ORIGIN_MESSAGE_ID = "ORIGIN_MESSAGE_ID"
+	//PROPERTY_TRANSFER_FLAG                 PROPERTY_TRANSFER_FLAG
+	PROPERTY_TRANSFER_FLAG = "TRANSFER_FLAG"
+	//PROPERTY_CORRECTION_FLAG               PROPERTY_CORRECTION_FLAG
+	PROPERTY_CORRECTION_FLAG = "CORRECTION_FLAG"
+	//PROPERTY_MQ2_FLAG                      PROPERTY_MQ2_FLAG
+	PROPERTY_MQ2_FLAG = "MQ2_FLAG"
+	//PROPERTY_RECONSUME_TIME                PROPERTY_RECONSUME_TIME
+	PROPERTY_RECONSUME_TIME = "RECONSUME_TIME"
+	//PROPERTY_MSG_REGION                    PROPERTY_MSG_REGION
+	PROPERTY_MSG_REGION = "MSG_REGION"
+	//PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX
 	PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX = "UNIQ_KEY"
-	PROPERTY_MAX_RECONSUME_TIMES           = "MAX_RECONSUME_TIMES"
-	PROPERTY_CONSUME_START_TIMESTAMP       = "CONSUME_START_TIME"
+	//PROPERTY_MAX_RECONSUME_TIMES           PROPERTY_MAX_RECONSUME_TIMES
+	PROPERTY_MAX_RECONSUME_TIMES = "MAX_RECONSUME_TIMES"
+	//PROPERTY_CONSUME_START_TIMESTAMP PROPERTY_CONSUME_START_TIMESTAMP
+	PROPERTY_CONSUME_START_TIMESTAMP = "CONSUME_START_TIME"
 
-	COMMUNICATIONMODE_SYNC   = "SYNC"
-	COMMUNICATIONMODE_ASYNC  = "ASYNC"
+	//COMMUNICATIONMODE_SYNC   COMMUNICATIONMODE_SYNC
+	COMMUNICATIONMODE_SYNC = "SYNC"
+	//COMMUNICATIONMODE_ASYNC  COMMUNICATIONMODE_ASYNC
+	COMMUNICATIONMODE_ASYNC = "ASYNC"
+	//COMMUNICATIONMODE_ONEWAY COMMUNICATIONMODE_ONEWAY
 	COMMUNICATIONMODE_ONEWAY = "ONEWAY"
 )
diff --git a/rocketmq-go/model/constant/message_sys_flag.go b/rocketmq-go/model/constant/message_sys_flag.go
index a53c4fd..ac6297b 100644
--- a/rocketmq-go/model/constant/message_sys_flag.go
+++ b/rocketmq-go/model/constant/message_sys_flag.go
@@ -1,26 +1,28 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
 const (
-	CompressedFlag          int32 = (0x1 << 0)
-	MultiTagsFlag           int32 = (0x1 << 1)
-	TransactionNotType      int32 = (0x0 << 2)
-	TransactionPreparedType int32 = (0x1 << 2)
-	TransactionCommitType   int32 = (0x2 << 2)
-	TransactionRollbackType int32 = (0x3 << 2)
+	//CompressedFlag  message compressed flag
+	CompressedFlag int32 = (0x1 << 0)
+	//MultiTagsFlag           int32 = (0x1 << 1)
+	//TransactionNotType      int32 = (0x0 << 2)
+	//TransactionPreparedType int32 = (0x1 << 2)
+	//TransactionCommitType   int32 = (0x2 << 2)
+	//TransactionRollbackType int32 = (0x3 << 2)
 )
diff --git a/rocketmq-go/model/constant/mix_all.go b/rocketmq-go/model/constant/mix_all.go
index 2c8f0a7..3286fe2 100644
--- a/rocketmq-go/model/constant/mix_all.go
+++ b/rocketmq-go/model/constant/mix_all.go
@@ -1,59 +1,46 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
 const (
-	ROCKETMQ_HOME_ENV      = "ROCKETMQ_HOME"
-	ROCKETMQ_HOME_PROPERTY = "rocketmq.home.dir"
-	NAMESRV_ADDR_ENV       = "NAMESRV_ADDR"
-	NAMESRV_ADDR_PROPERTY  = "rocketmq.namesrv.addr"
+	//MESSAGE_COMPRESS_LEVEL      MESSAGE_COMPRESS_LEVEL
 	MESSAGE_COMPRESS_LEVEL = "rocketmq.message.compressLevel"
-	//WS_DOMAIN_NAME = System.getProperty("rocketmq.namesrv.domain", "jmenv.tbsite.net")
-	//WS_DOMAIN_SUBGROUP = System.getProperty("rocketmq.namesrv.domain.subgroup", "nsaddr")
-	// http://jmenv.tbsite.net:8080/rocketmq/nsaddr
-	//WS_ADDR = "http://" + WS_DOMAIN_NAME + ":8080/rocketmq/" + WS_DOMAIN_SUBGROUP
-	DEFAULT_TOPIC               = "TBW102"
-	BENCHMARK_TOPIC             = "BenchmarkTest"
-	DEFAULT_PRODUCER_GROUP      = "DEFAULT_PRODUCER"
-	DEFAULT_CONSUMER_GROUP      = "DEFAULT_CONSUMER"
-	TOOLS_CONSUMER_GROUP        = "TOOLS_CONSUMER"
-	FILTERSRV_CONSUMER_GROUP    = "FILTERSRV_CONSUMER"
-	MONITOR_CONSUMER_GROUP      = "__MONITOR_CONSUMER"
+	//DEFAULT_TOPIC               DEFAULT_TOPIC
+	DEFAULT_TOPIC = "TBW102"
+	//CLIENT_INNER_PRODUCER_GROUP CLIENT_INNER_PRODUCER_GROUP
 	CLIENT_INNER_PRODUCER_GROUP = "CLIENT_INNER_PRODUCER"
-	SELF_TEST_PRODUCER_GROUP    = "SELF_TEST_P_GROUP"
-	SELF_TEST_CONSUMER_GROUP    = "SELF_TEST_C_GROUP"
-	SELF_TEST_TOPIC             = "SELF_TEST_TOPIC"
-	OFFSET_MOVED_EVENT          = "OFFSET_MOVED_EVENT"
-	ONS_HTTP_PROXY_GROUP        = "CID_ONS-HTTP-PROXY"
-	CID_ONSAPI_PERMISSION_GROUP = "CID_ONSAPI_PERMISSION"
-	CID_ONSAPI_OWNER_GROUP      = "CID_ONSAPI_OWNER"
-	CID_ONSAPI_PULL_GROUP       = "CID_ONSAPI_PULL"
-	CID_RMQ_SYS_PREFIX          = "CID_RMQ_SYS_"
 
+	//MASTER_ID MASTER_ID
 	MASTER_ID int64 = 0
+	//CURRENT_JVM_PID CURRENT_JVM_PID
 	CURRENT_JVM_PID
-
+	//RETRY_GROUP_TOPIC_PREFIX RETRY_GROUP_TOPIC_PREFIX
 	RETRY_GROUP_TOPIC_PREFIX = "%RETRY%"
-
-	DLQ_GROUP_TOPIC_PREFIX     = "%DLQ%"
-	SYSTEM_TOPIC_PREFIX        = "rmq_sys_"
-	UNIQUE_MSG_QUERY_FLAG      = "_UNIQUE_KEY_QUERY"
-	MAX_MESSAGE_BODY_SIZE  int = 4 * 1024 * 1024 //4m
-	MAX_MESSAGE_TOPIC_SIZE int = 255             //255char
-
+	//DLQ_GROUP_TOPIC_PREFIX     DLQ_GROUP_TOPIC_PREFIX
+	DLQ_GROUP_TOPIC_PREFIX = "%DLQ%"
+	//SYSTEM_TOPIC_PREFIX        SYSTEM_TOPIC_PREFIX
+	SYSTEM_TOPIC_PREFIX = "rmq_sys_"
+	//UNIQUE_MSG_QUERY_FLAG      UNIQUE_MSG_QUERY_FLAG
+	UNIQUE_MSG_QUERY_FLAG = "_UNIQUE_KEY_QUERY"
+	//MAX_MESSAGE_BODY_SIZE  MAX_MESSAGE_BODY_SIZE
+	MAX_MESSAGE_BODY_SIZE int = 4 * 1024 * 1024 //4m
+	//MAX_MESSAGE_TOPIC_SIZE MAX_MESSAGE_TOPIC_SIZE
+	MAX_MESSAGE_TOPIC_SIZE int = 255 //255char
+	//DEFAULT_TOPIC_QUEUE_NUMS DEFAULT_TOPIC_QUEUE_NUMS
 	DEFAULT_TOPIC_QUEUE_NUMS int32 = 4
 )
diff --git a/rocketmq-go/model/constant/perm.go b/rocketmq-go/model/constant/perm.go
index 962d989..aa7835a 100644
--- a/rocketmq-go/model/constant/perm.go
+++ b/rocketmq-go/model/constant/perm.go
@@ -1,33 +1,43 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
 const (
+	//PERM_PRIORITY PERM_PRIORITY
 	PERM_PRIORITY = 0x1 << 3
-	PERM_READ     = 0x1 << 2
-	PERM_WRITE    = 0x1 << 1
-	PERM_INHERIT  = 0x1 << 0
+
+	//PERM_READ this queue can read
+	PERM_READ = 0x1 << 2
+	//PERM_WRITE this queue can write
+	PERM_WRITE = 0x1 << 1
+
+	//PERM_INHERIT PERM_INHERIT
+	PERM_INHERIT = 0x1 << 0
 )
 
+//WriteAble this queue can write
 func WriteAble(perm int32) (ret bool) {
-	ret = ((perm & PERM_WRITE) == PERM_WRITE)
+	ret = (perm & PERM_WRITE) == PERM_WRITE
 	return
 }
+
+//ReadAble this queue can read
 func ReadAble(perm int32) (ret bool) {
-	ret = ((perm & PERM_READ) == PERM_READ)
+	ret = (perm & PERM_READ) == PERM_READ
 	return
 }
diff --git a/rocketmq-go/model/constant/pull_sys_flag.go b/rocketmq-go/model/constant/pull_sys_flag.go
index 0a2921c..d6f1e3f 100644
--- a/rocketmq-go/model/constant/pull_sys_flag.go
+++ b/rocketmq-go/model/constant/pull_sys_flag.go
@@ -1,24 +1,29 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package constant
 
 const (
+	//FLAG_COMMIT_OFFSET FLAG_COMMIT_OFFSET
 	FLAG_COMMIT_OFFSET int32 = 0x1 << 0
-	FLAG_SUSPEND       int32 = 0x1 << 1
-	FLAG_SUBSCRIPTION  int32 = 0x1 << 2
-	FLAG_CLASS_FILTER  int32 = 0x1 << 3
+	//FLAG_SUSPEND FLAG_SUSPEND
+	FLAG_SUSPEND int32 = 0x1 << 1
+	//FLAG_SUBSCRIPTION FLAG_SUBSCRIPTION
+	FLAG_SUBSCRIPTION int32 = 0x1 << 2
+	//FLAG_CLASS_FILTER FLAG_CLASS_FILTER
+	FLAG_CLASS_FILTER int32 = 0x1 << 3
 )
diff --git a/rocketmq-go/model/consume_concurrently_result.go b/rocketmq-go/model/consume_concurrently_result.go
deleted file mode 100644
index 6e4df7b..0000000
--- a/rocketmq-go/model/consume_concurrently_result.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-const (
-	CONSUME_SUCCESS = "CONSUME_SUCCESS"
-	RECONSUME_LATER = "RECONSUME_LATER"
-)
-
-type ConsumeConcurrentlyResult struct {
-	ConsumeConcurrentlyStatus string
-	AckIndex                  int
-}
diff --git a/rocketmq-go/model/consume_message_directly_result.go b/rocketmq-go/model/consume_message_directly_result.go
index a9af32e..52500b8 100644
--- a/rocketmq-go/model/consume_message_directly_result.go
+++ b/rocketmq-go/model/consume_message_directly_result.go
@@ -1,31 +1,42 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
+//ConsumeResultType message consume result type
+type ConsumeResultType string
+
+const (
+	//CR_SUCCESS consume success
+	CR_SUCCESS ConsumeResultType = "CR_SUCCESS"
+
+	//CR_THROW_EXCEPTION consume error
+	CR_THROW_EXCEPTION ConsumeResultType = "CR_THROW_EXCEPTION"
+	//CR_RETURN_NULL     ConsumeResultType = "CR_RETURN_NULL"
+	//CR_LATER           ConsumeResultType = "CR_LATER"
+	//CR_ROLLBACK        ConsumeResultType = "CR_ROLLBACK"
+	//CR_COMMIT          ConsumeResultType = "CR_COMMIT"
+)
+
+//ConsumeMessageDirectlyResult consume message directly's result
 type ConsumeMessageDirectlyResult struct {
-	Order      bool `json:"order"`
-	AutoCommit bool `json:"autoCommit"`
-	//CR_SUCCESS,
-	//CR_LATER,
-	//CR_ROLLBACK,
-	//CR_COMMIT,
-	//CR_THROW_EXCEPTION,
-	//CR_RETURN_NULL,
-	ConsumeResult  string `json:"consumeResult"`
-	Remark         string `json:"remark"`
-	SpentTimeMills int64  `json:"spentTimeMills"`
+	Order          bool              `json:"order"`
+	AutoCommit     bool              `json:"autoCommit"`
+	ConsumeResult  ConsumeResultType `json:"consumeResult"`
+	Remark         string            `json:"remark"`
+	SpentTimeMills int64             `json:"spentTimeMills"`
 }
diff --git a/rocketmq-go/model/consumer_running_info.go b/rocketmq-go/model/consumer_running_info.go
index 80c39ae..dc79d0f 100644
--- a/rocketmq-go/model/consumer_running_info.go
+++ b/rocketmq-go/model/consumer_running_info.go
@@ -1,43 +1,41 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
-import "encoding/json"
+import (
+	"encoding/json"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+)
 
+//ConsumerRunningInfo this client's consumer running info
 type ConsumerRunningInfo struct {
-	Properties map[string]string                 `json:"properties"`
-	MqTable    map[MessageQueue]ProcessQueueInfo `json:"mqTable"`
-	// todo
-	//private TreeSet<SubscriptionData> subscriptionSet = new TreeSet<SubscriptionData>();
-	//
-	//private TreeMap<MessageQueue, ProcessQueueInfo> mqTable = new TreeMap<MessageQueue, ProcessQueueInfo>();
-	//
-	//private TreeMap<String/* Topic */, ConsumeStatus> statusTable = new TreeMap<String, ConsumeStatus>();
-	//
-	//private String jstack;
+	Properties map[string]string                           `json:"properties"`
+	MqTable    map[rocketmqm.MessageQueue]ProcessQueueInfo `json:"mqTable"`
 }
 
-func (self *ConsumerRunningInfo) Encode() (jsonByte []byte, err error) {
+//Encode ConsumerRunningInfo to byte array
+func (c *ConsumerRunningInfo) Encode() (jsonByte []byte, err error) {
 	mqTableJsonStr := "{"
 	first := true
 	var keyJson []byte
 	var valueJson []byte
 
-	for key, value := range self.MqTable {
+	for key, value := range c.MqTable {
 		keyJson, err = json.Marshal(key)
 		if err != nil {
 			return
@@ -54,14 +52,14 @@
 	}
 	mqTableJsonStr = mqTableJsonStr + "}"
 	var propertiesJson []byte
-	propertiesJson, err = json.Marshal(self.Properties)
+	propertiesJson, err = json.Marshal(c.Properties)
 	if err != nil {
 		return
 	}
-	jsonByte = self.formatEncode("\"properties\"", string(propertiesJson), "\"mqTable\"", string(mqTableJsonStr))
+	jsonByte = c.formatEncode("\"properties\"", string(propertiesJson), "\"mqTable\"", string(mqTableJsonStr))
 	return
 }
-func (self *ConsumerRunningInfo) formatEncode(kVList ...string) []byte {
+func (c *ConsumerRunningInfo) formatEncode(kVList ...string) []byte {
 	jsonStr := "{"
 	first := true
 	for i := 0; i+1 < len(kVList); i += 2 {
diff --git a/rocketmq-go/model/header/consume_message_directly_result_request_header.go b/rocketmq-go/model/header/consume_message_directly_result_request_header.go
deleted file mode 100644
index a593d51..0000000
--- a/rocketmq-go/model/header/consume_message_directly_result_request_header.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type ConsumeMessageDirectlyResultRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-	ClientId      string `json:"clientId"`
-	MsgId         string `json:"msgId"`
-	BrokerName    string `json:"brokerName"`
-}
-
-func (self *ConsumeMessageDirectlyResultRequestHeader) FromMap(headerMap map[string]interface{}) {
-	self.ConsumerGroup = headerMap["consumerGroup"].(string)
-	self.ClientId = headerMap["clientId"].(string)
-	self.MsgId = headerMap["msgId"].(string)
-	self.BrokerName = headerMap["brokerName"].(string)
-	return
-}
diff --git a/rocketmq-go/model/header/consumer_send_msg_back_request_header.go b/rocketmq-go/model/header/consumer_send_msg_back_request_header.go
deleted file mode 100644
index 4e101c6..0000000
--- a/rocketmq-go/model/header/consumer_send_msg_back_request_header.go
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type ConsumerSendMsgBackRequestHeader struct {
-	Offset            int64
-	Group             string
-	DelayLevel        int32
-	OriginMsgId       string
-	OriginTopic       string
-	UnitMode          bool
-	MaxReconsumeTimes int32
-}
-
-func (self *ConsumerSendMsgBackRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/get_consumer_list_by_group.go b/rocketmq-go/model/header/get_consumer_list_by_group.go
deleted file mode 100644
index e06e1fa..0000000
--- a/rocketmq-go/model/header/get_consumer_list_by_group.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type GetConsumerListByGroupRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-}
-
-func (self *GetConsumerListByGroupRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
-
-type GetConsumerListByGroupResponseBody struct {
-	ConsumerIdList []string
-}
-
-func (self *GetConsumerListByGroupResponseBody) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/get_consumer_running_info_request_header.go b/rocketmq-go/model/header/get_consumer_running_info_request_header.go
deleted file mode 100644
index 5e7487f..0000000
--- a/rocketmq-go/model/header/get_consumer_running_info_request_header.go
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type GetConsumerRunningInfoRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-	ClientId      string `json:"clientId"`
-	JstackEnable  bool   `json:"jstackEnable"`
-}
-
-func (self *GetConsumerRunningInfoRequestHeader) FromMap(headerMap map[string]interface{}) {
-	self.ConsumerGroup = headerMap["consumerGroup"].(string)
-	self.ClientId = headerMap["clientId"].(string)
-	return
-}
diff --git a/rocketmq-go/model/header/get_max_offset_request_header.go b/rocketmq-go/model/header/get_max_offset_request_header.go
deleted file mode 100644
index 6d4723e..0000000
--- a/rocketmq-go/model/header/get_max_offset_request_header.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type GetMaxOffsetRequestHeader struct {
-	Topic   string `json:"topic"`
-	QueueId int32  `json:"queueId"`
-}
-
-func (self *GetMaxOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/get_max_offset_response_header.go b/rocketmq-go/model/header/get_max_offset_response_header.go
deleted file mode 100644
index eea6c2c..0000000
--- a/rocketmq-go/model/header/get_max_offset_response_header.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-
-type QueryOffsetResponseHeader struct {
-	Offset int64 `json:"offset"`
-}
-
-func (self *QueryOffsetResponseHeader) FromMap(headerMap map[string]interface{}) {
-	self.Offset = util.StrToInt64WithDefaultValue(headerMap["offset"].(string), -1)
-	return
-}
diff --git a/rocketmq-go/model/header/get_route_info_request_header.go b/rocketmq-go/model/header/get_route_info_request_header.go
deleted file mode 100644
index 7c33c25..0000000
--- a/rocketmq-go/model/header/get_route_info_request_header.go
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type GetRouteInfoRequestHeader struct {
-	Topic string `json:"topic"`
-}
-
-func (self *GetRouteInfoRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/pull_message_request_header.go b/rocketmq-go/model/header/pull_message_request_header.go
deleted file mode 100644
index f341b49..0000000
--- a/rocketmq-go/model/header/pull_message_request_header.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type PullMessageRequestHeader struct {
-	ConsumerGroup        string `json:"consumerGroup"`
-	Topic                string `json:"topic"`
-	QueueId              int32  `json:"queueId"`
-	QueueOffset          int64  `json:"queueOffset"`
-	MaxMsgNums           int32  `json:"maxMsgNums"`
-	SysFlag              int32  `json:"sysFlag"`
-	CommitOffset         int64  `json:"commitOffset"`
-	SuspendTimeoutMillis int64  `json:"suspendTimeoutMillis"`
-	Subscription         string `json:"subscription"`
-	SubVersion           int64  `json:"subVersion"`
-}
-
-func (self *PullMessageRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/query_consumer_offset_request_header.go b/rocketmq-go/model/header/query_consumer_offset_request_header.go
deleted file mode 100644
index ed455e7..0000000
--- a/rocketmq-go/model/header/query_consumer_offset_request_header.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type QueryConsumerOffsetRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-	Topic         string `json:"topic"`
-	QueueId       int32  `json:"queueId"`
-}
-
-func (self *QueryConsumerOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/reset_offset_request_header.go b/rocketmq-go/model/header/reset_offset_request_header.go
deleted file mode 100644
index 642b600..0000000
--- a/rocketmq-go/model/header/reset_offset_request_header.go
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"strconv"
-)
-
-type ResetOffsetRequestHeader struct {
-	Topic     string `json:"topic"`
-	Group     string `json:"group"`
-	Timestamp int64  `json:"timestamp"`
-	IsForce   bool   `json:"isForce"`
-}
-
-func (self *ResetOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
-	self.Group = headerMap["group"].(string)
-	self.Topic = headerMap["topic"].(string)
-	self.Timestamp = util.StrToInt64WithDefaultValue(headerMap["timestamp"].(string), -1)
-	self.IsForce, _ = strconv.ParseBool(headerMap["isForce"].(string))
-	return
-}
diff --git a/rocketmq-go/model/header/search_offset_request_header.go b/rocketmq-go/model/header/search_offset_request_header.go
deleted file mode 100644
index 5088eac..0000000
--- a/rocketmq-go/model/header/search_offset_request_header.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-import ()
-import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-
-type SearchOffsetRequestHeader struct {
-	Topic     string `json:"topic"`
-	QueueId   int32  `json:"queueId"`
-	Timestamp int64  `json:"timestamp"`
-}
-
-func (self *SearchOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
-	self.Topic = headerMap["topic"].(string)
-	self.Topic = headerMap["queueId"].(string)
-	self.Timestamp = util.StrToInt64WithDefaultValue(headerMap["timestamp"].(string), -1)
-	return
-}
diff --git a/rocketmq-go/model/header/send_message_request_header.go b/rocketmq-go/model/header/send_message_request_header.go
deleted file mode 100644
index 80f17cc..0000000
--- a/rocketmq-go/model/header/send_message_request_header.go
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type SendMessageRequestHeader struct {
-	ProducerGroup         string `json:"producerGroup"`
-	Topic                 string `json:"topic"`
-	DefaultTopic          string `json:"defaultTopic"`
-	DefaultTopicQueueNums int    `json:"defaultTopicQueueNums"`
-	QueueId               int32  `json:"queueId"`
-	SysFlag               int    `json:"sysFlag"`
-	BornTimestamp         int64  `json:"bornTimestamp"`
-	Flag                  int    `json:"flag"`
-	Properties            string `json:"properties"`
-	ReconsumeTimes        int    `json:"reconsumeTimes"`
-	UnitMode              bool   `json:"unitMode"`
-	MaxReconsumeTimes     int    `json:"maxReconsumeTimes"`
-}
-
-func (self *SendMessageRequestHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/send_message_response_header.go b/rocketmq-go/model/header/send_message_response_header.go
deleted file mode 100644
index 9ddacb2..0000000
--- a/rocketmq-go/model/header/send_message_response_header.go
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-type SendMessageResponseHeader struct {
-	MsgId         string
-	QueueId       int32
-	QueueOffset   int64
-	TransactionId string
-	MsgRegion     string
-}
-
-func (header *SendMessageResponseHeader) FromMap(headerMap map[string]interface{}) {
-	return
-}
diff --git a/rocketmq-go/model/header/update_consumer_offset_request_header.go b/rocketmq-go/model/header/update_consumer_offset_request_header.go
deleted file mode 100644
index 42612db..0000000
--- a/rocketmq-go/model/header/update_consumer_offset_request_header.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package header
-
-import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-
-type UpdateConsumerOffsetRequestHeader struct {
-	ConsumerGroup string `json:"consumerGroup"`
-	Topic         string `json:"topic"`
-	QueueId       int32  `json:"queueId"`
-	CommitOffset  int64  `json:"commitOffset"`
-}
-
-func (self *UpdateConsumerOffsetRequestHeader) FromMap(headerMap map[string]interface{}) {
-	self.ConsumerGroup = headerMap["consumerGroup"].(string)
-	self.QueueId = util.StrToInt32WithDefaultValue(util.ReadString(headerMap["queueId"]), 0)
-	self.CommitOffset = util.StrToInt64WithDefaultValue(headerMap["commitOffset"].(string), -1)
-	self.Topic = util.ReadString(headerMap["topic"])
-	return
-}
diff --git a/rocketmq-go/model/heart_beat.go b/rocketmq-go/model/heart_beat.go
index fc5eded..17e3e27 100644
--- a/rocketmq-go/model/heart_beat.go
+++ b/rocketmq-go/model/heart_beat.go
@@ -1,32 +1,40 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+//ConsumerData this client's ConsumerData
 type ConsumerData struct {
 	GroupName           string
 	ConsumeType         string
 	MessageModel        string
-	ConsumeFromWhere    string
+	ConsumeFromWhere    rocketmqm.ConsumeFromWhere
 	SubscriptionDataSet []*SubscriptionData
 	UnitMode            bool
 }
+
+//ProducerData producer data
 type ProducerData struct {
 	GroupName string
 }
+
+//HeartbeatData heartbeat data
 type HeartbeatData struct {
 	ClientId        string
 	ConsumerDataSet []*ConsumerData
diff --git a/rocketmq-go/model/message.go b/rocketmq-go/model/message.go
deleted file mode 100644
index 0cb3d97..0000000
--- a/rocketmq-go/model/message.go
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"strconv"
-	"strings"
-)
-
-type Message struct {
-	Topic      string
-	Flag       int
-	Properties map[string]string
-	Body       []byte
-}
-
-func (self *Message) SetTag(tag string) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_TAGS] = tag
-}
-func (self *Message) GetTag() (tag string) {
-	if self.Properties != nil {
-		tag = self.Properties[constant.PROPERTY_TAGS]
-	}
-	return
-}
-
-func (self *Message) SetKeys(keys []string) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_KEYS] = strings.Join(keys, KEY_SEPARATOR)
-}
-
-func (self *Message) SetDelayTimeLevel(delayTimeLevel int) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_DELAY_TIME_LEVEL] = util.IntToString(delayTimeLevel)
-}
-func (self *Message) SetWaitStoreMsgOK(waitStoreMsgOK bool) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_WAIT_STORE_MSG_OK] = strconv.FormatBool(waitStoreMsgOK)
-}
-func (self *Message) GeneratorMsgUniqueKey() {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	if len(self.Properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX]) > 0 {
-		return
-	}
-	self.Properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX] = util.GeneratorMessageClientId()
-}
-
-func (self *MessageExt) GetMsgUniqueKey() string {
-	if self.Properties != nil {
-		originMessageId := self.Properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX]
-		if len(originMessageId) > 0 {
-			return originMessageId
-		}
-	}
-	return self.MsgId
-}
-
-func (self *Message) SetOriginMessageId(messageId string) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_ORIGIN_MESSAGE_ID] = messageId
-}
-
-func (self *Message) SetRetryTopic(retryTopic string) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_RETRY_TOPIC] = retryTopic
-}
-func (self *Message) SetReconsumeTime(reConsumeTime int) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_RECONSUME_TIME] = util.IntToString(reConsumeTime)
-}
-
-func (self *Message) GetReconsumeTimes() (reConsumeTime int) {
-	reConsumeTime = 0
-	if self.Properties != nil {
-		reConsumeTimeStr := self.Properties[constant.PROPERTY_RECONSUME_TIME]
-		if len(reConsumeTimeStr) > 0 {
-			reConsumeTime = util.StrToIntWithDefaultValue(reConsumeTimeStr, 0)
-		}
-	}
-	return
-}
-
-func (self *Message) SetMaxReconsumeTimes(maxConsumeTime int) {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	self.Properties[constant.PROPERTY_MAX_RECONSUME_TIMES] = util.IntToString(maxConsumeTime)
-}
-
-func (self *Message) GetMaxReconsumeTimes() (maxConsumeTime int) {
-	maxConsumeTime = 0
-	if self.Properties != nil {
-		reConsumeTimeStr := self.Properties[constant.PROPERTY_MAX_RECONSUME_TIMES]
-		if len(reConsumeTimeStr) > 0 {
-			maxConsumeTime = util.StrToIntWithDefaultValue(reConsumeTimeStr, 0)
-		}
-	}
-	return
-}
-
-var KEY_SEPARATOR string = " "
diff --git a/rocketmq-go/model/message/message.go b/rocketmq-go/model/message/message.go
deleted file mode 100644
index 1dcd365..0000000
--- a/rocketmq-go/model/message/message.go
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package message
-
-import (
-	"bytes"
-	"compress/zlib"
-	"encoding/binary"
-	"encoding/json"
-	"fmt"
-	"github.com/golang/glog"
-	"io/ioutil"
-)
-
-const (
-	CompressedFlag          = 1 << 0
-	MultiTagsFlag           = 1 << 1
-	TransactionNotType      = 0 << 2
-	TransactionPreparedType = 1 << 2
-	TransactionCommitType   = 2 << 2
-	TransactionRollbackType = 3 << 2
-)
-
-const (
-	NameValueSeparator = 1 + iota
-	PropertySeparator
-)
-
-const (
-	CharacterMaxLength = 255
-)
-
-type Message struct {
-	Topic      string
-	Flag       int32
-	properties map[string]string
-	Body       []byte
-}
-
-func NewDefultMessage(topic string, body []byte) *Message {
-	return NewMessage(topic, "", "", 0, body, true)
-}
-
-type MessageExt struct {
-	Message
-	QueueId       int32
-	StoreSize     int32
-	QueueOffset   int64
-	SysFlag       int32
-	BornTimestamp int64
-	// bornHost
-	StoreTimestamp int64
-	// storeHost
-	MsgId                     string
-	CommitLogOffset           int64
-	BodyCRC                   int32
-	ReconsumeTimes            int32
-	PreparedTransactionOffset int64
-}
-
-func (msg *Message) encodeMessage() []byte {
-	// TODO
-	return nil
-}
-
-func decodeMessage(data []byte) []*MessageExt {
-	buf := bytes.NewBuffer(data)
-	var storeSize, magicCode, bodyCRC, queueId, flag, sysFlag, reconsumeTimes, bodyLength, bornPort, storePort int32
-	var queueOffset, physicOffset, preparedTransactionOffset, bornTimeStamp, storeTimestamp int64
-	var topicLen byte
-	var topic, body, properties, bornHost, storeHost []byte
-	var propertiesLength int16
-
-	var propertiesMap map[string]string
-
-	msgs := make([]*MessageExt, 0, 32)
-	for buf.Len() > 0 {
-		msg := new(MessageExt)
-		binary.Read(buf, binary.BigEndian, &storeSize)
-		binary.Read(buf, binary.BigEndian, &magicCode)
-		binary.Read(buf, binary.BigEndian, &bodyCRC)
-		binary.Read(buf, binary.BigEndian, &queueId)
-		binary.Read(buf, binary.BigEndian, &flag)
-		binary.Read(buf, binary.BigEndian, &queueOffset)
-		binary.Read(buf, binary.BigEndian, &physicOffset)
-		binary.Read(buf, binary.BigEndian, &sysFlag)
-		binary.Read(buf, binary.BigEndian, &bornTimeStamp)
-		bornHost = make([]byte, 4)
-		binary.Read(buf, binary.BigEndian, &bornHost)
-		binary.Read(buf, binary.BigEndian, &bornPort)
-		binary.Read(buf, binary.BigEndian, &storeTimestamp)
-		storeHost = make([]byte, 4)
-		binary.Read(buf, binary.BigEndian, &storeHost)
-		binary.Read(buf, binary.BigEndian, &storePort)
-		binary.Read(buf, binary.BigEndian, &reconsumeTimes)
-		binary.Read(buf, binary.BigEndian, &preparedTransactionOffset)
-		binary.Read(buf, binary.BigEndian, &bodyLength)
-		if bodyLength > 0 {
-			body = make([]byte, bodyLength)
-			binary.Read(buf, binary.BigEndian, body)
-
-			if (sysFlag & CompressedFlag) == CompressedFlag {
-				b := bytes.NewReader(body)
-				z, err := zlib.NewReader(b)
-				if err != nil {
-					fmt.Println(err)
-					return nil
-				}
-
-				body, err = ioutil.ReadAll(z)
-				if err != nil {
-					fmt.Println(err)
-					return nil
-				}
-				z.Close()
-			}
-
-		}
-		binary.Read(buf, binary.BigEndian, &topicLen)
-		topic = make([]byte, 0)
-		binary.Read(buf, binary.BigEndian, &topic)
-		binary.Read(buf, binary.BigEndian, &propertiesLength)
-		if propertiesLength > 0 {
-			properties = make([]byte, propertiesLength)
-			binary.Read(buf, binary.BigEndian, &properties)
-			propertiesMap = make(map[string]string)
-			json.Unmarshal(properties, &propertiesMap)
-		}
-
-		if magicCode != -626843481 {
-			fmt.Printf("magic code is error %d", magicCode)
-			return nil
-		}
-
-		msg.Topic = string(topic)
-		msg.QueueId = queueId
-		msg.SysFlag = sysFlag
-		msg.QueueOffset = queueOffset
-		msg.BodyCRC = bodyCRC
-		msg.StoreSize = storeSize
-		msg.BornTimestamp = bornTimeStamp
-		msg.ReconsumeTimes = reconsumeTimes
-		msg.Flag = flag
-		//msg.commitLogOffset=physicOffset
-		msg.StoreTimestamp = storeTimestamp
-		msg.PreparedTransactionOffset = preparedTransactionOffset
-		msg.Body = body
-		msg.properties = propertiesMap
-
-		msgs = append(msgs, msg)
-	}
-
-	return msgs
-}
-
-func messageProperties2String(properties map[string]string) string {
-	StringBuilder := bytes.NewBuffer([]byte{})
-	if properties != nil && len(properties) != 0 {
-		for k, v := range properties {
-			binary.Write(StringBuilder, binary.BigEndian, k)                  // 4
-			binary.Write(StringBuilder, binary.BigEndian, NameValueSeparator) // 4
-			binary.Write(StringBuilder, binary.BigEndian, v)                  // 4
-			binary.Write(StringBuilder, binary.BigEndian, PropertySeparator)  // 4
-		}
-	}
-	return StringBuilder.String()
-}
-
-//func (msg Message) checkMessage(producer *DefaultProducer) (err error) {
-//	if err = checkTopic(msg.Topic); err != nil {
-//		if len(msg.Body) == 0 {
-//			err = errors.New("ResponseCode:" + strconv.Itoa(MsgIllegal) + ", the message body is null")
-//		} else if len(msg.Body) > producer.maxMessageSize {
-//			err = errors.New("ResponseCode:" + strconv.Itoa(MsgIllegal) + ", the message body size over max value, MAX:" + strconv.Itoa(producer.maxMessageSize))
-//		}
-//	}
-//	return
-//}
-
-//func checkTopic(topic string) (err error) {
-//	if topic == "" {
-//		err = errors.New("the specified topic is blank")
-//	}
-//	if len(topic) > CharacterMaxLength {
-//		err = errors.New("the specified topic is longer than topic max length 255")
-//	}
-//	if topic == DefaultTopic {
-//		err = errors.New("the topic[" + topic + "] is conflict with default topic")
-//	}
-//	return
-//}
-
-func NewMessage(topic, tags, keys string, flag int32, body []byte, waitStoreMsgOK bool) *Message {
-	message := &Message{
-		Topic: topic,
-		Flag:  flag,
-		Body:  body,
-	}
-
-	if tags != "" {
-		message.SetTags(tags)
-	}
-
-	if keys != "" {
-		message.SetKeys(keys)
-	}
-
-	message.SetWaitStoreMsgOK(waitStoreMsgOK)
-	return message
-}
-
-func (msg *Message) SetTags(t string) {
-	msg.putProperty(MessageConst.PropertyTags, t)
-}
-
-func (msg *Message) SetKeys(k string) {
-	msg.putProperty(MessageConst.PropertyKeys, k)
-}
-
-func (msg *Message) SetWaitStoreMsgOK(b bool) {
-
-}
-
-func (msg *Message) Property() map[string]string {
-	return msg.properties
-}
-
-func (msg *Message) putProperty(k, v string) {
-	if msg.properties == nil {
-		msg.properties = make(map[string]string)
-	}
-	if v, found := msg.properties[k]; !found {
-		msg.properties[k] = v
-	} else {
-		glog.Infof("Message put peoperties key: %s existed.", k)
-	}
-}
-
-func (msg *Message) removeProperty(k, v string) string {
-	if v, ok := msg.properties[k]; ok {
-		delete(msg.properties, k)
-		return v
-	}
-	return ""
-}
-
-func (msg *Message) String() string {
-	return fmt.Sprintf("Message [topic=%s, flag=%s, properties=%s, body=%s]",
-		msg.Topic, msg.Flag, msg.properties, msg.Body)
-}
diff --git a/rocketmq-go/util/message_client_id_generator.go b/rocketmq-go/model/message/message_client_id_generator.go
similarity index 66%
rename from rocketmq-go/util/message_client_id_generator.go
rename to rocketmq-go/model/message/message_client_id_generator.go
index 23293c0..1dc4b86 100644
--- a/rocketmq-go/util/message_client_id_generator.go
+++ b/rocketmq-go/model/message/message_client_id_generator.go
@@ -1,24 +1,26 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package util
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package message
 
 import (
 	"bytes"
 	"encoding/binary"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
 	"os"
 	"strconv"
 	"strings"
@@ -27,9 +29,9 @@
 )
 
 var (
-	counter       int16 = 0
-	startTime     int64 //this month's first day 12 hour. for example. 2017-01-01 12:00:00
-	nextStartTime int64 //next month's first day 12 hour. for example. 2017-02-01 12:00:00
+	counter       int16
+	startTime     int64
+	nextStartTime int64
 	idPrefix      string
 	lock          sync.Mutex
 )
@@ -40,8 +42,8 @@
 //4 bytes for  classloaderid(for java,go put 0)
 
 //2 bytes for counter,
-//4 bytes for timediff, //(time.Now().UnixNano() - startTime) / 1000000) divide 1000000 because golang is different with java
-func GeneratorMessageClientId() (uniqMessageId string) {
+//4 bytes for timediff, //(time.Now().UnixNano() - startTime) / 1000000) divide 1000000 because use time millis
+func generatorMessageClientId() (uniqMessageId string) {
 	defer lock.Unlock()
 	lock.Lock()
 	if len(idPrefix) == 0 {
@@ -58,6 +60,7 @@
 	return
 }
 
+//GeneratorMessageOffsetId generator message offsetId
 func GeneratorMessageOffsetId(storeHost []byte, port int32, commitOffset int64) (messageOffsetId string) {
 	var buf = bytes.NewBuffer([]byte{})
 	binary.Write(buf, binary.BigEndian, storeHost)
@@ -74,7 +77,7 @@
 		pid           int16
 		classloaderId int32 = -1 // golang don't have this
 	)
-	ip4Bytes = GetIp4Bytes()
+	ip4Bytes = util.GetIp4Bytes()
 	pid = int16(os.Getpid())
 	var buf = bytes.NewBuffer([]byte{})
 	binary.Write(buf, binary.BigEndian, ip4Bytes)
diff --git a/rocketmq-go/model/message/message_client_id_generator_test.go b/rocketmq-go/model/message/message_client_id_generator_test.go
new file mode 100644
index 0000000..f30143e
--- /dev/null
+++ b/rocketmq-go/model/message/message_client_id_generator_test.go
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package message
+
+import (
+	"testing"
+)
+
+func TestGeneratorMessageClientId(t *testing.T) {
+	id1 := generatorMessageClientId()
+	if id1 == "" {
+		t.Errorf("TestGeneratorMessageClientId failed")
+	}
+	id2 := generatorMessageClientId()
+	if id2 == "" || id1 == id2 {
+		t.Errorf("TestGeneratorMessageClientId failed : create same clientId")
+	}
+}
+
+func TestGeneratorMessageOffsetId(t *testing.T) {
+	id := GeneratorMessageOffsetId([]byte{111}, 1, 1)
+	if id != "6F000000010000000000000001" {
+		t.Errorf("TestGeneratorMessageOffsetId failed")
+	}
+}
diff --git a/rocketmq-go/model/message/message_constant.go b/rocketmq-go/model/message/message_constant.go
index 3991c7e..a358ce8 100644
--- a/rocketmq-go/model/message/message_constant.go
+++ b/rocketmq-go/model/message/message_constant.go
@@ -1,98 +1,99 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
 
 package message
 
-type messageConst struct {
-	PropertyKeys                      string
-	PropertyTags                      string
-	PropertyWaitStoreMsgOk            string
-	PropertyDelayTimeLevel            string
-	PropertyRetryTopic                string
-	PropertyRealTopic                 string
-	PropertyRealQueueId               string
-	PropertyTransactionPrepared       string
-	PropertyProducerGroup             string
-	PropertyMinOffset                 string
-	PropertyMaxOffset                 string
-	PropertyBuyerId                   string
-	PropertyOriginMessageId           string
-	PropertyTransferFlag              string
-	PropertyCorrectionFlag            string
-	PropertyMq2Flag                   string
-	PropertyReconsumeTime             string
-	PropertyMsgRegion                 string
-	PropertyUniqClientMessageIdKeyidx string
-	PropertyMaxReconsumeTimes         string
-	PropertyConsumeStartTimeStamp     string
-
-	KeySeparator string
-	systemKeySet []string
-}
-
-var MessageConst = &messageConst{
-	PropertyKeys:                      "KEYS",
-	PropertyTags:                      "TAGS",
-	PropertyWaitStoreMsgOk:            "WAIT",
-	PropertyDelayTimeLevel:            "DELAY",
-	PropertyRetryTopic:                "RETRY_TOPIC",
-	PropertyRealTopic:                 "REAL_TOPIC",
-	PropertyRealQueueId:               "REAL_QID",
-	PropertyTransactionPrepared:       "TRAN_MSG",
-	PropertyProducerGroup:             "PGROUP",
-	PropertyMinOffset:                 "MIN_OFFSET",
-	PropertyMaxOffset:                 "MAX_OFFSET",
-	PropertyBuyerId:                   "BUYER_ID",
-	PropertyOriginMessageId:           "ORIGIN_MESSAGE_ID",
-	PropertyTransferFlag:              "TRANSFER_FLAG",
-	PropertyCorrectionFlag:            "CORRECTION_FLAG",
-	PropertyMq2Flag:                   "MQ2_FLAG",
-	PropertyReconsumeTime:             "RECONSUME_TIME",
-	PropertyMsgRegion:                 "MSG_REGION",
-	PropertyUniqClientMessageIdKeyidx: "UNIQ_KEY",
-	PropertyMaxReconsumeTimes:         "MAX_RECONSUME_TIMES",
-	PropertyConsumeStartTimeStamp:     "CONSUME_START_TIME",
-
-	KeySeparator: "",
-}
-
-func init() {
-	var systemKeySet = []string{}
-	systemKeySet = append(systemKeySet, MessageConst.PropertyKeys)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyTags)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyWaitStoreMsgOk)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyDelayTimeLevel)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyRetryTopic)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyRealTopic)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyRealQueueId)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyTransactionPrepared)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyProducerGroup)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyMinOffset)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyMaxOffset)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyBuyerId)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyOriginMessageId)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyTransferFlag)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyCorrectionFlag)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyMq2Flag)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyReconsumeTime)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyMsgRegion)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyUniqClientMessageIdKeyidx)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyMaxReconsumeTimes)
-	systemKeySet = append(systemKeySet, MessageConst.PropertyConsumeStartTimeStamp)
-
-	MessageConst.systemKeySet = systemKeySet
-}
+//
+//type messageConst struct {
+//	PropertyKeys                      string
+//	PropertyTags                      string
+//	PropertyWaitStoreMsgOk            string
+//	PropertyDelayTimeLevel            string
+//	PropertyRetryTopic                string
+//	PropertyRealTopic                 string
+//	PropertyRealQueueId               string
+//	PropertyTransactionPrepared       string
+//	PropertyProducerGroup             string
+//	PropertyMinOffset                 string
+//	PropertyMaxOffset                 string
+//	PropertyBuyerId                   string
+//	PropertyOriginMessageId           string
+//	PropertyTransferFlag              string
+//	PropertyCorrectionFlag            string
+//	PropertyMq2Flag                   string
+//	PropertyReconsumeTime             string
+//	PropertyMsgRegion                 string
+//	PropertyUniqClientMessageIdKeyidx string
+//	PropertyMaxReconsumeTimes         string
+//	PropertyConsumeStartTimeStamp     string
+//
+//	KeySeparator string
+//	systemKeySet []string
+//}
+//
+//var MessageConst = &messageConst{
+//	PropertyKeys:                      "KEYS",
+//	PropertyTags:                      "TAGS",
+//	PropertyWaitStoreMsgOk:            "WAIT",
+//	PropertyDelayTimeLevel:            "DELAY",
+//	PropertyRetryTopic:                "RETRY_TOPIC",
+//	PropertyRealTopic:                 "REAL_TOPIC",
+//	PropertyRealQueueId:               "REAL_QID",
+//	PropertyTransactionPrepared:       "TRAN_MSG",
+//	PropertyProducerGroup:             "PGROUP",
+//	PropertyMinOffset:                 "MIN_OFFSET",
+//	PropertyMaxOffset:                 "MAX_OFFSET",
+//	PropertyBuyerId:                   "BUYER_ID",
+//	PropertyOriginMessageId:           "ORIGIN_MESSAGE_ID",
+//	PropertyTransferFlag:              "TRANSFER_FLAG",
+//	PropertyCorrectionFlag:            "CORRECTION_FLAG",
+//	PropertyMq2Flag:                   "MQ2_FLAG",
+//	PropertyReconsumeTime:             "RECONSUME_TIME",
+//	PropertyMsgRegion:                 "MSG_REGION",
+//	PropertyUniqClientMessageIdKeyidx: "UNIQ_KEY",
+//	PropertyMaxReconsumeTimes:         "MAX_RECONSUME_TIMES",
+//	PropertyConsumeStartTimeStamp:     "CONSUME_START_TIME",
+//
+//	KeySeparator: "",
+//}
+//
+//func init() {
+//	var systemKeySet = []string{}
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyKeys)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyTags)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyWaitStoreMsgOk)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyDelayTimeLevel)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyRetryTopic)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyRealTopic)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyRealQueueId)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyTransactionPrepared)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyProducerGroup)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyMinOffset)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyMaxOffset)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyBuyerId)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyOriginMessageId)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyTransferFlag)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyCorrectionFlag)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyMq2Flag)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyReconsumeTime)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyMsgRegion)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyUniqClientMessageIdKeyidx)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyMaxReconsumeTimes)
+//	systemKeySet = append(systemKeySet, MessageConst.PropertyConsumeStartTimeStamp)
+//
+//	MessageConst.systemKeySet = systemKeySet
+//}
diff --git a/rocketmq-go/model/message/message_ext_impl.go b/rocketmq-go/model/message/message_ext_impl.go
new file mode 100644
index 0000000..9b19e1a
--- /dev/null
+++ b/rocketmq-go/model/message/message_ext_impl.go
@@ -0,0 +1,85 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package message
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"math"
+)
+
+//MessageExtImpl the implement of MessageExt
+type MessageExtImpl struct {
+	*MessageImpl
+	msgId                         string
+	QueueId                       int32
+	StoreSize                     int32
+	QueueOffset                   int64
+	SysFlag                       int32
+	BornTimestamp                 int64
+	BornHost                      string
+	StoreTimestamp                int64
+	StoreHost                     string
+	CommitLogOffset               int64
+	BodyCRC                       int32
+	ReconsumeTimes                int32
+	PreparedTransactionOffset     int64
+	propertyConsumeStartTimestamp string
+}
+
+//MsgId get MessageId
+func (m *MessageExtImpl) MsgId() (msgId string) {
+	msgId = m.msgId
+	return
+}
+
+//SetMsgId SetMsgId
+func (m *MessageExtImpl) SetMsgId(msgId string) {
+	m.msgId = msgId
+	return
+}
+
+//GetOriginMessageId GetOriginMessageId
+func (m *MessageExtImpl) GetOriginMessageId() string {
+	if m.properties != nil {
+		originMessageId := m.properties[constant.PROPERTY_ORIGIN_MESSAGE_ID]
+		if len(originMessageId) > 0 {
+			return originMessageId
+		}
+	}
+	return m.msgId
+}
+
+//GetConsumeStartTime GetConsumeStartTime
+func (m *MessageExtImpl) GetConsumeStartTime() int64 {
+	if len(m.propertyConsumeStartTimestamp) > 0 {
+		return util.StrToInt64WithDefaultValue(m.propertyConsumeStartTimestamp, -1)
+	}
+	return math.MaxInt64
+}
+
+//SetConsumeStartTime SetConsumeStartTime
+func (m *MessageExtImpl) SetConsumeStartTime() {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	nowTime := util.CurrentTimeMillisStr()
+	m.properties[constant.PROPERTY_KEYS] = nowTime
+	m.propertyConsumeStartTimestamp = nowTime
+	return
+}
diff --git a/rocketmq-go/model/message/message_impl.go b/rocketmq-go/model/message/message_impl.go
new file mode 100644
index 0000000..ad6fea0
--- /dev/null
+++ b/rocketmq-go/model/message/message_impl.go
@@ -0,0 +1,203 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package message
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"strings"
+)
+
+//MessageImpl the implement of Message
+type MessageImpl struct {
+	topic      string
+	flag       int
+	properties map[string]string
+	body       []byte
+}
+
+//NewMessageImpl create a Message instance
+func NewMessageImpl() (message *MessageImpl) {
+	message = &MessageImpl{}
+	return
+}
+
+//Properties get message's Properties
+func (m *MessageImpl) Properties() (properties map[string]string) {
+	properties = m.properties
+	return
+}
+
+//SetProperties set message's Properties
+func (m *MessageImpl) SetProperties(properties map[string]string) {
+	m.properties = properties
+	return
+}
+
+//PropertiesKeyValue get properties[key]'s value
+func (m *MessageImpl) PropertiesKeyValue(key string) (value string) {
+	value = m.properties[key]
+	return
+}
+
+//Body get message body
+func (m *MessageImpl) Body() (body []byte) {
+	body = m.body
+	return
+
+}
+
+//Topic get message Topic
+func (m *MessageImpl) Topic() (topic string) {
+	topic = m.topic
+	return
+
+}
+
+//SetFlag set message flag
+func (m *MessageImpl) SetFlag(flag int) {
+	m.flag = flag
+	return
+}
+
+//Flag get message flag
+func (m *MessageImpl) Flag() (flag int) {
+	flag = m.flag
+	return
+
+}
+
+//SetTopic set topic
+func (m *MessageImpl) SetTopic(topic string) {
+	m.topic = topic
+}
+
+//SetBody set body
+func (m *MessageImpl) SetBody(body []byte) {
+	m.body = body
+}
+
+//SetTag set message tag
+func (m *MessageImpl) SetTag(tag string) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_TAGS] = tag
+}
+
+//Tag get message tag from properties
+func (m *MessageImpl) Tag() (tag string) {
+	if m.properties != nil {
+		tag = m.properties[constant.PROPERTY_TAGS]
+	}
+	return
+}
+
+//SetKeys set message key
+func (m *MessageImpl) SetKeys(keys []string) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_KEYS] = strings.Join(keys, " ")
+}
+
+//SetDelayTimeLevel set message delay time level
+func (m *MessageImpl) SetDelayTimeLevel(delayTimeLevel int) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_DELAY_TIME_LEVEL] = util.IntToString(delayTimeLevel)
+}
+
+//GeneratorMsgUniqueKey only use by system
+func (m *MessageImpl) GeneratorMsgUniqueKey() {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	if len(m.properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX]) > 0 {
+		return
+	}
+	m.properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX] = generatorMessageClientId()
+}
+
+//GetMsgUniqueKey only use by system
+func (m *MessageExtImpl) GetMsgUniqueKey() string {
+	if m.properties != nil {
+		originMessageId := m.properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX]
+		if len(originMessageId) > 0 {
+			return originMessageId
+		}
+	}
+	return m.msgId
+}
+
+//SetOriginMessageId only use by system
+func (m *MessageImpl) SetOriginMessageId(messageId string) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_ORIGIN_MESSAGE_ID] = messageId
+}
+
+//SetRetryTopic only use by system
+func (m *MessageImpl) SetRetryTopic(retryTopic string) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_RETRY_TOPIC] = retryTopic
+}
+
+//SetReconsumeTime only use by system
+func (m *MessageImpl) SetReconsumeTime(reConsumeTime int) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_RECONSUME_TIME] = util.IntToString(reConsumeTime)
+}
+
+//GetReconsumeTimes only use by system
+func (m *MessageImpl) GetReconsumeTimes() (reConsumeTime int) {
+	reConsumeTime = 0
+	if m.properties != nil {
+		reConsumeTimeStr := m.properties[constant.PROPERTY_RECONSUME_TIME]
+		if len(reConsumeTimeStr) > 0 {
+			reConsumeTime = util.StrToIntWithDefaultValue(reConsumeTimeStr, 0)
+		}
+	}
+	return
+}
+
+//SetMaxReconsumeTimes only use by system
+func (m *MessageImpl) SetMaxReconsumeTimes(maxConsumeTime int) {
+	if m.properties == nil {
+		m.properties = make(map[string]string)
+	}
+	m.properties[constant.PROPERTY_MAX_RECONSUME_TIMES] = util.IntToString(maxConsumeTime)
+}
+
+//GetMaxReconsumeTimes only use by system
+func (m *MessageImpl) GetMaxReconsumeTimes() (maxConsumeTime int) {
+	maxConsumeTime = 0
+	if m.properties != nil {
+		reConsumeTimeStr := m.properties[constant.PROPERTY_MAX_RECONSUME_TIMES]
+		if len(reConsumeTimeStr) > 0 {
+			maxConsumeTime = util.StrToIntWithDefaultValue(reConsumeTimeStr, 0)
+		}
+	}
+	return
+}
diff --git a/rocketmq-go/model/message_ext.go b/rocketmq-go/model/message_ext.go
deleted file mode 100644
index 9a3aacb..0000000
--- a/rocketmq-go/model/message_ext.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"math"
-	"strconv"
-	"time"
-)
-
-type MessageExt struct {
-	*Message
-	QueueId                   int32
-	StoreSize                 int32
-	QueueOffset               int64
-	SysFlag                   int32
-	BornTimestamp             int64
-	BornHost                  string
-	StoreTimestamp            int64
-	StoreHost                 string
-	MsgId                     string
-	CommitLogOffset           int64
-	BodyCRC                   int32
-	ReconsumeTimes            int32
-	PreparedTransactionOffset int64
-
-	propertyConsumeStartTimestamp string // race condition
-}
-
-func (self *MessageExt) GetOriginMessageId() string {
-	if self.Properties != nil {
-		originMessageId := self.Properties[constant.PROPERTY_ORIGIN_MESSAGE_ID]
-		if len(originMessageId) > 0 {
-			return originMessageId
-		}
-	}
-	return self.MsgId
-}
-
-func (self *MessageExt) GetConsumeStartTime() int64 {
-	if len(self.propertyConsumeStartTimestamp) > 0 {
-		return util.StrToInt64WithDefaultValue(self.propertyConsumeStartTimestamp, -1)
-	}
-	return math.MaxInt64
-}
-
-func (self *MessageExt) SetConsumeStartTime() {
-	if self.Properties == nil {
-		self.Properties = make(map[string]string)
-	}
-	nowTime := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
-	self.Properties[constant.PROPERTY_KEYS] = nowTime
-	self.propertyConsumeStartTimestamp = nowTime
-	return
-}
diff --git a/rocketmq-go/model/message_listener.go b/rocketmq-go/model/message_listener.go
deleted file mode 100644
index 7ad2054..0000000
--- a/rocketmq-go/model/message_listener.go
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-type MessageListener func(msgs []MessageExt) ConsumeConcurrentlyResult
diff --git a/rocketmq-go/model/message_queue.go b/rocketmq-go/model/message_queue.go
deleted file mode 100644
index 27d70a6..0000000
--- a/rocketmq-go/model/message_queue.go
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-type MessageQueue struct {
-	Topic      string `json:"topic"`
-	BrokerName string `json:"brokerName"`
-	QueueId    int32  `json:"queueId"`
-}
-
-func (self *MessageQueue) clone() *MessageQueue {
-	no := new(MessageQueue)
-	no.Topic = self.Topic
-	no.QueueId = self.QueueId
-	no.BrokerName = self.BrokerName
-	return no
-}
-
-type MessageQueues []*MessageQueue
-
-func (self MessageQueues) Less(i, j int) bool {
-	imq := self[i]
-	jmq := self[j]
-
-	if imq.Topic < jmq.Topic {
-		return true
-	} else if imq.Topic < jmq.Topic {
-		return false
-	}
-
-	if imq.BrokerName < jmq.BrokerName {
-		return true
-	} else if imq.BrokerName < jmq.BrokerName {
-		return false
-	}
-
-	if imq.QueueId < jmq.QueueId {
-		return true
-	} else {
-		return false
-	}
-}
-
-func (self MessageQueues) Swap(i, j int) {
-	self[i], self[j] = self[j], self[i]
-}
-
-func (self MessageQueues) Len() int {
-	return len(self)
-}
-
-func (self MessageQueue) Equals(messageQueue *MessageQueue) bool {
-	if self.QueueId != messageQueue.QueueId {
-		return false
-	}
-	if self.Topic != messageQueue.Topic {
-		return false
-	}
-	if self.BrokerName != messageQueue.BrokerName {
-		return false
-	}
-	return true
-}
diff --git a/rocketmq-go/model/message_queues.go b/rocketmq-go/model/message_queues.go
new file mode 100644
index 0000000..9b44f0d
--- /dev/null
+++ b/rocketmq-go/model/message_queues.go
@@ -0,0 +1,52 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package model
+
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+//MessageQueues queue array
+type MessageQueues []*rocketmqm.MessageQueue
+
+//Less compare queue
+func (m MessageQueues) Less(i, j int) bool {
+	imq := m[i]
+	jmq := m[j]
+
+	if imq.Topic < jmq.Topic {
+		return true
+	} else if imq.Topic < jmq.Topic {
+		return false
+	}
+
+	if imq.BrokerName < jmq.BrokerName {
+		return true
+	} else if imq.BrokerName < jmq.BrokerName {
+		return false
+	}
+	return imq.QueueId < jmq.QueueId
+}
+
+//Swap swap queue
+func (m MessageQueues) Swap(i, j int) {
+	m[i], m[j] = m[j], m[i]
+}
+
+//Len messageQueues's length
+func (m MessageQueues) Len() int {
+	return len(m)
+}
diff --git a/rocketmq-go/model/process_queue.go b/rocketmq-go/model/process_queue.go
index e0075e0..aaf5849 100644
--- a/rocketmq-go/model/process_queue.go
+++ b/rocketmq-go/model/process_queue.go
@@ -1,23 +1,25 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
 import (
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
 	"github.com/emirpasic/gods/maps/treemap"
 	"github.com/golang/glog"
@@ -25,8 +27,9 @@
 	"time"
 )
 
+//ProcessQueue message process queue
 type ProcessQueue struct {
-	msgTreeMap            *treemap.Map // int | MessageExt
+	msgTreeMap            *treemap.Map // int | MessageExtImpl
 	msgCount              int
 	lockTreeMap           sync.RWMutex
 	locked                bool
@@ -42,6 +45,7 @@
 	msgTreeMapToBeConsume *treemap.Map
 }
 
+//NewProcessQueue create a ProcessQueue
 func NewProcessQueue() (processQueue *ProcessQueue) {
 	processQueue = new(ProcessQueue)
 	processQueue.dropped = false
@@ -50,143 +54,153 @@
 
 	return
 }
-func (self *ProcessQueue) GetMsgCount() int {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	return self.msgCount
+
+//GetMsgCount get message count
+func (p *ProcessQueue) GetMsgCount() int {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	return p.msgCount
 }
 
-func (self *ProcessQueue) Clear() {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	self.SetDrop(true)
-	self.msgTreeMap.Clear()
-	self.msgCount = 0
-	self.queueOffsetMax = 0
+//Clear clear
+func (p *ProcessQueue) Clear() {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	p.SetDrop(true)
+	p.msgTreeMap.Clear()
+	p.msgCount = 0
+	p.queueOffsetMax = 0
 
 }
 
-func (self *ProcessQueue) ChangeToProcessQueueInfo() (processQueueInfo ProcessQueueInfo) {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
+//ChangeToProcessQueueInfo changeToProcessQueueInfo
+func (p *ProcessQueue) ChangeToProcessQueueInfo() (processQueueInfo ProcessQueueInfo) {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
 	processQueueInfo = ProcessQueueInfo{}
 	minOffset := -1
 	maxOffset := -1
-	minKey, _ := self.msgTreeMap.Min()
+	minKey, _ := p.msgTreeMap.Min()
 	if minKey != nil {
 		minOffset = minKey.(int)
 	}
-	maxKey, _ := self.msgTreeMap.Max()
+	maxKey, _ := p.msgTreeMap.Max()
 	if maxKey != nil {
 		maxOffset = maxKey.(int)
 	}
-	processQueueInfo.CachedMsgCount = int32(self.msgCount)
+	processQueueInfo.CachedMsgCount = int32(p.msgCount)
 	processQueueInfo.CachedMsgMinOffset = int64(maxOffset)
 	processQueueInfo.CachedMsgMaxOffset = int64(minOffset)
-	//processQueueInfo.CommitOffset = -123 // todo
-	processQueueInfo.Droped = self.dropped
-	processQueueInfo.LastConsumeTimestamp = self.lastConsumeTimestamp.UnixNano()
-	processQueueInfo.LastPullTimestamp = self.lastPullTimestamp.UnixNano()
-	//processQueueInfo.
-
+	processQueueInfo.Droped = p.dropped
+	processQueueInfo.LastConsumeTimestamp = p.lastConsumeTimestamp.UnixNano()
+	processQueueInfo.LastPullTimestamp = p.lastPullTimestamp.UnixNano()
 	return
 }
 
-func (self *ProcessQueue) DeleteExpireMsg(queueOffset int) {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	key, _ := self.msgTreeMap.Min()
+//DeleteExpireMsg deleteExpireMsg
+func (p *ProcessQueue) DeleteExpireMsg(queueOffset int) {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	key, _ := p.msgTreeMap.Min()
 	if key == nil {
 		return
 	}
 	offset := key.(int)
-	glog.Infof("look min key and offset  %d  %s", offset, queueOffset)
+	glog.V(2).Infof("look min key and offset  %d  %s", offset, queueOffset)
 	if queueOffset == offset {
-		self.msgTreeMap.Remove(queueOffset)
-		self.msgCount = self.msgTreeMap.Size()
+		p.msgTreeMap.Remove(queueOffset)
+		p.msgCount = p.msgTreeMap.Size()
 	}
 }
 
-func (self *ProcessQueue) GetMinMessageInTree() (offset int, messagePoint *MessageExt) {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	key, value := self.msgTreeMap.Min()
+//GetMinMessageInTree getMinMessageInTree
+func (p *ProcessQueue) GetMinMessageInTree() (offset int, messagePoint *message.MessageExtImpl) {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	key, value := p.msgTreeMap.Min()
 	if key == nil || value == nil {
 		return
 	}
 	offset = key.(int)
 
-	message := value.(MessageExt)
+	message := value.(message.MessageExtImpl)
 	messagePoint = &message
 	return
 }
 
-func (self *ProcessQueue) SetDrop(drop bool) {
-	self.dropped = drop
+//SetDrop set this queue is dropped
+func (p *ProcessQueue) SetDrop(drop bool) {
+	p.dropped = drop
 }
-func (self *ProcessQueue) IsDropped() bool {
-	return self.dropped
+
+//IsDropped judge whether this queue is dropped
+func (p *ProcessQueue) IsDropped() bool {
+	return p.dropped
 }
-func (self *ProcessQueue) GetMaxSpan() int {
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	if self.msgTreeMap.Empty() {
+
+//GetMaxSpan getMaxSpan
+func (p *ProcessQueue) GetMaxSpan() int {
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	if p.msgTreeMap.Empty() {
 		return 0
 	}
-	minKey, _ := self.msgTreeMap.Min()
+	minKey, _ := p.msgTreeMap.Min()
 	minOffset := minKey.(int)
-	maxKey, _ := self.msgTreeMap.Max()
+	maxKey, _ := p.msgTreeMap.Max()
 	maxOffset := maxKey.(int)
 	return maxOffset - minOffset
 }
 
-func (self *ProcessQueue) RemoveMessage(msgs []MessageExt) (offset int64) {
+//RemoveMessage from this process queue
+func (p *ProcessQueue) RemoveMessage(msgs []message.MessageExtImpl) (offset int64) {
 	now := time.Now()
 	offset = -1
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
-	self.lastConsumeTimestamp = now
-	if self.msgCount > 0 {
-		maxKey, _ := self.msgTreeMap.Max()
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
+	p.lastConsumeTimestamp = now
+	if p.msgCount > 0 {
+		maxKey, _ := p.msgTreeMap.Max()
 		offset = int64(maxKey.(int)) + 1
 		for _, msg := range msgs {
-			self.msgTreeMap.Remove(int(msg.QueueOffset))
+			p.msgTreeMap.Remove(int(msg.QueueOffset))
 		}
-		self.msgCount = self.msgTreeMap.Size()
-		if self.msgCount > 0 {
-			minKey, _ := self.msgTreeMap.Min()
+		p.msgCount = p.msgTreeMap.Size()
+		if p.msgCount > 0 {
+			minKey, _ := p.msgTreeMap.Min()
 			offset = int64(minKey.(int))
 		}
 	}
 	return
 }
 
-func (self *ProcessQueue) PutMessage(msgs []MessageExt) (dispatchToConsume bool) {
+//PutMessage put message into this process queue
+func (p *ProcessQueue) PutMessage(msgs []message.MessageExtImpl) (dispatchToConsume bool) {
 	dispatchToConsume = false
 	msgsLen := len(msgs)
 	if msgsLen == 0 {
 		return
 	}
-	defer self.lockTreeMap.Unlock()
-	self.lockTreeMap.Lock()
+	defer p.lockTreeMap.Unlock()
+	p.lockTreeMap.Lock()
 
 	for _, msg := range msgs {
-		self.msgTreeMap.Put(int(msg.QueueOffset), msg)
+		p.msgTreeMap.Put(int(msg.QueueOffset), msg)
 
 	}
-	self.msgCount = self.msgTreeMap.Size()
-	maxOffset, _ := self.msgTreeMap.Max()
-	self.queueOffsetMax = int64(maxOffset.(int))
-	if self.msgCount > 0 && !self.consuming {
+	p.msgCount = p.msgTreeMap.Size()
+	maxOffset, _ := p.msgTreeMap.Max()
+	p.queueOffsetMax = int64(maxOffset.(int))
+	if p.msgCount > 0 && !p.consuming {
 		dispatchToConsume = true
-		self.consuming = true
+		p.consuming = true
 	}
 	lastMsg := msgs[msgsLen-1]
-	remoteMaxOffset := util.StrToInt64WithDefaultValue(lastMsg.Properties[constant.PROPERTY_MAX_OFFSET], -1)
+	remoteMaxOffset := util.StrToInt64WithDefaultValue(lastMsg.PropertiesKeyValue(constant.PROPERTY_MAX_OFFSET), -1)
 	if remoteMaxOffset > 0 {
 		accTotal := remoteMaxOffset - lastMsg.QueueOffset
 		if accTotal > 0 {
-			self.msgAccCnt = accTotal
+			p.msgAccCnt = accTotal
 		}
 	}
 	return
diff --git a/rocketmq-go/model/process_queue_info.go b/rocketmq-go/model/process_queue_info.go
index c221ef8..bf90134 100644
--- a/rocketmq-go/model/process_queue_info.go
+++ b/rocketmq-go/model/process_queue_info.go
@@ -1,21 +1,23 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
+//ProcessQueueInfo processQueueInfo
 type ProcessQueueInfo struct {
 	CommitOffset int64 `json:"commitOffset"`
 
diff --git a/rocketmq-go/model/pull_request.go b/rocketmq-go/model/pull_request.go
index bc1a46f..a529280 100644
--- a/rocketmq-go/model/pull_request.go
+++ b/rocketmq-go/model/pull_request.go
@@ -1,24 +1,32 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
+import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+
+//PullRequest pullRequest
 type PullRequest struct {
+	//consumer group
 	ConsumerGroup string
-	MessageQueue  *MessageQueue
-	ProcessQueue  *ProcessQueue
-	NextOffset    int64
+	//which message queue
+	MessageQueue *rocketmqm.MessageQueue
+	//process queue info
+	ProcessQueue *ProcessQueue
+	//next offset
+	NextOffset int64
 }
diff --git a/rocketmq-go/model/pull_result.go b/rocketmq-go/model/pull_result.go
deleted file mode 100644
index b34a2d9..0000000
--- a/rocketmq-go/model/pull_result.go
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package model
-
-import (
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
-)
-
-type PullStatus int
-
-const (
-	Found PullStatus = iota
-	NoNewMsg
-	NoMatchedMsg
-	OffsetIllegal
-)
-
-type PullResult struct {
-	pullStatus      PullStatus
-	nextBeginOffset int64
-	minOffset       int64
-	maxOffset       int64
-	msgFoundList    []*message.MessageExt
-}
-
-func NewPullResult(ps PullStatus, next, min, max int64, list []*message.MessageExt) *PullResult {
-	return &PullResult{
-		ps,
-		next,
-		min,
-		max,
-		list,
-	}
-}
-
-func (result *PullResult) PullStatus() PullStatus {
-	return result.pullStatus
-}
-
-func (result *PullResult) NextBeginOffset() int64 {
-	return result.nextBeginOffset
-}
-
-func (result *PullResult) MaxOffset() int64 {
-	return result.maxOffset
-}
-
-func (result *PullResult) MinOffset() int64 {
-	return result.minOffset
-}
-
-func (result *PullResult) MsgFoundList() []*message.MessageExt {
-	return result.msgFoundList
-}
-
-func (result *PullResult) SetMsgFoundList(list []*message.MessageExt) {
-	result.msgFoundList = list
-}
-
-func (result *PullResult) String() string {
-	return fmt.Sprintf("PullResult [pullStatus=%s, nextBeginOffset=%s, minOffset=%s, maxOffset=%s, msgFoundList=%s]",
-		result.pullStatus, result.nextBeginOffset, result.minOffset, result.maxOffset, len(result.msgFoundList))
-}
diff --git a/rocketmq-go/model/query_result.go b/rocketmq-go/model/query_result.go
deleted file mode 100644
index b9e9236..0000000
--- a/rocketmq-go/model/query_result.go
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package model
-
-import (
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
-)
-
-type QueryResult struct {
-	indexLastUpdateTimestamp int64
-	messageList              []*message.MessageExt
-}
-
-func NewQueryResult(timestamp int64, list []*message.MessageExt) *QueryResult {
-	return &QueryResult{
-		indexLastUpdateTimestamp: timestamp,
-		messageList:              list,
-	}
-}
-
-func (qr *QueryResult) IndexLastUpdateTimestamp() int64 {
-	return qr.indexLastUpdateTimestamp
-}
-
-func (qr *QueryResult) MessageList() []*message.MessageExt { //TODO: address?
-	return qr.messageList
-}
-
-func (qr *QueryResult) String() string {
-	return fmt.Sprintf("QueryResult [indexLastUpdateTimestamp=%s, messageList=%s]",
-		qr.indexLastUpdateTimestamp, qr.messageList)
-}
diff --git a/rocketmq-go/model/request_code.go b/rocketmq-go/model/request_code.go
deleted file mode 100644
index 495c1a7..0000000
--- a/rocketmq-go/model/request_code.go
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http:// www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package model
-
-const (
-	// send message
-	SendMsg = 10
-	// subscribe message
-	PullMsg = 11
-	// query message
-	QueryMessage = 12
-	// queryOffset
-	QueryBrokerOffset = 13
-	// query Consumer Offset
-	QueryConsumerOffset = 14
-	// update Consumer Offset
-	UpdateConsumerOffset = 15
-	// update or increase a topic
-	UpdateAndCreateTopic = 17
-	// get all config of topic (Slave and Namesrv query the config to master)
-	GetAllTopicConfig = 21
-	// get all config (Slave and Namesrv query the config to master)
-	GetTopicConfigList = 22
-	// get all name list of topic
-	GetTopicNameList = 23
-	// update config
-	UpdateBrokerConfig = 25
-	// get config
-	GetBrokerConfig = 26
-	// trigger delete files
-	TriggerDeleteFILES = 27
-	// get runtime information
-	GetBrokerRuntimeInfo = 28
-	// search offset by timestamp
-	SearchOffsetByTimeStamp = 29
-	// query max offset of queue
-	GetMaxOffset = 30
-	// query min offset of queue
-	GetMinOffset = 31
-	// query earliest message store time
-	GetEarliestMsgStoreTime = 32
-	// query message by id
-	ViewMsgById = 33
-	// client send heartbeat to broker, and register self
-	HeartBeat = 34
-	// unregister client
-	UnregisterClient = 35
-	// consumer send message back to broker when can't process message
-	ConsumerSendMsgBack = 36
-	// Commit or Rollback transaction
-	EndTransaction = 37
-	// get ConsumerId list by GroupName
-	GetConsumerListByGroup = 38
-	// ckeck transaction state from producer
-	CheckTransactionState = 39
-	// broker notify consumer ids changed
-	NotifyConsumerIdsChanged = 40
-	// Consumer lock queue to master
-	LockBatchMq = 41
-	// Consumer unlock queue to master
-	UNLockBatchMq = 42
-	// get all consumer offset
-	GetAllConsumerOffset = 43
-	// get all delay offset
-	GetAllDelayOffset = 45
-	// put kv config to Namesrv
-	PutKVConfig = 100
-	// get kv config to Namesrv
-	GetKVConfig = 101
-	// delete  kv config to Namesrv
-	DeleteKVConfig = 102
-	// register a broker to Namesrv. As data is persistent,
-	// the broker will overwrite if old config existed.
-	RegisterBroker = 103
-	// register a broker
-	UnregisterBroker = 104
-	// get broker name, queue numbers by topic.
-	GetRouteinfoByTopic = 105
-	// get all registered broker to namesrv info
-	GetBrokerClusterInfo             = 106
-	UpdateAndCreateSubscriptionGroup = 200
-	GetAllSubscriptionGroupConfig    = 201
-	GetTopicStatsInfo                = 202
-	GetConsumerConnList              = 203
-	GetProducerConnList              = 204
-	WipeWritePermOfBroker            = 205
-
-	// get all topic list from namesrv
-	GetAllTopicListFromNamesrv = 206
-	// delete subscription group from broker
-	DeleteSubscriptionGroup = 207
-	// get consume stats from broker
-	GetConsumeStats = 208
-	// Suspend Consumer
-	SuspendConsumer = 209
-	// Resume Consumer
-	ResumeConsumer = 210
-	// reset Consumer Offset
-	ResetConsumerOffsetInConsumer = 211
-	// reset Consumer Offset
-	ResetConsumerOffsetInBroker = 212
-	// query which consumer groups consume the msg
-	WhoConsumeMessage = 214
-
-	// namesrv delete topic config from broker
-	DeleteTopicInBroker = 215
-	// namesrv delete topic config from namesrv
-	DeleteTopicInNamesrv = 216
-	// namesrv get server ip info by project
-	GetKvConfigByValue = 217
-	// Namesrv delete all server ip by project group
-	DeleteKvConfigByValue = 218
-	// get all KV list by namespace
-	GetKvlistByNamespace = 219
-
-	// reset offset
-	ResetConsumerClientOffset = 220
-	// get consumer status from client
-	GetConsumerStatusFromClient = 221
-	// invoke broker to reset offset
-	InvokeBrokerToResetOffset = 222
-	// invoke broker to get consumer status
-	InvokeBrokerToGetConsumerStatus = 223
-
-	// query which consumer consume msg
-	QueryTopicConsumeByWho = 300
-
-	// get topics by cluster
-	GetTopicsByCluster = 224
-
-	// register filter server to broker
-	RegisterFilterServer = 301
-	// register class to filter server
-	RegisterMsgFilterClass = 302
-	// get time span by topic and group
-	QueryConsumeTimeSpan = 303
-	// get all system topics from namesrv
-	GetSysTopicListFromNS = 304
-	// get all system topics from broker
-	GetSysTopicListFromBroker = 305
-
-	// clean expired consume queue
-	CleanExpiredConsumequeue = 306
-
-	// query consumer memory data by broker
-	GetConsumerRunningInfo = 307
-
-	// TODO: query correction offset(transfer component?)
-	QueryCorrectionOffset = 308
-
-	// Send msg to one consumer by broker, The msg will immediately consume,
-	// and return result to broker, broker return result to caller
-	ConsumeMsgDirectly = 309
-
-	// send msg with optimized network datagram
-	SendMsgV2 = 310
-
-	// get unit topic list
-	GetUnitTopicList             = 311
-	GetHasUnitSubTopicList       = 312
-	GetHasUnitSubUnunitTopicList = 313
-	CloneGroupOffset             = 314
-
-	// query all status that broker count
-	ViewBrokerStatsData = 315
-)
diff --git a/rocketmq-go/model/reset_offset_body.go b/rocketmq-go/model/reset_offset_body.go
index 1a0221d..1747b2b 100644
--- a/rocketmq-go/model/reset_offset_body.go
+++ b/rocketmq-go/model/reset_offset_body.go
@@ -1,33 +1,37 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
 import (
 	"encoding/json"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
 	"github.com/golang/glog"
 )
 
+//ResetOffsetBody resetOffsetBody
 type ResetOffsetBody struct {
-	OffsetTable map[MessageQueue]int64 `json:"offsetTable"`
+	OffsetTable map[rocketmqm.MessageQueue]int64 `json:"offsetTable"`
 }
 
-func (self *ResetOffsetBody) Decode(data []byte) (err error) {
-	self.OffsetTable = map[MessageQueue]int64{}
+//Decode decode byte array to ResetOffsetBody
+func (r *ResetOffsetBody) Decode(data []byte) (err error) {
+	r.OffsetTable = map[rocketmqm.MessageQueue]int64{}
 	var kvMap map[string]string
 	kvMap, err = util.GetKvStringMap(string(data))
 	if err != nil {
@@ -39,7 +43,7 @@
 		return
 	}
 	for k, v := range kvMap {
-		messageQueue := &MessageQueue{}
+		messageQueue := &rocketmqm.MessageQueue{}
 		var offset int64
 		err = json.Unmarshal([]byte(k), messageQueue)
 		if err != nil {
@@ -49,7 +53,7 @@
 		if err != nil {
 			return
 		}
-		self.OffsetTable[*messageQueue] = offset
+		r.OffsetTable[*messageQueue] = offset
 	}
 	return
 }
diff --git a/rocketmq-go/model/response_code.go b/rocketmq-go/model/response_code.go
deleted file mode 100644
index a42120e..0000000
--- a/rocketmq-go/model/response_code.go
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-const (
-	// success
-	Success = 0
-	// happened unknow error exception
-	SystemError = 1
-	// system busy
-	SystemBusy = 2
-	// unsupport request code
-	RequestCodeNotSupported = 3
-	// transaction failed, because of add db failed
-	TransactionFailed = 4
-	// Broker flush disk timeout
-	//FlushDiskTimeout = 10
-	// Broker slave unavailable, just for sync double write
-	SlaveNotAvailable = 11
-	// Broker write slave timeout, just for sync double write
-	//FlushSlaveTimeout = 12
-	// Broker illegal message
-	MessageIllegal = 13
-	// Broker, Namesrv not available,maybe service is closing or incorrect permission
-	ServiceNotAvailable = 14
-	// Broker, Namesrv unsupport version
-	VersionNOtSupported = 15
-	// Broker, Namesrv no permission for operation with send/receive or other
-	NoPermission = 16
-	// Broker, topic not exist
-	TopicNotExist = 17
-	// Broker, topic already exist
-	TopicExistAlready = 18
-	// Broker message not found when pull
-	PullNotFound = 19
-	// Broker retry immediately, maybe msg was filtered or incorrect notification TODO confirm annotation
-	PullRetryImmediately = 20
-	// Broker pull offset moved, because of too big or to small TODO confirm annotation
-	PullOffsetMoved = 21
-	// Broker query not found
-	QueryNotFound = 22
-	// Broker parse subscription failed
-	SubscriptionParseFailed = 23
-	// Broker subscription relationship not existed
-	SubscriptionNotExist = 24
-	// Broker subscription relationship not latest
-	SubscriptionNotLatest = 25
-	// Broker subscription group not exist
-	SubscriptionGroupNotExist = 26
-	// Producer transaction should commit
-	TransactionShouldCommit = 200
-	// Producer transaction should rollback
-	TransactionShouldRollback = 201
-	// Producer transaction status unknow
-	TransactionStatusUnknow = 202
-	// Producer ProducerGroup transaction error
-	TransactionStatusGroupWrong = 203
-	// unit message,need set buyerId
-	NoBuyerID = 204
-
-	// unit message,not current unit msg
-	NotInCurrentUnit = 205
-
-	// Consumer not online
-	ConsumerNotOnline = 206
-
-	// Consumer consume msg timeout
-	ConsumeMsgTimeout = 207
-)
diff --git a/rocketmq-go/model/send_result.go b/rocketmq-go/model/send_result.go
deleted file mode 100644
index 857b6c4..0000000
--- a/rocketmq-go/model/send_result.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package model
-
-import (
-	"fmt"
-)
-
-type SendStatus int
-
-const (
-	SendOK SendStatus = iota
-	FlushDiskTimeout
-	FlushSlaveTimeout
-	SlaveNotAvaliable
-)
-
-type SendResult struct {
-	sendStatus    SendStatus
-	msgID         string
-	messageQueue  MessageQueue
-	queueOffset   int64
-	transactionID string
-	offsetMsgID   string
-	regionID      string
-	traceOn       bool
-}
-
-func NewSendResult(status SendStatus, msgID, offsetID string, queue MessageQueue, queueOffset int64) *SendResult {
-	return &SendResult{
-		sendStatus:   status,
-		msgID:        msgID,
-		offsetMsgID:  offsetID,
-		messageQueue: queue,
-		queueOffset:  queueOffset,
-	}
-}
-
-func EncoderSendResultToJson(obj interface{}) string {
-	return "" // TODO
-}
-
-func DecoderSendResultFromJson(json string) *SendResult {
-	return nil // TODO
-}
-
-func (result *SendResult) TraceOn() bool {
-	return result.traceOn
-}
-
-func (result *SendResult) SetTraceOn(b bool) {
-	result.traceOn = b
-}
-
-func (result *SendResult) SetRegionID(s string) {
-	result.regionID = s
-}
-
-func (result *SendResult) MsgID() string {
-	return result.msgID
-}
-
-func (result *SendResult) SetMsgID(s string) {
-	result.msgID = s
-}
-
-func (result *SendResult) SendStatus() SendStatus {
-	return result.sendStatus
-}
-
-func (result *SendResult) SetSendStatus(status SendStatus) {
-	result.sendStatus = status
-}
-
-func (result *SendResult) MessageQueue() MessageQueue {
-	return result.messageQueue
-}
-
-func (result *SendResult) SetMessageQueue(queue MessageQueue) {
-	result.messageQueue = queue
-}
-
-func (result *SendResult) QueueOffset() int64 {
-	return result.queueOffset
-}
-
-func (result *SendResult) SetQueueOffset(offset int64) {
-	result.queueOffset = offset
-}
-
-func (result *SendResult) TransactionID() string {
-	return result.transactionID
-}
-
-func (result *SendResult) SetTransactionID(s string) {
-	result.transactionID = s
-}
-
-func (result *SendResult) OffsetMsgID() string {
-	return result.offsetMsgID
-}
-
-func (result *SendResult) SetOffsetMsgID(s string) {
-	result.offsetMsgID = s
-}
-
-func (result *SendResult) String() string {
-	return fmt.Sprintf("SendResult [sendStatus=%s, msgId=%s, offsetMsgId=%s, messageQueue=%s, queueOffset=%s]",
-		result.sendStatus, result.msgID, result.offsetMsgID, result.messageQueue, result.queueOffset)
-}
diff --git a/rocketmq-go/model/subscription_data.go b/rocketmq-go/model/subscription_data.go
index ce5ae74..134559a 100644
--- a/rocketmq-go/model/subscription_data.go
+++ b/rocketmq-go/model/subscription_data.go
@@ -1,21 +1,23 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
+//SubscriptionData message subscription data
 type SubscriptionData struct {
 	Topic           string
 	SubString       string
diff --git a/rocketmq-go/model/topic_publish_info.go b/rocketmq-go/model/topic_publish_info.go
index 26a541c..6d833c9 100644
--- a/rocketmq-go/model/topic_publish_info.go
+++ b/rocketmq-go/model/topic_publish_info.go
@@ -1,56 +1,64 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package model
 
 import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
 	"sync/atomic"
 )
 
+//TopicPublishInfo TopicPublishInfo
 type TopicPublishInfo struct {
 	OrderTopic             bool
 	HaveTopicRouterInfo    bool
-	MessageQueueList       []MessageQueue
+	MessageQueueList       []rocketmqm.MessageQueue
 	TopicRouteDataInstance *TopicRouteData
 	topicQueueIndex        int32
 }
 
-func (self *TopicPublishInfo) JudgeTopicPublishInfoOk() (bIsTopicOk bool) {
-	bIsTopicOk = (len(self.MessageQueueList) > 0)
+//JudgeTopicPublishInfoOk JudgeTopicPublishInfoOk
+func (t *TopicPublishInfo) JudgeTopicPublishInfoOk() (bIsTopicOk bool) {
+	bIsTopicOk = (len(t.MessageQueueList) > 0)
 	return
 }
-func (self *TopicPublishInfo) FetchQueueIndex() (index int) {
-	qLen := len(self.MessageQueueList)
+
+//FetchQueueIndex FetchQueueIndex
+func (t *TopicPublishInfo) FetchQueueIndex() (index int) {
+	qLen := len(t.MessageQueueList)
 	if qLen > 0 {
-		qIndex := atomic.AddInt32(&self.topicQueueIndex, 1)
+		qIndex := atomic.AddInt32(&t.topicQueueIndex, 1)
 		qIndex = qIndex % int32(qLen)
 		index = int(qIndex)
 	}
 	return
 }
-func BuildTopicSubscribeInfoFromRoteData(topic string, topicRouteData *TopicRouteData) (mqList []*MessageQueue) {
-	mqList = make([]*MessageQueue, 0)
+
+//BuildTopicSubscribeInfoFromRoteData BuildTopicSubscribeInfoFromRoteData
+func BuildTopicSubscribeInfoFromRoteData(topic string, topicRouteData *TopicRouteData) (mqList []*rocketmqm.MessageQueue) {
+	mqList = make([]*rocketmqm.MessageQueue, 0)
 	for _, queueData := range topicRouteData.QueueDatas {
 		if !constant.ReadAble(queueData.Perm) {
 			continue
 		}
 		var i int32
 		for i = 0; i < queueData.ReadQueueNums; i++ {
-			mq := &MessageQueue{
+			mq := &rocketmqm.MessageQueue{
 				Topic:      topic,
 				BrokerName: queueData.BrokerName,
 				QueueId:    i,
@@ -61,12 +69,12 @@
 	return
 }
 
+//BuildTopicPublishInfoFromTopicRoteData BuildTopicPublishInfoFromTopicRoteData
 func BuildTopicPublishInfoFromTopicRoteData(topic string, topicRouteData *TopicRouteData) (topicPublishInfo *TopicPublishInfo) {
-	// all order topic is false  todo change
 	topicPublishInfo = &TopicPublishInfo{
 		TopicRouteDataInstance: topicRouteData,
 		OrderTopic:             false,
-		MessageQueueList:       []MessageQueue{}}
+		MessageQueueList:       []rocketmqm.MessageQueue{}}
 	for _, queueData := range topicRouteData.QueueDatas {
 		if !constant.WriteAble(queueData.Perm) {
 			continue
@@ -78,7 +86,7 @@
 				}
 				var i int32
 				for i = 0; i < queueData.WriteQueueNums; i++ {
-					messageQueue := MessageQueue{Topic: topic, BrokerName: queueData.BrokerName, QueueId: i}
+					messageQueue := rocketmqm.MessageQueue{Topic: topic, BrokerName: queueData.BrokerName, QueueId: i}
 					topicPublishInfo.MessageQueueList = append(topicPublishInfo.MessageQueueList, messageQueue)
 					topicPublishInfo.HaveTopicRouterInfo = true
 				}
diff --git a/rocketmq-go/model/topic_route_data.go b/rocketmq-go/model/topic_route_data.go
index 9c1ab27..eabd50e 100644
--- a/rocketmq-go/model/topic_route_data.go
+++ b/rocketmq-go/model/topic_route_data.go
@@ -1,19 +1,19 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
 
 package model
 
@@ -21,11 +21,14 @@
 	"sync"
 )
 
+//TopicRouteData TopicRouteData
 type TopicRouteData struct {
 	OrderTopicConf string
 	QueueDatas     []*QueueData
 	BrokerDatas    []*BrokerData
 }
+
+//QueueData QueueData
 type QueueData struct {
 	BrokerName     string
 	ReadQueueNums  int32
@@ -33,6 +36,8 @@
 	Perm           int32
 	TopicSynFlag   int32
 }
+
+//BrokerData BrokerData
 type BrokerData struct {
 	BrokerName      string
 	BrokerAddrs     map[string]string
diff --git a/rocketmq-go/mq_client_manage.go b/rocketmq-go/mq_client_manage.go
deleted file mode 100644
index 7903116..0000000
--- a/rocketmq-go/mq_client_manage.go
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util/structs"
-	"github.com/golang/glog"
-	"strings"
-	"sync"
-	"time"
-)
-
-//@see com.alibaba.rocketmq.client.impl.factory.MQClientInstance
-type MqClientManager struct {
-	rocketMqManagerLock sync.Mutex
-	//ClientId            string
-	BootTimestamp int64
-
-	clientFactory *ClientFactory
-
-	NamesrvLock   sync.Mutex
-	HeartBeatLock sync.Mutex
-	//all producer and consumer use this
-	mqClient service.RocketMqClient
-	//all producer and consumer use this
-	//private final ClientRemotingProcessor clientRemotingProcessor;
-	//	private final PullMessageService pullMessageService;
-	//private final RebalanceService rebalanceService;
-	//	private final ConsumerStatsManager consumerStatsManager;
-	//	private final AtomicLong storeTimesTotal = new AtomicLong(0);
-	ServiceState int
-
-	//should be here because need all producer consumer
-	pullMessageController    *PullMessageController
-	cleanExpireMsgController *CleanExpireMsgController
-	rebalanceControllr       *RebalanceController
-	//should be here because need all producer consumer
-	defaultProducerService *service.DefaultProducerService //for send back message
-}
-
-func MqClientManagerInit(clientConfig *config.ClientConfig) (rocketMqManager *MqClientManager) {
-	rocketMqManager = &MqClientManager{}
-	rocketMqManager.BootTimestamp = time.Now().Unix()
-	rocketMqManager.clientFactory = ClientFactoryInit()
-	rocketMqManager.mqClient = service.MqClientInit(clientConfig, rocketMqManager.InitClientRequestProcessor()) // todo todo todo
-	rocketMqManager.pullMessageController = NewPullMessageController(rocketMqManager.mqClient, rocketMqManager.clientFactory)
-	rocketMqManager.cleanExpireMsgController = NewCleanExpireMsgController(rocketMqManager.mqClient, rocketMqManager.clientFactory)
-	rocketMqManager.rebalanceControllr = NewRebalanceController(rocketMqManager.clientFactory)
-
-	return
-}
-
-//CHECK_TRANSACTION_STATE
-//NOTIFY_CONSUMER_IDS_CHANGED
-//RESET_CONSUMER_CLIENT_OFFSET
-//GET_CONSUMER_STATUS_FROM_CLIENT
-//GET_CONSUMER_RUNNING_INFO
-//CONSUME_MESSAGE_DIRECTLY
-func (self *MqClientManager) InitClientRequestProcessor() (clientRequestProcessor remoting.ClientRequestProcessor) {
-	clientRequestProcessor = func(cmd *remoting.RemotingCommand) (response *remoting.RemotingCommand) {
-		switch cmd.Code {
-		case remoting.CHECK_TRANSACTION_STATE:
-			glog.V(2).Info("receive_request_code CHECK_TRANSACTION_STATE")
-			// todo this version don't impl this
-			break
-		case remoting.NOTIFY_CONSUMER_IDS_CHANGED:
-			glog.V(1).Info("receive_request_code NOTIFY_CONSUMER_IDS_CHANGED")
-			self.rebalanceControllr.doRebalance()
-			break
-		case remoting.RESET_CONSUMER_CLIENT_OFFSET: //  struct json key supported
-			glog.V(2).Info("receive_request_code RESET_CONSUMER_CLIENT_OFFSET")
-			glog.V(2).Info("op=look cmd body", string(cmd.Body))
-			var resetOffsetRequestHeader = &header.ResetOffsetRequestHeader{}
-			if cmd.ExtFields != nil {
-				resetOffsetRequestHeader.FromMap(cmd.ExtFields) //change map[string]interface{} into CustomerHeader struct
-				glog.V(2).Info("op=look ResetOffsetRequestHeader", resetOffsetRequestHeader)
-				resetOffsetBody := &model.ResetOffsetBody{}
-				err := resetOffsetBody.Decode(cmd.Body)
-				if err != nil {
-					return
-				}
-				glog.V(2).Info("op=look resetOffsetBody xxxxx", resetOffsetBody)
-				self.resetConsumerOffset(resetOffsetRequestHeader.Topic, resetOffsetRequestHeader.Group, resetOffsetBody.OffsetTable)
-			}
-			break
-		case remoting.GET_CONSUMER_STATUS_FROM_CLIENT: // useless we can use GET_CONSUMER_RUNNING_INFO instead
-			glog.V(2).Info("receive_request_code GET_CONSUMER_STATUS_FROM_CLIENT")
-			break
-		case remoting.GET_CONSUMER_RUNNING_INFO:
-			glog.V(2).Info("receive_request_code GET_CONSUMER_RUNNING_INFO")
-			var getConsumerRunningInfoRequestHeader = &header.GetConsumerRunningInfoRequestHeader{}
-			if cmd.ExtFields != nil {
-				getConsumerRunningInfoRequestHeader.FromMap(cmd.ExtFields) //change map[string]interface{} into CustomerHeader struct
-				consumerRunningInfo := model.ConsumerRunningInfo{}
-				consumerRunningInfo.Properties = map[string]string{}
-				defaultMQPushConsumer := self.clientFactory.ConsumerTable[getConsumerRunningInfoRequestHeader.ConsumerGroup]
-				consumerConfigMap := structs.Map(defaultMQPushConsumer.ConsumerConfig) // todo test
-				for key, value := range consumerConfigMap {
-					consumerRunningInfo.Properties[key] = fmt.Sprintf("%v", value)
-				}
-
-				consumerRunningInfo.Properties["PROP_NAMESERVER_ADDR"] = strings.Join(defaultMQPushConsumer.mqClient.GetRemotingClient().GetNamesrvAddrList(), ";")
-				consumerRunningInfo.MqTable = defaultMQPushConsumer.rebalance.GetMqTableInfo()
-
-				glog.V(2).Info("op=look consumerRunningInfo", consumerRunningInfo)
-				jsonByte, err := consumerRunningInfo.Encode()
-				glog.V(2).Info("op=enCode jsonByte", string(jsonByte))
-				if err != nil {
-					glog.Error(err)
-					return
-				}
-				response = remoting.NewRemotingCommandWithBody(remoting.SUCCESS, nil, jsonByte)
-			}
-
-			break
-		case remoting.CONSUME_MESSAGE_DIRECTLY:
-			glog.V(2).Info("receive_request_code CONSUME_MESSAGE_DIRECTLY")
-			var consumeMessageDirectlyResultRequestHeader = &header.ConsumeMessageDirectlyResultRequestHeader{}
-			if cmd.ExtFields != nil {
-				consumeMessageDirectlyResultRequestHeader.FromMap(cmd.ExtFields)
-				messageExt := &DecodeMessage(cmd.Body)[0]
-				glog.V(2).Info("op=look", messageExt)
-				defaultMQPushConsumer := self.clientFactory.ConsumerTable[consumeMessageDirectlyResultRequestHeader.ConsumerGroup]
-				consumeResult, err := defaultMQPushConsumer.consumeMessageService.ConsumeMessageDirectly(messageExt, consumeMessageDirectlyResultRequestHeader.BrokerName)
-				if err != nil {
-					return
-				}
-				jsonByte, err := json.Marshal(consumeResult)
-				if err != nil {
-					glog.Error(err)
-					return
-				}
-				response = remoting.NewRemotingCommandWithBody(remoting.SUCCESS, nil, jsonByte)
-			}
-		default:
-			glog.Error("illeage requestCode ", cmd.Code)
-		}
-		return
-	}
-	return
-}
-func (self *MqClientManager) RegistProducer(producer *DefaultMQProducer) {
-	producer.producerService = service.NewDefaultProducerService(producer.producerGroup, producer.ProducerConfig, self.mqClient)
-	self.clientFactory.ProducerTable[producer.producerGroup] = producer
-	return
-}
-
-func (self *MqClientManager) resetConsumerOffset(topic, group string, offsetTable map[model.MessageQueue]int64) {
-	consumer := self.clientFactory.ConsumerTable[group]
-	if consumer == nil {
-		glog.Error("resetConsumerOffset beacuse consumer not online,group=", group)
-		return
-	}
-	consumer.resetOffset(offsetTable)
-}
-func (self *MqClientManager) RegistConsumer(consumer *DefaultMQPushConsumer) {
-	if self.defaultProducerService == nil {
-		self.defaultProducerService = service.NewDefaultProducerService(constant.CLIENT_INNER_PRODUCER_GROUP, config.NewProducerConfig(), self.mqClient)
-	}
-	consumer.mqClient = self.mqClient
-	consumer.offsetStore = service.RemoteOffsetStoreInit(consumer.consumerGroup, self.mqClient)
-	self.clientFactory.ConsumerTable[consumer.consumerGroup] = consumer
-	consumer.rebalance = service.NewRebalance(consumer.consumerGroup, consumer.subscription, consumer.mqClient, consumer.offsetStore, consumer.ConsumerConfig)
-
-	fmt.Println(consumer.consumeMessageService)
-
-	consumer.consumeMessageService.Init(consumer.consumerGroup, self.mqClient, consumer.offsetStore, self.defaultProducerService, consumer.ConsumerConfig)
-	return
-}
-
-func (self *MqClientManager) Start() {
-	//self.SendHeartbeatToAllBrokerWithLock()//we should send heartbeat first
-	self.StartAllScheduledTask()
-}
-
-func (self MqClientManager) ShutDown() {
-
-}
-
-type ClientFactory struct {
-	ProducerTable map[string]*DefaultMQProducer     //group|RocketMQProducer
-	ConsumerTable map[string]*DefaultMQPushConsumer //group|Consumer
-}
-
-func ClientFactoryInit() (clientFactory *ClientFactory) {
-	clientFactory = &ClientFactory{}
-	clientFactory.ProducerTable = make(map[string]*DefaultMQProducer)
-	clientFactory.ConsumerTable = make(map[string]*DefaultMQPushConsumer)
-	return
-}
-
-//heart beat
-func (self MqClientManager) SendHeartbeatToAllBrokerWithLock() error {
-	heartbeatData := self.prepareHeartbeatData()
-	if len(heartbeatData.ConsumerDataSet) == 0 {
-		return errors.New("send heartbeat error")
-	}
-	self.mqClient.SendHeartbeatToAllBroker(heartbeatData)
-	return nil
-}
-
-//routeInfo
-func (self MqClientManager) UpdateTopicRouteInfoFromNameServer() {
-	var topicSet []string
-	for _, consumer := range self.clientFactory.ConsumerTable {
-		for key, _ := range consumer.subscription {
-			topicSet = append(topicSet, key)
-		}
-	}
-	topicSet = append(topicSet, self.mqClient.GetPublishTopicList()...)
-	for _, topic := range topicSet {
-		self.mqClient.UpdateTopicRouteInfoFromNameServer(topic)
-
-	}
-}
-
-func (self MqClientManager) prepareHeartbeatData() *model.HeartbeatData {
-	heartbeatData := new(model.HeartbeatData)
-	heartbeatData.ClientId = self.mqClient.GetClientId()
-	heartbeatData.ConsumerDataSet = make([]*model.ConsumerData, 0)
-	heartbeatData.ProducerDataSet = make([]*model.ProducerData, 0)
-	for group, consumer := range self.clientFactory.ConsumerTable {
-		consumerData := new(model.ConsumerData)
-		consumerData.GroupName = group
-		consumerData.ConsumeType = consumer.consumeType
-		consumerData.ConsumeFromWhere = consumer.ConsumerConfig.ConsumeFromWhere
-		consumerData.MessageModel = consumer.messageModel
-		consumerData.SubscriptionDataSet = consumer.Subscriptions()
-		consumerData.UnitMode = consumer.unitMode
-		heartbeatData.ConsumerDataSet = append(heartbeatData.ConsumerDataSet, consumerData)
-	}
-	for group := range self.clientFactory.ProducerTable {
-		producerData := new(model.ProducerData)
-		producerData.GroupName = group
-		heartbeatData.ProducerDataSet = append(heartbeatData.ProducerDataSet, producerData)
-	}
-	return heartbeatData
-}
diff --git a/rocketmq-go/mq_producer.go b/rocketmq-go/mq_producer.go
deleted file mode 100644
index 098377d..0000000
--- a/rocketmq-go/mq_producer.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package rocketmq
-
-import ()
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-)
-
-type RocketMQProducer interface {
-	Send(message *model.Message) (sendResult *model.SendResult, err error)
-	SendWithTimeout(message *model.Message, timeout int) (sendResult *model.SendResult, err error)
-	//SendAsync(message *model.Message) (sendResult *model.SendResult,err error)
-	//SendAsyncWithTimeout(message *model.Message) (sendResult *model.SendResult,err error)
-	//SendOneWay(message *model.Message) (sendResult *model.SendResult,err error)
-}
-type DefaultMQProducer struct {
-	producerGroup  string
-	ProducerConfig *config.RocketMqProducerConfig
-
-	producerService service.ProducerService
-}
-
-func NewDefaultMQProducer(producerGroup string) (rocketMQProducer *DefaultMQProducer) {
-	rocketMQProducer = &DefaultMQProducer{
-		producerGroup:  producerGroup,
-		ProducerConfig: config.NewProducerConfig(),
-	}
-	return
-}
-
-func (self *DefaultMQProducer) Send(message *model.Message) (sendResult *model.SendResult, err error) {
-	sendResult, err = self.producerService.SendDefaultImpl(message, constant.COMMUNICATIONMODE_SYNC, "", self.ProducerConfig.SendMsgTimeout)
-	return
-}
-func (self *DefaultMQProducer) SendWithTimeout(message *model.Message, timeout int64) (sendResult *model.SendResult, err error) {
-	sendResult, err = self.producerService.SendDefaultImpl(message, constant.COMMUNICATIONMODE_SYNC, "", timeout)
-	return
-}
diff --git a/rocketmq-go/mq_push_consumer.go b/rocketmq-go/mq_push_consumer.go
deleted file mode 100644
index 245bbe4..0000000
--- a/rocketmq-go/mq_push_consumer.go
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-	"github.com/golang/glog"
-	"strings"
-	"time"
-)
-
-type Consumer interface {
-	RegisterMessageListener(listener model.MessageListener)
-	Subscribe(topic string, subExpression string)
-}
-
-type DefaultMQPushConsumer struct {
-	consumerGroup string
-	//consumeFromWhere      string
-	consumeType  string
-	messageModel string
-	unitMode     bool
-
-	subscription          map[string]string   //topic|subExpression
-	subscriptionTag       map[string][]string // we use it filter again
-	offsetStore           service.OffsetStore
-	mqClient              service.RocketMqClient
-	rebalance             *service.Rebalance
-	pause                 bool //when reset offset we need pause
-	consumeMessageService service.ConsumeMessageService
-	ConsumerConfig        *config.RocketMqConsumerConfig
-}
-
-func NewDefaultMQPushConsumer(consumerGroup string) (defaultMQPushConsumer *DefaultMQPushConsumer) {
-	defaultMQPushConsumer = &DefaultMQPushConsumer{
-		consumerGroup: consumerGroup,
-		//consumeFromWhere:"CONSUME_FROM_FIRST_OFFSET", //todo  use config
-		consumeType:  "CONSUME_PASSIVELY",
-		messageModel: "CLUSTERING",
-		pause:        false}
-	defaultMQPushConsumer.subscription = make(map[string]string)
-	defaultMQPushConsumer.subscriptionTag = make(map[string][]string)
-	defaultMQPushConsumer.ConsumerConfig = config.NewRocketMqConsumerConfig()
-	return
-}
-func (self *DefaultMQPushConsumer) Subscribe(topic string, subExpression string) {
-	self.subscription[topic] = subExpression
-	if len(subExpression) == 0 || subExpression == "*" {
-		return
-	}
-	tags := strings.Split(subExpression, "||")
-	tagsList := []string{}
-	for _, tag := range tags {
-		t := strings.TrimSpace(tag)
-		if len(t) == 0 {
-			continue
-		}
-		tagsList = append(tagsList, t)
-	}
-	if len(tagsList) > 0 {
-		self.subscriptionTag[topic] = tagsList
-	}
-}
-
-func (self *DefaultMQPushConsumer) RegisterMessageListener(messageListener model.MessageListener) {
-	self.consumeMessageService = service.NewConsumeMessageConcurrentlyServiceImpl(messageListener)
-}
-
-func (self *DefaultMQPushConsumer) resetOffset(offsetTable map[model.MessageQueue]int64) {
-	self.pause = true
-	glog.Info("now we ClearProcessQueue 0 ", offsetTable)
-
-	self.rebalance.ClearProcessQueue(offsetTable)
-	glog.Info("now we ClearProcessQueue", offsetTable)
-	go func() {
-		waitTime := time.NewTimer(10 * time.Second)
-		<-waitTime.C
-		defer func() {
-			self.pause = false
-			self.rebalance.DoRebalance()
-		}()
-
-		for messageQueue, offset := range offsetTable {
-			processQueue := self.rebalance.GetProcessQueue(messageQueue)
-			if processQueue == nil || offset < 0 {
-				continue
-			}
-			glog.Info("now we UpdateOffset", messageQueue, offset)
-			self.offsetStore.UpdateOffset(&messageQueue, offset, false)
-			self.rebalance.RemoveProcessQueue(&messageQueue)
-		}
-	}()
-}
-
-func (self *DefaultMQPushConsumer) Subscriptions() []*model.SubscriptionData {
-	subscriptions := make([]*model.SubscriptionData, 0)
-	for _, subscription := range self.rebalance.SubscriptionInner {
-		subscriptions = append(subscriptions, subscription)
-	}
-	return subscriptions
-}
-
-func (self *DefaultMQPushConsumer) CleanExpireMsg() {
-	nowTime := int64(time.Now().UnixNano()) / 1000000 //will cause nowTime - consumeStartTime <0 ,but no matter
-	messageQueueList, processQueueList := self.rebalance.GetProcessQueueList()
-	for messageQueueIndex, processQueue := range processQueueList {
-		loop := processQueue.GetMsgCount()
-		if loop > 16 {
-			loop = 16
-		}
-		for i := 0; i < loop; i++ {
-			_, message := processQueue.GetMinMessageInTree()
-			if message == nil {
-				break
-			}
-			consumeStartTime := message.GetConsumeStartTime()
-			maxDiffTime := self.ConsumerConfig.ConsumeTimeout * 1000 * 60
-			//maxDiffTime := self.ConsumerConfig.ConsumeTimeout
-			glog.V(2).Info("look message.GetConsumeStartTime()", consumeStartTime)
-			glog.V(2).Infof("look diff %d  %d", nowTime-consumeStartTime, maxDiffTime)
-			//if(nowTime - consumeStartTime <0){
-			//	panic("nowTime - consumeStartTime <0")
-			//}
-			if nowTime-consumeStartTime < maxDiffTime {
-				break
-			}
-			glog.Info("look now we send expire message back", message.Topic, message.MsgId)
-			err := self.consumeMessageService.SendMessageBack(message, 3, messageQueueList[messageQueueIndex].BrokerName)
-			if err != nil {
-				glog.Error("op=send_expire_message_back_error", err)
-				continue
-			}
-			processQueue.DeleteExpireMsg(int(message.QueueOffset))
-		}
-	}
-	return
-}
diff --git a/rocketmq-go/pull_message_controller.go b/rocketmq-go/pull_message_controller.go
deleted file mode 100644
index 320cc31..0000000
--- a/rocketmq-go/pull_message_controller.go
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-import (
-	"bytes"
-	"compress/zlib"
-	"encoding/binary"
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"github.com/golang/glog"
-	"io/ioutil"
-	"strconv"
-	"time"
-)
-
-type PullMessageController struct {
-	mqClient      service.RocketMqClient
-	clientFactory *ClientFactory
-}
-
-func NewPullMessageController(mqClient service.RocketMqClient, clientFactory *ClientFactory) *PullMessageController {
-	return &PullMessageController{
-		mqClient:      mqClient,
-		clientFactory: clientFactory,
-	}
-}
-
-func (self *PullMessageController) Start() {
-	go func() {
-		for {
-			pullRequest := self.mqClient.DequeuePullMessageRequest()
-			self.pullMessage(pullRequest)
-		}
-	}()
-}
-
-func (self *PullMessageController) needDelayPullMessage(mqPushConsumer *DefaultMQPushConsumer, pullRequest *model.PullRequest) (needDelayTime int64) {
-	if pullRequest.ProcessQueue.GetMsgCount() > mqPushConsumer.ConsumerConfig.PullThresholdForQueue {
-		return mqPushConsumer.ConsumerConfig.PullTimeDelayMillsWhenFlowControl
-	}
-	if pullRequest.ProcessQueue.GetMaxSpan() > mqPushConsumer.ConsumerConfig.ConsumeConcurrentlyMaxSpan {
-		return mqPushConsumer.ConsumerConfig.PullTimeDelayMillsWhenFlowControl
-	}
-	return
-}
-
-func (self *PullMessageController) pullMessageLater(pullRequest *model.PullRequest, millisecond int64) {
-	go func() {
-		timeoutTimer := time.NewTimer(time.Duration(millisecond) * time.Millisecond)
-		<-timeoutTimer.C
-		self.pullMessage(pullRequest)
-	}()
-	return
-}
-
-func (self *PullMessageController) pullMessage(pullRequest *model.PullRequest) {
-	defaultMQPullConsumer := self.clientFactory.ConsumerTable[pullRequest.ConsumerGroup]
-	if pullRequest.ProcessQueue.IsDropped() {
-		return
-	}
-
-	//pullRequest.ProcessQueue.SetLastPullTimestamp(System.currentTimeMillis());
-	// state ok
-	// isPause
-
-	delayPullTime := self.needDelayPullMessage(defaultMQPullConsumer, pullRequest)
-	if delayPullTime > 0 {
-		self.pullMessageLater(pullRequest, delayPullTime)
-		return
-	}
-	commitOffsetValue := defaultMQPullConsumer.offsetStore.ReadOffset(pullRequest.MessageQueue, service.READ_FROM_MEMORY)
-
-	subscriptionData, ok := defaultMQPullConsumer.rebalance.SubscriptionInner[pullRequest.MessageQueue.Topic]
-	if !ok {
-		self.pullMessageLater(pullRequest, defaultMQPullConsumer.ConsumerConfig.PullTimeDelayMillsWhenException)
-		return
-	}
-
-	var sysFlag int32 = 0
-	if commitOffsetValue > 0 {
-		sysFlag |= constant.FLAG_COMMIT_OFFSET
-	}
-	sysFlag |= constant.FLAG_SUSPEND
-	sysFlag |= constant.FLAG_SUBSCRIPTION
-	requestHeader := new(header.PullMessageRequestHeader)
-	requestHeader.ConsumerGroup = pullRequest.ConsumerGroup
-	requestHeader.Topic = pullRequest.MessageQueue.Topic
-	requestHeader.QueueId = pullRequest.MessageQueue.QueueId
-	requestHeader.QueueOffset = pullRequest.NextOffset
-
-	requestHeader.CommitOffset = commitOffsetValue
-	requestHeader.SuspendTimeoutMillis = defaultMQPullConsumer.ConsumerConfig.BrokerSuspendMaxTimeMillis
-	requestHeader.MaxMsgNums = int32(defaultMQPullConsumer.ConsumerConfig.PullBatchSize)
-	requestHeader.SubVersion = subscriptionData.SubVersion
-	requestHeader.Subscription = subscriptionData.SubString
-
-	requestHeader.SysFlag = sysFlag
-
-	pullCallback := func(responseFuture *remoting.ResponseFuture) {
-		var nextBeginOffset int64 = pullRequest.NextOffset
-
-		if responseFuture != nil {
-			responseCommand := responseFuture.ResponseCommand
-			if responseCommand.Code == remoting.SUCCESS && len(responseCommand.Body) > 0 {
-				//FOUND
-				var err error
-				pullResult := responseCommand.ExtFields
-				if ok {
-					if nextBeginOffsetInter, ok := pullResult["nextBeginOffset"]; ok {
-						if nextBeginOffsetStr, ok := nextBeginOffsetInter.(string); ok {
-							nextBeginOffset, err = strconv.ParseInt(nextBeginOffsetStr, 10, 64)
-							if err != nil {
-								glog.Error(err)
-								return
-							}
-						}
-					}
-				}
-				msgs := DecodeMessage(responseFuture.ResponseCommand.Body)
-
-				msgs = FilterMessageAgainByTags(msgs, defaultMQPullConsumer.subscriptionTag[pullRequest.MessageQueue.Topic])
-				if len(msgs) == 0 {
-					if pullRequest.ProcessQueue.GetMsgCount() == 0 {
-						defaultMQPullConsumer.offsetStore.UpdateOffset(pullRequest.MessageQueue, nextBeginOffset, true)
-					}
-				}
-				//
-				pullRequest.ProcessQueue.PutMessage(msgs)
-				defaultMQPullConsumer.consumeMessageService.SubmitConsumeRequest(msgs, pullRequest.ProcessQueue, pullRequest.MessageQueue, true)
-			} else {
-				//glog.Error(fmt.Sprintf("pull message error,code=%d,body=%s", responseCommand.Code, string(responseCommand.Body)))
-				var err error // change the offset , use nextBeginOffset
-				pullResult := responseCommand.ExtFields
-				if ok {
-					if nextBeginOffsetInter, ok := pullResult["nextBeginOffset"]; ok {
-						if nextBeginOffsetStr, ok := nextBeginOffsetInter.(string); ok {
-							nextBeginOffset, err = strconv.ParseInt(nextBeginOffsetStr, 10, 64)
-							if err != nil {
-								glog.Error(err)
-							}
-						}
-					}
-				}
-				if responseCommand.Code == remoting.PULL_NOT_FOUND || responseCommand.Code == remoting.PULL_RETRY_IMMEDIATELY {
-					//NO_NEW_MSG //NO_MATCHED_MSG
-					if pullRequest.ProcessQueue.GetMsgCount() == 0 {
-						defaultMQPullConsumer.offsetStore.UpdateOffset(pullRequest.MessageQueue, nextBeginOffset, true)
-					}
-					//update offset increase only
-					//failedPullRequest, _ := json.Marshal(pullRequest)
-					//glog.Error("the pull request offset illegal", string(failedPullRequest))
-				} else if responseCommand.Code == remoting.PULL_OFFSET_MOVED {
-					//OFFSET_ILLEGAL
-					glog.Error(fmt.Sprintf("PULL_OFFSET_MOVED,code=%d,body=%s", responseCommand.Code, string(responseCommand.Body)))
-					pullRequest.ProcessQueue.SetDrop(true)
-					go func() {
-						executeTaskLater := time.NewTimer(10 * time.Second)
-						<-executeTaskLater.C
-						defaultMQPullConsumer.offsetStore.UpdateOffset(pullRequest.MessageQueue, nextBeginOffset, false)
-						defaultMQPullConsumer.rebalance.RemoveProcessQueue(pullRequest.MessageQueue)
-					}()
-				} else {
-					glog.Errorf("illegal response code. pull message error,code=%d,request=%v OFFSET_ILLEGAL", responseCommand.Code, requestHeader)
-					glog.Error(pullRequest.MessageQueue)
-					time.Sleep(1 * time.Second)
-				}
-			}
-		} else {
-			glog.Error("responseFuture is nil")
-		}
-
-		if pullRequest.ProcessQueue.IsDropped() {
-			return
-		}
-		nextPullRequest := &model.PullRequest{
-			ConsumerGroup: pullRequest.ConsumerGroup,
-			NextOffset:    nextBeginOffset,
-			MessageQueue:  pullRequest.MessageQueue,
-			ProcessQueue:  pullRequest.ProcessQueue,
-		}
-		if defaultMQPullConsumer.ConsumerConfig.PullInterval > 0 {
-			go func() {
-				nextPullTime := time.NewTimer(time.Duration(defaultMQPullConsumer.ConsumerConfig.PullInterval) * time.Millisecond)
-				<-nextPullTime.C
-				self.mqClient.EnqueuePullMessageRequest(nextPullRequest)
-			}()
-		} else {
-			self.mqClient.EnqueuePullMessageRequest(nextPullRequest)
-		}
-	}
-	glog.V(2).Infof("requestHeader look offset %s %s %s %s", requestHeader.QueueOffset, requestHeader.Topic, requestHeader.QueueId, requestHeader.CommitOffset)
-	self.consumerPullMessageAsync(pullRequest.MessageQueue.BrokerName, requestHeader, pullCallback)
-}
-func FilterMessageAgainByTags(msgExts []model.MessageExt, subscriptionTagList []string) (result []model.MessageExt) {
-	result = msgExts
-	if len(subscriptionTagList) == 0 {
-		return
-	}
-	result = []model.MessageExt{}
-	for _, msg := range msgExts {
-		for _, tag := range subscriptionTagList {
-			if tag == msg.GetTag() {
-				result = append(result, msg)
-				break
-			}
-		}
-	}
-	return
-}
-
-func (self *PullMessageController) consumerPullMessageAsync(brokerName string, requestHeader remoting.CustomerHeader, invokeCallback remoting.InvokeCallback) {
-	brokerAddr, _, found := self.mqClient.FindBrokerAddressInSubscribe(brokerName, 0, false)
-	if found {
-		remotingCommand := remoting.NewRemotingCommand(remoting.PULL_MESSAGE, requestHeader)
-		self.mqClient.GetRemotingClient().InvokeAsync(brokerAddr, remotingCommand, 1000, invokeCallback)
-	}
-}
-
-func DecodeMessage(data []byte) []model.MessageExt {
-	buf := bytes.NewBuffer(data)
-	var storeSize, magicCode, bodyCRC, queueId, flag, sysFlag, reconsumeTimes, bodyLength, bornPort, storePort int32
-	var queueOffset, physicOffset, preparedTransactionOffset, bornTimeStamp, storeTimestamp int64
-	var topicLen byte
-	var topic, body, properties, bornHost, storeHost []byte
-	var propertiesLength int16
-
-	var propertiesmap = make(map[string]string)
-
-	msgs := []model.MessageExt{}
-	for buf.Len() > 0 {
-		msg := model.MessageExt{Message: &model.Message{}}
-		binary.Read(buf, binary.BigEndian, &storeSize)
-		binary.Read(buf, binary.BigEndian, &magicCode)
-		binary.Read(buf, binary.BigEndian, &bodyCRC)
-		binary.Read(buf, binary.BigEndian, &queueId)
-		binary.Read(buf, binary.BigEndian, &flag)
-		binary.Read(buf, binary.BigEndian, &queueOffset)
-		binary.Read(buf, binary.BigEndian, &physicOffset)
-		binary.Read(buf, binary.BigEndian, &sysFlag)
-		binary.Read(buf, binary.BigEndian, &bornTimeStamp)
-		bornHost = make([]byte, 4)
-		binary.Read(buf, binary.BigEndian, &bornHost)
-		binary.Read(buf, binary.BigEndian, &bornPort)
-		binary.Read(buf, binary.BigEndian, &storeTimestamp)
-		storeHost = make([]byte, 4)
-		binary.Read(buf, binary.BigEndian, &storeHost)
-		binary.Read(buf, binary.BigEndian, &storePort)
-		binary.Read(buf, binary.BigEndian, &reconsumeTimes)
-		binary.Read(buf, binary.BigEndian, &preparedTransactionOffset)
-		binary.Read(buf, binary.BigEndian, &bodyLength)
-		if bodyLength > 0 {
-			body = make([]byte, bodyLength)
-			binary.Read(buf, binary.BigEndian, body)
-			if (sysFlag & constant.CompressedFlag) == constant.CompressedFlag {
-				b := bytes.NewReader(body)
-				z, err := zlib.NewReader(b)
-				if err != nil {
-					glog.Error(err)
-					return nil
-				}
-				body, err = ioutil.ReadAll(z)
-				z.Close()
-				if err != nil {
-					glog.Error(err)
-					return nil
-				}
-			}
-		}
-		binary.Read(buf, binary.BigEndian, &topicLen)
-		topic = make([]byte, int(topicLen))
-		binary.Read(buf, binary.BigEndian, &topic)
-		binary.Read(buf, binary.BigEndian, &propertiesLength)
-		if propertiesLength > 0 {
-			properties = make([]byte, propertiesLength)
-			binary.Read(buf, binary.BigEndian, &properties)
-			propertiesmap = util.String2MessageProperties(string(properties))
-		}
-
-		if magicCode != -626843481 {
-			glog.Errorf("magic code is error %d", magicCode)
-			return nil
-		}
-
-		msg.Topic = string(topic)
-		msg.QueueId = queueId
-		msg.SysFlag = sysFlag
-		msg.QueueOffset = queueOffset
-		msg.BodyCRC = bodyCRC
-		msg.StoreSize = storeSize
-		msg.BornTimestamp = bornTimeStamp
-		msg.ReconsumeTimes = reconsumeTimes
-		msg.Flag = int(flag)
-		msg.CommitLogOffset = physicOffset
-		msg.StoreTimestamp = storeTimestamp
-		msg.PreparedTransactionOffset = preparedTransactionOffset
-		msg.Body = body
-		msg.Properties = propertiesmap
-
-		//  <  3.5.8 use messageOffsetId
-		//  >= 3.5.8 use clientUniqMsgId
-		msg.MsgId = msg.GetMsgUniqueKey()
-		if len(msg.MsgId) == 0 {
-			msg.MsgId = util.GeneratorMessageOffsetId(storeHost, storePort, msg.CommitLogOffset)
-		}
-		msgs = append(msgs, msg)
-	}
-
-	return msgs
-}
diff --git a/rocketmq-go/rebalance_controller.go b/rocketmq-go/rebalance_controller.go
deleted file mode 100644
index d6d4001..0000000
--- a/rocketmq-go/rebalance_controller.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-type RebalanceController struct {
-	clientFactory *ClientFactory
-}
-
-func NewRebalanceController(clientFactory *ClientFactory) *RebalanceController {
-	return &RebalanceController{
-		clientFactory: clientFactory,
-	}
-}
-
-func (self *RebalanceController) doRebalance() {
-	for _, consumer := range self.clientFactory.ConsumerTable {
-		consumer.rebalance.DoRebalance()
-	}
-}
diff --git a/rocketmq-go/remoting/communication_mode.go b/rocketmq-go/remoting/communication_mode.go
index 3380955..71afc6b 100644
--- a/rocketmq-go/remoting/communication_mode.go
+++ b/rocketmq-go/remoting/communication_mode.go
@@ -1,26 +1,30 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
 
 package remoting
 
+//CommunicationMode Sync|Async|OneWay
 type CommunicationMode int
 
 const (
+	//Sync Sync invoke
 	Sync CommunicationMode = iota
+	//Async ASync invoke
 	Async
+	//OneWay OneWay invoke
 	OneWay
 )
diff --git a/rocketmq-go/remoting/custom_header.go b/rocketmq-go/remoting/custom_header.go
index 04a46be..537875c 100644
--- a/rocketmq-go/remoting/custom_header.go
+++ b/rocketmq-go/remoting/custom_header.go
@@ -1,22 +1,25 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
+//CustomerHeader see kernel.header
 type CustomerHeader interface {
+	//FromMap convert map[string]interface to struct
 	FromMap(headerMap map[string]interface{})
 	//ToMap()(headerMap map[string]interface{})
 }
diff --git a/rocketmq-go/remoting/json_serializable.go b/rocketmq-go/remoting/json_serializable.go
index c2c5ea0..f826c22 100644
--- a/rocketmq-go/remoting/json_serializable.go
+++ b/rocketmq-go/remoting/json_serializable.go
@@ -1,36 +1,38 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 import (
 	"encoding/json"
 )
 
+//JsonSerializer of Serializer
 type JsonSerializer struct {
 }
 
-func (self *JsonSerializer) EncodeHeaderData(command *RemotingCommand) []byte {
+func (j *JsonSerializer) encodeHeaderData(command *RemotingCommand) []byte {
 	buf, err := json.Marshal(command)
 	if err != nil {
 		return nil
 	}
 	return buf
 }
-func (self *JsonSerializer) DecodeRemoteCommand(header, body []byte) *RemotingCommand {
+func (j *JsonSerializer) decodeRemoteCommand(header, body []byte) *RemotingCommand {
 	cmd := &RemotingCommand{}
 	cmd.ExtFields = make(map[string]interface{})
 	err := json.Unmarshal(header, cmd)
diff --git a/rocketmq-go/remoting/json_serializable_test.go b/rocketmq-go/remoting/json_serializable_test.go
new file mode 100644
index 0000000..f9415e0
--- /dev/null
+++ b/rocketmq-go/remoting/json_serializable_test.go
@@ -0,0 +1,58 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package remoting
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
+	"testing"
+)
+
+var testJson = "{\"code\":1,\"language\":\"GO\",\"version\":1,\"opaque\":1,\"flag\":1,\"remark\":\"remark\",\"extFields\":{\"key1\":\"str\",\"key2\":1},\"body\":\"AQIDBA==\"}"
+
+func TestEncodeHeaderData(t *testing.T) {
+	testMap := make(map[string]interface{})
+	testMap["key1"] = "str"
+	testMap["key2"] = 1
+	command := &remoting.RemotingCommand{
+		Code:      1,
+		Language:  "GO",
+		Version:   1,
+		Opaque:    1,
+		Flag:      1,
+		Remark:    "remark",
+		ExtFields: testMap,
+		Body:      []byte{1, 2, 3, 4},
+	}
+	jsonSerializer := remoting.JsonSerializer{}
+
+	resultJson := jsonSerializer.encodeHeaderData(command)
+	if testJson != string(resultJson) {
+		t.Errorf("resultJson is not equals testJson resultJson=%s ", resultJson)
+	}
+}
+
+func TestDecodeRemoteCommand(t *testing.T) {
+	jsonSerializer := remoting.JsonSerializer{}
+	testByte := []byte(testJson)
+	remotingCommand := jsonSerializer.decodeRemoteCommand(testByte, []byte{1, 2, 3, 4})
+	if remotingCommand.Language != "GO" || remotingCommand.Remark != "remark" {
+		t.Error("TestDecodeRemoteCommand fail reslutData")
+	} else {
+		t.Log("TestDecodeRemoteCommandSuccess")
+	}
+}
diff --git a/rocketmq-go/remoting/remoting_client.go b/rocketmq-go/remoting/remoting_client.go
index 206fdcf..3cf0e04 100644
--- a/rocketmq-go/remoting/remoting_client.go
+++ b/rocketmq-go/remoting/remoting_client.go
@@ -1,26 +1,27 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 import (
 	"bytes"
 	"encoding/binary"
 	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
 	"github.com/golang/glog"
 	"math/rand"
@@ -31,46 +32,52 @@
 	"time"
 )
 
+//RemotingClient mq remoting client
 type RemotingClient interface {
+	//InvokeSync sync invoke remote
 	InvokeSync(addr string, request *RemotingCommand, timeoutMillis int64) (remotingCommand *RemotingCommand, err error)
+	//InvokeAsync async invoke remote
 	InvokeAsync(addr string, request *RemotingCommand, timeoutMillis int64, invokeCallback InvokeCallback) error
+	//InvokeOneWay one way invoke remote
 	InvokeOneWay(addr string, request *RemotingCommand, timeoutMillis int64) error
 }
-type DefalutRemotingClient struct {
+
+//DefaultRemotingClient of RemotingClient
+type DefaultRemotingClient struct {
 	clientId     string
-	clientConfig *config.ClientConfig
+	clientConfig *rocketmqm.MqClientConfig
 
 	connTable     map[string]net.Conn
 	connTableLock sync.RWMutex
 
-	responseTable  util.ConcurrentMap //map[int32]*ResponseFuture
-	processorTable util.ConcurrentMap //map[int]ClientRequestProcessor //requestCode|ClientRequestProcessor
-	//	protected final HashMap<Integer/* request code */, Pair<NettyRequestProcessor, ExecutorService>> processorTable =
-	//new HashMap<Integer, Pair<NettyRequestProcessor, ExecutorService>>(64);
+	responseTable            util.ConcurrentMap //map[int32]*ResponseFuture
+	processorTable           util.ConcurrentMap //map[int]ClientRequestProcessor //requestCode|ClientRequestProcessor
 	namesrvAddrList          []string
 	namesrvAddrSelectedAddr  string
-	namesrvAddrSelectedIndex int                    //how to chose. done
-	namesvrLockRW            sync.RWMutex           //
+	namesrvAddrSelectedIndex int
+	namesvrLockRW            sync.RWMutex
 	clientRequestProcessor   ClientRequestProcessor //mange register the processor here
 	serializerHandler        SerializerHandler      //rocketmq encode decode
 }
 
-func RemotingClientInit(clientConfig *config.ClientConfig, clientRequestProcessor ClientRequestProcessor) (client *DefalutRemotingClient) {
-	client = &DefalutRemotingClient{}
+//RemotingClientInit create a RemotingClient instance
+func RemotingClientInit(clientConfig *rocketmqm.MqClientConfig, clientRequestProcessor ClientRequestProcessor) (client *DefaultRemotingClient) {
+	client = &DefaultRemotingClient{}
 	client.connTable = map[string]net.Conn{}
-	client.responseTable = util.New()
+	client.responseTable = util.NewConcurrentMap()
 	client.clientConfig = clientConfig
 
-	client.namesrvAddrList = strings.Split(clientConfig.NameServerAddress(), ";")
+	client.namesrvAddrList = strings.Split(clientConfig.NameServerAddress, ";")
 	client.namesrvAddrSelectedIndex = -1
 	client.clientRequestProcessor = clientRequestProcessor
-	client.serializerHandler = NewSerializerHandler()
+	client.serializerHandler = newSerializerHandler(clientConfig.ClientSerializeType)
 	return
 }
 
-func (self *DefalutRemotingClient) InvokeSync(addr string, request *RemotingCommand, timeoutMillis int64) (remotingCommand *RemotingCommand, err error) {
+//InvokeSync sync invoke remote
+func (drc *DefaultRemotingClient) InvokeSync(addr string, request *RemotingCommand, timeoutMillis int64) (remotingCommand *RemotingCommand, err error) {
 	var conn net.Conn
-	conn, err = self.GetOrCreateConn(addr)
+	conn, err = drc.getOrCreateConn(addr)
 	response := &ResponseFuture{
 		SendRequestOK:  false,
 		Opaque:         request.Opaque,
@@ -78,10 +85,10 @@
 		BeginTimestamp: time.Now().Unix(),
 		Done:           make(chan bool),
 	}
-	header := self.serializerHandler.EncodeHeader(request)
+	header := drc.serializerHandler.encodeHeader(request)
 	body := request.Body
-	self.SetResponse(request.Opaque, response)
-	err = self.sendRequest(header, body, conn, addr)
+	drc.setResponse(request.Opaque, response)
+	err = drc.sendRequest(header, body, conn, addr)
 	if err != nil {
 		glog.Error(err)
 		return
@@ -95,8 +102,10 @@
 		return
 	}
 }
-func (self *DefalutRemotingClient) InvokeAsync(addr string, request *RemotingCommand, timeoutMillis int64, invokeCallback InvokeCallback) error {
-	conn, err := self.GetOrCreateConn(addr)
+
+//InvokeAsync async invoke remote
+func (drc *DefaultRemotingClient) InvokeAsync(addr string, request *RemotingCommand, timeoutMillis int64, invokeCallback InvokeCallback) error {
+	conn, err := drc.getOrCreateConn(addr)
 	if err != nil {
 		return err
 	}
@@ -107,24 +116,10 @@
 		BeginTimestamp: time.Now().Unix(),
 		InvokeCallback: invokeCallback,
 	}
-	self.SetResponse(request.Opaque, response)
-	header := self.serializerHandler.EncodeHeader(request)
+	drc.setResponse(request.Opaque, response)
+	header := drc.serializerHandler.encodeHeader(request)
 	body := request.Body
-	err = self.sendRequest(header, body, conn, addr)
-	if err != nil {
-		glog.Error(err)
-		return err
-	}
-	return err
-}
-func (self *DefalutRemotingClient) InvokeOneWay(addr string, request *RemotingCommand, timeoutMillis int64) error {
-	conn, err := self.GetOrCreateConn(addr)
-	if err != nil {
-		return err
-	}
-	header := self.serializerHandler.EncodeHeader(request)
-	body := request.Body
-	err = self.sendRequest(header, body, conn, addr)
+	err = drc.sendRequest(header, body, conn, addr)
 	if err != nil {
 		glog.Error(err)
 		return err
@@ -132,7 +127,23 @@
 	return err
 }
 
-func (self *DefalutRemotingClient) sendRequest(header, body []byte, conn net.Conn, addr string) error {
+//InvokeOneWay one way invoke remote
+func (drc *DefaultRemotingClient) InvokeOneWay(addr string, request *RemotingCommand, timeoutMillis int64) error {
+	conn, err := drc.getOrCreateConn(addr)
+	if err != nil {
+		return err
+	}
+	header := drc.serializerHandler.encodeHeader(request)
+	body := request.Body
+	err = drc.sendRequest(header, body, conn, addr)
+	if err != nil {
+		glog.Error(err)
+		return err
+	}
+	return err
+}
+
+func (drc *DefaultRemotingClient) sendRequest(header, body []byte, conn net.Conn, addr string) error {
 	var requestBytes []byte
 	requestBytes = append(requestBytes, header...)
 	if body != nil && len(body) > 0 {
@@ -142,21 +153,23 @@
 	if err != nil {
 		glog.Error(err)
 		if len(addr) > 0 {
-			self.ReleaseConn(addr, conn)
+			drc.releaseConn(addr, conn)
 		}
 		return err
 	}
 	return nil
 }
-func (self *DefalutRemotingClient) GetNamesrvAddrList() []string {
-	return self.namesrvAddrList
+
+//GetNamesrvAddrList GetNamesrvAddrList
+func (drc *DefaultRemotingClient) GetNamesrvAddrList() []string {
+	return drc.namesrvAddrList
 }
 
-func (self *DefalutRemotingClient) SetResponse(index int32, response *ResponseFuture) {
-	self.responseTable.Set(strconv.Itoa(int(index)), response)
+func (drc *DefaultRemotingClient) setResponse(index int32, response *ResponseFuture) {
+	drc.responseTable.Set(strconv.Itoa(int(index)), response)
 }
-func (self *DefalutRemotingClient) getResponse(index int32) (response *ResponseFuture, err error) {
-	obj, ok := self.responseTable.Get(strconv.Itoa(int(index)))
+func (drc *DefaultRemotingClient) getResponse(index int32) (response *ResponseFuture, err error) {
+	obj, ok := drc.responseTable.Get(strconv.Itoa(int(index)))
 	if !ok {
 		err = errors.New("get conn from responseTable error")
 		return
@@ -164,102 +177,102 @@
 	response = obj.(*ResponseFuture)
 	return
 }
-func (self *DefalutRemotingClient) removeResponse(index int32) {
-	self.responseTable.Remove(strconv.Itoa(int(index)))
+func (drc *DefaultRemotingClient) removeResponse(index int32) {
+	drc.responseTable.Remove(strconv.Itoa(int(index)))
 }
-func (self *DefalutRemotingClient) GetOrCreateConn(address string) (conn net.Conn, err error) {
+func (drc *DefaultRemotingClient) getOrCreateConn(address string) (conn net.Conn, err error) {
 	if len(address) == 0 {
-		conn, err = self.getNamesvrConn()
+		conn, err = drc.getNamesvrConn()
 		return
 	}
-	conn = self.GetConn(address)
+	conn = drc.getConn(address)
 	if conn != nil {
 		return
 	}
-	conn, err = self.CreateConn(address)
+	conn, err = drc.createConn(address)
 	return
 }
-func (self *DefalutRemotingClient) GetConn(address string) (conn net.Conn) {
-	self.connTableLock.RLock()
-	conn = self.connTable[address]
-	self.connTableLock.RUnlock()
+func (drc *DefaultRemotingClient) getConn(address string) (conn net.Conn) {
+	drc.connTableLock.RLock()
+	conn = drc.connTable[address]
+	drc.connTableLock.RUnlock()
 	return
 }
-func (self *DefalutRemotingClient) CreateConn(address string) (conn net.Conn, err error) {
-	defer self.connTableLock.Unlock()
-	self.connTableLock.Lock()
-	conn = self.connTable[address]
+func (drc *DefaultRemotingClient) createConn(address string) (conn net.Conn, err error) {
+	defer drc.connTableLock.Unlock()
+	drc.connTableLock.Lock()
+	conn = drc.connTable[address]
 	if conn != nil {
 		return
 	}
-	conn, err = self.createAndHandleTcpConn(address)
-	self.connTable[address] = conn
+	conn, err = drc.createAndHandleTcpConn(address)
+	drc.connTable[address] = conn
 	return
 }
 
-func (self *DefalutRemotingClient) getNamesvrConn() (conn net.Conn, err error) {
-	self.namesvrLockRW.RLock()
-	address := self.namesrvAddrSelectedAddr
-	self.namesvrLockRW.RUnlock()
+func (drc *DefaultRemotingClient) getNamesvrConn() (conn net.Conn, err error) {
+	drc.namesvrLockRW.RLock()
+	address := drc.namesrvAddrSelectedAddr
+	drc.namesvrLockRW.RUnlock()
 	if len(address) != 0 {
-		conn = self.GetConn(address)
+		conn = drc.getConn(address)
 		if conn != nil {
 			return
 		}
 	}
 
-	defer self.namesvrLockRW.Unlock()
-	self.namesvrLockRW.Lock()
+	defer drc.namesvrLockRW.Unlock()
+	drc.namesvrLockRW.Lock()
 	//already connected by another write lock owner
-	address = self.namesrvAddrSelectedAddr
+	address = drc.namesrvAddrSelectedAddr
 	if len(address) != 0 {
-		conn = self.GetConn(address)
+		conn = drc.getConn(address)
 		if conn != nil {
 			return
 		}
 	}
 
-	addressCount := len(self.namesrvAddrList)
-	if self.namesrvAddrSelectedIndex < 0 {
-		self.namesrvAddrSelectedIndex = rand.Intn(addressCount)
+	addressCount := len(drc.namesrvAddrList)
+	if drc.namesrvAddrSelectedIndex < 0 {
+		drc.namesrvAddrSelectedIndex = rand.Intn(addressCount)
 	}
 	for i := 1; i <= addressCount; i++ {
-		selectedIndex := (self.namesrvAddrSelectedIndex + i) % addressCount
-		selectAddress := self.namesrvAddrList[selectedIndex]
+		selectedIndex := (drc.namesrvAddrSelectedIndex + i) % addressCount
+		selectAddress := drc.namesrvAddrList[selectedIndex]
 		if len(selectAddress) == 0 {
 			continue
 		}
-		conn, err = self.CreateConn(selectAddress)
+		conn, err = drc.createConn(selectAddress)
 		if err == nil {
-			self.namesrvAddrSelectedAddr = selectAddress
-			self.namesrvAddrSelectedIndex = selectedIndex
+			drc.namesrvAddrSelectedAddr = selectAddress
+			drc.namesrvAddrSelectedIndex = selectedIndex
 			return
 		}
 	}
-	err = errors.New("all namesvrAddress can't use!,address:" + self.clientConfig.NameServerAddress())
+	err = errors.New("all namesvrAddress can't use!,address:" + drc.clientConfig.NameServerAddress)
 	return
 }
-func (self *DefalutRemotingClient) createAndHandleTcpConn(address string) (conn net.Conn, err error) {
+func (drc *DefaultRemotingClient) createAndHandleTcpConn(address string) (conn net.Conn, err error) {
 	conn, err = net.Dial("tcp", address)
 	if err != nil {
 		glog.Error(err)
 		return nil, err
 	}
-	go self.handlerReceiveLoop(conn, address) //handler连接 处理这个连接返回的结果
+	go drc.handlerReceiveLoop(conn, address) //handler连接 处理这个连接返回的结果
 	return
 }
-func (self *DefalutRemotingClient) ReleaseConn(addr string, conn net.Conn) {
-	defer self.connTableLock.Unlock()
+func (drc *DefaultRemotingClient) releaseConn(addr string, conn net.Conn) {
+	defer drc.connTableLock.Unlock()
 	conn.Close()
-	self.connTableLock.Lock()
-	delete(self.connTable, addr)
+	drc.connTableLock.Lock()
+	delete(drc.connTable, addr)
 }
 
-func (self *DefalutRemotingClient) handlerReceiveLoop(conn net.Conn, addr string) (err error) {
+func (drc *DefaultRemotingClient) handlerReceiveLoop(conn net.Conn, addr string) (err error) {
 	defer func() {
 		//when for is break releaseConn
 		glog.Error(err, addr)
-		self.ReleaseConn(addr, conn)
+		drc.releaseConn(addr, conn)
 	}()
 	b := make([]byte, 1024)
 	var length, headerLength, bodyLength int32
@@ -313,35 +326,35 @@
 			} else {
 				_, err = buf.Read(body)
 			}
-			go self.handlerReceivedMessage(conn, headerSerializableType, header, body)
+			go drc.handlerReceivedMessage(conn, headerSerializableType, header, body)
 		}
 	}
 }
-func (self *DefalutRemotingClient) handlerReceivedMessage(conn net.Conn, headerSerializableType byte, headBytes []byte, bodyBytes []byte) {
-	cmd := self.serializerHandler.DecodeRemoteCommand(headerSerializableType, headBytes, bodyBytes)
-	if cmd.IsResponseType() {
-		self.handlerResponse(cmd)
+func (drc *DefaultRemotingClient) handlerReceivedMessage(conn net.Conn, headerSerializableType byte, headBytes []byte, bodyBytes []byte) {
+	cmd := drc.serializerHandler.decodeRemoteCommand(headerSerializableType, headBytes, bodyBytes)
+	if cmd.isResponseType() {
+		drc.handlerResponse(cmd)
 		return
 	}
-	go self.handlerRequest(conn, cmd)
+	go drc.handlerRequest(conn, cmd)
 }
-func (self *DefalutRemotingClient) handlerRequest(conn net.Conn, cmd *RemotingCommand) {
-	responseCommand := self.clientRequestProcessor(cmd)
+func (drc *DefaultRemotingClient) handlerRequest(conn net.Conn, cmd *RemotingCommand) {
+	responseCommand := drc.clientRequestProcessor(cmd)
 	if responseCommand == nil {
 		return
 	}
 	responseCommand.Opaque = cmd.Opaque
-	responseCommand.MarkResponseType()
-	header := self.serializerHandler.EncodeHeader(responseCommand)
+	responseCommand.markResponseType()
+	header := drc.serializerHandler.encodeHeader(responseCommand)
 	body := responseCommand.Body
-	err := self.sendRequest(header, body, conn, "")
+	err := drc.sendRequest(header, body, conn, "")
 	if err != nil {
 		glog.Error(err)
 	}
 }
-func (self *DefalutRemotingClient) handlerResponse(cmd *RemotingCommand) {
-	response, err := self.getResponse(cmd.Opaque)
-	self.removeResponse(cmd.Opaque)
+func (drc *DefaultRemotingClient) handlerResponse(cmd *RemotingCommand) {
+	response, err := drc.getResponse(cmd.Opaque)
+	drc.removeResponse(cmd.Opaque)
 	if err != nil {
 		return
 	}
@@ -355,12 +368,12 @@
 	}
 }
 
-func (self *DefalutRemotingClient) ClearExpireResponse() {
-	for seq, responseObj := range self.responseTable.Items() {
+//ClearExpireResponse clear expire response which is not consumed after 30 seconds
+func (drc *DefaultRemotingClient) ClearExpireResponse() {
+	for seq, responseObj := range drc.responseTable.Items() {
 		response := responseObj.(*ResponseFuture)
 		if (response.BeginTimestamp + 30) <= time.Now().Unix() {
-			//30 mins expire
-			self.responseTable.Remove(seq)
+			drc.responseTable.Remove(seq)
 			if response.InvokeCallback != nil {
 				response.InvokeCallback(nil)
 				glog.Warningf("remove time out request %v", response)
diff --git a/rocketmq-go/remoting/remoting_client_test.go b/rocketmq-go/remoting/remoting_client_test.go
new file mode 100644
index 0000000..0a3baaf
--- /dev/null
+++ b/rocketmq-go/remoting/remoting_client_test.go
@@ -0,0 +1,31 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package remoting_test
+
+//func TestClearExpireResponse(t *testing.T) {
+//	for seq, responseObj := range drc.responseTable.Items() {
+//		response := responseObj.(*ResponseFuture)
+//		if (response.BeginTimestamp + 30) <= time.Now().Unix() {
+//			drc.responseTable.Remove(seq)
+//			if response.InvokeCallback != nil {
+//				response.InvokeCallback(nil)
+//				glog.Warningf("remove time out request %v", response)
+//			}
+//		}
+//	}
+//}
diff --git a/rocketmq-go/remoting/remoting_command.go b/rocketmq-go/remoting/remoting_command.go
index a8361bd..71e4def 100644
--- a/rocketmq-go/remoting/remoting_command.go
+++ b/rocketmq-go/remoting/remoting_command.go
@@ -1,51 +1,61 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 import (
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util/structs"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
 	"sync/atomic"
 )
 
 var opaque int32
 
-var RPC_TYPE int = 0   // 0, REQUEST_COMMAND
-var RPC_ONEWAY int = 1 // 0, RPC
-
-//var RESPONSE_TYPE int= 1 << RPC_TYPE
+//RESPONSE_TYPE RESPONSE_TYPE int= 1 << RPC_TYPE
 var RESPONSE_TYPE int = 1
 
+//RemotingCommand rocketmq remoting command
+// both request and response use it
 type RemotingCommand struct {
-	//header
-	Code      int16                  `json:"code"`
-	Language  string                 `json:"language"` //int 8
-	Version   int16                  `json:"version"`
-	Opaque    int32                  `json:"opaque"`
-	Flag      int                    `json:"flag"`
-	Remark    string                 `json:"remark"`
+	//request:  request_code.go
+	//response: response_code.go
+	Code int16 `json:"code"`
+	//this client's language. see config.go
+	Language string `json:"language"` //int 8
+	//this client's version. see config.go
+	Version int16 `json:"version"`
+	//the client's Opaque,it is auto increase
+	Opaque int32 `json:"opaque"`
+	//this request's flag
+	Flag int `json:"flag"`
+	//remark, for example error message
+	Remark string `json:"remark"`
+	//this request's param
 	ExtFields map[string]interface{} `json:"extFields"` //java's ExtFields and customHeader is use this key word
-	Body      []byte                 `json:"body,omitempty"`
+	//response content
+	Body []byte `json:"body,omitempty"`
 }
 
+//NewRemotingCommand NewRemotingCommand
 func NewRemotingCommand(commandCode int16, customerHeader CustomerHeader) *RemotingCommand {
 	return NewRemotingCommandWithBody(commandCode, customerHeader, nil)
 }
 
+//NewRemotingCommandWithBody NewRemotingCommandWithBody
 func NewRemotingCommandWithBody(commandCode int16, customerHeader CustomerHeader, body []byte) *RemotingCommand {
 	remotingCommand := new(RemotingCommand)
 	remotingCommand.Code = commandCode
@@ -55,15 +65,15 @@
 	remotingCommand.Language = constant.REMOTING_COMMAND_LANGUAGE
 	remotingCommand.Version = constant.REMOTING_COMMAND_VERSION
 	if customerHeader != nil {
-		remotingCommand.ExtFields = structs.Map(customerHeader)
+		remotingCommand.ExtFields = util.Struct2Map(customerHeader)
 	}
 	remotingCommand.Body = body
 	return remotingCommand
 }
 
-func (self *RemotingCommand) IsResponseType() bool {
-	return self.Flag&(RESPONSE_TYPE) == RESPONSE_TYPE
+func (r *RemotingCommand) isResponseType() bool {
+	return r.Flag&(RESPONSE_TYPE) == RESPONSE_TYPE
 }
-func (self *RemotingCommand) MarkResponseType() {
-	self.Flag = (self.Flag | RESPONSE_TYPE)
+func (r *RemotingCommand) markResponseType() {
+	r.Flag = (r.Flag | RESPONSE_TYPE)
 }
diff --git a/rocketmq-go/remoting/request_code.go b/rocketmq-go/remoting/request_code.go
index 52965d5..69806da 100644
--- a/rocketmq-go/remoting/request_code.go
+++ b/rocketmq-go/remoting/request_code.go
@@ -1,111 +1,56 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 const (
-	SEND_MESSAGE                        = 10
-	PULL_MESSAGE                        = 11
-	QUERY_MESSAGE                       = 12
-	QUERY_BROKER_OFFSET                 = 13
-	QUERY_CONSUMER_OFFSET               = 14
-	UPDATE_CONSUMER_OFFSET              = 15
-	UPDATE_AND_CREATE_TOPIC             = 17
-	GET_ALL_TOPIC_CONFIG                = 21
-	GET_TOPIC_CONFIG_LIST               = 22
-	GET_TOPIC_NAME_LIST                 = 23
-	UPDATE_BROKER_CONFIG                = 25
-	GET_BROKER_CONFIG                   = 26
-	TRIGGER_DELETE_FILES                = 27
-	GET_BROKER_RUNTIME_INFO             = 28
-	SEARCH_OFFSET_BY_TIMESTAMP          = 29
-	GET_MAX_OFFSET                      = 30
-	GET_MIN_OFFSET                      = 31
-	GET_EARLIEST_MSG_STORETIME          = 32
-	VIEW_MESSAGE_BY_ID                  = 33
-	HEART_BEAT                          = 34
-	UNREGISTER_CLIENT                   = 35
-	CONSUMER_SEND_MSG_BACK              = 36
-	END_TRANSACTION                     = 37
-	GET_CONSUMER_LIST_BY_GROUP          = 38
-	CHECK_TRANSACTION_STATE             = 39
-	NOTIFY_CONSUMER_IDS_CHANGED         = 40
-	LOCK_BATCH_MQ                       = 41
-	UNLOCK_BATCH_MQ                     = 42
-	GET_ALL_CONSUMER_OFFSET             = 43
-	GET_ALL_DELAY_OFFSET                = 45
-	PUT_KV_CONFIG                       = 100
-	GET_KV_CONFIG                       = 101
-	DELETE_KV_CONFIG                    = 102
-	REGISTER_BROKER                     = 103
-	UNREGISTER_BROKER                   = 104
-	GET_ROUTEINTO_BY_TOPIC              = 105
-	GET_BROKER_CLUSTER_INFO             = 106
-	UPDATE_AND_CREATE_SUBSCRIPTIONGROUP = 200
-	GET_ALL_SUBSCRIPTIONGROUP_CONFIG    = 201
-	GET_TOPIC_STATS_INFO                = 202
-	GET_CONSUMER_CONNECTION_LIST        = 203
-	GET_PRODUCER_CONNECTION_LIST        = 204
-	WIPE_WRITE_PERM_OF_BROKER           = 205
+	//SEND_MESSAGE                SEND_MESSAGE
+	SEND_MESSAGE = 10
+	//PULL_MESSAGE                PULL_MESSAGE
+	PULL_MESSAGE = 11
+	//QUERY_CONSUMER_OFFSET       QUERY_CONSUMER_OFFSET
+	QUERY_CONSUMER_OFFSET = 14
+	//UPDATE_CONSUMER_OFFSET      UPDATE_CONSUMER_OFFSET
+	UPDATE_CONSUMER_OFFSET = 15
+	//SEARCH_OFFSET_BY_TIMESTAMP SEARCH_OFFSET_BY_TIMESTAMP
+	SEARCH_OFFSET_BY_TIMESTAMP = 29
+	//GET_MAX_OFFSET              GET_MAX_OFFSET
+	GET_MAX_OFFSET = 30
+	//HEART_BEAT                  HEART_BEAT
+	HEART_BEAT = 34
+	//CONSUMER_SEND_MSG_BACK      CONSUMER_SEND_MSG_BACK
+	CONSUMER_SEND_MSG_BACK = 36
+	//GET_CONSUMER_LIST_BY_GROUP  GET_CONSUMER_LIST_BY_GROUP
+	GET_CONSUMER_LIST_BY_GROUP = 38
+	//CHECK_TRANSACTION_STATE     CHECK_TRANSACTION_STATE
+	CHECK_TRANSACTION_STATE = 39
+	//NOTIFY_CONSUMER_IDS_CHANGED NOTIFY_CONSUMER_IDS_CHANGED
+	NOTIFY_CONSUMER_IDS_CHANGED = 40
+	//GET_ROUTEINTO_BY_TOPIC      GET_ROUTEINTO_BY_TOPIC
+	GET_ROUTEINTO_BY_TOPIC = 105
 
-	GET_ALL_TOPIC_LIST_FROM_NAMESERVER = 206
-	DELETE_SUBSCRIPTIONGROUP           = 207
-	GET_CONSUME_STATS                  = 208
-	SUSPEND_CONSUMER                   = 209
-	RESUME_CONSUMER                    = 210
-	RESET_CONSUMER_OFFSET_IN_CONSUMER  = 211
-	RESET_CONSUMER_OFFSET_IN_BROKER    = 212
-	ADJUST_CONSUMER_THREAD_POOL        = 213
-	WHO_CONSUME_THE_MESSAGE            = 214
+	//RESET_CONSUMER_CLIENT_OFFSET RESET_CONSUMER_CLIENT_OFFSET
+	RESET_CONSUMER_CLIENT_OFFSET = 220
+	//GET_CONSUMER_STATUS_FROM_CLIENT GET_CONSUMER_STATUS_FROM_CLIENT
+	GET_CONSUMER_STATUS_FROM_CLIENT = 221
 
-	DELETE_TOPIC_IN_BROKER    = 215
-	DELETE_TOPIC_IN_NAMESRV   = 216
-	GET_KV_CONFIG_BY_VALUE    = 217
-	DELETE_KV_CONFIG_BY_VALUE = 218
-	GET_KVLIST_BY_NAMESPACE   = 219
-
-	RESET_CONSUMER_CLIENT_OFFSET         = 220
-	GET_CONSUMER_STATUS_FROM_CLIENT      = 221
-	INVOKE_BROKER_TO_RESET_OFFSET        = 222
-	INVOKE_BROKER_TO_GET_CONSUMER_STATUS = 223
-
-	QUERY_TOPIC_CONSUME_BY_WHO = 300
-
-	GET_TOPICS_BY_CLUSTER = 224
-
-	REGISTER_FILTER_SERVER            = 301
-	REGISTER_MESSAGE_FILTER_CLASS     = 302
-	QUERY_CONSUME_TIME_SPAN           = 303
-	GET_SYSTEM_TOPIC_LIST_FROM_NS     = 304
-	GET_SYSTEM_TOPIC_LIST_FROM_BROKER = 305
-
-	CLEAN_EXPIRED_CONSUMEQUEUE = 306
-
+	//GET_CONSUMER_RUNNING_INFO GET_CONSUMER_RUNNING_INFO
 	GET_CONSUMER_RUNNING_INFO = 307
 
-	QUERY_CORRECTION_OFFSET = 308
-
+	//CONSUME_MESSAGE_DIRECTLY CONSUME_MESSAGE_DIRECTLY
 	CONSUME_MESSAGE_DIRECTLY = 309
-
-	SEND_MESSAGE_V2 = 310
-
-	GET_UNIT_TOPIC_LIST                = 311
-	GET_HAS_UNIT_SUB_TOPIC_LIST        = 312
-	GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST = 313
-	CLONE_GROUP_OFFSET                 = 314
-
-	VIEW_BROKER_STATS_DATA = 315
 )
diff --git a/rocketmq-go/remoting/request_processor.go b/rocketmq-go/remoting/request_processor.go
index eec8cd8..f5b8a95 100644
--- a/rocketmq-go/remoting/request_processor.go
+++ b/rocketmq-go/remoting/request_processor.go
@@ -1,21 +1,24 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
+//ClientRequestProcessor ClientRequestProcessor when invoke this client
+// see initClientRequestProcessor
 type ClientRequestProcessor func(remotingCommand *RemotingCommand) (responseCommand *RemotingCommand)
 
 //CHECK_TRANSACTION_STATE
diff --git a/rocketmq-go/remoting/response_code.go b/rocketmq-go/remoting/response_code.go
index 6a49c77..3f1c462 100644
--- a/rocketmq-go/remoting/response_code.go
+++ b/rocketmq-go/remoting/response_code.go
@@ -1,53 +1,37 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 const (
-	SUCCESS                       = 0
-	SYSTEM_ERROR                  = 1
-	SYSTEM_BUSY                   = 2
-	REQUEST_CODE_NOT_SUPPORTED    = 3
-	TRANSACTION_FAILED            = 4
-	FLUSH_DISK_TIMEOUT            = 10
-	SLAVE_NOT_AVAILABLE           = 11
-	FLUSH_SLAVE_TIMEOUT           = 12
-	MESSAGE_ILLEGAL               = 13
-	SERVICE_NOT_AVAILABLE         = 14
-	VERSION_NOT_SUPPORTED         = 15
-	NO_PERMISSION                 = 16
-	TOPIC_NOT_EXIST               = 17
-	TOPIC_EXIST_ALREADY           = 18
-	PULL_NOT_FOUND                = 19
-	PULL_RETRY_IMMEDIATELY        = 20
-	PULL_OFFSET_MOVED             = 21
-	QUERY_NOT_FOUND               = 22
-	SUBSCRIPTION_PARSE_FAILED     = 23
-	SUBSCRIPTION_NOT_EXIST        = 24
-	SUBSCRIPTION_NOT_LATEST       = 25
-	SUBSCRIPTION_GROUP_NOT_EXIST  = 26
-	TRANSACTION_SHOULD_COMMIT     = 200
-	TRANSACTION_SHOULD_ROLLBACK   = 201
-	TRANSACTION_STATE_UNKNOW      = 202
-	TRANSACTION_STATE_GROUP_WRONG = 203
-	NO_BUYER_ID                   = 204
-
-	NOT_IN_CURRENT_UNIT = 205
-
-	CONSUMER_NOT_ONLINE = 206
-
-	CONSUME_MSG_TIMEOUT = 207
+	//SUCCESS                       SUCCESS
+	SUCCESS = 0
+	//FLUSH_DISK_TIMEOUT            FLUSH_DISK_TIMEOUT
+	FLUSH_DISK_TIMEOUT = 10
+	//SLAVE_NOT_AVAILABLE           SLAVE_NOT_AVAILABLE
+	SLAVE_NOT_AVAILABLE = 11
+	//FLUSH_SLAVE_TIMEOUT           FLUSH_SLAVE_TIMEOUT
+	FLUSH_SLAVE_TIMEOUT = 12
+	//PULL_NOT_FOUND                PULL_NOT_FOUND
+	PULL_NOT_FOUND = 19
+	//PULL_RETRY_IMMEDIATELY        PULL_RETRY_IMMEDIATELY
+	PULL_RETRY_IMMEDIATELY = 20
+	//PULL_OFFSET_MOVED             PULL_OFFSET_MOVED
+	PULL_OFFSET_MOVED = 21
+	//QUERY_NOT_FOUND QUERY_NOT_FOUND
+	QUERY_NOT_FOUND = 22
 )
diff --git a/rocketmq-go/remoting/response_future.go b/rocketmq-go/remoting/response_future.go
index 1bece6d..869daa5 100644
--- a/rocketmq-go/remoting/response_future.go
+++ b/rocketmq-go/remoting/response_future.go
@@ -1,21 +1,23 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
+//ResponseFuture ResponseFuture
 type ResponseFuture struct {
 	ResponseCommand *RemotingCommand
 	SendRequestOK   bool
@@ -26,4 +28,6 @@
 	BeginTimestamp  int64
 	Done            chan bool
 }
+
+//InvokeCallback InvokeCallback
 type InvokeCallback func(responseFuture *ResponseFuture)
diff --git a/rocketmq-go/remoting/rocketmq_serializable.go b/rocketmq-go/remoting/rocketmq_serializable.go
index 22dc41f..b230efd 100644
--- a/rocketmq-go/remoting/rocketmq_serializable.go
+++ b/rocketmq-go/remoting/rocketmq_serializable.go
@@ -1,19 +1,20 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 import (
@@ -23,10 +24,18 @@
 	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
 )
 
+//RocketMqSerializer RocketMqSerializer
 type RocketMqSerializer struct {
 }
 
-func (self *RocketMqSerializer) EncodeHeaderData(cmd *RemotingCommand) []byte {
+type itemType int8
+
+const (
+	keyItem itemType = iota
+	valueItem
+)
+
+func (r *RocketMqSerializer) encodeHeaderData(cmd *RemotingCommand) []byte {
 	var (
 		remarkBytes       []byte
 		remarkBytesLen    int
@@ -56,11 +65,10 @@
 	if extFieldsBytesLen > 0 {
 		buf.Write(extFieldsBytes)
 	}
-	fmt.Println(buf.Bytes())
 	return buf.Bytes()
 }
 
-func (self *RocketMqSerializer) DecodeRemoteCommand(headerArray, body []byte) (cmd *RemotingCommand) {
+func (r *RocketMqSerializer) decodeRemoteCommand(headerArray, body []byte) (cmd *RemotingCommand) {
 	cmd = &RemotingCommand{}
 	buf := bytes.NewBuffer(headerArray)
 	// int code(~32767)
@@ -68,7 +76,7 @@
 	// LanguageCode language
 	var LanguageCodeNope byte
 	binary.Read(buf, binary.BigEndian, &LanguageCodeNope)
-	cmd.Language = constant.REMOTING_COMMAND_LANGUAGE //todo use code from remote
+	cmd.Language = constant.REMOTING_COMMAND_LANGUAGE
 	// int version(~32767)
 	binary.Read(buf, binary.BigEndian, &cmd.Version)
 	// int opaque
@@ -83,8 +91,6 @@
 		binary.Read(buf, binary.BigEndian, &remarkData)
 		cmd.Remark = string(remarkData)
 	}
-	//map ext
-	// HashMap<String, String> extFields
 	binary.Read(buf, binary.BigEndian, &extFieldsLen)
 	if extFieldsLen > 0 {
 		var extFieldsData = make([]byte, extFieldsLen)
@@ -114,24 +120,24 @@
 	extFiledMap = make(map[string]interface{})
 	buf := bytes.NewBuffer(extFiledDataBytes)
 	for buf.Len() > 0 {
-		var key = getItemFormExtFiledDataBytes(buf, "key")
-		var value = getItemFormExtFiledDataBytes(buf, "value")
+		var key = getItemFormExtFiledDataBytes(buf, keyItem)
+		var value = getItemFormExtFiledDataBytes(buf, valueItem)
 		extFiledMap[key] = value
 	}
 	return
 }
-func getItemFormExtFiledDataBytes(buff *bytes.Buffer, itemType string) (item string) {
-	if itemType == "key" {
-		var len int16
-		binary.Read(buff, binary.BigEndian, &len)
-		var data = make([]byte, len)
+func getItemFormExtFiledDataBytes(buff *bytes.Buffer, iType itemType) (item string) {
+	if iType == keyItem {
+		var length int16
+		binary.Read(buff, binary.BigEndian, &length)
+		var data = make([]byte, length)
 		binary.Read(buff, binary.BigEndian, &data)
 		item = string(data)
 	}
-	if itemType == "value" {
-		var len int32
-		binary.Read(buff, binary.BigEndian, &len)
-		var data = make([]byte, len)
+	if iType == valueItem {
+		var length int32
+		binary.Read(buff, binary.BigEndian, &length)
+		var data = make([]byte, length)
 		binary.Read(buff, binary.BigEndian, &data)
 		item = string(data)
 	}
diff --git a/rocketmq-go/remoting/rocketmq_serializable_test.go b/rocketmq-go/remoting/rocketmq_serializable_test.go
new file mode 100644
index 0000000..91d5f08
--- /dev/null
+++ b/rocketmq-go/remoting/rocketmq_serializable_test.go
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package remoting_test
+
+import (
+	"testing"
+)
+
+func TestEncodeHeaderDataRocketMq(t *testing.T) {
+
+}
+func TestDecodeRemoteCommandRocketMq(t *testing.T) {
+
+}
+func TestRocketMqCustomHeaderSerialize(t *testing.T) {
+
+}
+
+func TestCustomHeaderDeserialize(t *testing.T) {
+
+}
+
+func TestGetItemFormExtFiledDataBytes(t *testing.T) {
+
+}
diff --git a/rocketmq-go/remoting/rpchook.go b/rocketmq-go/remoting/rpchook.go
index 150ffe0..894f25c 100644
--- a/rocketmq-go/remoting/rpchook.go
+++ b/rocketmq-go/remoting/rpchook.go
@@ -1,23 +1,26 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
 
 package remoting
 
+//RPCHook RPCHook
 type RPCHook interface {
+	//DoBeforeRequest DoBeforeRequest
 	DoBeforeRequest(string, *RemotingCommand)
+	//DoBeforeResponse DoBeforeResponse
 	DoBeforeResponse(string, *RemotingCommand)
 }
diff --git a/rocketmq-go/remoting/serializable.go b/rocketmq-go/remoting/serializable.go
index 24420cd..4f9ac62 100644
--- a/rocketmq-go/remoting/serializable.go
+++ b/rocketmq-go/remoting/serializable.go
@@ -1,48 +1,55 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package remoting
 
 import (
 	"bytes"
 	"encoding/binary"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
 	"github.com/golang/glog"
 )
 
+//SerializerHandler rocketmq client SerializerHandler
 type SerializerHandler struct {
-	serializer Serializer //which serializer this client use, depend on  constant.USE_HEADER_SERIALIZETYPE
+	serializeType rocketmqm.SerializeType
+	serializer    Serializer //which serializer this client use, depend on  constant.USE_HEADER_SERIALIZE_TYPE
 }
 
+//Serializer rocketmq Serializer
 type Serializer interface {
-	EncodeHeaderData(request *RemotingCommand) []byte
-	DecodeRemoteCommand(header, body []byte) *RemotingCommand
+	encodeHeaderData(request *RemotingCommand) []byte
+	decodeRemoteCommand(header, body []byte) *RemotingCommand
 }
 
+//JSON_SERIALIZER json serializer
 var JSON_SERIALIZER = &JsonSerializer{}
+
+//ROCKETMQ_SERIALIZER rocketmq serializer
 var ROCKETMQ_SERIALIZER = &RocketMqSerializer{}
 
-func NewSerializerHandler() SerializerHandler {
-	serializerHandler := SerializerHandler{}
-	switch constant.USE_HEADER_SERIALIZETYPE {
-	case constant.JSON_SERIALIZE:
+func newSerializerHandler(serializeType rocketmqm.SerializeType) SerializerHandler {
+	serializerHandler := SerializerHandler{serializeType: serializeType}
+	switch serializeType {
+	case rocketmqm.JSON_SERIALIZE:
 		serializerHandler.serializer = JSON_SERIALIZER
 		break
 
-	case constant.ROCKETMQ_SERIALIZE:
+	case rocketmqm.ROCKETMQ_SERIALIZE:
 		serializerHandler.serializer = ROCKETMQ_SERIALIZER
 		break
 	default:
@@ -50,31 +57,31 @@
 	}
 	return serializerHandler
 }
-func (self *SerializerHandler) EncodeHeader(request *RemotingCommand) []byte {
+func (s *SerializerHandler) encodeHeader(request *RemotingCommand) []byte {
 	length := 4
-	headerData := self.serializer.EncodeHeaderData(request)
+	headerData := s.serializer.encodeHeaderData(request)
 	length += len(headerData)
 	if request.Body != nil {
 		length += len(request.Body)
 	}
 	buf := bytes.NewBuffer([]byte{})
-	binary.Write(buf, binary.BigEndian, int32(length))                                                       // len
-	binary.Write(buf, binary.BigEndian, int32(len(headerData)|(int(constant.USE_HEADER_SERIALIZETYPE)<<24))) // header len
+	binary.Write(buf, binary.BigEndian, int32(length))                                     // len
+	binary.Write(buf, binary.BigEndian, int32(len(headerData)|(int(s.serializeType)<<24))) // header len
 	buf.Write(headerData)
 	return buf.Bytes()
 }
 
-func (self *SerializerHandler) DecodeRemoteCommand(headerSerializableType byte, header, body []byte) *RemotingCommand {
+func (s *SerializerHandler) decodeRemoteCommand(headerSerializableType byte, header, body []byte) *RemotingCommand {
 	var serializer Serializer
-	switch headerSerializableType {
-	case constant.JSON_SERIALIZE:
+	switch rocketmqm.SerializeType(headerSerializableType) {
+	case rocketmqm.JSON_SERIALIZE:
 		serializer = JSON_SERIALIZER
 		break
-	case constant.ROCKETMQ_SERIALIZE:
+	case rocketmqm.ROCKETMQ_SERIALIZE:
 		serializer = ROCKETMQ_SERIALIZER
 		break
 	default:
 		glog.Error("Unknow headerSerializableType", headerSerializableType)
 	}
-	return serializer.DecodeRemoteCommand(header, body)
+	return serializer.decodeRemoteCommand(header, body)
 }
diff --git a/rocketmq-go/service/allocate_message/allocate_message_averagely.go b/rocketmq-go/service/allocate_message/allocate_message_averagely.go
deleted file mode 100644
index cdfe775..0000000
--- a/rocketmq-go/service/allocate_message/allocate_message_averagely.go
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service_allocate_message
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-)
-
-type AllocateMessageQueueAveragely struct{}
-
-func (self *AllocateMessageQueueAveragely) Allocate(consumerGroup string, currentCID string, mqAll []*model.MessageQueue, cidAll []string) ([]model.MessageQueue, error) {
-
-	if currentCID == "" {
-		return nil, errors.New("currentCID is empty")
-	}
-
-	if mqAll == nil || len(mqAll) == 0 {
-		return nil, errors.New("mqAll is nil or mqAll empty")
-	}
-
-	if cidAll == nil || len(cidAll) == 0 {
-		return nil, errors.New("cidAll is nil or cidAll empty")
-	}
-
-	result := make([]model.MessageQueue, 0)
-	for i, cid := range cidAll {
-		if cid == currentCID {
-			mqLen := len(mqAll)
-			cidLen := len(cidAll)
-			mod := mqLen % cidLen
-			var averageSize int
-			if mqLen < cidLen {
-				averageSize = 1
-			} else {
-				if mod > 0 && i < mod {
-					averageSize = mqLen/cidLen + 1
-				} else {
-					averageSize = mqLen / cidLen
-				}
-			}
-
-			var startIndex int
-			if mod > 0 && i < mod {
-				startIndex = i * averageSize
-			} else {
-				startIndex = i*averageSize + mod
-			}
-
-			var min int
-			if averageSize > mqLen-startIndex {
-				min = mqLen - startIndex
-			} else {
-				min = averageSize
-			}
-
-			for j := 0; j < min; j++ {
-				result = append(result, *mqAll[(startIndex+j)%mqLen])
-			}
-			return result, nil
-
-		}
-	}
-
-	return nil, errors.New("cant't find currentCID")
-}
diff --git a/rocketmq-go/service/allocate_message/allocate_message_averagely_by_circle.go b/rocketmq-go/service/allocate_message/allocate_message_averagely_by_circle.go
deleted file mode 100644
index cdfd668..0000000
--- a/rocketmq-go/service/allocate_message/allocate_message_averagely_by_circle.go
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service_allocate_message
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-)
-
-type AllocateMessageQueueAveragelyByCircle struct{}
-
-func (self *AllocateMessageQueueAveragelyByCircle) Allocate(consumerGroup string, currentCID string, mqAll []*model.MessageQueue, cidAll []string) ([]model.MessageQueue, error) {
-	if currentCID == "" {
-		return nil, errors.New("currentCID is empty")
-	}
-
-	if mqAll == nil || len(mqAll) == 0 {
-		return nil, errors.New("mqAll is nil or mqAll empty")
-	}
-
-	if cidAll == nil || len(cidAll) == 0 {
-		return nil, errors.New("cidAll is nil or cidAll empty")
-	}
-
-	result := make([]model.MessageQueue, 0)
-	for i, cid := range cidAll {
-		if cid == currentCID {
-			mqLen := len(mqAll)
-			cidLen := len(cidAll)
-			mod := mqLen % cidLen
-			var averageSize int
-			if mqLen < cidLen {
-				averageSize = 1
-			} else {
-				if mod > 0 && i < mod {
-					averageSize = mqLen/cidLen + 1
-				} else {
-					averageSize = mqLen / cidLen
-				}
-			}
-
-			var startIndex int
-			if mod > 0 && i < mod {
-				startIndex = i * averageSize
-			} else {
-				startIndex = i*averageSize + mod
-			}
-
-			var min int
-			if averageSize > mqLen-startIndex {
-				min = mqLen - startIndex
-			} else {
-				min = averageSize
-			}
-
-			for j := 0; j < min; j++ {
-				result = append(result, *mqAll[(startIndex+j)%mqLen])
-			}
-			return result, nil
-
-		}
-	}
-
-	return nil, errors.New("cant't find currentCID")
-}
diff --git a/rocketmq-go/service/allocate_message/allocate_message_by_config.go b/rocketmq-go/service/allocate_message/allocate_message_by_config.go
deleted file mode 100644
index 2046ffd..0000000
--- a/rocketmq-go/service/allocate_message/allocate_message_by_config.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service_allocate_message
-
-import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-
-type AllocateMessageQueueByConfig struct {
-	messageQueueList []model.MessageQueue
-}
-
-func (self *AllocateMessageQueueByConfig) Allocate(consumerGroup string, currentCID string, mqAll []*model.MessageQueue, cidAll []string) ([]model.MessageQueue, error) {
-	return self.messageQueueList, nil
-}
diff --git a/rocketmq-go/service/allocate_message/allocate_message_by_machine_room.go b/rocketmq-go/service/allocate_message/allocate_message_by_machine_room.go
deleted file mode 100644
index 6fe1cbb..0000000
--- a/rocketmq-go/service/allocate_message/allocate_message_by_machine_room.go
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service_allocate_message
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-)
-
-type AllocateMessageQueueByMachineRoom struct {
-}
-
-func (self *AllocateMessageQueueByMachineRoom) Allocate(consumerGroup string, currentCID string, mqAll []*model.MessageQueue, cidAll []string) ([]model.MessageQueue, error) {
-	if currentCID == "" {
-		return nil, errors.New("currentCID is empty")
-	}
-
-	if mqAll == nil || len(mqAll) == 0 {
-		return nil, errors.New("mqAll is nil or mqAll empty")
-	}
-
-	if cidAll == nil || len(cidAll) == 0 {
-		return nil, errors.New("cidAll is nil or cidAll empty")
-	}
-
-	result := make([]model.MessageQueue, 0)
-	for i, cid := range cidAll {
-		if cid == currentCID {
-			mqLen := len(mqAll)
-			cidLen := len(cidAll)
-			mod := mqLen % cidLen
-			var averageSize int
-			if mqLen < cidLen {
-				averageSize = 1
-			} else {
-				if mod > 0 && i < mod {
-					averageSize = mqLen/cidLen + 1
-				} else {
-					averageSize = mqLen / cidLen
-				}
-			}
-
-			var startIndex int
-			if mod > 0 && i < mod {
-				startIndex = i * averageSize
-			} else {
-				startIndex = i*averageSize + mod
-			}
-
-			var min int
-			if averageSize > mqLen-startIndex {
-				min = mqLen - startIndex
-			} else {
-				min = averageSize
-			}
-
-			for j := 0; j < min; j++ {
-				result = append(result, *mqAll[(startIndex+j)%mqLen])
-			}
-			return result, nil
-
-		}
-	}
-
-	return nil, errors.New("cant't find currentCID")
-}
diff --git a/rocketmq-go/service/allocate_message/allocate_message_queue_strategy.go b/rocketmq-go/service/allocate_message/allocate_message_queue_strategy.go
deleted file mode 100644
index e838c7b..0000000
--- a/rocketmq-go/service/allocate_message/allocate_message_queue_strategy.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service_allocate_message
-
-import "github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-
-type AllocateMessageQueueStrategy interface {
-	Allocate(consumerGroup string, currentCID string, mqAll []*model.MessageQueue, cidAll []string) ([]model.MessageQueue, error)
-}
-
-func GetAllocateMessageQueueStrategyByConfig(allocateMessageQueueStrategy string) AllocateMessageQueueStrategy {
-	return new(AllocateMessageQueueAveragely)
-}
diff --git a/rocketmq-go/service/client_api.go b/rocketmq-go/service/client_api.go
deleted file mode 100644
index 6901f4c..0000000
--- a/rocketmq-go/service/client_api.go
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package service
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/message"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-)
-
-var sendSmartMsg bool = true // TODO get from system env
-
-type TopAddress struct {
-}
-
-type ClientRemotingProcessor interface {
-}
-
-func init() {
-	// TODO
-}
-
-type MQClientAPI struct {
-	remotingClient    *remoting.RemotingClient
-	topAddress        *TopAddress
-	crp               *ClientRemotingProcessor
-	nameServerAddress string
-	config            *config.ClientConfig
-}
-
-//func NewMQClientAPI(cfg *config.ClientConfig, processor *ClientRemotingProcessor, hook remoting.RPCHook) *MQClientAPI {
-//	api := &MQClientAPI{
-//		remotingClient: &remoting.RemotingClient{}, //TODO
-//		topAddress:     &TopAddress{},              // TODO
-//		crp:            processor,
-//		config:         cfg,
-//	}
-//
-//	// TODO register
-//	return api
-//}
-//
-//func (api *MQClientAPI) SendMessage(addr, brokerName string,
-//	msg message.Message, requestHeader header.SendMessageRequestHeader, timeout int64) *model.SendResult {
-//	var request *remoting.RemotingCommand
-//	request = remoting.CreateRemotingCommand(model.SendMsg, &requestHeader)
-//	request.SetBody(msg.Body)
-//	return api.sendMessageSync(addr, brokerName, msg, timeout, request)
-//}
-
-func (api *MQClientAPI) sendMessageSync(addr, brokerName string,
-	msg message.Message,
-	timeout int64,
-	request *remoting.RemotingCommand) *model.SendResult {
-	response := api.invokeSync(addr, request, timeout)
-	if response == nil {
-		panic("invokeSync panci!")
-	}
-	return nil
-	// TODO return api.processSendResponse(brokerName, msg, response)
-}
-
-func (api *MQClientAPI) invokeSync(addr string, cmd *remoting.RemotingCommand, timeout int64) *remoting.RemotingCommand {
-	return nil
-}
-
-func (api *MQClientAPI) processSendResponse(name string, msg message.Message, cmd *remoting.RemotingCommand) *remoting.RemotingCommand {
-	return nil
-}
diff --git a/rocketmq-go/service/client_error_code.go b/rocketmq-go/service/client_error_code.go
deleted file mode 100644
index d031638..0000000
--- a/rocketmq-go/service/client_error_code.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package service
-
-const (
-	ConnecBrokerError        = 10001
-	AccessBrokerTimeoutError = 10002
-	BrokerNotExistError      = 10003
-	NoNameServerError        = 10004
-	NotFoundTopicError       = 10005
-)
diff --git a/rocketmq-go/service/consume_message_service.go b/rocketmq-go/service/consume_message_service.go
deleted file mode 100644
index e4a08df..0000000
--- a/rocketmq-go/service/consume_message_service.go
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/golang/glog"
-	"time"
-)
-
-type ConsumeMessageService interface {
-	//ConsumeMessageDirectlyResult consumeMessageDirectly(final MessageExt msg, final String brokerName);
-
-	Init(consumerGroup string, mqClient RocketMqClient, offsetStore OffsetStore, defaultProducerService *DefaultProducerService, consumerConfig *config.RocketMqConsumerConfig)
-	SubmitConsumeRequest(msgs []model.MessageExt, processQueue *model.ProcessQueue,
-		messageQueue *model.MessageQueue, dispathToConsume bool)
-	SendMessageBack(messageExt *model.MessageExt, delayLayLevel int, brokerName string) (err error)
-	ConsumeMessageDirectly(messageExt *model.MessageExt, brokerName string) (consumeMessageDirectlyResult model.ConsumeMessageDirectlyResult, err error)
-}
-
-type ConsumeMessageConcurrentlyServiceImpl struct {
-	consumerGroup                  string
-	messageListener                model.MessageListener
-	sendMessageBackProducerService SendMessageBackProducerService //for send retry Message
-	offsetStore                    OffsetStore
-	consumerConfig                 *config.RocketMqConsumerConfig
-}
-
-func NewConsumeMessageConcurrentlyServiceImpl(messageListener model.MessageListener) (consumeService ConsumeMessageService) {
-	consumeService = &ConsumeMessageConcurrentlyServiceImpl{messageListener: messageListener, sendMessageBackProducerService: &SendMessageBackProducerServiceImpl{}}
-	return
-}
-
-func (self *ConsumeMessageConcurrentlyServiceImpl) Init(consumerGroup string, mqClient RocketMqClient, offsetStore OffsetStore, defaultProducerService *DefaultProducerService, consumerConfig *config.RocketMqConsumerConfig) {
-	self.consumerGroup = consumerGroup
-	self.offsetStore = offsetStore
-	self.sendMessageBackProducerService.InitSendMessageBackProducerService(consumerGroup, mqClient, defaultProducerService, consumerConfig)
-	self.consumerConfig = consumerConfig
-}
-
-func (self *ConsumeMessageConcurrentlyServiceImpl) SubmitConsumeRequest(msgs []model.MessageExt, processQueue *model.ProcessQueue, messageQueue *model.MessageQueue, dispathToConsume bool) {
-	msgsLen := len(msgs)
-	for i := 0; i < msgsLen; {
-		begin := i
-		end := i + self.consumerConfig.ConsumeMessageBatchMaxSize
-		if end > msgsLen {
-			end = msgsLen
-		}
-		go func() {
-			glog.V(2).Infof("look slice begin %d end %d msgsLen %d", begin, end, msgsLen)
-			batchMsgs := transformMessageToConsume(self.consumerGroup, msgs[begin:end])
-			consumeState := self.messageListener(batchMsgs)
-			self.processConsumeResult(consumeState, batchMsgs, messageQueue, processQueue)
-		}()
-		i = end
-	}
-	return
-}
-
-func (self *ConsumeMessageConcurrentlyServiceImpl) SendMessageBack(messageExt *model.MessageExt, delayLayLevel int, brokerName string) (err error) {
-	err = self.sendMessageBackProducerService.SendMessageBack(messageExt, 0, brokerName)
-	return
-}
-
-func (self *ConsumeMessageConcurrentlyServiceImpl) ConsumeMessageDirectly(messageExt *model.MessageExt, brokerName string) (consumeMessageDirectlyResult model.ConsumeMessageDirectlyResult, err error) {
-	start := time.Now().UnixNano() / 1000000
-	consumeResult := self.messageListener([]model.MessageExt{*messageExt})
-	consumeMessageDirectlyResult.AutoCommit = true
-	consumeMessageDirectlyResult.Order = false
-	consumeMessageDirectlyResult.SpentTimeMills = time.Now().UnixNano()/1000000 - start
-	if consumeResult.ConsumeConcurrentlyStatus == "CONSUME_SUCCESS" && consumeResult.AckIndex >= 0 {
-		consumeMessageDirectlyResult.ConsumeResult = "CR_SUCCESS"
-
-	} else {
-		consumeMessageDirectlyResult.ConsumeResult = "CR_THROW_EXCEPTION"
-	}
-	return
-}
-
-func (self *ConsumeMessageConcurrentlyServiceImpl) processConsumeResult(result model.ConsumeConcurrentlyResult, msgs []model.MessageExt, messageQueue *model.MessageQueue, processQueue *model.ProcessQueue) {
-	if processQueue.IsDropped() {
-		glog.Warning("processQueue is dropped without process consume result. ", msgs)
-		return
-	}
-	if len(msgs) == 0 {
-		return
-	}
-	ackIndex := result.AckIndex
-	if model.CONSUME_SUCCESS == result.ConsumeConcurrentlyStatus {
-		if ackIndex >= len(msgs) {
-			ackIndex = len(msgs) - 1
-		} else {
-			if result.AckIndex < 0 {
-				ackIndex = -1
-			}
-		}
-	}
-	var failedMessages []model.MessageExt
-	successMessages := []model.MessageExt{}
-	if ackIndex >= 0 {
-		successMessages = msgs[:ackIndex+1]
-	}
-	for i := ackIndex + 1; i < len(msgs); i++ {
-		err := self.SendMessageBack(&msgs[i], 0, messageQueue.BrokerName)
-		if err != nil {
-			msgs[i].ReconsumeTimes = msgs[i].ReconsumeTimes + 1
-			failedMessages = append(failedMessages, msgs[i])
-		} else {
-			successMessages = append(successMessages, msgs[i])
-		}
-	}
-	if len(failedMessages) > 0 {
-		self.SubmitConsumeRequest(failedMessages, processQueue, messageQueue, true)
-	}
-	commitOffset := processQueue.RemoveMessage(successMessages)
-	if commitOffset > 0 && !processQueue.IsDropped() {
-		self.offsetStore.UpdateOffset(messageQueue, commitOffset, true)
-	}
-
-}
-
-func transformMessageToConsume(consumerGroup string, msgs []model.MessageExt) []model.MessageExt {
-	retryTopicName := constant.RETRY_GROUP_TOPIC_PREFIX + consumerGroup
-
-	for _, msg := range msgs {
-		//reset retry topic name
-		if msg.Message.Topic == retryTopicName {
-			retryTopic := msg.Properties[constant.PROPERTY_RETRY_TOPIC]
-			if len(retryTopic) > 0 {
-				msg.Message.Topic = retryTopic
-			}
-		}
-		//set consume start time
-		msg.SetConsumeStartTime()
-	}
-	return msgs
-}
diff --git a/rocketmq-go/service/mq_client.go b/rocketmq-go/service/mq_client.go
deleted file mode 100644
index 366aa3f..0000000
--- a/rocketmq-go/service/mq_client.go
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"github.com/golang/glog"
-	"os"
-	"strconv"
-	"strings"
-	"time"
-)
-
-//this struct is for something common,for example
-//1.brokerInfo
-//2.routerInfo
-//3.subscribeInfo
-//4.heartbeat
-type RocketMqClient interface {
-	GetClientId() (clientId string)
-	GetRemotingClient() (remotingClient *remoting.DefalutRemotingClient)
-	GetTopicSubscribeInfo(topic string) (messageQueueList []*model.MessageQueue)
-	GetPublishTopicList() []string
-	FetchMasterBrokerAddress(brokerName string) (masterAddress string)
-	EnqueuePullMessageRequest(pullRequest *model.PullRequest)
-	DequeuePullMessageRequest() (pullRequest *model.PullRequest)
-	FindBrokerAddressInSubscribe(brokerName string, brokerId int, onlyThisBroker bool) (brokerAddr string, slave bool, found bool)
-	TryToFindTopicPublishInfo(topic string) (topicPublicInfo *model.TopicPublishInfo, err error)
-	FindBrokerAddrByTopic(topic string) (addr string, ok bool)
-	UpdateTopicRouteInfoFromNameServer(topic string) (err error)
-	UpdateTopicRouteInfoFromNameServerUseDefaultTopic(topic string) (err error)
-	SendHeartbeatToAllBroker(heartBeatData *model.HeartbeatData) (err error)
-	ClearExpireResponse()
-	GetMaxOffset(mq *model.MessageQueue) int64
-	SearchOffset(mq *model.MessageQueue, time time.Time) int64
-}
-
-var DEFAULT_TIMEOUT int64 = 6000
-
-type MqClientImpl struct {
-	ClientId                string
-	remotingClient          *remoting.DefalutRemotingClient
-	TopicRouteTable         util.ConcurrentMap      // map[string]*model.TopicRouteData   //topic | topicRoteData
-	BrokerAddrTable         util.ConcurrentMap      //map[string]map[int]string          //brokerName | map[brokerId]address
-	TopicPublishInfoTable   util.ConcurrentMap      //map[string]*model.TopicPublishInfo //topic | TopicPublishInfo //all use this
-	TopicSubscribeInfoTable util.ConcurrentMap      //map[string][]*model.MessageQueue   //topic | MessageQueue
-	PullRequestQueue        chan *model.PullRequest //todo move
-}
-
-func MqClientInit(clientConfig *config.ClientConfig, clientRequestProcessor remoting.ClientRequestProcessor) (mqClientImpl *MqClientImpl) {
-	mqClientImpl = &MqClientImpl{}
-	mqClientImpl.ClientId = buildMqClientImplId()
-	mqClientImpl.TopicRouteTable = util.New() // make(map[string]*model.TopicRouteData)
-	mqClientImpl.BrokerAddrTable = util.New() //make(map[string]map[int]string)
-	mqClientImpl.remotingClient = remoting.RemotingClientInit(clientConfig, clientRequestProcessor)
-	mqClientImpl.TopicPublishInfoTable = util.New()   //make(map[string]*model.TopicPublishInfo)
-	mqClientImpl.TopicSubscribeInfoTable = util.New() //make(map[string][]*model.MessageQueue)
-	mqClientImpl.PullRequestQueue = make(chan *model.PullRequest, 1024)
-	return
-}
-func (self *MqClientImpl) GetTopicSubscribeInfo(topic string) (messageQueueList []*model.MessageQueue) {
-	value, ok := self.TopicSubscribeInfoTable.Get(topic)
-	if ok {
-		messageQueueList = value.([]*model.MessageQueue)
-	}
-	return
-}
-func (self *MqClientImpl) GetMaxOffset(mq *model.MessageQueue) int64 {
-	brokerAddr := self.FetchMasterBrokerAddress(mq.BrokerName)
-	if len(brokerAddr) == 0 {
-		self.TryToFindTopicPublishInfo(mq.Topic)
-		brokerAddr = self.FetchMasterBrokerAddress(mq.BrokerName)
-	}
-	getMaxOffsetRequestHeader := &header.GetMaxOffsetRequestHeader{Topic: mq.Topic, QueueId: mq.QueueId}
-	remotingCmd := remoting.NewRemotingCommand(remoting.GET_MAX_OFFSET, getMaxOffsetRequestHeader)
-	response, err := self.remotingClient.InvokeSync(brokerAddr, remotingCmd, DEFAULT_TIMEOUT)
-	if err != nil {
-		return -1
-	}
-	queryOffsetResponseHeader := header.QueryOffsetResponseHeader{}
-	queryOffsetResponseHeader.FromMap(response.ExtFields)
-	glog.Info("op=look max offset result", string(response.Body))
-	return queryOffsetResponseHeader.Offset
-}
-func (self *MqClientImpl) SearchOffset(mq *model.MessageQueue, time time.Time) int64 {
-	brokerAddr := self.FetchMasterBrokerAddress(mq.BrokerName)
-	if len(brokerAddr) == 0 {
-		self.TryToFindTopicPublishInfo(mq.Topic)
-		brokerAddr = self.FetchMasterBrokerAddress(mq.BrokerName)
-	}
-	timeStamp := time.UnixNano() / 1000000
-	searchOffsetRequestHeader := &header.SearchOffsetRequestHeader{Topic: mq.Topic, QueueId: mq.QueueId, Timestamp: timeStamp}
-	remotingCmd := remoting.NewRemotingCommand(remoting.SEARCH_OFFSET_BY_TIMESTAMP, searchOffsetRequestHeader)
-	response, err := self.remotingClient.InvokeSync(brokerAddr, remotingCmd, DEFAULT_TIMEOUT)
-	if err != nil {
-		return -1
-	}
-	queryOffsetResponseHeader := header.QueryOffsetResponseHeader{}
-
-	queryOffsetResponseHeader.FromMap(response.ExtFields)
-	glog.Info("op=look search offset result", string(response.Body))
-	return queryOffsetResponseHeader.Offset
-}
-func (self *MqClientImpl) GetClientId() string {
-	return self.ClientId
-}
-func (self *MqClientImpl) GetPublishTopicList() []string {
-	var publishTopicList []string
-	for _, topic := range self.TopicPublishInfoTable.Keys() {
-		publishTopicList = append(publishTopicList, topic)
-	}
-	return publishTopicList
-}
-func (self *MqClientImpl) GetRemotingClient() *remoting.DefalutRemotingClient {
-	return self.remotingClient
-}
-
-func (self *MqClientImpl) EnqueuePullMessageRequest(pullRequest *model.PullRequest) {
-	self.PullRequestQueue <- pullRequest
-}
-func (self *MqClientImpl) DequeuePullMessageRequest() (pullRequest *model.PullRequest) {
-	pullRequest = <-self.PullRequestQueue
-	return
-}
-
-func (self *MqClientImpl) ClearExpireResponse() {
-	self.remotingClient.ClearExpireResponse()
-}
-
-func (self *MqClientImpl) FetchMasterBrokerAddress(brokerName string) (masterAddress string) {
-	value, ok := self.BrokerAddrTable.Get(brokerName)
-	if ok {
-		masterAddress = value.(map[string]string)["0"]
-	}
-	return
-}
-func (self *MqClientImpl) TryToFindTopicPublishInfo(topic string) (topicPublicInfo *model.TopicPublishInfo, err error) {
-	value, ok := self.TopicPublishInfoTable.Get(topic)
-	if ok {
-		topicPublicInfo = value.(*model.TopicPublishInfo)
-	}
-
-	if topicPublicInfo == nil || !topicPublicInfo.JudgeTopicPublishInfoOk() {
-		self.TopicPublishInfoTable.Set(topic, &model.TopicPublishInfo{HaveTopicRouterInfo: false})
-		err = self.UpdateTopicRouteInfoFromNameServer(topic)
-		if err != nil {
-			glog.Warning(err) // if updateRouteInfo error, maybe we can use the defaultTopic
-		}
-		value, ok := self.TopicPublishInfoTable.Get(topic)
-		if ok {
-			topicPublicInfo = value.(*model.TopicPublishInfo)
-		}
-	}
-	if topicPublicInfo.HaveTopicRouterInfo && topicPublicInfo.JudgeTopicPublishInfoOk() {
-		return
-	}
-	//try to use the defaultTopic
-	err = self.UpdateTopicRouteInfoFromNameServerUseDefaultTopic(topic)
-
-	defaultValue, defaultValueOk := self.TopicPublishInfoTable.Get(topic)
-	if defaultValueOk {
-		topicPublicInfo = defaultValue.(*model.TopicPublishInfo)
-	}
-
-	return
-}
-
-func (self MqClientImpl) GetTopicRouteInfoFromNameServer(topic string, timeoutMillis int64) (*model.TopicRouteData, error) {
-	requestHeader := &header.GetRouteInfoRequestHeader{
-		Topic: topic,
-	}
-	var remotingCommand = remoting.NewRemotingCommand(remoting.GET_ROUTEINTO_BY_TOPIC, requestHeader)
-	response, err := self.remotingClient.InvokeSync("", remotingCommand, timeoutMillis)
-
-	if err != nil {
-		return nil, err
-	}
-	if response.Code == remoting.SUCCESS {
-		topicRouteData := new(model.TopicRouteData)
-		bodyjson := strings.Replace(string(response.Body), ",0:", ",\"0\":", -1)
-		bodyjson = strings.Replace(bodyjson, ",1:", ",\"1\":", -1) // fastJson key is string todo todo
-		bodyjson = strings.Replace(bodyjson, "{0:", "{\"0\":", -1)
-		bodyjson = strings.Replace(bodyjson, "{1:", "{\"1\":", -1)
-		err = json.Unmarshal([]byte(bodyjson), topicRouteData)
-		if err != nil {
-			glog.Error(err, bodyjson)
-			return nil, err
-		}
-		return topicRouteData, nil
-	} else {
-		return nil, errors.New(fmt.Sprintf("get topicRouteInfo from nameServer error[code:%d,topic:%s]", response.Code, topic))
-	}
-}
-
-func (self MqClientImpl) FindBrokerAddressInSubscribe(brokerName string, brokerId int, onlyThisBroker bool) (brokerAddr string, slave bool, found bool) {
-	slave = false
-	found = false
-	value, ok := self.BrokerAddrTable.Get(brokerName)
-	if !ok {
-		return
-	}
-	brokerMap := value.(map[string]string)
-	//self.brokerAddrTableLock.RUnlock()
-	brokerAddr, ok = brokerMap[util.IntToString(brokerId)]
-	slave = (brokerId != 0)
-	found = ok
-
-	if !found && !onlyThisBroker {
-		var id string
-		for id, brokerAddr = range brokerMap {
-			slave = (id != "0")
-			found = true
-			break
-		}
-	}
-	return
-}
-
-func (self MqClientImpl) UpdateTopicRouteInfoFromNameServer(topic string) (err error) {
-	var (
-		topicRouteData *model.TopicRouteData
-	)
-	//namesvr lock
-	//topicRouteData = this.MqClientImplAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3);
-	topicRouteData, err = self.GetTopicRouteInfoFromNameServer(topic, 1000*3)
-	if err != nil {
-		return
-	}
-	self.updateTopicRouteInfoLocal(topic, topicRouteData)
-	return
-}
-func (self MqClientImpl) UpdateTopicRouteInfoFromNameServerUseDefaultTopic(topic string) (err error) {
-	var (
-		topicRouteData *model.TopicRouteData
-	)
-	//namesvr lock
-	//topicRouteData = this.MqClientImplAPIImpl.getTopicRouteInfoFromNameServer(topic, 1000 * 3);
-	topicRouteData, err = self.GetTopicRouteInfoFromNameServer(constant.DEFAULT_TOPIC, 1000*3)
-	if err != nil {
-		return
-	}
-
-	for _, queueData := range topicRouteData.QueueDatas {
-		defaultQueueData := constant.DEFAULT_TOPIC_QUEUE_NUMS
-		if queueData.ReadQueueNums < defaultQueueData {
-			defaultQueueData = queueData.ReadQueueNums
-		}
-		queueData.ReadQueueNums = defaultQueueData
-		queueData.WriteQueueNums = defaultQueueData
-	}
-	self.updateTopicRouteInfoLocal(topic, topicRouteData)
-	return
-}
-func (self MqClientImpl) updateTopicRouteInfoLocal(topic string, topicRouteData *model.TopicRouteData) (err error) {
-	if topicRouteData == nil {
-		return
-	}
-	// topicRouteData judgeTopicRouteData need update
-	needUpdate := true
-	if !needUpdate {
-		return
-	}
-	//update brokerAddrTable
-	for _, brokerData := range topicRouteData.BrokerDatas {
-		self.BrokerAddrTable.Set(brokerData.BrokerName, brokerData.BrokerAddrs)
-	}
-
-	//update pubInfo for each
-	topicPublishInfo := model.BuildTopicPublishInfoFromTopicRoteData(topic, topicRouteData)
-	self.TopicPublishInfoTable.Set(topic, topicPublishInfo) // todo
-
-	mqList := model.BuildTopicSubscribeInfoFromRoteData(topic, topicRouteData)
-	self.TopicSubscribeInfoTable.Set(topic, mqList)
-	self.TopicRouteTable.Set(topic, topicRouteData)
-	return
-}
-
-func (self MqClientImpl) FindBrokerAddrByTopic(topic string) (addr string, ok bool) {
-	value, findValue := self.TopicRouteTable.Get(topic)
-	if !findValue {
-		return "", false
-	}
-	topicRouteData := value.(*model.TopicRouteData)
-	brokers := topicRouteData.BrokerDatas
-	if brokers != nil && len(brokers) > 0 {
-		brokerData := brokers[0]
-		brokerData.BrokerAddrsLock.RLock()
-		addr, ok = brokerData.BrokerAddrs["0"]
-		brokerData.BrokerAddrsLock.RUnlock()
-
-		if ok {
-			return
-		}
-		for _, addr = range brokerData.BrokerAddrs {
-			return addr, ok
-		}
-	}
-	return
-}
-
-func buildMqClientImplId() (clientId string) {
-	clientId = util.GetLocalIp4() + "@" + strconv.Itoa(os.Getpid())
-	return
-}
-
-func (self MqClientImpl) sendHeartBeat(addr string, remotingCommand *remoting.RemotingCommand, timeoutMillis int64) error {
-	remotingCommand, err := self.remotingClient.InvokeSync(addr, remotingCommand, timeoutMillis)
-	if err != nil {
-		glog.Error(err)
-	} else {
-		if remotingCommand == nil || remotingCommand.Code != remoting.SUCCESS {
-			glog.Error("send heartbeat response  error")
-		}
-	}
-	return err
-}
-
-func (self MqClientImpl) SendHeartbeatToAllBroker(heartBeatData *model.HeartbeatData) (err error) {
-	//self.brokerAddrTableLock.RLock()
-
-	for _, brokerTable := range self.BrokerAddrTable.Items() {
-		for brokerId, addr := range brokerTable.(map[string]string) {
-			if len(addr) == 0 || brokerId != "0" {
-				continue
-			}
-			data, err := json.Marshal(heartBeatData)
-			if err != nil {
-				glog.Error(err)
-				return err
-			}
-			glog.V(2).Info("send heartbeat to broker look data[", string(data)+"]")
-			remotingCommand := remoting.NewRemotingCommandWithBody(remoting.HEART_BEAT, nil, data)
-			glog.V(2).Info("send heartbeat to broker[", addr+"]")
-			self.sendHeartBeat(addr, remotingCommand, 3000)
-
-		}
-	}
-	return nil
-}
diff --git a/rocketmq-go/service/mq_fault_strategy.go b/rocketmq-go/service/mq_fault_strategy.go
deleted file mode 100644
index 852ab98..0000000
--- a/rocketmq-go/service/mq_fault_strategy.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-)
-
-type MQFaultStrategy struct {
-}
-
-//if first select : random one
-//if has error broker before ,skip the err broker
-func selectOneMessageQueue(topicPublishInfo *model.TopicPublishInfo, lastFailedBroker string) (mqQueue model.MessageQueue, err error) {
-	queueIndex := topicPublishInfo.FetchQueueIndex()
-	queues := topicPublishInfo.MessageQueueList
-	if len(lastFailedBroker) == 0 {
-		mqQueue = queues[queueIndex]
-		return
-	}
-	for i := 0; i < len(queues); i++ {
-		nowQueueIndex := queueIndex + i
-		if nowQueueIndex >= len(queues) {
-			nowQueueIndex = nowQueueIndex - len(queues)
-		}
-		if lastFailedBroker == queues[nowQueueIndex].BrokerName {
-			continue
-		}
-		mqQueue = queues[nowQueueIndex]
-		return
-	}
-	err = errors.New("send to [" + lastFailedBroker + "] fail,no other broker")
-	return
-}
diff --git a/rocketmq-go/service/offset_store.go b/rocketmq-go/service/offset_store.go
deleted file mode 100644
index 0bfe640..0000000
--- a/rocketmq-go/service/offset_store.go
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/golang/glog"
-	"strconv"
-	"sync"
-)
-
-const (
-	MEMORY_FIRST_THEN_STORE = 0
-	READ_FROM_MEMORY        = 1
-	READ_FROM_STORE         = 2
-)
-
-type OffsetStore interface {
-	UpdateOffset(mq *model.MessageQueue, offset int64, increaseOnly bool)
-	ReadOffset(mq *model.MessageQueue, readType int) int64
-	Persist(mq *model.MessageQueue)
-	RemoveOffset(mq *model.MessageQueue)
-}
-type RemoteOffsetStore struct {
-	groupName       string
-	mqClient        RocketMqClient
-	offsetTable     map[model.MessageQueue]int64
-	offsetTableLock sync.RWMutex
-}
-
-func RemoteOffsetStoreInit(groupName string, mqClient RocketMqClient) OffsetStore {
-	offsetStore := new(RemoteOffsetStore)
-	offsetStore.groupName = groupName
-	offsetStore.mqClient = mqClient
-	offsetStore.offsetTable = make(map[model.MessageQueue]int64)
-	return offsetStore
-}
-func (self *RemoteOffsetStore) RemoveOffset(mq *model.MessageQueue) {
-	defer self.offsetTableLock.Unlock()
-	self.offsetTableLock.Lock()
-	delete(self.offsetTable, *mq)
-}
-
-func (self *RemoteOffsetStore) Persist(mq *model.MessageQueue) {
-	brokerAddr := self.mqClient.FetchMasterBrokerAddress(mq.BrokerName)
-	if len(brokerAddr) == 0 {
-		self.mqClient.TryToFindTopicPublishInfo(mq.Topic)
-		brokerAddr = self.mqClient.FetchMasterBrokerAddress(mq.BrokerName)
-	}
-	self.offsetTableLock.RLock()
-	offset := self.offsetTable[*mq]
-	self.offsetTableLock.RUnlock()
-	updateConsumerOffsetRequestHeader := &header.UpdateConsumerOffsetRequestHeader{ConsumerGroup: self.groupName, Topic: mq.Topic, QueueId: mq.QueueId, CommitOffset: offset}
-	requestCommand := remoting.NewRemotingCommand(remoting.UPDATE_CONSUMER_OFFSET, updateConsumerOffsetRequestHeader)
-	self.mqClient.GetRemotingClient().InvokeOneWay(brokerAddr, requestCommand, 1000*5)
-}
-
-func (self *RemoteOffsetStore) ReadOffset(mq *model.MessageQueue, readType int) int64 {
-
-	switch readType {
-	case MEMORY_FIRST_THEN_STORE:
-	case READ_FROM_MEMORY:
-		self.offsetTableLock.RLock()
-		offset, ok := self.offsetTable[*mq]
-		self.offsetTableLock.RUnlock()
-		if ok {
-			return offset
-		} else {
-			return -1
-		}
-	case READ_FROM_STORE:
-		offset, err := self.fetchConsumeOffsetFromBroker(mq)
-		if err != nil {
-			glog.Error(err)
-			return -1
-		}
-		glog.V(2).Info("READ_FROM_STORE", offset)
-		self.UpdateOffset(mq, offset, false)
-		return offset
-	}
-
-	return -1
-
-}
-
-func (self *RemoteOffsetStore) fetchConsumeOffsetFromBroker(mq *model.MessageQueue) (int64, error) {
-	brokerAddr, _, found := self.mqClient.FindBrokerAddressInSubscribe(mq.BrokerName, 0, false)
-
-	if !found {
-		brokerAddr, _, found = self.mqClient.FindBrokerAddressInSubscribe(mq.BrokerName, 0, false)
-	}
-
-	if found {
-		requestHeader := &header.QueryConsumerOffsetRequestHeader{}
-		requestHeader.Topic = mq.Topic
-		requestHeader.QueueId = mq.QueueId
-		requestHeader.ConsumerGroup = self.groupName
-		return self.queryConsumerOffset(brokerAddr, requestHeader, 3000)
-	}
-
-	return -1, errors.New("fetch consumer offset error")
-}
-
-func (self RemoteOffsetStore) queryConsumerOffset(addr string, requestHeader *header.QueryConsumerOffsetRequestHeader, timeoutMillis int64) (int64, error) {
-	remotingCommand := remoting.NewRemotingCommand(remoting.QUERY_CONSUMER_OFFSET, requestHeader)
-	reponse, err := self.mqClient.GetRemotingClient().InvokeSync(addr, remotingCommand, timeoutMillis)
-	if err != nil {
-		glog.Error(err)
-		return -1, err
-	}
-
-	if reponse.Code == remoting.QUERY_NOT_FOUND {
-		return -1, nil
-	}
-
-	if offsetInter, ok := reponse.ExtFields["offset"]; ok {
-		if offsetStr, ok := offsetInter.(string); ok {
-			offset, err := strconv.ParseInt(offsetStr, 10, 64)
-			if err != nil {
-				glog.Error(err)
-				return -1, err
-			}
-			return offset, nil
-
-		}
-	}
-	glog.Error(requestHeader, reponse)
-	return -1, errors.New("query offset error")
-}
-
-func (self *RemoteOffsetStore) UpdateOffset(mq *model.MessageQueue, offset int64, increaseOnly bool) {
-	defer self.offsetTableLock.Unlock()
-	self.offsetTableLock.Lock()
-	if mq != nil {
-		if increaseOnly {
-			offsetOld := self.offsetTable[*mq]
-			if offsetOld >= offset {
-				return
-			}
-			self.offsetTable[*mq] = offset
-		} else {
-			self.offsetTable[*mq] = offset
-		}
-
-	}
-}
diff --git a/rocketmq-go/service/producer_service.go b/rocketmq-go/service/producer_service.go
deleted file mode 100644
index 2f2a7b6..0000000
--- a/rocketmq-go/service/producer_service.go
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
-	"github.com/golang/glog"
-	"time"
-)
-
-type ProducerService interface {
-	CheckConfig() (err error)
-	SendDefaultImpl(message *model.Message, communicationMode string, sendCallback string, timeout int64) (sendResult *model.SendResult, err error)
-}
-
-type DefaultProducerService struct {
-	producerGroup   string
-	producerConfig  *config.RocketMqProducerConfig
-	mqClient        RocketMqClient
-	mqFaultStrategy MQFaultStrategy
-}
-
-func NewDefaultProducerService(producerGroup string, producerConfig *config.RocketMqProducerConfig, mqClient RocketMqClient) (defaultProducerService *DefaultProducerService) {
-	defaultProducerService = &DefaultProducerService{
-		mqClient:       mqClient,
-		producerGroup:  producerGroup,
-		producerConfig: producerConfig,
-	}
-	defaultProducerService.CheckConfig()
-	return
-}
-func (self *DefaultProducerService) CheckConfig() (err error) {
-	// todo check if not pass panic
-	return
-}
-
-func (self *DefaultProducerService) SendDefaultImpl(message *model.Message, communicationMode string, sendCallback string, timeout int64) (sendResult *model.SendResult, err error) {
-	var (
-		topicPublishInfo *model.TopicPublishInfo
-	)
-	err = self.checkMessage(message)
-	if err != nil {
-		return
-	}
-	topicPublishInfo, err = self.mqClient.TryToFindTopicPublishInfo(message.Topic)
-	if err != nil {
-		return
-	}
-	if topicPublishInfo.JudgeTopicPublishInfoOk() == false {
-		err = errors.New("topicPublishInfo is error,topic=" + message.Topic)
-		return
-	}
-	glog.V(2).Info("op=look topicPublishInfo", topicPublishInfo)
-	//if(!ok) return error
-	sendResult, err = self.sendMsgUseTopicPublishInfo(message, communicationMode, sendCallback, topicPublishInfo, timeout)
-	return
-}
-
-func (self *DefaultProducerService) producerSendMessageRequest(brokerAddr string, sendMessageHeader remoting.CustomerHeader, message *model.Message, timeout int64) (sendResult *model.SendResult, err error) {
-	remotingCommand := remoting.NewRemotingCommandWithBody(remoting.SEND_MESSAGE, sendMessageHeader, message.Body)
-	var response *remoting.RemotingCommand
-	response, err = self.mqClient.GetRemotingClient().InvokeSync(brokerAddr, remotingCommand, timeout)
-	if err != nil {
-		glog.Error(err)
-		return
-	}
-	sendResult, err = processSendResponse(brokerAddr, message, response)
-	return
-}
-func processSendResponse(brokerName string, message *model.Message, response *remoting.RemotingCommand) (sendResult *model.SendResult, err error) {
-	sendResult = &model.SendResult{}
-	switch response.Code {
-	case remoting.FLUSH_DISK_TIMEOUT:
-		{
-			sendResult.SetSendStatus(model.FlushDiskTimeout)
-			break
-		}
-	case remoting.FLUSH_SLAVE_TIMEOUT:
-		{
-			sendResult.SetSendStatus(model.FlushSlaveTimeout)
-			break
-		}
-	case remoting.SLAVE_NOT_AVAILABLE:
-		{
-			sendResult.SetSendStatus(model.SlaveNotAvaliable)
-			break
-		}
-	case remoting.SUCCESS:
-		{
-			sendResult.SetSendStatus(model.SendOK)
-			break
-		}
-	default:
-		err = errors.New("response.Code error code")
-		return
-	}
-	var responseHeader = &header.SendMessageResponseHeader{}
-	if response.ExtFields != nil {
-		responseHeader.FromMap(response.ExtFields) //change map[string]interface{} into CustomerHeader struct
-	}
-	sendResult.SetMsgID(message.Properties[constant.PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX])
-	sendResult.SetOffsetMsgID(responseHeader.MsgId)
-	sendResult.SetQueueOffset(responseHeader.QueueOffset)
-	sendResult.SetTransactionID(responseHeader.TransactionId)
-	messageQueue := model.MessageQueue{Topic: message.Topic, BrokerName: brokerName,
-		QueueId: responseHeader.QueueId}
-	sendResult.SetMessageQueue(messageQueue)
-	var regionId = responseHeader.MsgRegion
-	if len(regionId) == 0 {
-		regionId = "DefaultRegion"
-	}
-	sendResult.SetRegionID(regionId)
-	return
-}
-
-func (self *DefaultProducerService) checkMessage(message *model.Message) (err error) {
-	if message == nil {
-		err = errors.New("message is nil")
-		return
-	}
-	if len(message.Topic) == 0 {
-		err = errors.New("topic is empty")
-		return
-	}
-	if message.Topic == constant.DEFAULT_TOPIC {
-		err = errors.New("the topic[" + message.Topic + "] is conflict with default topic.")
-		return
-	}
-
-	if len(message.Topic) > constant.MAX_MESSAGE_TOPIC_SIZE {
-		err = errors.New("the specified topic is longer than topic max length 255.")
-		return
-	}
-	//todo todo     public static final String VALID_PATTERN_STR = "";
-
-	if !util.MatchString(message.Topic, `^[%|a-zA-Z0-9_-]+$`) {
-		err = errors.New("the specified topic[" + message.Topic + "] contains illegal characters")
-		return
-	}
-	if len(message.Body) == 0 {
-		err = errors.New("messageBody is empty")
-		return
-	}
-	if len(message.Body) > self.producerConfig.MaxMessageSize {
-		err = errors.New("messageBody is large than " + util.IntToString(self.producerConfig.MaxMessageSize))
-		return
-	}
-	return
-}
-
-func (self *DefaultProducerService) sendMsgUseTopicPublishInfo(message *model.Message, communicationMode string, sendCallback string, topicPublishInfo *model.TopicPublishInfo, timeout int64) (sendResult *model.SendResult, err error) {
-	var (
-		sendTotalTime int
-		messageQueue  model.MessageQueue
-	)
-
-	sendTotalTime = 1
-	var lastFailedBroker = ""
-	//todo transaction
-	// todo retry
-	for i := 0; i < sendTotalTime; i++ {
-		messageQueue, err = selectOneMessageQueue(topicPublishInfo, lastFailedBroker)
-		if err != nil {
-			return
-		}
-		sendResult, err = self.doSendMessage(message, messageQueue, communicationMode, sendCallback, topicPublishInfo, timeout)
-		if err != nil {
-			// todo retry
-			return
-		}
-	}
-	return
-}
-
-func (self *DefaultProducerService) doSendMessage(message *model.Message, messageQueue model.MessageQueue,
-	communicationMode string, sendCallback string,
-	topicPublishInfo *model.TopicPublishInfo,
-	timeout int64) (sendResult *model.SendResult, err error) {
-	var (
-		brokerAddr          string
-		sysFlag             int
-		compressMessageFlag int
-	)
-	compressMessageFlag, err = self.tryToCompressMessage(message)
-	if err != nil {
-		return
-	}
-	sysFlag = sysFlag | compressMessageFlag
-	brokerAddr = self.mqClient.FetchMasterBrokerAddress(messageQueue.BrokerName)
-	if len(brokerAddr) == 0 {
-		err = errors.New("The broker[" + messageQueue.BrokerName + "] not exist")
-		return
-	}
-	message.GeneratorMsgUniqueKey()
-	sendMessageHeader := &header.SendMessageRequestHeader{
-		ProducerGroup:         self.producerGroup,
-		Topic:                 message.Topic,
-		DefaultTopic:          constant.DEFAULT_TOPIC,
-		DefaultTopicQueueNums: 4,
-		QueueId:               messageQueue.QueueId,
-		SysFlag:               sysFlag,
-		BornTimestamp:         time.Now().UnixNano() / 1000000,
-		Flag:                  message.Flag,
-		Properties:            util.MessageProperties2String(message.Properties),
-
-		UnitMode:          false,
-		ReconsumeTimes:    message.GetReconsumeTimes(),
-		MaxReconsumeTimes: message.GetMaxReconsumeTimes(),
-	}
-	sendResult, err = self.producerSendMessageRequest(brokerAddr, sendMessageHeader, message, timeout)
-	return
-}
-
-func (self *DefaultProducerService) tryToCompressMessage(message *model.Message) (compressedFlag int, err error) {
-	if len(message.Body) < self.producerConfig.CompressMsgBodyOverHowMuch {
-		compressedFlag = 0
-		return
-	}
-	compressedFlag = int(constant.CompressedFlag)
-	message.Body, err = util.CompressWithLevel(message.Body, self.producerConfig.ZipCompressLevel)
-	return
-}
diff --git a/rocketmq-go/service/producer_service_for_send_back.go b/rocketmq-go/service/producer_service_for_send_back.go
deleted file mode 100644
index 290da27..0000000
--- a/rocketmq-go/service/producer_service_for_send_back.go
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"encoding/json"
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/golang/glog"
-)
-
-type SendMessageBackProducerService interface {
-	SendMessageBack(messageExt *model.MessageExt, delayLayLevel int, brokerName string) (err error)
-	InitSendMessageBackProducerService(consumerGroup string, mqClient RocketMqClient, defaultProducerService *DefaultProducerService, consumerConfig *config.RocketMqConsumerConfig)
-}
-
-type SendMessageBackProducerServiceImpl struct {
-	mqClient               RocketMqClient
-	defaultProducerService *DefaultProducerService // one namesvr only one
-	consumerGroup          string
-	consumerConfig         *config.RocketMqConsumerConfig //one mq group have one
-}
-
-// send to original broker,if fail send a new retry message
-func (self *SendMessageBackProducerServiceImpl) SendMessageBack(messageExt *model.MessageExt, delayLayLevel int, brokerName string) (err error) {
-	glog.V(2).Info("op=look_send_message_back", messageExt.MsgId, messageExt.Properties, string(messageExt.Body))
-	err = self.consumerSendMessageBack(brokerName, messageExt, delayLayLevel) // todo use
-	if err == nil {
-		return
-	}
-	glog.Error(err)
-	err = self.sendRetryMessageBack(messageExt)
-	return
-}
-
-func (self *SendMessageBackProducerServiceImpl) sendRetryMessageBack(messageExt *model.MessageExt) error {
-	// todo build a retry topic todo check todo check
-	retryMessage := &model.Message{}
-	originMessageId := messageExt.GetOriginMessageId()
-	retryMessage.Properties = messageExt.Properties
-	retryMessage.SetOriginMessageId(originMessageId)
-	retryMessage.Flag = messageExt.Flag
-	retryMessage.Topic = constant.RETRY_GROUP_TOPIC_PREFIX + self.consumerGroup
-	retryMessage.Body = messageExt.Body
-	retryMessage.SetRetryTopic(messageExt.Topic)
-	retryMessage.SetReconsumeTime(messageExt.GetReconsumeTimes() + 1)
-	retryMessage.SetMaxReconsumeTimes(self.consumerConfig.MaxReconsumeTimes)
-	retryMessage.SetDelayTimeLevel(3 + messageExt.GetReconsumeTimes())
-	pp, _ := json.Marshal(retryMessage)
-	glog.Info("look retryMessage ", string(pp), string(messageExt.Body))
-	sendResult, err := self.defaultProducerService.SendDefaultImpl(retryMessage, constant.COMMUNICATIONMODE_SYNC, "", self.defaultProducerService.producerConfig.SendMsgTimeout)
-	if err != nil {
-		glog.Error(err)
-		return err
-	}
-	xx, _ := json.Marshal(sendResult)
-	glog.Info("look retryMessage result", string(xx))
-	// todo need check send result
-	return nil
-
-}
-
-func (self *SendMessageBackProducerServiceImpl) InitSendMessageBackProducerService(consumerGroup string, mqClient RocketMqClient, defaultProducerService *DefaultProducerService, consumerConfig *config.RocketMqConsumerConfig) {
-	self.mqClient = mqClient
-	self.consumerGroup = consumerGroup
-	self.defaultProducerService = defaultProducerService
-	self.consumerConfig = consumerConfig
-}
-
-func (self *SendMessageBackProducerServiceImpl) consumerSendMessageBack(brokerName string, messageExt *model.MessageExt, delayLayLevel int) (err error) {
-	if len(brokerName) == 0 {
-		err = errors.New("broker can't be empty")
-		glog.Error(err)
-		return
-	}
-	brokerAddr := self.mqClient.FetchMasterBrokerAddress(brokerName)
-	sendMsgBackHeader := &header.ConsumerSendMsgBackRequestHeader{
-		Offset:            messageExt.CommitLogOffset,
-		Group:             self.consumerGroup,
-		DelayLevel:        0, //Message consume retry strategy<br>-1,no retry,put into DLQ directly<br>0,broker control retry frequency<br>>0,client control retry frequency
-		OriginMsgId:       messageExt.MsgId,
-		OriginTopic:       messageExt.Topic,
-		UnitMode:          false,
-		MaxReconsumeTimes: int32(self.consumerConfig.MaxReconsumeTimes),
-	}
-	remotingCommand := remoting.NewRemotingCommand(remoting.CONSUMER_SEND_MSG_BACK, sendMsgBackHeader)
-	response, invokeErr := self.mqClient.GetRemotingClient().InvokeSync(brokerAddr, remotingCommand, 5000)
-	if invokeErr != nil {
-		err = invokeErr
-		return
-	}
-	if response == nil || response.Code != remoting.SUCCESS {
-		glog.Error("sendMsgBackRemarkError", response.Remark)
-		err = errors.New("send Message back error")
-	}
-	return
-}
diff --git a/rocketmq-go/service/rebalance.go b/rocketmq-go/service/rebalance.go
deleted file mode 100644
index 8f4f4fb..0000000
--- a/rocketmq-go/service/rebalance.go
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package service
-
-import (
-	"encoding/json"
-	"errors"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/config"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/constant"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/model/header"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/remoting"
-	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/service/allocate_message"
-	"github.com/golang/glog"
-	"sort"
-	"strings"
-	"sync"
-	"time"
-)
-
-type Rebalance struct {
-	groupName                    string
-	messageModel                 string
-	topicSubscribeInfoTableLock  sync.RWMutex
-	SubscriptionInner            map[string]*model.SubscriptionData
-	subscriptionInnerLock        sync.RWMutex
-	mqClient                     RocketMqClient
-	allocateMessageQueueStrategy service_allocate_message.AllocateMessageQueueStrategy
-	processQueueTable            map[model.MessageQueue]*model.ProcessQueue // both subscribe topic and retry group
-	processQueueTableLock        sync.RWMutex
-	mutex                        sync.Mutex
-	offsetStore                  OffsetStore
-	consumerConfig               *config.RocketMqConsumerConfig
-}
-
-func (self *Rebalance) GetMqTableInfo() map[model.MessageQueue]model.ProcessQueueInfo {
-	defer self.processQueueTableLock.RUnlock()
-	self.processQueueTableLock.RLock()
-	mqTable := map[model.MessageQueue]model.ProcessQueueInfo{}
-	for messageQueue, processQueue := range self.processQueueTable {
-		mqTable[messageQueue] = processQueue.ChangeToProcessQueueInfo()
-	}
-	return mqTable
-}
-
-func (self *Rebalance) GetProcessQueue(messageQueue model.MessageQueue) *model.ProcessQueue {
-	defer self.processQueueTableLock.RUnlock()
-	self.processQueueTableLock.RLock()
-	return self.processQueueTable[messageQueue]
-}
-
-func (self *Rebalance) ClearProcessQueue(offsetTable map[model.MessageQueue]int64) {
-	defer self.processQueueTableLock.Unlock()
-	self.processQueueTableLock.Lock()
-	for mq, _ := range offsetTable {
-		processQueue, ok := self.processQueueTable[mq]
-		if !ok {
-			continue
-		}
-		processQueue.Clear()
-	}
-
-}
-
-func (self *Rebalance) GetProcessQueueList() (messageQueueList []model.MessageQueue, processQueueList []*model.ProcessQueue) {
-	defer self.processQueueTableLock.RUnlock()
-	self.processQueueTableLock.RLock()
-	for messageQueue, processQueue := range self.processQueueTable {
-		processQueueList = append(processQueueList, processQueue)
-		messageQueueList = append(messageQueueList, messageQueue)
-	}
-	return
-}
-
-//removeUnnecessaryMessageQueue you should drop it first
-func (self *Rebalance) RemoveProcessQueue(messageQueue *model.MessageQueue) {
-	self.offsetStore.Persist(messageQueue)
-	self.offsetStore.RemoveOffset(messageQueue)
-	self.removeMessageQueueFromMap(*messageQueue)
-}
-func (self *Rebalance) removeMessageQueueFromMap(messageQueue model.MessageQueue) {
-	defer self.processQueueTableLock.Unlock()
-	self.processQueueTableLock.Lock()
-	delete(self.processQueueTable, messageQueue)
-
-}
-
-func NewRebalance(groupName string, subscription map[string]string, mqClient RocketMqClient, offsetStore OffsetStore, consumerConfig *config.RocketMqConsumerConfig) *Rebalance {
-	subscriptionInner := make(map[string]*model.SubscriptionData)
-	for topic, subExpression := range subscription {
-		subData := &model.SubscriptionData{
-			Topic:      topic,
-			SubString:  subExpression,
-			SubVersion: time.Now().Unix(),
-		}
-		subscriptionInner[topic] = subData
-	}
-	// put retry
-	retryTopic := constant.RETRY_GROUP_TOPIC_PREFIX + groupName
-	subscriptionInner[retryTopic] = &model.SubscriptionData{
-		Topic:      retryTopic,
-		SubString:  "*",
-		SubVersion: time.Now().Unix(),
-	}
-	return &Rebalance{
-		groupName:                    groupName,
-		mqClient:                     mqClient,
-		offsetStore:                  offsetStore,
-		SubscriptionInner:            subscriptionInner,
-		allocateMessageQueueStrategy: service_allocate_message.GetAllocateMessageQueueStrategyByConfig("default"),
-		messageModel:                 "CLUSTERING",
-		processQueueTable:            make(map[model.MessageQueue]*model.ProcessQueue),
-		consumerConfig:               consumerConfig,
-	}
-}
-
-func (self *Rebalance) DoRebalance() {
-	self.mutex.Lock()
-	defer self.mutex.Unlock()
-	for topic, _ := range self.SubscriptionInner {
-		self.rebalanceByTopic(topic)
-	}
-}
-
-type ConsumerIdSorter []string
-
-func (self ConsumerIdSorter) Len() int {
-	return len(self)
-}
-func (self ConsumerIdSorter) Swap(i, j int) {
-	self[i], self[j] = self[j], self[i]
-}
-func (self ConsumerIdSorter) Less(i, j int) bool {
-	if self[i] < self[j] {
-		return true
-	}
-	return false
-}
-
-func (self *Rebalance) rebalanceByTopic(topic string) error {
-	var cidAll []string
-	cidAll, err := self.findConsumerIdList(topic, self.groupName)
-	if err != nil {
-		glog.Error(err)
-		return err
-	}
-	self.topicSubscribeInfoTableLock.RLock()
-	mqs := self.mqClient.GetTopicSubscribeInfo(topic)
-	self.topicSubscribeInfoTableLock.RUnlock()
-	if len(mqs) > 0 && len(cidAll) > 0 {
-		var messageQueues model.MessageQueues = mqs
-		var consumerIdSorter ConsumerIdSorter = cidAll
-
-		sort.Sort(messageQueues)
-		sort.Sort(consumerIdSorter)
-	}
-	allocateResult, err := self.allocateMessageQueueStrategy.Allocate(self.groupName, self.mqClient.GetClientId(), mqs, cidAll)
-
-	if err != nil {
-		glog.Error(err)
-		return err
-	}
-
-	glog.V(2).Infof("rebalance topic[%s]", topic)
-	self.updateProcessQueueTableInRebalance(topic, allocateResult)
-	return nil
-}
-
-func (self *Rebalance) updateProcessQueueTableInRebalance(topic string, mqSet []model.MessageQueue) {
-	defer self.processQueueTableLock.RUnlock()
-	self.processQueueTableLock.RLock()
-	self.removeTheQueueDontBelongHere(topic, mqSet)
-	self.putTheQueueToProcessQueueTable(topic, mqSet)
-
-}
-func (self *Rebalance) removeTheQueueDontBelongHere(topic string, mqSet []model.MessageQueue) {
-	// there is n^2 todo improve
-	for key, value := range self.processQueueTable {
-		if topic != key.Topic {
-			continue
-		}
-		needDelete := true
-		for _, messageQueueItem := range mqSet {
-			if key == messageQueueItem {
-				needDelete = false
-				// todo if expire
-				break
-			}
-		}
-		if needDelete {
-			value.SetDrop(true)
-			delete(self.processQueueTable, key)
-		}
-	}
-}
-
-func (self *Rebalance) putTheQueueToProcessQueueTable(topic string, mqSet []model.MessageQueue) {
-	for index, mq := range mqSet {
-		_, ok := self.processQueueTable[mq]
-		if !ok {
-			pullRequest := new(model.PullRequest)
-			pullRequest.ConsumerGroup = self.groupName
-			pullRequest.MessageQueue = &mqSet[index]
-			pullRequest.NextOffset = self.computePullFromWhere(&mq) // todo use remote offset
-			pullRequest.ProcessQueue = model.NewProcessQueue()
-			self.processQueueTable[mq] = pullRequest.ProcessQueue
-			self.mqClient.EnqueuePullMessageRequest(pullRequest)
-		}
-	}
-
-}
-func (self *Rebalance) computePullFromWhere(mq *model.MessageQueue) int64 {
-	var result int64 = -1
-	lastOffset := self.offsetStore.ReadOffset(mq, READ_FROM_STORE)
-	switch self.consumerConfig.ConsumeFromWhere {
-	case config.CONSUME_FROM_LAST_OFFSET:
-		if lastOffset >= 0 {
-			result = lastOffset
-		} else {
-			if strings.HasPrefix(mq.Topic, constant.RETRY_GROUP_TOPIC_PREFIX) {
-				result = 0
-			} else {
-				result = self.mqClient.GetMaxOffset(mq)
-			}
-		}
-		break
-	case config.CONSUME_FROM_FIRST_OFFSET:
-		if lastOffset >= 0 {
-			result = lastOffset
-		} else {
-			result = 0 // use the begin offset
-		}
-		break
-	case config.CONSUME_FROM_TIMESTAMP:
-		if lastOffset >= 0 {
-			result = lastOffset
-		} else {
-			if strings.HasPrefix(mq.Topic, constant.RETRY_GROUP_TOPIC_PREFIX) {
-				result = 0
-			} else {
-				result = self.mqClient.SearchOffset(mq, self.consumerConfig.ConsumeTimestamp)
-			}
-		}
-		break
-	default:
-
-	}
-
-	return result
-}
-
-func (self *Rebalance) findConsumerIdList(topic string, groupName string) ([]string, error) {
-	brokerAddr, ok := self.mqClient.FindBrokerAddrByTopic(topic)
-	if !ok {
-		err := self.mqClient.UpdateTopicRouteInfoFromNameServer(topic)
-		if err != nil {
-			glog.Error(err)
-		}
-		brokerAddr, ok = self.mqClient.FindBrokerAddrByTopic(topic)
-	}
-
-	if ok {
-		return self.getConsumerIdListByGroup(brokerAddr, groupName, 3000)
-	}
-
-	return nil, errors.New("can't find broker")
-
-}
-
-func (self *Rebalance) getConsumerIdListByGroup(addr string, consumerGroup string, timeoutMillis int64) ([]string, error) {
-	requestHeader := new(header.GetConsumerListByGroupRequestHeader)
-	requestHeader.ConsumerGroup = consumerGroup
-
-	request := remoting.NewRemotingCommand(remoting.GET_CONSUMER_LIST_BY_GROUP, requestHeader)
-
-	response, err := self.mqClient.GetRemotingClient().InvokeSync(addr, request, timeoutMillis)
-	if err != nil {
-		glog.Error(err)
-		return nil, err
-	}
-	if response.Code == remoting.SUCCESS {
-		getConsumerListByGroupResponseBody := new(header.GetConsumerListByGroupResponseBody)
-		bodyjson := strings.Replace(string(response.Body), "0:", "\"0\":", -1)
-		bodyjson = strings.Replace(bodyjson, "1:", "\"1\":", -1)
-		err := json.Unmarshal([]byte(bodyjson), getConsumerListByGroupResponseBody)
-		if err != nil {
-			glog.Error(err)
-			return nil, err
-		}
-		return getConsumerListByGroupResponseBody.ConsumerIdList, nil
-	}
-	return nil, errors.New("getConsumerIdListByGroup error=" + response.Remark)
-}
diff --git a/rocketmq-go/tasks.go b/rocketmq-go/tasks.go
deleted file mode 100644
index 604222f..0000000
--- a/rocketmq-go/tasks.go
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package rocketmq
-
-import (
-	"math/rand"
-	"time"
-)
-
-type TaskManager struct {
-}
-
-func (self MqClientManager) StartAllScheduledTask() {
-	rand.Seed(time.Now().UnixNano())
-	go func() {
-		updateTopicRouteTimer := time.NewTimer(5 * time.Second)
-		for {
-			<-updateTopicRouteTimer.C
-			self.UpdateTopicRouteInfoFromNameServer()
-			updateTopicRouteTimer.Reset(5 * time.Second)
-		}
-	}()
-
-	go func() {
-		heartbeatTimer := time.NewTimer(10 * time.Second)
-		for {
-			<-heartbeatTimer.C
-			self.SendHeartbeatToAllBrokerWithLock()
-			heartbeatTimer.Reset(5 * time.Second)
-		}
-	}()
-
-	go func() {
-		rebalanceTimer := time.NewTimer(15 * time.Second)
-		for {
-			<-rebalanceTimer.C
-			self.rebalanceControllr.doRebalance()
-			rebalanceTimer.Reset(30 * time.Second)
-		}
-	}()
-
-	go func() {
-		timeoutTimer := time.NewTimer(3 * time.Second)
-		for {
-			<-timeoutTimer.C
-			self.mqClient.ClearExpireResponse()
-			timeoutTimer.Reset(time.Second)
-		}
-	}()
-	self.pullMessageController.Start()
-
-	//cleanExpireMsg
-	self.cleanExpireMsgController.Start()
-}
diff --git a/rocketmq-go/test/test_consume_message_retry.go b/rocketmq-go/test/test_consume_message_retry.go
new file mode 100644
index 0000000..7c1a8f6
--- /dev/null
+++ b/rocketmq-go/test/test_consume_message_retry.go
@@ -0,0 +1,78 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+	"time"
+)
+
+//test consume message, first and second time consume error,third time consume success
+func main() {
+	chResult := make(chan bool, 3)
+	var (
+		nameServerAddress = "127.0.0.1:9876"
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestRetryProducerGroup"
+		testConsumerGroup = "TestRetryConsumerGroup"
+		tag               = "RetryTestTag"
+		testMessageBody   = "RetryTestMessageBody"
+		consumeTime       = 0
+	)
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, tag)
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, message := range messageList {
+			if string(message.Body()) != testMessageBody {
+				panic("message.body is wrong message.body=" + string(message.Body()) + " testMessageBody=" + testMessageBody + " tag=" + message.Tag())
+			}
+			if consumeTime < 2 {
+				consumeTime++
+				chResult <- true
+				glog.Info("test consume fail")
+				break
+			}
+			glog.Info("test consume success")
+			chResult <- true
+			successIndex = index
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+	rocketMQClientInstance.Start()
+	var message = rocketmqm.NewMessage()
+	message.SetTopic(testTopic)
+	message.SetBody([]byte(testMessageBody))
+	message.SetTag(tag)
+	result, err := producer.Send(message)
+	glog.Infof("test sendMessageResult messageId=[%s] err=[%s]", result.MsgID(), err)
+	for i := 0; i < 3; i++ {
+		select {
+		case <-chResult:
+		case <-time.After(time.Second * 50):
+			panic("receive tag message timeout")
+		}
+	}
+	glog.Info("Test tag message success")
+}
diff --git a/rocketmq-go/test/test_delay_message_send_and_receive.go b/rocketmq-go/test/test_delay_message_send_and_receive.go
new file mode 100644
index 0000000..e57ffbb
--- /dev/null
+++ b/rocketmq-go/test/test_delay_message_send_and_receive.go
@@ -0,0 +1,79 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+	"time"
+)
+
+func main() {
+	var (
+		nameServerAddress = "127.0.0.1:9876"
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestDelayProducerGroup"
+		testConsumerGroup = "TestDelayConsumerGroup"
+		tag               = "TestDelayMessageTag"
+	)
+	var messageId string
+	var startTime time.Time
+	chResult := make(chan bool, 1)
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, tag)
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			endTime := time.Now()
+			if msg.MsgId() != messageId {
+				panic("messageId is wrong " + msg.MsgId())
+			}
+			costSeconds := endTime.Unix() - startTime.Unix()
+			if costSeconds < 14 || costSeconds > 16 {
+				panic("delay time message is error ")
+			}
+			chResult <- true
+			successIndex = index
+
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+	rocketMQClientInstance.Start()
+	<-time.After(time.Second * 30) // wait
+	var message = rocketmqm.NewMessage()
+	message.SetTopic(testTopic)
+	message.SetBody([]byte("hello world"))
+	message.SetTag(tag)
+	message.SetDelayTimeLevel(3) // cost 15 second
+	result, err := producer.Send(message)
+	startTime = time.Now()
+	messageId = result.MsgID()
+	glog.Infof("test sendMessageResult messageId=[%s] err=[%s]", result.MsgID(), err)
+	select {
+	case <-chResult:
+	case <-time.After(time.Second * 30):
+		panic("receive tag message timeout")
+	}
+	glog.Info("Test tag message success")
+
+}
diff --git a/rocketmq-go/test/test_rocketmq_serialize_message_send_and_receive.go b/rocketmq-go/test/test_rocketmq_serialize_message_send_and_receive.go
new file mode 100644
index 0000000..78ab8d3
--- /dev/null
+++ b/rocketmq-go/test/test_rocketmq_serialize_message_send_and_receive.go
@@ -0,0 +1,75 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+	"time"
+)
+
+func main() {
+	var (
+		nameServerAddress = "127.0.0.1:9876"
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestSerializeProducerGroup"
+		testConsumerGroup = "TestSerializeConsumerGroup"
+		tag               = "TestSerializeMessageTag"
+		messageBody       = "testMessageBody_testMessageBody"
+		messageCount      = 100
+	)
+	chResult := make(chan bool, messageCount)
+	mqClientConfig := rocketmqm.NewMqClientConfig(nameServerAddress)
+	mqClientConfig.ClientSerializeType = rocketmqm.ROCKETMQ_SERIALIZE
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstanceWithCustomClientConfig(mqClientConfig)
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, tag)
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			if msg.Tag() == tag && messageBody == string(messageBody) {
+				chResult <- true
+			}
+			successIndex = index
+
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+	rocketMQClientInstance.Start()
+	for i := 0; i < messageCount; i++ {
+		var message = rocketmqm.NewMessage()
+		message.SetTopic(testTopic)
+		message.SetBody([]byte(messageBody))
+		message.SetTag(tag)
+		result, err := producer.Send(message)
+		glog.Infof("test sendMessageResult messageId=[%s] err=[%s]", result.MsgID(), err)
+	}
+	for i := 0; i < messageCount; i++ {
+		select {
+		case <-chResult:
+		case <-time.After(time.Second * 30):
+			panic("receive tag message timeout")
+		}
+	}
+	glog.Info("Test tag message success")
+
+}
diff --git a/rocketmq-go/test/test_send_and_receive_compress_message.go b/rocketmq-go/test/test_send_and_receive_compress_message.go
new file mode 100644
index 0000000..e80c2b8
--- /dev/null
+++ b/rocketmq-go/test/test_send_and_receive_compress_message.go
@@ -0,0 +1,76 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/golang/glog"
+	"time"
+)
+
+func main() {
+	chResult := make(chan bool, 1)
+	var (
+		nameServerAddress = "127.0.0.1:9876"
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestCompressProducerGroup"
+		testConsumerGroup = "TestCompressConsumerGroup"
+	)
+	var bigMessageBody = "test_string"
+	for i := 0; i < 16; i++ {
+		bigMessageBody += bigMessageBody
+	}
+	//bigMessageBody len will be 720896,it will be compressed
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	producerConfig := rocketmqm.NewProducerConfig()
+	producerConfig.CompressMsgBodyOverHowMuch = 500
+	var producer = rocketmq.NewDefaultMQProducerWithCustomConfig(testProducerGroup, producerConfig)
+	rocketMQClientInstance.RegisterProducer(producer)
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, "compress_message_test")
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			//if msg.SysFlag&constant.CompressedFlag != constant.CompressedFlag {
+			//	panic("message not be compressed")
+			//}
+			if string(msg.Body()) != bigMessageBody {
+				panic("message not be unCompressed")
+			}
+			glog.Info("Test compress and tag success")
+			successIndex = index
+
+		}
+		chResult <- true
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+	rocketMQClientInstance.Start()
+	var message = rocketmqm.NewMessage()
+	message.SetTopic(testTopic)
+	message.SetBody([]byte(bigMessageBody))
+	message.SetTag("compress_message_test")
+	result, err := producer.Send(message)
+	glog.Infof("test sendMessageResult messageId=[%s] err=[%s]", result.MsgID(), err)
+	select {
+	case <-chResult:
+	case <-time.After(time.Second * 30):
+		panic("receive compressed message timeout")
+	}
+}
diff --git a/rocketmq-go/test/test_send_and_receive_tag_message.go b/rocketmq-go/test/test_send_and_receive_tag_message.go
new file mode 100644
index 0000000..b1155b3
--- /dev/null
+++ b/rocketmq-go/test/test_send_and_receive_tag_message.go
@@ -0,0 +1,75 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package main
+
+import (
+	"fmt"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/api/model"
+	"github.com/apache/incubator-rocketmq-externals/rocketmq-go/util"
+	"github.com/golang/glog"
+	"time"
+)
+
+func main() {
+	chResult := make(chan bool, 3)
+	var (
+		nameServerAddress = "127.0.0.1:9876"
+		testTopic         = "GoLangRocketMQ"
+		testProducerGroup = "TestTagProducerGroup"
+		testConsumerGroup = "TestTagConsumerGroup"
+	)
+	rocketMQClientInstance := rocketmq.InitRocketMQClientInstance(nameServerAddress)
+	var producer = rocketmq.NewDefaultMQProducer(testProducerGroup)
+	rocketMQClientInstance.RegisterProducer(producer)
+	var consumer = rocketmq.NewDefaultMQPushConsumer(testConsumerGroup)
+	consumer.Subscribe(testTopic, "tag0 || tag2||tag4")
+	consumer.RegisterMessageListener(func(messageList []rocketmqm.MessageExt) rocketmqm.ConsumeConcurrentlyResult {
+		successIndex := -1
+		for index, msg := range messageList {
+			if msg.Tag() != "tag0" && msg.Tag() != "tag2" && msg.Tag() != "tag4" {
+				panic("receive message not belong here tag=" + msg.Tag())
+			}
+			fmt.Println("got " + msg.Tag())
+			chResult <- true
+			successIndex = index
+
+		}
+		return rocketmqm.ConsumeConcurrentlyResult{ConsumeConcurrentlyStatus: rocketmqm.CONSUME_SUCCESS, AckIndex: successIndex}
+	})
+	rocketMQClientInstance.RegisterConsumer(consumer)
+	rocketMQClientInstance.Start()
+	for i := 0; i < 5; i++ {
+		var message = rocketmqm.NewMessage()
+		message.SetTopic(testTopic)
+		message.SetBody([]byte("Hello world"))
+		message.SetTag("tag" + util.IntToString(i))
+		result, err := producer.Send(message)
+		glog.Infof("test sendMessageResult messageId=[%s] err=[%s]", result.MsgID(), err)
+	}
+	for i := 0; i < 3; i++ {
+		select {
+		case <-chResult:
+
+		case <-time.After(time.Second * 30):
+			panic("receive tag message timeout")
+		}
+	}
+	glog.Info("Test tag message success")
+
+}
diff --git a/rocketmq-go/util/compress_util.go b/rocketmq-go/util/compress_util.go
index 0617911..30df33c 100644
--- a/rocketmq-go/util/compress_util.go
+++ b/rocketmq-go/util/compress_util.go
@@ -1,19 +1,20 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import (
@@ -23,20 +24,20 @@
 	"io/ioutil"
 )
 
+//UnCompress un compress byte array
 func UnCompress(body []byte) (unCompressBody []byte, err error) {
 	b := bytes.NewReader(body)
 	z, err := zlib.NewReader(b)
 	if err != nil {
 		glog.Error(err)
-		return
+		return nil, err
 	}
-	defer z.Close()
 	unCompressBody, err = ioutil.ReadAll(z)
-	if err != nil {
-		glog.Error(err)
-	}
-	return
+	z.Close()
+	return unCompressBody, nil
 }
+
+//Compress compress byte array
 func Compress(body []byte) (compressBody []byte, err error) {
 	var in bytes.Buffer
 	w := zlib.NewWriter(&in)
@@ -46,6 +47,7 @@
 	return
 }
 
+//CompressWithLevel compress byte array with level
 func CompressWithLevel(body []byte, level int) (compressBody []byte, err error) {
 	var (
 		in bytes.Buffer
diff --git a/rocketmq-go/util/compress_util_test.go b/rocketmq-go/util/compress_util_test.go
new file mode 100644
index 0000000..2673feb
--- /dev/null
+++ b/rocketmq-go/util/compress_util_test.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"testing"
+)
+
+func TestCompressWithLevel(t *testing.T) {
+	bytes := []byte{120, 156, 202, 72, 205, 201, 201, 215, 81, 40, 207,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147,
+		47, 202, 73, 225, 2, 4, 0, 0, 255, 255, 33, 231, 4, 147}
+	body1, error1 := CompressWithLevel(bytes, 5)
+	if len(body1) > len(bytes) && error1 != nil {
+		t.Errorf("CompressWithLevel failed : cannot transfer byte[]")
+	}
+	body2, error2 := CompressWithLevel(nil, 10)
+	if body2 != nil && error2 != nil {
+		t.Errorf("CompressWithLevel failed : cannot handle error")
+	}
+}
diff --git a/rocketmq-go/util/concurrent_map.go b/rocketmq-go/util/concurrent_map.go
deleted file mode 100644
index 9d3e273..0000000
--- a/rocketmq-go/util/concurrent_map.go
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package util
-
-import (
-	"encoding/json"
-	"sync"
-)
-
-var SHARD_COUNT = 33
-
-// A "thread" safe map of type string:Anything.
-// To avoid lock bottlenecks this map is dived to several (SHARD_COUNT) map shards.
-type ConcurrentMap []*concurrentMapShared
-
-// A "thread" safe string to anything map.
-type concurrentMapShared struct {
-	items        map[string]interface{}
-	sync.RWMutex // Read Write mutex, guards access to internal map.
-}
-
-// Creates a new concurrent map.
-func New() ConcurrentMap {
-	m := make(ConcurrentMap, SHARD_COUNT)
-	for i := 0; i < SHARD_COUNT; i++ {
-		m[i] = &concurrentMapShared{items: make(map[string]interface{})}
-	}
-	return m
-}
-
-// Returns shard under given key
-func (m ConcurrentMap) GetShard(key string) *concurrentMapShared {
-	return m[uint(fnv32(key))%uint(SHARD_COUNT)]
-}
-
-func (m ConcurrentMap) MSet(data map[string]interface{}) {
-	for key, value := range data {
-		shard := m.GetShard(key)
-		shard.Lock()
-		shard.items[key] = value
-		shard.Unlock()
-	}
-}
-
-// Sets the given value under the specified key.
-func (m *ConcurrentMap) Set(key string, value interface{}) {
-	// Get map shard.
-	shard := m.GetShard(key)
-	shard.Lock()
-	shard.items[key] = value
-	shard.Unlock()
-}
-
-// Callback to return new element to be inserted into the map
-// It is called while lock is held, therefore it MUST NOT
-// try to access other keys in same map, as it can lead to deadlock since
-// Go sync.RWLock is not reentrant
-type UpsertCb func(exist bool, valueInMap interface{}, newValue interface{}) interface{}
-
-// Insert or Update - updates existing element or inserts a new one using UpsertCb
-func (m *ConcurrentMap) Upsert(key string, value interface{}, cb UpsertCb) (res interface{}) {
-	shard := m.GetShard(key)
-	shard.Lock()
-	v, ok := shard.items[key]
-	res = cb(ok, v, value)
-	shard.items[key] = res
-	shard.Unlock()
-	return res
-}
-
-// Sets the given value under the specified key if no value was associated with it.
-func (m *ConcurrentMap) SetIfAbsent(key string, value interface{}) bool {
-	// Get map shard.
-	shard := m.GetShard(key)
-	shard.Lock()
-	_, ok := shard.items[key]
-	if !ok {
-		shard.items[key] = value
-	}
-	shard.Unlock()
-	return !ok
-}
-
-// Retrieves an element from map under given key.
-func (m ConcurrentMap) Get(key string) (interface{}, bool) {
-	// Get shard
-	shard := m.GetShard(key)
-	shard.RLock()
-	// Get item from shard.
-	val, ok := shard.items[key]
-	shard.RUnlock()
-	return val, ok
-}
-
-// Returns the number of elements within the map.
-func (m ConcurrentMap) Count() int {
-	count := 0
-	for i := 0; i < SHARD_COUNT; i++ {
-		shard := m[i]
-		shard.RLock()
-		count += len(shard.items)
-		shard.RUnlock()
-	}
-	return count
-}
-
-// Looks up an item under specified key
-func (m *ConcurrentMap) Has(key string) bool {
-	// Get shard
-	shard := m.GetShard(key)
-	shard.RLock()
-	// See if element is within shard.
-	_, ok := shard.items[key]
-	shard.RUnlock()
-	return ok
-}
-
-// Removes an element from the map.
-func (m *ConcurrentMap) Remove(key string) {
-	// Try to get shard.
-	shard := m.GetShard(key)
-	shard.Lock()
-	delete(shard.items, key)
-	shard.Unlock()
-}
-
-// Removes an element from the map and returns it
-func (m *ConcurrentMap) Pop(key string) (v interface{}, exists bool) {
-	// Try to get shard.
-	shard := m.GetShard(key)
-	shard.Lock()
-	v, exists = shard.items[key]
-	delete(shard.items, key)
-	shard.Unlock()
-	return v, exists
-}
-
-// Checks if map is empty.
-func (m *ConcurrentMap) IsEmpty() bool {
-	return m.Count() == 0
-}
-
-// Used by the Iter & IterBuffered functions to wrap two variables together over a channel,
-type Tuple struct {
-	Key string
-	Val interface{}
-}
-
-// Returns an iterator which could be used in a for range loop.
-//
-// Deprecated: using IterBuffered() will get a better performence
-func (m ConcurrentMap) Iter() <-chan Tuple {
-	ch := make(chan Tuple)
-	go func() {
-		wg := sync.WaitGroup{}
-		wg.Add(SHARD_COUNT)
-		// Foreach shard.
-		for _, shard := range m {
-			go func(shard *concurrentMapShared) {
-				// Foreach key, value pair.
-				shard.RLock()
-				for key, val := range shard.items {
-					ch <- Tuple{key, val}
-				}
-				shard.RUnlock()
-				wg.Done()
-			}(shard)
-		}
-		wg.Wait()
-		close(ch)
-	}()
-	return ch
-}
-
-// Returns a buffered iterator which could be used in a for range loop.
-func (m ConcurrentMap) IterBuffered() <-chan Tuple {
-	ch := make(chan Tuple, m.Count())
-	go func() {
-		wg := sync.WaitGroup{}
-		wg.Add(SHARD_COUNT)
-		// Foreach shard.
-		for _, shard := range m {
-			go func(shard *concurrentMapShared) {
-				// Foreach key, value pair.
-				shard.RLock()
-				for key, val := range shard.items {
-					ch <- Tuple{key, val}
-				}
-				shard.RUnlock()
-				wg.Done()
-			}(shard)
-		}
-		wg.Wait()
-		close(ch)
-	}()
-	return ch
-}
-
-// Returns all items as map[string]interface{}
-func (m ConcurrentMap) Items() map[string]interface{} {
-	tmp := make(map[string]interface{})
-
-	// Insert items to temporary map.
-	for item := range m.IterBuffered() {
-		tmp[item.Key] = item.Val
-	}
-
-	return tmp
-}
-
-// Iterator callback,called for every key,value found in
-// maps. RLock is held for all calls for a given shard
-// therefore callback sess consistent view of a shard,
-// but not across the shards
-type IterCb func(key string, v interface{})
-
-// Callback based iterator, cheapest way to read
-// all elements in a map.
-func (m *ConcurrentMap) IterCb(fn IterCb) {
-	for idx := range *m {
-		shard := (*m)[idx]
-		shard.RLock()
-		for key, value := range shard.items {
-			fn(key, value)
-		}
-		shard.RUnlock()
-	}
-}
-
-// Return all keys as []string
-func (m ConcurrentMap) Keys() []string {
-	count := m.Count()
-	ch := make(chan string, count)
-	go func() {
-		// Foreach shard.
-		wg := sync.WaitGroup{}
-		wg.Add(SHARD_COUNT)
-		for _, shard := range m {
-			go func(shard *concurrentMapShared) {
-				// Foreach key, value pair.
-				shard.RLock()
-				for key := range shard.items {
-					ch <- key
-				}
-				shard.RUnlock()
-				wg.Done()
-			}(shard)
-		}
-		wg.Wait()
-		close(ch)
-	}()
-
-	keys := make([]string, 0, count)
-	for k := range ch {
-		keys = append(keys, k)
-	}
-	return keys
-}
-
-//Reviles ConcurrentMap "private" variables to json marshal.
-func (m ConcurrentMap) MarshalJSON() ([]byte, error) {
-	// Create a temporary map, which will hold all item spread across shards.
-	tmp := make(map[string]interface{})
-
-	// Insert items to temporary map.
-	for item := range m.IterBuffered() {
-		tmp[item.Key] = item.Val
-	}
-	return json.Marshal(tmp)
-}
-
-func fnv32(key string) uint32 {
-	hash := uint32(2166136261)
-	const prime32 = uint32(16777619)
-	for i := 0; i < len(key); i++ {
-		hash *= prime32
-		hash ^= uint32(key[i])
-	}
-	return hash
-}
diff --git a/rocketmq-go/util/concurrentmap.go b/rocketmq-go/util/concurrentmap.go
new file mode 100644
index 0000000..b2f3840
--- /dev/null
+++ b/rocketmq-go/util/concurrentmap.go
@@ -0,0 +1,164 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"hash/fnv"
+	"sync"
+)
+
+//ConcurrentMap concurrent map
+type ConcurrentMap interface {
+	Get(key string) (interface{}, bool)
+	Set(key string, value interface{})
+	Count() int
+	Remove(key string)
+	Items() map[string]interface{}
+	Keys() []string
+	Values() []interface{}
+}
+
+//defaultMapSegmentCount default is 33,because map's default is 32
+//you can use NewConcurrentMapWithSegmentCount to change the segment count(it depend on your map size)
+var defaultMapSegmentCount = 33
+
+//concurrentMapImpl
+type concurrentMapImpl struct {
+	segments     []*concurrentMapSegment
+	segmentCount int
+}
+
+type concurrentMapSegment struct {
+	item map[string]interface{}
+	sync.RWMutex
+}
+
+//NewConcurrentMap create a concurrentMap instance with default segments count
+func NewConcurrentMap() (concurrentMap ConcurrentMap) {
+	return NewConcurrentMapWithSegmentCount(defaultMapSegmentCount)
+}
+
+//NewConcurrentMapWithSegmentCount create a concurrentMap instance with segments count
+func NewConcurrentMapWithSegmentCount(segmentCount int) (concurrentMap ConcurrentMap) {
+	concurrentMapSegments := make([]*concurrentMapSegment, segmentCount)
+	for i := 0; i < segmentCount; i++ {
+		concurrentMapSegments[i] = &concurrentMapSegment{item: make(map[string]interface{})}
+	}
+	concurrentMap = &concurrentMapImpl{segments: concurrentMapSegments, segmentCount: segmentCount}
+	return
+}
+
+//Get get map[key]
+func (m concurrentMapImpl) Get(key string) (interface{}, bool) {
+	segment := m.getMapSegment(key)
+	segment.RLock()
+	val, ok := segment.item[key]
+	segment.RUnlock()
+	return val, ok
+}
+
+func (m concurrentMapImpl) getMapSegment(key string) *concurrentMapSegment {
+	h := fnv.New32a()
+	h.Write([]byte(key))
+	segmentIndex := uint(h.Sum32() % uint32(m.segmentCount))
+	return m.segments[segmentIndex]
+}
+
+//Set set map[key] = value
+func (m *concurrentMapImpl) Set(key string, value interface{}) {
+	segment := m.getMapSegment(key)
+	segment.Lock()
+	segment.item[key] = value
+	segment.Unlock()
+}
+
+//Count count the number of items in this map.
+func (m concurrentMapImpl) Count() int {
+	count := 0
+	for i := 0; i < m.segmentCount; i++ {
+		segment := m.segments[i]
+		segment.RLock()
+		count += len(segment.item)
+		segment.RUnlock()
+	}
+	return count
+}
+
+//Remove remove item by key
+func (m *concurrentMapImpl) Remove(key string) {
+	segment := m.getMapSegment(key)
+	segment.Lock()
+	delete(segment.item, key)
+	segment.Unlock()
+}
+
+//Items put all item into one map
+func (m concurrentMapImpl) Items() map[string]interface{} {
+	tmp := make(map[string]interface{})
+	for item := range m.allMapEntry() {
+		tmp[item.Key] = item.Value
+	}
+	return tmp
+}
+
+//Keys all keys in this concurrent map
+func (m concurrentMapImpl) Keys() []string {
+	allMapEntry := m.allMapEntry()
+	keys := make([]string, 0, len(allMapEntry))
+	for entry := range allMapEntry {
+		keys = append(keys, entry.Key)
+	}
+	return keys
+}
+
+//Values all values in this concurrent map
+func (m concurrentMapImpl) Values() []interface{} {
+	allMapEntry := m.allMapEntry()
+	values := make([]interface{}, 0, len(allMapEntry))
+	for entry := range allMapEntry {
+		values = append(values, entry.Value)
+	}
+	return values
+}
+
+//MapEntry map entry,has key and value
+type MapEntry struct {
+	Key   string
+	Value interface{}
+}
+
+func (m concurrentMapImpl) allMapEntry() <-chan MapEntry {
+	ch := make(chan MapEntry, m.Count())
+	go func() {
+		wg := sync.WaitGroup{}
+		wg.Add(m.segmentCount)
+		for _, segment := range m.segments {
+			go func(segment *concurrentMapSegment) {
+				segment.RLock()
+				for key, val := range segment.item {
+					ch <- MapEntry{key, val}
+				}
+				segment.RUnlock()
+				wg.Done()
+			}(segment)
+		}
+		wg.Wait()
+		close(ch)
+	}()
+	return ch
+}
diff --git a/rocketmq-go/util/concurrentmap_test.go b/rocketmq-go/util/concurrentmap_test.go
new file mode 100644
index 0000000..337cb47
--- /dev/null
+++ b/rocketmq-go/util/concurrentmap_test.go
@@ -0,0 +1,106 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"testing"
+)
+
+func TestGetAndSet(t *testing.T) {
+	existKey := "123"
+	existValue := 1
+	notExistKey := "321"
+	concurrentMap := NewConcurrentMap()
+	concurrentMap.Set(existKey, existValue)
+	value, isHave := concurrentMap.Get(existKey)
+	if !isHave {
+		t.Errorf("can't read existKey")
+	}
+	if value != existValue {
+		t.Errorf("get value fail")
+	}
+	value2, isHave2 := concurrentMap.Get(notExistKey)
+	if isHave2 {
+		t.Errorf("read notExistKey")
+	}
+	if value2 != nil {
+		t.Errorf("read notExistKey error")
+	}
+}
+func TesCount(t *testing.T) {
+	count := 123
+	concurrentMap := NewConcurrentMap()
+	for i := 0; i < count; i++ {
+		concurrentMap.Set(IntToString(i), "")
+	}
+	if concurrentMap.Count() != count {
+		t.Errorf("Count error")
+	}
+}
+func TesRemove(t *testing.T) {
+	count := 123
+	removeKey := "111"
+	concurrentMap := NewConcurrentMap()
+	for i := 0; i < count; i++ {
+		concurrentMap.Set(IntToString(i), "")
+	}
+	concurrentMap.Remove(removeKey)
+	if concurrentMap.Count() != count-1 {
+		t.Errorf("remove error")
+	}
+	_, isHave := concurrentMap.Get(removeKey)
+	if isHave {
+		t.Errorf("remove error")
+
+	}
+}
+func TesItems(t *testing.T) {
+	count := 123
+	concurrentMap := NewConcurrentMap()
+	for i := 0; i < count; i++ {
+		concurrentMap.Set(IntToString(i), "")
+	}
+	itemMap := concurrentMap.Items()
+	if len(itemMap) != count {
+		t.Errorf("Items error")
+	}
+
+}
+func TesKeys(t *testing.T) {
+	count := 123
+	concurrentMap := NewConcurrentMap()
+	for i := 0; i < count; i++ {
+		concurrentMap.Set(IntToString(i), "")
+	}
+	keys := concurrentMap.Keys()
+	if len(keys) != count {
+		t.Errorf("keys error")
+	}
+
+}
+func TesValues(t *testing.T) {
+	count := 123
+	concurrentMap := NewConcurrentMap()
+	for i := 0; i < count; i++ {
+		concurrentMap.Set(IntToString(i), "")
+	}
+	values := concurrentMap.Values()
+	if len(values) != count {
+		t.Errorf("values error")
+	}
+}
diff --git a/rocketmq-go/util/ip.go b/rocketmq-go/util/ip.go
index f87000d..6599842 100644
--- a/rocketmq-go/util/ip.go
+++ b/rocketmq-go/util/ip.go
@@ -1,19 +1,20 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import (
@@ -21,12 +22,14 @@
 	"strings"
 )
 
+//GetIp4Bytes get ip4 byte array
 func GetIp4Bytes() (ret []byte) {
 	ip := getIp()
 	ret = ip[len(ip)-4:]
 	return
 }
 
+//GetLocalIp4 get local ip4
 func GetLocalIp4() (ip4 string) {
 	ip := getIp()
 	if ip.To4() != nil {
diff --git a/rocketmq-go/util/ip_test.go b/rocketmq-go/util/ip_test.go
new file mode 100644
index 0000000..ee543a5
--- /dev/null
+++ b/rocketmq-go/util/ip_test.go
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"strings"
+	"testing"
+)
+
+func TestGetIp4Bytes(t *testing.T) {
+	ip := GetIp4Bytes()
+	if ip == nil && len(ip) != 4 {
+		t.Error("GetIp4Bytes failed")
+	}
+}
+
+func TestGetLocalIp4(t *testing.T) {
+	ip4 := GetLocalIp4()
+	split := strings.Split(ip4, ".")
+	if len(split) != 4 {
+		t.Errorf("GetLocalIp4 failed")
+	}
+}
diff --git a/rocketmq-go/util/json_util.go b/rocketmq-go/util/json_util.go
index 91fdc5d..60fb71b 100644
--- a/rocketmq-go/util/json_util.go
+++ b/rocketmq-go/util/json_util.go
@@ -1,119 +1,143 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import (
 	"errors"
 )
 
+//TOKEN_TYPE json string's token type
+type TOKEN_TYPE byte
+
 const (
-	STRING = "STRING"
-	NUMBER = "NUMBER"
-
-	START_OBJ = "START_OBJ" //{
-	END_OBJ   = "END_OBJ"   //}
-	COMMA     = "COMMA"     //,
-	COLON     = "COLON"     //:
-
-	//// may be next version impl it
-	//BOOL
-	//NULL
-	//START_ARRAY //[
-	//END_ARRAY //]
-	//EOF
+	//STRING string
+	STRING TOKEN_TYPE = iota
+	//NUMBER number
+	NUMBER
+	//START_OBJ start object
+	START_OBJ
+	//END_OBJ end object
+	END_OBJ
+	//COMMA comma
+	COMMA
+	//COLON colon
+	COLON
 )
 
-type Token struct {
-	tokenType  string
+type token struct {
+	tokenType  TOKEN_TYPE
 	tokenValue string
 }
 
 ////{"offsetTable":{{"brokerName":"broker-b","queueId":122222,"topic":"GoLang"}:9420,{"brokerName":"broker-b","queueId":2,"topic":"GoLang"}:9184,{"brokerName":"broker-b","queueId":1,"topic":"GoLang"}:9260,{"brokerName":"broker-b","queueId":3,"topic":"GoLang"}:9139}}
 
+type parseInfo struct {
+	startObjCount int
+	// 0 begin 1 key 2 value
+	readType int
+	nowKey   string
+	nowValue string
+}
+
+//GetKvStringMap convert json string to map[string]string
 func GetKvStringMap(str string) (kvMap map[string]string, err error) {
-	var tokenList []Token
+	var tokenList []token
 	tokenList, err = parseTokenList(str)
 	kvMap = map[string]string{}
-	startObjCount := 0
-	readType := 0 // 0 begin 1 key 2 value
-	nowKey := ""
-	nowValue := ""
+	currentParseInfo := &parseInfo{
+		startObjCount: 0,
+		readType:      0,
+		nowKey:        "",
+		nowValue:      "",
+	}
 	for i := 0; i < len(tokenList); i++ {
-		nowToken := tokenList[i]
+		nowToken := &tokenList[i]
 		if nowToken.tokenType == START_OBJ {
-			startObjCount++
+			currentParseInfo.startObjCount++
 		}
 		if nowToken.tokenType == END_OBJ {
-			startObjCount--
+			currentParseInfo.startObjCount--
 		}
-		if readType == 0 {
+		if currentParseInfo.readType == 0 {
 			if nowToken.tokenType != START_OBJ {
 				err = errors.New("json not start with {")
 				return
 			}
-			readType = 1
-		} else if readType == 1 {
-			if nowToken.tokenType == COLON { //: split k and v
-				if startObjCount == 1 {
-					readType = 2
-					continue
-				}
+			currentParseInfo.readType = 1
+		} else if currentParseInfo.readType == 1 {
+			parseKey(currentParseInfo, nowToken)
+		} else if currentParseInfo.readType == 2 {
+			var k, v string
+			k, v = parseValue(currentParseInfo, nowToken)
+			if len(k) > 0 {
+				kvMap[k] = v
 			}
-			if nowToken.tokenType == STRING {
-				nowKey = nowKey + "\"" + nowToken.tokenValue + "\""
-			} else {
-				nowKey = nowKey + nowToken.tokenValue
-			}
-		} else if readType == 2 {
-			if nowToken.tokenType == COMMA { // , split kv pair
-				if startObjCount == 1 {
-					kvMap[nowKey] = nowValue
-					nowKey = ""
-					nowValue = ""
-					readType = 1
-					continue
-				}
-			}
-			if nowToken.tokenType == STRING {
-				nowValue = nowValue + "\"" + nowToken.tokenValue + "\""
-
-			} else {
-				if startObjCount > 0 { //use less end }
-					nowValue = nowValue + nowToken.tokenValue
-				}
-			}
-
 		} else {
 			err = errors.New("this is a bug")
 			return
 		}
 	}
-	if len(nowKey) > 0 {
+	if len(currentParseInfo.nowKey) > 0 {
+		kvMap[currentParseInfo.nowKey] = currentParseInfo.nowValue
+	}
+	return
+}
+func parseValue(info *parseInfo, nowToken *token) (key, value string) {
+	if nowToken.tokenType == COMMA { // , split kv pair
+		if info.startObjCount == 1 {
+			key = info.nowKey
+			value = info.nowValue
+			info.nowKey = ""
+			info.nowValue = ""
+			info.readType = 1
+			return
+		}
+	}
+	if nowToken.tokenType == STRING {
+		info.nowValue = info.nowValue + "\"" + nowToken.tokenValue + "\""
 
-		kvMap[nowKey] = nowValue
+	} else {
+		if info.startObjCount > 0 { //use less end }
+			info.nowValue = info.nowValue + nowToken.tokenValue
+		}
+	}
+	return
+}
+func parseKey(info *parseInfo, nowToken *token) {
+	if nowToken.tokenType == COLON { //: split k and v
+		if info.startObjCount == 1 {
+			info.readType = 2
+			return
+		}
+	}
+	if nowToken.tokenType == STRING {
+		info.nowKey = info.nowKey + "\"" + nowToken.tokenValue + "\""
+	} else {
+		info.nowKey = info.nowKey + nowToken.tokenValue
 	}
 	return
 }
 
-func parseTokenList(str string) (tokenList []Token, err error) {
+func parseTokenList(str string) (tokenList []token, err error) {
 
 	for i := 0; i < len(str); i++ {
 		c := str[i]
-		token := Token{}
+		token := token{}
 		switch c {
 		case '{':
 			token.tokenType = START_OBJ
diff --git a/rocketmq-go/util/json_util_test.go b/rocketmq-go/util/json_util_test.go
new file mode 100644
index 0000000..7440ca7
--- /dev/null
+++ b/rocketmq-go/util/json_util_test.go
@@ -0,0 +1,40 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"testing"
+)
+
+func TestGetKvStringMap(t *testing.T) {
+	s1 := "{\"key1\":\"value1\",\"key2\":\"value2\"}"
+	kvMap, err := GetKvStringMap(s1)
+	if kvMap["\"key1\""] != "\"value1\"" || kvMap["\"key2\""] != "\"value2\"" || err != nil {
+		t.Errorf("TestGetKvStringMap failed : cannot transfer normal json")
+	}
+	s2 := "\"key1\":\"value1\",\"key2\":\"value2\"}"
+	kvMap2, err2 := GetKvStringMap(s2)
+	if len(kvMap2) != 0 || err2.Error() != "json not start with {" {
+		t.Errorf("TestGetKvStringMap failed : cannot found json error")
+	}
+	s3 := "{key1:value1,key2:value2}"
+	kvMap3, err3 := GetKvStringMap(s3)
+	if len(kvMap3) != 0 || err3.Error() != "INVALID JSON" {
+		t.Errorf("TestGetKvStringMap failed : cannot found invalidjson")
+	}
+}
diff --git a/rocketmq-go/util/map_util.go b/rocketmq-go/util/map_util.go
new file mode 100644
index 0000000..c0d9181
--- /dev/null
+++ b/rocketmq-go/util/map_util.go
@@ -0,0 +1,30 @@
+package util
+
+import (
+	"reflect"
+	"strings"
+)
+
+//Struct2Map convert interface{} to map[string]interface{}
+func Struct2Map(structBody interface{}) (resultMap map[string]interface{}) {
+	resultMap = make(map[string]interface{})
+	value := reflect.ValueOf(structBody)
+	for value.Kind() == reflect.Ptr {
+		value = value.Elem()
+	}
+	if value.Kind() != reflect.Struct {
+		panic("input is not a struct")
+	}
+	valueType := value.Type()
+	for i := 0; i < valueType.NumField(); i++ {
+		field := valueType.Field(i)
+		if field.PkgPath != "" {
+			continue
+		}
+		name := field.Name
+		smallName := strings.Replace(name, string(name[0]), string(strings.ToLower(string(name[0]))), 1)
+		val := value.FieldByName(name).Interface()
+		resultMap[smallName] = val
+	}
+	return
+}
diff --git a/rocketmq-go/util/message_properties.go b/rocketmq-go/util/message_properties.go
index 59fd5b8..56babb4 100644
--- a/rocketmq-go/util/message_properties.go
+++ b/rocketmq-go/util/message_properties.go
@@ -1,30 +1,33 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import (
 	"strings"
 )
 
-//char 1 and 2 from java code
+//NAME_VALUE_SEPARATOR char 1 and 2 from java code
 var NAME_VALUE_SEPARATOR = string(rune(1))
 
+//PROPERTY_SEPARATOR property separator
 var PROPERTY_SEPARATOR = string(rune(2))
 
+//MessageProperties2String convert message properties to string
 func MessageProperties2String(propertiesMap map[string]string) (ret string) {
 	for key, value := range propertiesMap {
 		ret = ret + key + NAME_VALUE_SEPARATOR + value + PROPERTY_SEPARATOR
@@ -32,6 +35,7 @@
 	return
 }
 
+//String2MessageProperties convert string properties to map
 func String2MessageProperties(properties string) (ret map[string]string) {
 	ret = make(map[string]string)
 	for _, nameValueStr := range strings.Split(properties, PROPERTY_SEPARATOR) {
diff --git a/rocketmq-go/util/message_properties_test.go b/rocketmq-go/util/message_properties_test.go
new file mode 100644
index 0000000..8f430d7
--- /dev/null
+++ b/rocketmq-go/util/message_properties_test.go
@@ -0,0 +1,47 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"testing"
+)
+
+func TestMessageProperties2String(t *testing.T) {
+	stringMap := make(map[string]string)
+	stringMap["key1"] = "value1"
+	stringMap["key2"] = "value2"
+	var NAME_VALUE_SEPARATOR = string(rune(1))
+	var PROPERTY_SEPARATOR = string(rune(2))
+	s1 := "key1" + NAME_VALUE_SEPARATOR + "value1" + PROPERTY_SEPARATOR + "key2" +
+		NAME_VALUE_SEPARATOR + "value2" + PROPERTY_SEPARATOR
+	ret := MessageProperties2String(stringMap)
+	if ret != s1 {
+		t.Errorf("TestMessageProperties2String failed")
+	}
+}
+
+func TestString2MessageProperties(t *testing.T) {
+	var NAME_VALUE_SEPARATOR = string(rune(1))
+	var PROPERTY_SEPARATOR = string(rune(2))
+	s1 := "key1" + NAME_VALUE_SEPARATOR + "value1" + PROPERTY_SEPARATOR + "key2" +
+		NAME_VALUE_SEPARATOR + "value2"
+	mapString := String2MessageProperties(s1)
+	if mapString["key1"] != "value1" || mapString["key2"] != "value2" {
+		t.Errorf("TestString2MessageProperties failed")
+	}
+}
diff --git a/rocketmq-go/util/regex_util.go b/rocketmq-go/util/regex_util.go
index 5357452..1352415 100644
--- a/rocketmq-go/util/regex_util.go
+++ b/rocketmq-go/util/regex_util.go
@@ -1,29 +1,27 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import (
 	"regexp"
 )
 
-//var regexpMap map[string]*regexp.Regexp
-//var rwMutex sync.RWMutex
-
-// todo improve
+//MatchString reports whether the Regexp matches the string
 func MatchString(value, pattern string) bool {
 	re, err := regexp.Compile(pattern)
 	if err != nil {
diff --git a/rocketmq-go/util/regex_util_test.go b/rocketmq-go/util/regex_util_test.go
new file mode 100644
index 0000000..f056fe0
--- /dev/null
+++ b/rocketmq-go/util/regex_util_test.go
@@ -0,0 +1,38 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"testing"
+)
+
+func TestMatchString(t *testing.T) {
+	s1 := "123"
+	s2 := "123qwe"
+	pattern := "^[0-9]+$"
+	notPattern := "\\123\\"
+	result1 := MatchString(s1, pattern)
+	result2 := MatchString(s2, pattern)
+	if !result1 || result2 {
+		t.Errorf("TestMatchString failed : cannot match")
+	}
+	result3 := MatchString(s1, notPattern)
+	if result3 {
+		t.Errorf("TestMatchString failed : cannot find pattern mistake")
+	}
+}
diff --git a/rocketmq-go/util/string_util.go b/rocketmq-go/util/string_util.go
index 7e31e00..07a96d9 100644
--- a/rocketmq-go/util/string_util.go
+++ b/rocketmq-go/util/string_util.go
@@ -1,23 +1,25 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package util
 
 import "strconv"
 
+//StrToIntWithDefaultValue convert string to int
 func StrToIntWithDefaultValue(str string, defaultValue int) (result int) {
 	ret, err := strconv.Atoi(str)
 	if err != nil {
@@ -27,6 +29,8 @@
 	}
 	return
 }
+
+//ReadString read string if the interface{} is string
 func ReadString(obj interface{}) (ret string) {
 	if obj == nil {
 		ret = ""
@@ -36,32 +40,35 @@
 	return
 }
 
+//IntToString convert int to string
 func IntToString(intValue int) (ret string) {
 	ret = strconv.Itoa(intValue)
 	return
 }
 
-func StrToInt(str string) (result int, err error) {
-	result, err = strconv.Atoi(str)
-	return
-}
+//StrToInt32 convert string to int32
 func StrToInt32(str string) (result int32, err error) {
 	var ret int64
 	ret, err = strconv.ParseInt(str, 10, 32)
 	result = int32(ret)
 	return
 }
+
+//StrToInt16 convert string to int16
 func StrToInt16(str string) (result int16, err error) {
 	var ret int64
 	ret, err = strconv.ParseInt(str, 10, 16)
 	result = int16(ret)
 	return
 }
+
+//StrToInt64 convert string to int64
 func StrToInt64(str string) (result int64, err error) {
 	result, err = strconv.ParseInt(str, 10, 64)
 	return
 }
 
+//StrToInt32WithDefaultValue convert string to int32,if error return defaultValue
 func StrToInt32WithDefaultValue(str string, defaultValue int32) (result int32) {
 	ret, err := StrToInt32(str)
 	if err != nil {
@@ -71,6 +78,8 @@
 	}
 	return
 }
+
+//StrToInt16WithDefaultValue convert string to int16,if error return defaultValue
 func StrToInt16WithDefaultValue(str string, defaultValue int16) (result int16) {
 	ret, err := StrToInt16(str)
 	if err != nil {
@@ -80,6 +89,8 @@
 	}
 	return
 }
+
+//StrToInt64WithDefaultValue convert string to int64,if error return defaultValue
 func StrToInt64WithDefaultValue(str string, defaultValue int64) (result int64) {
 	ret, err := StrToInt64(str)
 	if err != nil {
diff --git a/rocketmq-go/util/string_util_test.go b/rocketmq-go/util/string_util_test.go
new file mode 100644
index 0000000..8697567
--- /dev/null
+++ b/rocketmq-go/util/string_util_test.go
@@ -0,0 +1,79 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"strings"
+	"testing"
+)
+
+func TestStrToIntWithDefaultValue(t *testing.T) {
+	result1 := StrToIntWithDefaultValue("1", 0)
+	if result1 != 1 {
+		t.Errorf("StrToIntWithDefaultValue failed : cannot transfer string 1 to int 1")
+	}
+	result2 := StrToIntWithDefaultValue("", 2)
+	if result2 != 2 {
+		t.Errorf("StrToIntWithDefaultValue failed : cannot use default value")
+	}
+}
+
+func TestReadString(t *testing.T) {
+	var i interface{} = "testReadString"
+	ret := ReadString(i)
+	if !strings.EqualFold(ret, "testReadString") {
+		t.Errorf("TestReadString failed : cannot transfer string")
+	}
+	ret2 := ReadString(nil)
+	if ret2 != "" {
+		t.Errorf("TestReadString failed : cannot transfer nil to \"\"")
+	}
+}
+
+func TestIntToString(t *testing.T) {
+	ret := IntToString(1)
+	if ret != "1" {
+		t.Errorf("TestIntToString failed : cannot tansfer int 1 to  string1")
+	}
+}
+
+func TestStrToInt32WithDefaultValue(t *testing.T) {
+	i1 := int32(2147483646)
+	i2 := int32(2147483647)
+	result1 := StrToInt32WithDefaultValue("2147483646", i2)
+	if result1 != i1 {
+		t.Errorf("StrToIntWithDefaultValue failed : cannot transfer string 2147483646 to int32 2147483646")
+	}
+	result2 := StrToInt32WithDefaultValue("2147483648", i2)
+	if result2 != i2 {
+		t.Errorf("StrToIntWithDefaultValue failed : cannot use default value")
+	}
+}
+
+func TestStrToInt64WithDefaultValue(t *testing.T) {
+	i1 := int64(9223372036854775806)
+	i2 := int64(9223372036854775807)
+	result1 := StrToInt64WithDefaultValue("9223372036854775806", i2)
+	if result1 != i1 {
+		t.Errorf("StrToIntWithDefaultValue failed : cannot transfer string 9223372036854775806 to int64 9223372036854775806")
+	}
+	result2 := StrToInt64WithDefaultValue("9223372036854775808", i2)
+	if result2 != i2 {
+		t.Errorf("StrToIntWithDefaultValue failed : use default value")
+	}
+}
diff --git a/rocketmq-go/util/structs/field.go b/rocketmq-go/util/structs/field.go
deleted file mode 100644
index e697832..0000000
--- a/rocketmq-go/util/structs/field.go
+++ /dev/null
@@ -1,141 +0,0 @@
-package structs
-
-import (
-	"errors"
-	"fmt"
-	"reflect"
-)
-
-var (
-	errNotExported = errors.New("field is not exported")
-	errNotSettable = errors.New("field is not settable")
-)
-
-// Field represents a single struct field that encapsulates high level
-// functions around the field.
-type Field struct {
-	value      reflect.Value
-	field      reflect.StructField
-	defaultTag string
-}
-
-// Tag returns the value associated with key in the tag string. If there is no
-// such key in the tag, Tag returns the empty string.
-func (f *Field) Tag(key string) string {
-	return f.field.Tag.Get(key)
-}
-
-// Value returns the underlying value of the field. It panics if the field
-// is not exported.
-func (f *Field) Value() interface{} {
-	return f.value.Interface()
-}
-
-// IsEmbedded returns true if the given field is an anonymous field (embedded)
-func (f *Field) IsEmbedded() bool {
-	return f.field.Anonymous
-}
-
-// IsExported returns true if the given field is exported.
-func (f *Field) IsExported() bool {
-	return f.field.PkgPath == ""
-}
-
-// IsZero returns true if the given field is not initialized (has a zero value).
-// It panics if the field is not exported.
-func (f *Field) IsZero() bool {
-	zero := reflect.Zero(f.value.Type()).Interface()
-	current := f.Value()
-
-	return reflect.DeepEqual(current, zero)
-}
-
-// Name returns the name of the given field
-func (f *Field) Name() string {
-	return f.field.Name
-}
-
-// Kind returns the fields kind, such as "string", "map", "bool", etc ..
-func (f *Field) Kind() reflect.Kind {
-	return f.value.Kind()
-}
-
-// Set sets the field to given value v. It returns an error if the field is not
-// settable (not addressable or not exported) or if the given value's type
-// doesn't match the fields type.
-func (f *Field) Set(val interface{}) error {
-	// we can't set unexported fields, so be sure this field is exported
-	if !f.IsExported() {
-		return errNotExported
-	}
-
-	// do we get here? not sure...
-	if !f.value.CanSet() {
-		return errNotSettable
-	}
-
-	given := reflect.ValueOf(val)
-
-	if f.value.Kind() != given.Kind() {
-		return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind())
-	}
-
-	f.value.Set(given)
-	return nil
-}
-
-// Zero sets the field to its zero value. It returns an error if the field is not
-// settable (not addressable or not exported).
-func (f *Field) Zero() error {
-	zero := reflect.Zero(f.value.Type()).Interface()
-	return f.Set(zero)
-}
-
-// Fields returns a slice of Fields. This is particular handy to get the fields
-// of a nested struct . A struct tag with the content of "-" ignores the
-// checking of that particular field. Example:
-//
-//   // Field is ignored by this package.
-//   Field *http.Request `structs:"-"`
-//
-// It panics if field is not exported or if field's kind is not struct
-func (f *Field) Fields() []*Field {
-	return getFields(f.value, f.defaultTag)
-}
-
-// Field returns the field from a nested struct. It panics if the nested struct
-// is not exported or if the field was not found.
-func (f *Field) Field(name string) *Field {
-	field, ok := f.FieldOk(name)
-	if !ok {
-		panic("field not found")
-	}
-
-	return field
-}
-
-// FieldOk returns the field from a nested struct. The boolean returns whether
-// the field was found (true) or not (false).
-func (f *Field) FieldOk(name string) (*Field, bool) {
-	value := &f.value
-	// value must be settable so we need to make sure it holds the address of the
-	// variable and not a copy, so we can pass the pointer to strctVal instead of a
-	// copy (which is not assigned to any variable, hence not settable).
-	// see "https://blog.golang.org/laws-of-reflection#TOC_8."
-	if f.value.Kind() != reflect.Ptr {
-		a := f.value.Addr()
-		value = &a
-	}
-	v := strctVal(value.Interface())
-	t := v.Type()
-
-	field, ok := t.FieldByName(name)
-	if !ok {
-		return nil, false
-	}
-
-	return &Field{
-		field: field,
-		value: v.FieldByName(name),
-	}, true
-}
diff --git a/rocketmq-go/util/structs/structs.go b/rocketmq-go/util/structs/structs.go
deleted file mode 100644
index 87b7970..0000000
--- a/rocketmq-go/util/structs/structs.go
+++ /dev/null
@@ -1,581 +0,0 @@
-// Package structs contains various utilities functions to work with structs.
-package structs
-
-import (
-	"fmt"
-
-	"reflect"
-	"strings"
-)
-
-var (
-	// DefaultTagName is the default tag name for struct fields which provides
-	// a more granular to tweak certain structs. Lookup the necessary functions
-	// for more info.
-	DefaultTagName = "structs" // struct's field default tag name
-)
-
-// Struct encapsulates a struct type to provide several high level functions
-// around the struct.
-type Struct struct {
-	raw     interface{}
-	value   reflect.Value
-	TagName string
-}
-
-// New returns a new *Struct with the struct s. It panics if the s's kind is
-// not struct.
-func New(s interface{}) *Struct {
-	return &Struct{
-		raw:     s,
-		value:   strctVal(s),
-		TagName: DefaultTagName,
-	}
-}
-
-// Map converts the given struct to a map[string]interface{}, where the keys
-// of the map are the field names and the values of the map the associated
-// values of the fields. The default key string is the struct field name but
-// can be changed in the struct field's tag value. The "structs" key in the
-// struct's field tag value is the key name. Example:
-//
-//   // Field appears in map as key "myName".
-//   Name string `structs:"myName"`
-//
-// A tag value with the content of "-" ignores that particular field. Example:
-//
-//   // Field is ignored by this package.
-//   Field bool `structs:"-"`
-//
-// A tag value with the content of "string" uses the stringer to get the value. Example:
-//
-//   // The value will be output of Animal's String() func.
-//   // Map will panic if Animal does not implement String().
-//   Field *Animal `structs:"field,string"`
-//
-// A tag value with the option of "flatten" used in a struct field is to flatten its fields
-// in the output map. Example:
-//
-//   // The FieldStruct's fields will be flattened into the output map.
-//   FieldStruct time.Time `structs:",flatten"`
-//
-// A tag value with the option of "omitnested" stops iterating further if the type
-// is a struct. Example:
-//
-//   // Field is not processed further by this package.
-//   Field time.Time     `structs:"myName,omitnested"`
-//   Field *http.Request `structs:",omitnested"`
-//
-// A tag value with the option of "omitempty" ignores that particular field if
-// the field value is empty. Example:
-//
-//   // Field appears in map as key "myName", but the field is
-//   // skipped if empty.
-//   Field string `structs:"myName,omitempty"`
-//
-//   // Field appears in map as key "Field" (the default), but
-//   // the field is skipped if empty.
-//   Field string `structs:",omitempty"`
-//
-// Note that only exported fields of a struct can be accessed, non exported
-// fields will be neglected.
-func (s *Struct) Map() map[string]interface{} {
-	out := make(map[string]interface{})
-	s.FillMap(out)
-	return out
-}
-
-// FillMap is the same as Map. Instead of returning the output, it fills the
-// given map.
-func (s *Struct) FillMap(out map[string]interface{}) {
-	if out == nil {
-		return
-	}
-
-	fields := s.structFields()
-
-	for _, field := range fields {
-		name := field.Name
-		smallName := strings.Replace(name, string(name[0]), string(strings.ToLower(string(name[0]))), 1) //todo
-		val := s.value.FieldByName(name)
-		isSubStruct := false
-		var finalVal interface{}
-
-		tagName, tagOpts := parseTag(field.Tag.Get(s.TagName))
-		if tagName != "" {
-			name = tagName
-		}
-
-		// if the value is a zero value and the field is marked as omitempty do
-		// not include
-		if tagOpts.Has("omitempty") {
-			zero := reflect.Zero(val.Type()).Interface()
-			current := val.Interface()
-
-			if reflect.DeepEqual(current, zero) {
-				continue
-			}
-		}
-
-		if !tagOpts.Has("omitnested") {
-			finalVal = s.nested(val)
-
-			v := reflect.ValueOf(val.Interface())
-			if v.Kind() == reflect.Ptr {
-				v = v.Elem()
-			}
-
-			switch v.Kind() {
-			case reflect.Map, reflect.Struct:
-				isSubStruct = true
-			}
-		} else {
-			finalVal = val.Interface()
-		}
-
-		if tagOpts.Has("string") {
-			s, ok := val.Interface().(fmt.Stringer)
-			if ok {
-				out[smallName] = s.String()
-			}
-			continue
-		}
-
-		if isSubStruct && (tagOpts.Has("flatten")) {
-			for k := range finalVal.(map[string]interface{}) {
-				out[k] = finalVal.(map[string]interface{})[k]
-			}
-		} else {
-			out[smallName] = finalVal
-		}
-	}
-}
-
-// Values converts the given s struct's field values to a []interface{}.  A
-// struct tag with the content of "-" ignores the that particular field.
-// Example:
-//
-//   // Field is ignored by this package.
-//   Field int `structs:"-"`
-//
-// A value with the option of "omitnested" stops iterating further if the type
-// is a struct. Example:
-//
-//   // Fields is not processed further by this package.
-//   Field time.Time     `structs:",omitnested"`
-//   Field *http.Request `structs:",omitnested"`
-//
-// A tag value with the option of "omitempty" ignores that particular field and
-// is not added to the values if the field value is empty. Example:
-//
-//   // Field is skipped if empty
-//   Field string `structs:",omitempty"`
-//
-// Note that only exported fields of a struct can be accessed, non exported
-// fields  will be neglected.
-func (s *Struct) Values() []interface{} {
-	fields := s.structFields()
-
-	var t []interface{}
-
-	for _, field := range fields {
-		val := s.value.FieldByName(field.Name)
-
-		_, tagOpts := parseTag(field.Tag.Get(s.TagName))
-
-		// if the value is a zero value and the field is marked as omitempty do
-		// not include
-		if tagOpts.Has("omitempty") {
-			zero := reflect.Zero(val.Type()).Interface()
-			current := val.Interface()
-
-			if reflect.DeepEqual(current, zero) {
-				continue
-			}
-		}
-
-		if tagOpts.Has("string") {
-			s, ok := val.Interface().(fmt.Stringer)
-			if ok {
-				t = append(t, s.String())
-			}
-			continue
-		}
-
-		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
-			// look out for embedded structs, and convert them to a
-			// []interface{} to be added to the final values slice
-			for _, embeddedVal := range Values(val.Interface()) {
-				t = append(t, embeddedVal)
-			}
-		} else {
-			t = append(t, val.Interface())
-		}
-	}
-
-	return t
-}
-
-// Fields returns a slice of Fields. A struct tag with the content of "-"
-// ignores the checking of that particular field. Example:
-//
-//   // Field is ignored by this package.
-//   Field bool `structs:"-"`
-//
-// It panics if s's kind is not struct.
-func (s *Struct) Fields() []*Field {
-	return getFields(s.value, s.TagName)
-}
-
-// Names returns a slice of field names. A struct tag with the content of "-"
-// ignores the checking of that particular field. Example:
-//
-//   // Field is ignored by this package.
-//   Field bool `structs:"-"`
-//
-// It panics if s's kind is not struct.
-func (s *Struct) Names() []string {
-	fields := getFields(s.value, s.TagName)
-
-	names := make([]string, len(fields))
-
-	for i, field := range fields {
-		names[i] = field.Name()
-	}
-
-	return names
-}
-
-func getFields(v reflect.Value, tagName string) []*Field {
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-	}
-
-	t := v.Type()
-
-	var fields []*Field
-
-	for i := 0; i < t.NumField(); i++ {
-		field := t.Field(i)
-
-		if tag := field.Tag.Get(tagName); tag == "-" {
-			continue
-		}
-
-		f := &Field{
-			field: field,
-			value: v.FieldByName(field.Name),
-		}
-
-		fields = append(fields, f)
-
-	}
-
-	return fields
-}
-
-// Field returns a new Field struct that provides several high level functions
-// around a single struct field entity. It panics if the field is not found.
-func (s *Struct) Field(name string) *Field {
-	f, ok := s.FieldOk(name)
-	if !ok {
-		panic("field not found")
-	}
-
-	return f
-}
-
-// FieldOk returns a new Field struct that provides several high level functions
-// around a single struct field entity. The boolean returns true if the field
-// was found.
-func (s *Struct) FieldOk(name string) (*Field, bool) {
-	t := s.value.Type()
-
-	field, ok := t.FieldByName(name)
-	if !ok {
-		return nil, false
-	}
-
-	return &Field{
-		field:      field,
-		value:      s.value.FieldByName(name),
-		defaultTag: s.TagName,
-	}, true
-}
-
-// IsZero returns true if all fields in a struct is a zero value (not
-// initialized) A struct tag with the content of "-" ignores the checking of
-// that particular field. Example:
-//
-//   // Field is ignored by this package.
-//   Field bool `structs:"-"`
-//
-// A value with the option of "omitnested" stops iterating further if the type
-// is a struct. Example:
-//
-//   // Field is not processed further by this package.
-//   Field time.Time     `structs:"myName,omitnested"`
-//   Field *http.Request `structs:",omitnested"`
-//
-// Note that only exported fields of a struct can be accessed, non exported
-// fields  will be neglected. It panics if s's kind is not struct.
-func (s *Struct) IsZero() bool {
-	fields := s.structFields()
-
-	for _, field := range fields {
-		val := s.value.FieldByName(field.Name)
-
-		_, tagOpts := parseTag(field.Tag.Get(s.TagName))
-
-		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
-			ok := IsZero(val.Interface())
-			if !ok {
-				return false
-			}
-
-			continue
-		}
-
-		// zero value of the given field, such as "" for string, 0 for int
-		zero := reflect.Zero(val.Type()).Interface()
-
-		//  current value of the given field
-		current := val.Interface()
-
-		if !reflect.DeepEqual(current, zero) {
-			return false
-		}
-	}
-
-	return true
-}
-
-// HasZero returns true if a field in a struct is not initialized (zero value).
-// A struct tag with the content of "-" ignores the checking of that particular
-// field. Example:
-//
-//   // Field is ignored by this package.
-//   Field bool `structs:"-"`
-//
-// A value with the option of "omitnested" stops iterating further if the type
-// is a struct. Example:
-//
-//   // Field is not processed further by this package.
-//   Field time.Time     `structs:"myName,omitnested"`
-//   Field *http.Request `structs:",omitnested"`
-//
-// Note that only exported fields of a struct can be accessed, non exported
-// fields  will be neglected. It panics if s's kind is not struct.
-func (s *Struct) HasZero() bool {
-	fields := s.structFields()
-
-	for _, field := range fields {
-		val := s.value.FieldByName(field.Name)
-
-		_, tagOpts := parseTag(field.Tag.Get(s.TagName))
-
-		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
-			ok := HasZero(val.Interface())
-			if ok {
-				return true
-			}
-
-			continue
-		}
-
-		// zero value of the given field, such as "" for string, 0 for int
-		zero := reflect.Zero(val.Type()).Interface()
-
-		//  current value of the given field
-		current := val.Interface()
-
-		if reflect.DeepEqual(current, zero) {
-			return true
-		}
-	}
-
-	return false
-}
-
-// Name returns the structs's type name within its package. For more info refer
-// to Name() function.
-func (s *Struct) Name() string {
-	return s.value.Type().Name()
-}
-
-// structFields returns the exported struct fields for a given s struct. This
-// is a convenient helper method to avoid duplicate code in some of the
-// functions.
-func (s *Struct) structFields() []reflect.StructField {
-	t := s.value.Type()
-
-	var f []reflect.StructField
-
-	for i := 0; i < t.NumField(); i++ {
-		field := t.Field(i)
-		// we can't access the value of unexported fields
-		if field.PkgPath != "" {
-			continue
-		}
-
-		// don't check if it's omitted
-		if tag := field.Tag.Get(s.TagName); tag == "-" {
-			continue
-		}
-
-		f = append(f, field)
-	}
-
-	return f
-}
-
-func strctVal(s interface{}) reflect.Value {
-	v := reflect.ValueOf(s)
-
-	// if pointer get the underlying element≤
-	for v.Kind() == reflect.Ptr {
-		v = v.Elem()
-	}
-
-	if v.Kind() != reflect.Struct {
-		panic("not struct")
-	}
-
-	return v
-}
-
-// Map converts the given struct to a map[string]interface{}. For more info
-// refer to Struct types Map() method. It panics if s's kind is not struct.
-func Map(s interface{}) map[string]interface{} {
-	return New(s).Map()
-}
-
-// FillMap is the same as Map. Instead of returning the output, it fills the
-// given map.
-func FillMap(s interface{}, out map[string]interface{}) {
-	New(s).FillMap(out)
-}
-
-// Values converts the given struct to a []interface{}. For more info refer to
-// Struct types Values() method.  It panics if s's kind is not struct.
-func Values(s interface{}) []interface{} {
-	return New(s).Values()
-}
-
-// Fields returns a slice of *Field. For more info refer to Struct types
-// Fields() method.  It panics if s's kind is not struct.
-func Fields(s interface{}) []*Field {
-	return New(s).Fields()
-}
-
-// Names returns a slice of field names. For more info refer to Struct types
-// Names() method.  It panics if s's kind is not struct.
-func Names(s interface{}) []string {
-	return New(s).Names()
-}
-
-// IsZero returns true if all fields is equal to a zero value. For more info
-// refer to Struct types IsZero() method.  It panics if s's kind is not struct.
-func IsZero(s interface{}) bool {
-	return New(s).IsZero()
-}
-
-// HasZero returns true if any field is equal to a zero value. For more info
-// refer to Struct types HasZero() method.  It panics if s's kind is not struct.
-func HasZero(s interface{}) bool {
-	return New(s).HasZero()
-}
-
-// IsStruct returns true if the given variable is a struct or a pointer to
-// struct.
-func IsStruct(s interface{}) bool {
-	v := reflect.ValueOf(s)
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-	}
-
-	// uninitialized zero value of a struct
-	if v.Kind() == reflect.Invalid {
-		return false
-	}
-
-	return v.Kind() == reflect.Struct
-}
-
-// Name returns the structs's type name within its package. It returns an
-// empty string for unnamed types. It panics if s's kind is not struct.
-func Name(s interface{}) string {
-	return New(s).Name()
-}
-
-// nested retrieves recursively all types for the given value and returns the
-// nested value.
-func (s *Struct) nested(val reflect.Value) interface{} {
-	var finalVal interface{}
-
-	v := reflect.ValueOf(val.Interface())
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-	}
-
-	switch v.Kind() {
-	case reflect.Struct:
-		n := New(val.Interface())
-		n.TagName = s.TagName
-		m := n.Map()
-
-		// do not add the converted value if there are no exported fields, ie:
-		// time.Time
-		if len(m) == 0 {
-			finalVal = val.Interface()
-		} else {
-			finalVal = m
-		}
-	case reflect.Map:
-		v := val.Type().Elem()
-		if v.Kind() == reflect.Ptr {
-			v = v.Elem()
-		}
-
-		// only iterate over struct types, ie: map[string]StructType,
-		// map[string][]StructType,
-		if v.Kind() == reflect.Struct ||
-			(v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Struct) {
-			m := make(map[string]interface{}, val.Len())
-			for _, k := range val.MapKeys() {
-				m[k.String()] = s.nested(val.MapIndex(k))
-			}
-			finalVal = m
-			break
-		}
-
-		// TODO(arslan): should this be optional?
-		finalVal = val.Interface()
-	case reflect.Slice, reflect.Array:
-		if val.Type().Kind() == reflect.Interface {
-			finalVal = val.Interface()
-			break
-		}
-
-		// TODO(arslan): should this be optional?
-		// do not iterate of non struct types, just pass the value. Ie: []int,
-		// []string, co... We only iterate further if it's a struct.
-		// i.e []foo or []*foo
-		if val.Type().Elem().Kind() != reflect.Struct &&
-			!(val.Type().Elem().Kind() == reflect.Ptr &&
-				val.Type().Elem().Elem().Kind() == reflect.Struct) {
-			finalVal = val.Interface()
-			break
-		}
-
-		slices := make([]interface{}, val.Len(), val.Len())
-		for x := 0; x < val.Len(); x++ {
-			slices[x] = s.nested(val.Index(x))
-		}
-		finalVal = slices
-	default:
-		finalVal = val.Interface()
-	}
-
-	return finalVal
-}
diff --git a/rocketmq-go/util/structs/tags.go b/rocketmq-go/util/structs/tags.go
deleted file mode 100644
index 8859341..0000000
--- a/rocketmq-go/util/structs/tags.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package structs
-
-import "strings"
-
-// tagOptions contains a slice of tag options
-type tagOptions []string
-
-// Has returns true if the given optiton is available in tagOptions
-func (t tagOptions) Has(opt string) bool {
-	for _, tagOpt := range t {
-		if tagOpt == opt {
-			return true
-		}
-	}
-
-	return false
-}
-
-// parseTag splits a struct field's tag into its name and a list of options
-// which comes after a name. A tag is in the form of: "name,option1,option2".
-// The name can be neglectected.
-func parseTag(tag string) (string, tagOptions) {
-	// tag is one of followings:
-	// ""
-	// "name"
-	// "name,opt"
-	// "name,opt,opt2"
-	// ",opt"
-
-	res := strings.Split(tag, ",")
-	return res[0], res[1:]
-}
diff --git a/rocketmq-go/util/time_util.go b/rocketmq-go/util/time_util.go
new file mode 100644
index 0000000..352728c
--- /dev/null
+++ b/rocketmq-go/util/time_util.go
@@ -0,0 +1,35 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"strconv"
+	"time"
+)
+
+//CurrentTimeMillisInt64 get current time millis
+func CurrentTimeMillisInt64() (ret int64) {
+	ret = time.Now().UnixNano() / 1000000
+	return
+}
+
+//CurrentTimeMillisStr get current time millis string
+func CurrentTimeMillisStr() (ret string) {
+	ret = strconv.FormatInt(CurrentTimeMillisInt64(), 10)
+	return
+}
diff --git a/rocketmq-go/util/time_util_test.go b/rocketmq-go/util/time_util_test.go
new file mode 100644
index 0000000..42320a0
--- /dev/null
+++ b/rocketmq-go/util/time_util_test.go
@@ -0,0 +1,29 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util_test
+
+import (
+	"testing"
+)
+
+func TestCurrentTimeMillisInt64(t *testing.T) {
+	return
+}
+func TestCurrentTimeMillisStr(t *testing.T) {
+	return
+}