THRIFT-5337 Go set fields write improvement
Client: go
There is a duplicate elements check for set in writeFields* function,
and it compares elements using reflect.DeepEqual which is expensive.
It's much faster that generates a *Equals* function for set elements and
call it in duplicate elements check, especially for nested struct
element.
Closes #2307.
diff --git a/lib/go/test/EqualsTest.thrift b/lib/go/test/EqualsTest.thrift
new file mode 100644
index 0000000..c699232
--- /dev/null
+++ b/lib/go/test/EqualsTest.thrift
@@ -0,0 +1,109 @@
+typedef i8 mybyte
+typedef string mystr
+typedef binary mybin
+
+enum EnumFoo {
+ e1
+ e2
+}
+
+struct BasicEqualsFoo {
+ 1: bool BoolFoo,
+ 2: optional bool OptBoolFoo,
+ 3: i8 I8Foo,
+ 4: optional i8 OptI8Foo,
+ 5: i16 I16Foo,
+ 6: optional i16 OptI16Foo,
+ 7: i32 I32Foo,
+ 8: optional i32 OptI32Foo,
+ 9: i64 I64Foo,
+ 10: optional i64 OptI64Foo,
+ 11: double DoubleFoo,
+ 12: optional double OptDoubleFoo,
+ 13: string StrFoo,
+ 14: optional string OptStrFoo,
+ 15: binary BinFoo,
+ 16: optional binary OptBinFoo,
+ 17: EnumFoo EnumFoo,
+ 18: optional EnumFoo OptEnumFoo,
+ 19: mybyte MyByteFoo,
+ 20: optional mybyte OptMyByteFoo,
+ 21: mystr MyStrFoo,
+ 22: optional mystr OptMyStrFoo,
+ 23: mybin MyBinFoo,
+ 24: optional mybin OptMyBinFoo,
+}
+
+struct StructEqualsFoo {
+ 1: BasicEqualsFoo StructFoo,
+ 2: optional BasicEqualsFoo OptStructFoo,
+}
+
+struct ListEqualsFoo {
+ 1: list<i64> I64ListFoo,
+ 2: optional list<i64> OptI64ListFoo,
+ 3: list<string> StrListFoo,
+ 4: optional list<string> OptStrListFoo,
+ 5: list<binary> BinListFoo,
+ 6: optional list<binary> OptBinListFoo,
+ 7: list<BasicEqualsFoo> StructListFoo,
+ 8: optional list<BasicEqualsFoo> OptStructListFoo,
+ 9: list<list<i64>> I64ListListFoo,
+ 10: optional list<list<i64>> OptI64ListListFoo,
+ 11: list<set<i64>> I64SetListFoo,
+ 12: optional list<set<i64>> OptI64SetListFoo,
+ 13: list<map<i64, string>> I64StringMapListFoo,
+ 14: optional list<map<i64, string>> OptI64StringMapListFoo,
+ 15: list<mybyte> MyByteListFoo,
+ 16: optional list<mybyte> OptMyByteListFoo,
+ 17: list<mystr> MyStrListFoo,
+ 18: optional list<mystr> OptMyStrListFoo,
+ 19: list<mybin> MyBinListFoo,
+ 20: optional list<mybin> OptMyBinListFoo,
+}
+
+struct SetEqualsFoo {
+ 1: set<i64> I64SetFoo,
+ 2: optional set<i64> OptI64SetFoo,
+ 3: set<string> StrSetFoo,
+ 4: optional set<string> OptStrSetFoo,
+ 5: set<binary> BinSetFoo,
+ 6: optional set<binary> OptBinSetFoo,
+ 7: set<BasicEqualsFoo> StructSetFoo,
+ 8: optional set<BasicEqualsFoo> OptStructSetFoo,
+ 9: set<list<i64>> I64ListSetFoo,
+ 10: optional set<list<i64>> OptI64ListSetFoo,
+ 11: set<set<i64>> I64SetSetFoo,
+ 12: optional set<set<i64>> OptI64SetSetFoo,
+ 13: set<map<i64, string>> I64StringMapSetFoo,
+ 14: optional set<map<i64, string>> OptI64StringMapSetFoo,
+ 15: set<mybyte> MyByteSetFoo,
+ 16: optional set<mybyte> OptMyByteSetFoo,
+ 17: set<mystr> MyStrSetFoo,
+ 18: optional set<mystr> OptMyStrSetFoo,
+ 19: set<mybin> MyBinSetFoo,
+ 20: optional set<mybin> OptMyBinSetFoo,
+}
+
+struct MapEqualsFoo {
+ 1: map<i64, string> I64StrMapFoo,
+ 2: optional map<i64, string> OptI64StrMapFoo,
+ 3: map<string, i64> StrI64MapFoo,
+ 4: optional map<string, i64> OptStrI64MapFoo,
+ 5: map<BasicEqualsFoo, binary> StructBinMapFoo,
+ 6: optional map<BasicEqualsFoo, binary> OptStructBinMapFoo,
+ 7: map<binary, BasicEqualsFoo> BinStructMapFoo,
+ 8: optional map<binary, BasicEqualsFoo> OptBinStructMapFoo,
+ 9: map<i64, list<i64>> I64I64ListMapFoo,
+ 10: optional map<i64, list<i64>> OptI64I64ListMapFoo,
+ 11: map<i64, set<i64>> I64I64SetMapFoo,
+ 12: optional map<i64, set<i64>> OptI64I64SetMapFoo,
+ 13: map<i64, map<i64, string>> I64I64StringMapMapFoo,
+ 14: optional map<i64, map<i64, string>> OptI64I64StringMapMapFoo,
+ 15: map<mystr, mybin> MyStrMyBinMapFoo,
+ 16: optional map<mystr, mybin> OptMyStrMyBinMapFoo,
+ 17: map<i64, mybyte> Int64MyByteMapFoo,
+ 18: optional map<i64, mybyte> OptInt64MyByteMapFoo,
+ 19: map<mybyte, i64> MyByteInt64MapFoo,
+ 20: optional map<mybyte, i64> OptMyByteInt64MapFoo,
+}
\ No newline at end of file
diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am
index f5de26e..4419577 100644
--- a/lib/go/test/Makefile.am
+++ b/lib/go/test/Makefile.am
@@ -73,6 +73,7 @@
$(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift
$(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift
$(THRIFT) $(THRIFTARGS) -r DuplicateImportsTest.thrift
+ $(THRIFT) $(THRIFTARGS) EqualsTest.thrift
GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true
sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true
GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock
@@ -97,7 +98,8 @@
conflictnamespacetestsuperthing \
conflict/context/conflict_service-remote \
servicestest/container_test-remote \
- duplicateimportstest
+ duplicateimportstest \
+ equalstest
GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest
clean-local:
@@ -132,4 +134,5 @@
ConflictNamespaceTestC.thrift \
ConflictNamespaceTestD.thrift \
ConflictNamespaceTestSuperThing.thrift \
- ConflictNamespaceServiceTest.thrift
+ ConflictNamespaceServiceTest.thrift \
+ EqualsTest.thrift
diff --git a/lib/go/test/tests/equals_test.go b/lib/go/test/tests/equals_test.go
new file mode 100644
index 0000000..3489efa
--- /dev/null
+++ b/lib/go/test/tests/equals_test.go
@@ -0,0 +1,243 @@
+package tests
+
+import (
+ "equalstest"
+ "strconv"
+ "testing"
+)
+
+func TestEquals(t *testing.T) {
+ // test basic field
+ basicTgt, basicSrc := genBasicFoo(), genBasicFoo()
+ if !basicTgt.Equals(basicSrc) {
+ t.Error("BasicEqualsFoo.Equals() test failed")
+ }
+ basicSrc.EnumFoo = equalstest.EnumFoo_e2
+ if basicTgt.Equals(basicSrc) {
+ t.Error("BasicEqualsFoo.Equals() test failed")
+ }
+ basicSrc = genBasicFoo()
+ basicSrc.OptBoolFoo = nil
+ if basicTgt.Equals(basicSrc) || basicSrc.Equals(basicTgt) {
+ t.Error("BasicEqualsFoo.Equals() test failed")
+ }
+ if !(&equalstest.BasicEqualsFoo{}).Equals(&equalstest.BasicEqualsFoo{}) {
+ t.Error("BasicEqualsFoo.Equals() test failed")
+ }
+ // test struct field
+ structTgt, structSrc := genStructFoo(), genStructFoo()
+ if !structTgt.Equals(structSrc) {
+ t.Error("StructEqualsFoo.Equals() test failed")
+ }
+ structSrc.OptStructFoo.EnumFoo = equalstest.EnumFoo_e2
+ if structTgt.Equals(structSrc) {
+ t.Error("StructEqualsFoo.Equals() test failed")
+ }
+ structSrc = genStructFoo()
+ structSrc.OptStructFoo = nil
+ if structTgt.Equals(structSrc) || structSrc.Equals(structTgt) {
+ t.Error("StructEqualsFoo.Equals() test failed")
+ }
+ if !(&equalstest.StructEqualsFoo{}).Equals(&equalstest.StructEqualsFoo{}) {
+ t.Error("StructEqualsFoo.Equals() test failed")
+ }
+ // test list field
+ listTgt, listSrc := genListFoo(), genListFoo()
+ if !listTgt.Equals(listSrc) {
+ t.Error("ListEqualsFoo.Equals() test failed")
+ }
+ listSrc.OptI64StringMapListFoo[0][1] = "0"
+ if listTgt.Equals(listSrc) {
+ t.Error("ListEqualsFoo.Equals() test failed")
+ }
+ listSrc = genListFoo()
+ listSrc.OptI64StringMapListFoo = nil
+ if listTgt.Equals(listSrc) || listSrc.Equals(listTgt) {
+ t.Error("ListEqualsFoo.Equals() test failed")
+ }
+ if !(&equalstest.ListEqualsFoo{}).Equals(&equalstest.ListEqualsFoo{}) {
+ t.Error("ListEqualsFoo.Equals() test failed")
+ }
+ // test set field
+ setTgt, setSrc := genSetFoo(), genSetFoo()
+ if !setTgt.Equals(setSrc) {
+ t.Error("SetEqualsFoo.Equals() test failed")
+ }
+ setSrc.OptI64StringMapSetFoo[0][1] = "0"
+ if setTgt.Equals(setSrc) {
+ t.Error("SetEqualsFoo.Equals() test failed")
+ }
+ setSrc = genSetFoo()
+ setSrc.OptI64StringMapSetFoo = nil
+ if setTgt.Equals(setSrc) || setSrc.Equals(setTgt) {
+ t.Error("SetEqualsFoo.Equals() test failed")
+ }
+ if !(&equalstest.SetEqualsFoo{}).Equals(&equalstest.SetEqualsFoo{}) {
+ t.Error("SetEqualsFoo.Equals() test failed")
+ }
+ // test map field
+ mapTgt, mapSrc := genMapFoo(), genMapFoo()
+ if !mapTgt.Equals(mapSrc) {
+ t.Error("MapEqualsFoo.Equals() test failed")
+ }
+ mapSrc.OptI64I64StringMapMapFoo[1][1] = "0"
+ if mapTgt.Equals(mapSrc) {
+ t.Error("MapEqualsFoo.Equals() test failed")
+ }
+ mapSrc = genMapFoo()
+ mapSrc.OptI64I64StringMapMapFoo = nil
+ if mapTgt.Equals(mapSrc) || mapSrc.Equals(mapTgt) {
+ t.Error("MapEqualsFoo.Equals() test failed")
+ }
+ if !(&equalstest.MapEqualsFoo{}).Equals(&equalstest.MapEqualsFoo{}) {
+ t.Error("MapEqualsFoo.Equals() test failed")
+ }
+}
+
+func genBasicFoo() *equalstest.BasicEqualsFoo {
+ return &equalstest.BasicEqualsFoo{
+ BoolFoo: true,
+ OptBoolFoo: &(&struct{ x bool }{true}).x,
+ I8Foo: 1,
+ OptI8Foo: &(&struct{ x int8 }{1}).x,
+ I16Foo: 2,
+ OptI16Foo: &(&struct{ x int16 }{2}).x,
+ I32Foo: 3,
+ OptI32Foo: &(&struct{ x int32 }{3}).x,
+ I64Foo: 4,
+ OptI64Foo: &(&struct{ x int64 }{4}).x,
+ DoubleFoo: 5,
+ OptDoubleFoo: &(&struct{ x float64 }{5}).x,
+ StrFoo: "6",
+ OptStrFoo: &(&struct{ x string }{"6"}).x,
+ BinFoo: []byte("7"),
+ OptBinFoo: []byte("7"),
+ EnumFoo: equalstest.EnumFoo_e1,
+ OptEnumFoo: equalstest.EnumFooPtr(equalstest.EnumFoo_e1),
+ MyByteFoo: equalstest.Mybyte(8),
+ OptMyByteFoo: equalstest.MybytePtr(8),
+ MyStrFoo: equalstest.Mystr("9"),
+ OptMyStrFoo: equalstest.MystrPtr(equalstest.Mystr("9")),
+ MyBinFoo: equalstest.Mybin("10"),
+ OptMyBinFoo: equalstest.Mybin("10"),
+ }
+}
+
+func genStructFoo() *equalstest.StructEqualsFoo {
+ return &equalstest.StructEqualsFoo{
+ StructFoo: genBasicFoo(),
+ OptStructFoo: genBasicFoo(),
+ }
+}
+
+func genListFoo() *equalstest.ListEqualsFoo {
+ return &equalstest.ListEqualsFoo{
+ I64ListFoo: genInt64Slice(6),
+ OptI64ListFoo: genInt64Slice(6),
+ StrListFoo: genStringSlice(6),
+ OptStrListFoo: genStringSlice(6),
+ BinListFoo: genBytesSlice(6),
+ OptBinListFoo: genBytesSlice(6),
+ StructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}},
+ OptStructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}},
+ I64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ OptI64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ I64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ OptI64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ I64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}},
+ OptI64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}},
+ MyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1},
+ OptMyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1},
+ MyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
+ OptMyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
+ MyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+ OptMyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+ }
+}
+
+func genSetFoo() *equalstest.SetEqualsFoo {
+ return &equalstest.SetEqualsFoo{
+ I64SetFoo: genInt64Slice(6),
+ OptI64SetFoo: genInt64Slice(6),
+ StrSetFoo: genStringSlice(6),
+ OptStrSetFoo: genStringSlice(6),
+ BinSetFoo: genBytesSlice(6),
+ OptBinSetFoo: genBytesSlice(6),
+ StructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}},
+ OptStructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}},
+ I64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ OptI64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ I64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ OptI64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)},
+ I64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}},
+ OptI64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}},
+ MyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1},
+ OptMyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1},
+ MyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
+ OptMyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
+ MyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+ OptMyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+ }
+}
+
+var (
+ structMapKey0 = genBasicFoo()
+ structMapKey1 = &equalstest.BasicEqualsFoo{}
+)
+
+func genMapFoo() *equalstest.MapEqualsFoo {
+ return &equalstest.MapEqualsFoo{
+ I64StrMapFoo: genInt64StringMap(6),
+ OptI64StrMapFoo: genInt64StringMap(6),
+ StrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1},
+ OptStrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1},
+ StructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")},
+ OptStructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")},
+ BinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}},
+ OptBinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}},
+ I64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)},
+ OptI64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)},
+ I64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)},
+ OptI64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)},
+ I64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)},
+ OptI64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)},
+ MyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")},
+ OptMyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")},
+ Int64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)},
+ OptInt64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)},
+ MyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1},
+ OptMyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1},
+ }
+}
+
+func genInt64Slice(length int) []int64 {
+ ret := make([]int64, length)
+ for i := 0; i < length; i++ {
+ ret[i] = int64(length - i)
+ }
+ return ret
+}
+
+func genStringSlice(length int) []string {
+ ret := make([]string, length)
+ for i := 0; i < length; i++ {
+ ret[i] = strconv.Itoa(length - i)
+ }
+ return ret
+}
+
+func genBytesSlice(length int) [][]byte {
+ ret := make([][]byte, length)
+ for i := 0; i < length; i++ {
+ ret[i] = []byte(strconv.Itoa(length - i))
+ }
+ return ret
+}
+
+func genInt64StringMap(length int) map[int64]string {
+ ret := make(map[int64]string, length)
+ for i := 0; i < length; i++ {
+ ret[int64(i)] = strconv.Itoa(i)
+ }
+ return ret
+}