From ace6ba8096b407f3c811e729b997ae2d069f6236 Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Mon, 8 Apr 2019 17:02:57 +0800 Subject: [PATCH 01/28] =?UTF-8?q?Gmap=20=E6=B5=8B=E8=AF=95=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gmap_z_interface_interface_basic_test.go | 50 +++++++++++++ .../gmap/gmap_z_normal_example_test.go | 71 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 g/container/gmap/gmap_z_interface_interface_basic_test.go create mode 100644 g/container/gmap/gmap_z_normal_example_test.go diff --git a/g/container/gmap/gmap_z_interface_interface_basic_test.go b/g/container/gmap/gmap_z_interface_interface_basic_test.go new file mode 100644 index 000000000..bf10d70f6 --- /dev/null +++ b/g/container/gmap/gmap_z_interface_interface_basic_test.go @@ -0,0 +1,50 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) +func getValue()interface{}{ + return 3 +} + +func Test_Map_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.New() + m.Set("key1", "val1") + gtest.Assert(m.Get("key1"), "val1") + m.BatchSet(map[interface{}]interface{}{1: 1, "key2": "val2", "key3": "val3"}) + gtest.Assert(m.Size(), 4) + gtest.Assert(m.IsEmpty(), false) + gtest.Assert(m.GetOrSet("key4", "val4"), "val4") + gtest.Assert(m.SetIfNotExist("key4", "val4"), false) + gtest.Assert(m.Remove("key2"), "val2") + m.BatchRemove([]interface{}{"key1", 1}) + gtest.Assert(m.Contains("key3"), true) + m.Flip() + gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val4": "key4"}) + m.GetOrSetFunc("fun",getValue) + gtest.Assert(m.Get("fun"),3) + m.GetOrSetFunc("fun",getValue) + gtest.Assert(m.SetIfNotExistFunc("fun",getValue),false) + + m.Clear() + gtest.Assert(m.Size(), 0) + m2 := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"}) + gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) + m3 := gmap.NewFromArray([]interface{}{1, "key1"}, []interface{}{1, "val1"}) + gtest.Assert(m3.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) + m4 := m3.Clone() + gtest.Assert(m4.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) + + }) +} +func Test_Map_Basic_Merge(t *testing.T) { + m1 := gmap.New() + m2 := gmap.New() + m1.Set("key1", "val1") + m2.Set("key2", "val2") + m1.Merge(m2) + gtest.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"}) +} diff --git a/g/container/gmap/gmap_z_normal_example_test.go b/g/container/gmap/gmap_z_normal_example_test.go new file mode 100644 index 000000000..b134c5ff8 --- /dev/null +++ b/g/container/gmap/gmap_z_normal_example_test.go @@ -0,0 +1,71 @@ +package gmap_test + +import ( + "fmt" + "github.com/gogf/gf/g/container/gmap" +) + +func Example_Normal_Basic() { + m := gmap.New() + + //Add data + m.Set("key1", "val1") + + //Print size + fmt.Println(m.Size()) + //output 1 + + add_map := make(map[interface{}]interface{}) + add_map["key2"] = "val2" + add_map["key3"] = "val3" + add_map[1] = 1 + + fmt.Println(m.Values()) + + //Batch add data + m.BatchSet(add_map) + + //Gets the value of the corresponding key + key3_val := m.Get("key3") + fmt.Println(key3_val) + + //Get the value by key, or set it with given key-value if not exist. + get_or_set_val := m.GetOrSet("key4", "val4") + fmt.Println(get_or_set_val) + + // Set key-value if the key does not exist, then return true; or else return false. + is_set := m.SetIfNotExist("key3", "val3") + fmt.Println(is_set) + + //Remove key + m.Remove("key2") + fmt.Println(m.Keys()) + + //Batch remove keys + remove_keys := []interface{}{"key1", 1} + m.BatchRemove(remove_keys) + fmt.Println(m.Keys()) + + //Contains checks whether a key exists. + is_contain := m.Contains("key3") + fmt.Println(is_contain) + + //Flip exchanges key-value of the map, it will change key-value to value-key. + m.Flip() + fmt.Println(m.Map()) + + // Clear deletes all data of the map, + m.Clear() + + fmt.Println(m.Size()) + +} +func Example_Normal_Merge(){ + m1 := gmap.New() + m2 := gmap.New() + m1.Set("key1","val1") + m2.Set("key2","val2") + m1.Merge(m2) + fmt.Println(m1.Map()) +} + From b97bbbfa3d216db06d70f4a2620f10d9e8d2e94e Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Mon, 8 Apr 2019 17:32:07 +0800 Subject: [PATCH 02/28] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/gmap_z_interface_interface_basic_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/g/container/gmap/gmap_z_interface_interface_basic_test.go b/g/container/gmap/gmap_z_interface_interface_basic_test.go index bf10d70f6..079c20015 100644 --- a/g/container/gmap/gmap_z_interface_interface_basic_test.go +++ b/g/container/gmap/gmap_z_interface_interface_basic_test.go @@ -13,6 +13,9 @@ func Test_Map_Basic(t *testing.T) { gtest.Case(t, func() { m := gmap.New() m.Set("key1", "val1") + gtest.Assert(m.Keys(),[]interface{}{"key1"}) + gtest.Assert(m.Values(),[]interface{}{"val1"}) + gtest.Assert(m.Get("key1"), "val1") m.BatchSet(map[interface{}]interface{}{1: 1, "key2": "val2", "key3": "val3"}) gtest.Assert(m.Size(), 4) @@ -25,10 +28,11 @@ func Test_Map_Basic(t *testing.T) { m.Flip() gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val4": "key4"}) m.GetOrSetFunc("fun",getValue) + m.GetOrSetFuncLock("funlock",getValue) + gtest.Assert(m.Get("funlock"),3) gtest.Assert(m.Get("fun"),3) m.GetOrSetFunc("fun",getValue) gtest.Assert(m.SetIfNotExistFunc("fun",getValue),false) - m.Clear() gtest.Assert(m.Size(), 0) m2 := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"}) From 39c65d9e9a0beadb045151a693466f7959875d58 Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Mon, 8 Apr 2019 17:49:15 +0800 Subject: [PATCH 03/28] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/gmap_z_interface_interface_basic_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/g/container/gmap/gmap_z_interface_interface_basic_test.go b/g/container/gmap/gmap_z_interface_interface_basic_test.go index 079c20015..b5de111d2 100644 --- a/g/container/gmap/gmap_z_interface_interface_basic_test.go +++ b/g/container/gmap/gmap_z_interface_interface_basic_test.go @@ -33,6 +33,8 @@ func Test_Map_Basic(t *testing.T) { gtest.Assert(m.Get("fun"),3) m.GetOrSetFunc("fun",getValue) gtest.Assert(m.SetIfNotExistFunc("fun",getValue),false) + gtest.Assert(m.SetIfNotExistFuncLock("funlock",getValue),false) + m.Clear() gtest.Assert(m.Size(), 0) m2 := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"}) From 277b7a453641f3f84fe829490248d721272a0a9a Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Tue, 9 Apr 2019 15:06:12 +0800 Subject: [PATCH 04/28] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gmap_z_interface_interface_basic_test.go | 76 ++++++++++++++----- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/g/container/gmap/gmap_z_interface_interface_basic_test.go b/g/container/gmap/gmap_z_interface_interface_basic_test.go index b5de111d2..6f23e4155 100644 --- a/g/container/gmap/gmap_z_interface_interface_basic_test.go +++ b/g/container/gmap/gmap_z_interface_interface_basic_test.go @@ -5,47 +5,83 @@ import ( "github.com/gogf/gf/g/test/gtest" "testing" ) -func getValue()interface{}{ + +func getValue() interface{} { return 3 } - +func callBack(k interface{}, v interface{}) bool { + return true +} func Test_Map_Basic(t *testing.T) { gtest.Case(t, func() { m := gmap.New() m.Set("key1", "val1") - gtest.Assert(m.Keys(),[]interface{}{"key1"}) - gtest.Assert(m.Values(),[]interface{}{"val1"}) + gtest.Assert(m.Keys(), []interface{}{"key1"}) + gtest.Assert(m.Values(), []interface{}{"val1"}) gtest.Assert(m.Get("key1"), "val1") - m.BatchSet(map[interface{}]interface{}{1: 1, "key2": "val2", "key3": "val3"}) - gtest.Assert(m.Size(), 4) + gtest.Assert(m.Size(), 1) gtest.Assert(m.IsEmpty(), false) - gtest.Assert(m.GetOrSet("key4", "val4"), "val4") - gtest.Assert(m.SetIfNotExist("key4", "val4"), false) + + gtest.Assert(m.GetOrSet("key2", "val2"), "val2") + gtest.Assert(m.SetIfNotExist("key2", "val2"), false) + + gtest.Assert(m.SetIfNotExist("key3", "val3"), true) + gtest.Assert(m.Remove("key2"), "val2") - m.BatchRemove([]interface{}{"key1", 1}) - gtest.Assert(m.Contains("key3"), true) + gtest.Assert(m.Contains("key2"), false) + + gtest.AssertIN("key3", m.Keys()) + gtest.AssertIN("key1", m.Keys()) + gtest.AssertIN("val3", m.Values()) + gtest.AssertIN("val1", m.Values()) + m.Flip() - gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val4": "key4"}) - m.GetOrSetFunc("fun",getValue) - m.GetOrSetFuncLock("funlock",getValue) - gtest.Assert(m.Get("funlock"),3) - gtest.Assert(m.Get("fun"),3) - m.GetOrSetFunc("fun",getValue) - gtest.Assert(m.SetIfNotExistFunc("fun",getValue),false) - gtest.Assert(m.SetIfNotExistFuncLock("funlock",getValue),false) + gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"}) m.Clear() gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + m2 := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"}) gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) m3 := gmap.NewFromArray([]interface{}{1, "key1"}, []interface{}{1, "val1"}) gtest.Assert(m3.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) - m4 := m3.Clone() - gtest.Assert(m4.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) }) } +func Test_Map_Set_Fun(t *testing.T) { + m := gmap.New() + m.GetOrSetFunc("fun", getValue) + m.GetOrSetFuncLock("funlock", getValue) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + m.GetOrSetFunc("fun", getValue) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) +} + +func Test_Map_Batch(t *testing.T) { + m := gmap.New() + m.BatchSet(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"}) + m.Iterator(callBack) + gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"}) + m.BatchRemove([]interface{}{"key1", 1}) + gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) +} + +func Test_Map_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"}) + m_clone := m.Clone() + m.Remove(1) + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN(1, m_clone.Keys()) + + m_clone.Remove("key1") + //修改clone map,原 map 不影响 + gtest.AssertIN("key1", m.Keys()) +} func Test_Map_Basic_Merge(t *testing.T) { m1 := gmap.New() m2 := gmap.New() From 6d8ced21b92d49e667ef60f78cc5d116303c6874 Mon Sep 17 00:00:00 2001 From: farmer chen <10946081@qq.com> Date: Tue, 9 Apr 2019 17:27:58 +0800 Subject: [PATCH 05/28] Add unit test for gring --- g/container/gring/gring_unit_test.go | 179 +++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 g/container/gring/gring_unit_test.go diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go new file mode 100644 index 000000000..c80913b72 --- /dev/null +++ b/g/container/gring/gring_unit_test.go @@ -0,0 +1,179 @@ +package gring_test + +import ( + "container/ring" + "github.com/gogf/gf/g/container/gring" + "github.com/gogf/gf/g/test/gtest" + "testing" +) +type Student struct { + position int + name string + upgrade bool +} + +func TestRing_Val(t *testing.T) { + gtest.Case(t, func() { + //定义cap 为3的ring类型数据 + r := gring.New(3, true) + //分别给3个元素初始化赋值 + r.Put(&Student{1,"jimmy", true}) + r.Put(&Student{2,"tom", true}) + r.Put(&Student{3,"alon", false}) + + //元素取值并判断和预设值是否相等 + gtest.AssertEQ(r.Val().(*Student).name,"jimmy") + //从当前位置往后移两个元素 + r.Move(2) + gtest.AssertEQ(r.Val().(*Student).name,"alon") + if r.Val().(*Student).upgrade == false { + r.Val().(*Student).upgrade = true + //更新元素值 + r.Set(&Student{3, "jack", true}) + } + + + }) +} +func TestRing_CapLen(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(10) + r.Put("goframe") + //cap长度 10 + gtest.AssertEQ(r.Cap(), 10) + //已有数据项 1 + gtest.AssertEQ(r.Len(), 1) + }) +} + +func TestRing_Position(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(2) + r.Put(1) + r.Put(2) + //往后移动1个元素 + r.Next() + gtest.AssertEQ(r.Val(),2) + //往前移动1个元素 + r.Prev() + gtest.AssertEQ(r.Val(),1) + + }) +} + +func TestRing_Link(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(3) + r.Put(1) + r.Put(2) + r.Put(3) + s := gring.New(2) + s.Put("a") + s.Put("b") + + rs := r.Link(s) + gtest.AssertEQ(rs.Move(2).Val(), "b") + + }) +} + +func TestRing_Unlink(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(5) + for i := 0; i< 5; i++ { + r.Put(i+1) + } + // 1 2 3 4 5 + // 删除当前位置往后的2个数据,返回被删除的数据 + s := r.Unlink(2) // 2 3 + gtest.AssertEQ(s.Val(), 2) + }) +} + +func TestRing_Slice(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + r.Move(2) // 3 + array := r.SliceNext() // [3 4 5 1 2] + gtest.AssertEQ(array[0], 3) + gtest.AssertEQ(len(array), 5) + + //判断array是否等于[3 4 5 1 2] + ra := []int{3,4,5,1,2} + eq := true + for i, v := range array { + if v != ra[i] { + eq = false + } + } + gtest.AssertEQ(eq, true) + + //第3个元素设为nil + r.Set(nil) + array2 := r.SliceNext() //[4 5 1 2] + //返回当前位置往后不为空的元素数组,长度为4 + gtest.AssertEQ(len(array2), 4) + + array3 := r.SlicePrev() //[2 1 5 4] + //数组array3第一个元素为2 + gtest.AssertEQ(array3[0], 2) + //数组长度4 + gtest.AssertEQ(len(array3), 4) + + }) +} + +func TestRing_RLockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + //回调函数返回true,RLockIteratorNext遍历5次 + r.RLockIteratorNext(func(value interface{}) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + //RLockIteratorPrev遍历3次返回 false,退出遍历 + r.RLockIteratorPrev(func(value interface{}) bool { + if j++; j < 3 { + return true + } + return false + }) + gtest.AssertEQ(j, 3) + }) +} + +func TestRing_LockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + r.LockIteratorNext(func(item *ring.Ring) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + r.LockIteratorPrev(func(item *ring.Ring) bool { + if j++; j < 3 { + return true + } + return false + }) + + gtest.AssertEQ(j, 3) + }) +} \ No newline at end of file From 4f792b347ddf135f08c6a2c9f7981ff0304c58c7 Mon Sep 17 00:00:00 2001 From: farmer chen <10946081@qq.com> Date: Tue, 9 Apr 2019 17:27:58 +0800 Subject: [PATCH 06/28] Add unit test for gring --- g/container/gring/gring_unit_test.go | 179 +++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 g/container/gring/gring_unit_test.go diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go new file mode 100644 index 000000000..c80913b72 --- /dev/null +++ b/g/container/gring/gring_unit_test.go @@ -0,0 +1,179 @@ +package gring_test + +import ( + "container/ring" + "github.com/gogf/gf/g/container/gring" + "github.com/gogf/gf/g/test/gtest" + "testing" +) +type Student struct { + position int + name string + upgrade bool +} + +func TestRing_Val(t *testing.T) { + gtest.Case(t, func() { + //定义cap 为3的ring类型数据 + r := gring.New(3, true) + //分别给3个元素初始化赋值 + r.Put(&Student{1,"jimmy", true}) + r.Put(&Student{2,"tom", true}) + r.Put(&Student{3,"alon", false}) + + //元素取值并判断和预设值是否相等 + gtest.AssertEQ(r.Val().(*Student).name,"jimmy") + //从当前位置往后移两个元素 + r.Move(2) + gtest.AssertEQ(r.Val().(*Student).name,"alon") + if r.Val().(*Student).upgrade == false { + r.Val().(*Student).upgrade = true + //更新元素值 + r.Set(&Student{3, "jack", true}) + } + + + }) +} +func TestRing_CapLen(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(10) + r.Put("goframe") + //cap长度 10 + gtest.AssertEQ(r.Cap(), 10) + //已有数据项 1 + gtest.AssertEQ(r.Len(), 1) + }) +} + +func TestRing_Position(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(2) + r.Put(1) + r.Put(2) + //往后移动1个元素 + r.Next() + gtest.AssertEQ(r.Val(),2) + //往前移动1个元素 + r.Prev() + gtest.AssertEQ(r.Val(),1) + + }) +} + +func TestRing_Link(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(3) + r.Put(1) + r.Put(2) + r.Put(3) + s := gring.New(2) + s.Put("a") + s.Put("b") + + rs := r.Link(s) + gtest.AssertEQ(rs.Move(2).Val(), "b") + + }) +} + +func TestRing_Unlink(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(5) + for i := 0; i< 5; i++ { + r.Put(i+1) + } + // 1 2 3 4 5 + // 删除当前位置往后的2个数据,返回被删除的数据 + s := r.Unlink(2) // 2 3 + gtest.AssertEQ(s.Val(), 2) + }) +} + +func TestRing_Slice(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + r.Move(2) // 3 + array := r.SliceNext() // [3 4 5 1 2] + gtest.AssertEQ(array[0], 3) + gtest.AssertEQ(len(array), 5) + + //判断array是否等于[3 4 5 1 2] + ra := []int{3,4,5,1,2} + eq := true + for i, v := range array { + if v != ra[i] { + eq = false + } + } + gtest.AssertEQ(eq, true) + + //第3个元素设为nil + r.Set(nil) + array2 := r.SliceNext() //[4 5 1 2] + //返回当前位置往后不为空的元素数组,长度为4 + gtest.AssertEQ(len(array2), 4) + + array3 := r.SlicePrev() //[2 1 5 4] + //数组array3第一个元素为2 + gtest.AssertEQ(array3[0], 2) + //数组长度4 + gtest.AssertEQ(len(array3), 4) + + }) +} + +func TestRing_RLockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + //回调函数返回true,RLockIteratorNext遍历5次 + r.RLockIteratorNext(func(value interface{}) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + //RLockIteratorPrev遍历3次返回 false,退出遍历 + r.RLockIteratorPrev(func(value interface{}) bool { + if j++; j < 3 { + return true + } + return false + }) + gtest.AssertEQ(j, 3) + }) +} + +func TestRing_LockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + r.LockIteratorNext(func(item *ring.Ring) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + r.LockIteratorPrev(func(item *ring.Ring) bool { + if j++; j < 3 { + return true + } + return false + }) + + gtest.AssertEQ(j, 3) + }) +} \ No newline at end of file From 78010d2bd759b474086e9bda3939e808a5d16fe2 Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 00:22:10 +0800 Subject: [PATCH 07/28] Update unit test for gring --- g/container/gring/gring_unit_test.go | 81 +++++++++++++++------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index c80913b72..214d9e3d1 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -2,6 +2,7 @@ package gring_test import ( "container/ring" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/container/gring" "github.com/gogf/gf/g/test/gtest" "testing" @@ -22,17 +23,16 @@ func TestRing_Val(t *testing.T) { r.Put(&Student{3,"alon", false}) //元素取值并判断和预设值是否相等 - gtest.AssertEQ(r.Val().(*Student).name,"jimmy") + gtest.Assert(r.Val().(*Student).name,"jimmy") //从当前位置往后移两个元素 r.Move(2) - gtest.AssertEQ(r.Val().(*Student).name,"alon") - if r.Val().(*Student).upgrade == false { - r.Val().(*Student).upgrade = true - //更新元素值 - r.Set(&Student{3, "jack", true}) - } - - + gtest.Assert(r.Val().(*Student).name,"alon") + //更新元素值 + //测试 value == nil + r.Set(nil) + gtest.Assert(r.Val(),nil) + //测试value != nil + r.Set(&Student{3, "jack", true}) }) } func TestRing_CapLen(t *testing.T) { @@ -40,9 +40,9 @@ func TestRing_CapLen(t *testing.T) { r := gring.New(10) r.Put("goframe") //cap长度 10 - gtest.AssertEQ(r.Cap(), 10) + gtest.Assert(r.Cap(), 10) //已有数据项 1 - gtest.AssertEQ(r.Len(), 1) + gtest.Assert(r.Len(), 1) }) } @@ -53,10 +53,10 @@ func TestRing_Position(t *testing.T) { r.Put(2) //往后移动1个元素 r.Next() - gtest.AssertEQ(r.Val(),2) + gtest.Assert(r.Val(),2) //往前移动1个元素 r.Prev() - gtest.AssertEQ(r.Val(),1) + gtest.Assert(r.Val(),1) }) } @@ -72,7 +72,7 @@ func TestRing_Link(t *testing.T) { s.Put("b") rs := r.Link(s) - gtest.AssertEQ(rs.Move(2).Val(), "b") + gtest.Assert(rs.Move(2).Val(), "b") }) } @@ -86,7 +86,7 @@ func TestRing_Unlink(t *testing.T) { // 1 2 3 4 5 // 删除当前位置往后的2个数据,返回被删除的数据 s := r.Unlink(2) // 2 3 - gtest.AssertEQ(s.Val(), 2) + gtest.Assert(s.Val(), 2) }) } @@ -99,30 +99,25 @@ func TestRing_Slice(t *testing.T) { } r.Move(2) // 3 array := r.SliceNext() // [3 4 5 1 2] - gtest.AssertEQ(array[0], 3) - gtest.AssertEQ(len(array), 5) + gtest.Assert(array[0], 3) + gtest.Assert(len(array), 5) //判断array是否等于[3 4 5 1 2] ra := []int{3,4,5,1,2} - eq := true - for i, v := range array { - if v != ra[i] { - eq = false - } - } - gtest.AssertEQ(eq, true) + gtest.Assert(ra, array) //第3个元素设为nil r.Set(nil) array2 := r.SliceNext() //[4 5 1 2] //返回当前位置往后不为空的元素数组,长度为4 - gtest.AssertEQ(len(array2), 4) + gtest.Assert(array2, g.Slice{4,5,1,2}) array3 := r.SlicePrev() //[2 1 5 4] - //数组array3第一个元素为2 - gtest.AssertEQ(array3[0], 2) - //数组长度4 - gtest.AssertEQ(len(array3), 4) + gtest.Assert(array3, g.Slice{2,1,5,4}) + + s := gring.New(ringLen) + array4 := s.SlicePrev() // [] + gtest.Assert(array4, g.Slice{}) }) } @@ -131,25 +126,35 @@ func TestRing_RLockIterator(t *testing.T) { gtest.Case(t, func() { ringLen := 5 r := gring.New(ringLen) + + //ring不存在有值元素 + r.RLockIteratorNext(func(value interface{}) bool { + gtest.Assert(r.Val(), nil) + return true + }) + + + r.RLockIteratorPrev(func(value interface{}) bool { + gtest.Assert(r.Val(), nil) + return true + }) + for i := 0; i< ringLen; i++ { r.Put(i+1) } - var i,j int + //回调函数返回true,RLockIteratorNext遍历5次 r.RLockIteratorNext(func(value interface{}) bool { - i++; + gtest.Assert(r.Val(), 1) return true }) - gtest.AssertEQ(i, 5) //RLockIteratorPrev遍历3次返回 false,退出遍历 r.RLockIteratorPrev(func(value interface{}) bool { - if j++; j < 3 { - return true - } + gtest.Assert(r.Val(), 1) return false }) - gtest.AssertEQ(j, 3) + }) } @@ -165,7 +170,7 @@ func TestRing_LockIterator(t *testing.T) { i++; return true }) - gtest.AssertEQ(i, 5) + gtest.Assert(i, 5) r.LockIteratorPrev(func(item *ring.Ring) bool { if j++; j < 3 { @@ -174,6 +179,6 @@ func TestRing_LockIterator(t *testing.T) { return false }) - gtest.AssertEQ(j, 3) + gtest.Assert(j, 3) }) } \ No newline at end of file From 4b5153950f04e8749e48db0c9975e20e010a8446 Mon Sep 17 00:00:00 2001 From: farmer chen <10946081@qq.com> Date: Tue, 9 Apr 2019 17:27:58 +0800 Subject: [PATCH 08/28] Add unit test for gring --- g/container/gring/gring_unit_test.go | 179 +++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 g/container/gring/gring_unit_test.go diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go new file mode 100644 index 000000000..c80913b72 --- /dev/null +++ b/g/container/gring/gring_unit_test.go @@ -0,0 +1,179 @@ +package gring_test + +import ( + "container/ring" + "github.com/gogf/gf/g/container/gring" + "github.com/gogf/gf/g/test/gtest" + "testing" +) +type Student struct { + position int + name string + upgrade bool +} + +func TestRing_Val(t *testing.T) { + gtest.Case(t, func() { + //定义cap 为3的ring类型数据 + r := gring.New(3, true) + //分别给3个元素初始化赋值 + r.Put(&Student{1,"jimmy", true}) + r.Put(&Student{2,"tom", true}) + r.Put(&Student{3,"alon", false}) + + //元素取值并判断和预设值是否相等 + gtest.AssertEQ(r.Val().(*Student).name,"jimmy") + //从当前位置往后移两个元素 + r.Move(2) + gtest.AssertEQ(r.Val().(*Student).name,"alon") + if r.Val().(*Student).upgrade == false { + r.Val().(*Student).upgrade = true + //更新元素值 + r.Set(&Student{3, "jack", true}) + } + + + }) +} +func TestRing_CapLen(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(10) + r.Put("goframe") + //cap长度 10 + gtest.AssertEQ(r.Cap(), 10) + //已有数据项 1 + gtest.AssertEQ(r.Len(), 1) + }) +} + +func TestRing_Position(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(2) + r.Put(1) + r.Put(2) + //往后移动1个元素 + r.Next() + gtest.AssertEQ(r.Val(),2) + //往前移动1个元素 + r.Prev() + gtest.AssertEQ(r.Val(),1) + + }) +} + +func TestRing_Link(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(3) + r.Put(1) + r.Put(2) + r.Put(3) + s := gring.New(2) + s.Put("a") + s.Put("b") + + rs := r.Link(s) + gtest.AssertEQ(rs.Move(2).Val(), "b") + + }) +} + +func TestRing_Unlink(t *testing.T) { + gtest.Case(t, func() { + r := gring.New(5) + for i := 0; i< 5; i++ { + r.Put(i+1) + } + // 1 2 3 4 5 + // 删除当前位置往后的2个数据,返回被删除的数据 + s := r.Unlink(2) // 2 3 + gtest.AssertEQ(s.Val(), 2) + }) +} + +func TestRing_Slice(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + r.Move(2) // 3 + array := r.SliceNext() // [3 4 5 1 2] + gtest.AssertEQ(array[0], 3) + gtest.AssertEQ(len(array), 5) + + //判断array是否等于[3 4 5 1 2] + ra := []int{3,4,5,1,2} + eq := true + for i, v := range array { + if v != ra[i] { + eq = false + } + } + gtest.AssertEQ(eq, true) + + //第3个元素设为nil + r.Set(nil) + array2 := r.SliceNext() //[4 5 1 2] + //返回当前位置往后不为空的元素数组,长度为4 + gtest.AssertEQ(len(array2), 4) + + array3 := r.SlicePrev() //[2 1 5 4] + //数组array3第一个元素为2 + gtest.AssertEQ(array3[0], 2) + //数组长度4 + gtest.AssertEQ(len(array3), 4) + + }) +} + +func TestRing_RLockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + //回调函数返回true,RLockIteratorNext遍历5次 + r.RLockIteratorNext(func(value interface{}) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + //RLockIteratorPrev遍历3次返回 false,退出遍历 + r.RLockIteratorPrev(func(value interface{}) bool { + if j++; j < 3 { + return true + } + return false + }) + gtest.AssertEQ(j, 3) + }) +} + +func TestRing_LockIterator(t *testing.T) { + gtest.Case(t, func() { + ringLen := 5 + r := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + r.Put(i+1) + } + var i,j int + r.LockIteratorNext(func(item *ring.Ring) bool { + i++; + return true + }) + gtest.AssertEQ(i, 5) + + r.LockIteratorPrev(func(item *ring.Ring) bool { + if j++; j < 3 { + return true + } + return false + }) + + gtest.AssertEQ(j, 3) + }) +} \ No newline at end of file From 922eaf4d4232e9215d920e8f249aa502ac87ab9b Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 00:22:10 +0800 Subject: [PATCH 09/28] Update unit test for gring --- g/container/gring/gring_unit_test.go | 81 +++++++++++++++------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index c80913b72..214d9e3d1 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -2,6 +2,7 @@ package gring_test import ( "container/ring" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/container/gring" "github.com/gogf/gf/g/test/gtest" "testing" @@ -22,17 +23,16 @@ func TestRing_Val(t *testing.T) { r.Put(&Student{3,"alon", false}) //元素取值并判断和预设值是否相等 - gtest.AssertEQ(r.Val().(*Student).name,"jimmy") + gtest.Assert(r.Val().(*Student).name,"jimmy") //从当前位置往后移两个元素 r.Move(2) - gtest.AssertEQ(r.Val().(*Student).name,"alon") - if r.Val().(*Student).upgrade == false { - r.Val().(*Student).upgrade = true - //更新元素值 - r.Set(&Student{3, "jack", true}) - } - - + gtest.Assert(r.Val().(*Student).name,"alon") + //更新元素值 + //测试 value == nil + r.Set(nil) + gtest.Assert(r.Val(),nil) + //测试value != nil + r.Set(&Student{3, "jack", true}) }) } func TestRing_CapLen(t *testing.T) { @@ -40,9 +40,9 @@ func TestRing_CapLen(t *testing.T) { r := gring.New(10) r.Put("goframe") //cap长度 10 - gtest.AssertEQ(r.Cap(), 10) + gtest.Assert(r.Cap(), 10) //已有数据项 1 - gtest.AssertEQ(r.Len(), 1) + gtest.Assert(r.Len(), 1) }) } @@ -53,10 +53,10 @@ func TestRing_Position(t *testing.T) { r.Put(2) //往后移动1个元素 r.Next() - gtest.AssertEQ(r.Val(),2) + gtest.Assert(r.Val(),2) //往前移动1个元素 r.Prev() - gtest.AssertEQ(r.Val(),1) + gtest.Assert(r.Val(),1) }) } @@ -72,7 +72,7 @@ func TestRing_Link(t *testing.T) { s.Put("b") rs := r.Link(s) - gtest.AssertEQ(rs.Move(2).Val(), "b") + gtest.Assert(rs.Move(2).Val(), "b") }) } @@ -86,7 +86,7 @@ func TestRing_Unlink(t *testing.T) { // 1 2 3 4 5 // 删除当前位置往后的2个数据,返回被删除的数据 s := r.Unlink(2) // 2 3 - gtest.AssertEQ(s.Val(), 2) + gtest.Assert(s.Val(), 2) }) } @@ -99,30 +99,25 @@ func TestRing_Slice(t *testing.T) { } r.Move(2) // 3 array := r.SliceNext() // [3 4 5 1 2] - gtest.AssertEQ(array[0], 3) - gtest.AssertEQ(len(array), 5) + gtest.Assert(array[0], 3) + gtest.Assert(len(array), 5) //判断array是否等于[3 4 5 1 2] ra := []int{3,4,5,1,2} - eq := true - for i, v := range array { - if v != ra[i] { - eq = false - } - } - gtest.AssertEQ(eq, true) + gtest.Assert(ra, array) //第3个元素设为nil r.Set(nil) array2 := r.SliceNext() //[4 5 1 2] //返回当前位置往后不为空的元素数组,长度为4 - gtest.AssertEQ(len(array2), 4) + gtest.Assert(array2, g.Slice{4,5,1,2}) array3 := r.SlicePrev() //[2 1 5 4] - //数组array3第一个元素为2 - gtest.AssertEQ(array3[0], 2) - //数组长度4 - gtest.AssertEQ(len(array3), 4) + gtest.Assert(array3, g.Slice{2,1,5,4}) + + s := gring.New(ringLen) + array4 := s.SlicePrev() // [] + gtest.Assert(array4, g.Slice{}) }) } @@ -131,25 +126,35 @@ func TestRing_RLockIterator(t *testing.T) { gtest.Case(t, func() { ringLen := 5 r := gring.New(ringLen) + + //ring不存在有值元素 + r.RLockIteratorNext(func(value interface{}) bool { + gtest.Assert(r.Val(), nil) + return true + }) + + + r.RLockIteratorPrev(func(value interface{}) bool { + gtest.Assert(r.Val(), nil) + return true + }) + for i := 0; i< ringLen; i++ { r.Put(i+1) } - var i,j int + //回调函数返回true,RLockIteratorNext遍历5次 r.RLockIteratorNext(func(value interface{}) bool { - i++; + gtest.Assert(r.Val(), 1) return true }) - gtest.AssertEQ(i, 5) //RLockIteratorPrev遍历3次返回 false,退出遍历 r.RLockIteratorPrev(func(value interface{}) bool { - if j++; j < 3 { - return true - } + gtest.Assert(r.Val(), 1) return false }) - gtest.AssertEQ(j, 3) + }) } @@ -165,7 +170,7 @@ func TestRing_LockIterator(t *testing.T) { i++; return true }) - gtest.AssertEQ(i, 5) + gtest.Assert(i, 5) r.LockIteratorPrev(func(item *ring.Ring) bool { if j++; j < 3 { @@ -174,6 +179,6 @@ func TestRing_LockIterator(t *testing.T) { return false }) - gtest.AssertEQ(j, 3) + gtest.Assert(j, 3) }) } \ No newline at end of file From 6fad737617fa64932c27d4c9e9495cb0967b6248 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2019 01:00:51 +0800 Subject: [PATCH 10/28] update unit test cases of gjson/gparser --- g/encoding/gjson/gjson_unit_basic_test.go | 4 ++-- g/encoding/gparser/gparser_unit_basic_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/g/encoding/gjson/gjson_unit_basic_test.go b/g/encoding/gjson/gjson_unit_basic_test.go index 790878289..2575cc6c1 100644 --- a/g/encoding/gjson/gjson_unit_basic_test.go +++ b/g/encoding/gjson/gjson_unit_basic_test.go @@ -139,7 +139,7 @@ func Test_GetMap(t *testing.T) { gtest.Case(t, func() { j, err := gjson.DecodeToJson(data) gtest.Assert(err, nil) - gtest.Assert(j.GetMap("n"), g.Map{}) + gtest.Assert(j.GetMap("n"), nil) gtest.Assert(j.GetMap("m"), g.Map{"k" : "v"}) gtest.Assert(j.GetMap("a"), g.Map{}) }) @@ -189,7 +189,7 @@ func Test_GetStrings(t *testing.T) { gtest.AssertEQ(j.GetStrings("n"), g.SliceStr{"123456789"}) gtest.AssertEQ(j.GetStrings("m"), g.SliceStr{`{"k":"v"}`}) gtest.AssertEQ(j.GetStrings("a"), g.SliceStr{"1", "2", "3"}) - gtest.AssertEQ(j.GetStrings("i"), g.SliceStr{}) + gtest.AssertEQ(j.GetStrings("i"), nil) }) } diff --git a/g/encoding/gparser/gparser_unit_basic_test.go b/g/encoding/gparser/gparser_unit_basic_test.go index bf7067753..4fb894d4f 100644 --- a/g/encoding/gparser/gparser_unit_basic_test.go +++ b/g/encoding/gparser/gparser_unit_basic_test.go @@ -107,9 +107,9 @@ func Test_GetMap(t *testing.T) { gtest.Case(t, func() { j := gparser.New(data) gtest.AssertNE(j, nil) - gtest.Assert(j.GetMap("n"), g.Map{}) + gtest.Assert(j.GetMap("n"), nil) gtest.Assert(j.GetMap("m"), g.Map{"k" : "v"}) - gtest.Assert(j.GetMap("a"), g.Map{}) + gtest.Assert(j.GetMap("a"), nil) }) } @@ -144,7 +144,7 @@ func Test_GetStrings(t *testing.T) { gtest.AssertEQ(j.GetStrings("n"), g.SliceStr{"123456789"}) gtest.AssertEQ(j.GetStrings("m"), g.SliceStr{`{"k":"v"}`}) gtest.AssertEQ(j.GetStrings("a"), g.SliceStr{"1", "2", "3"}) - gtest.AssertEQ(j.GetStrings("i"), g.SliceStr{}) + gtest.AssertEQ(j.GetStrings("i"), nil) }) } From bd0207c938ebbd756949a24bf8f240b1574a6674 Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 01:16:45 +0800 Subject: [PATCH 11/28] update unit test for gring --- g/container/gring/gring_unit_test.go | 41 ++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index 214d9e3d1..eb9eb9a7f 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -162,23 +162,46 @@ func TestRing_LockIterator(t *testing.T) { gtest.Case(t, func() { ringLen := 5 r := gring.New(ringLen) + + //不存在有值元素 + r.LockIteratorNext(func(item *ring.Ring) bool { + gtest.Assert(item.Value, nil) + return true + }) + + r.LockIteratorPrev(func(item *ring.Ring) bool { + gtest.Assert(item.Value, nil) + return true + }) + + //ring初始化元素值 for i := 0; i< ringLen; i++ { r.Put(i+1) } - var i,j int + + //往后遍历组成数据 [1,2,3,4,5] + array1 := g.Slice{1,2,3,4,5} + ii := 0 r.LockIteratorNext(func(item *ring.Ring) bool { + //校验每一次遍历取值是否是期望值 + gtest.Assert(item.Value, array1[ii]) + ii++; + return true + }) + + //往后取3个元素组成数组 + //获得 [1,5,4] + i := 0 + a := g.Slice{1,5,4} + r.LockIteratorPrev(func(item *ring.Ring) bool { + if i > 2 { + return false + } + gtest.Assert(item.Value, a[i]) i++; return true }) - gtest.Assert(i, 5) - r.LockIteratorPrev(func(item *ring.Ring) bool { - if j++; j < 3 { - return true - } - return false - }) - gtest.Assert(j, 3) }) } \ No newline at end of file From 08785cb272dd29de8fd7269b0da4d09cf0329a26 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2019 08:54:49 +0800 Subject: [PATCH 12/28] update unit test cases of gjson --- g/encoding/gjson/gjson_unit_basic_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/g/encoding/gjson/gjson_unit_basic_test.go b/g/encoding/gjson/gjson_unit_basic_test.go index 2575cc6c1..102a2e15b 100644 --- a/g/encoding/gjson/gjson_unit_basic_test.go +++ b/g/encoding/gjson/gjson_unit_basic_test.go @@ -141,7 +141,7 @@ func Test_GetMap(t *testing.T) { gtest.Assert(err, nil) gtest.Assert(j.GetMap("n"), nil) gtest.Assert(j.GetMap("m"), g.Map{"k" : "v"}) - gtest.Assert(j.GetMap("a"), g.Map{}) + gtest.Assert(j.GetMap("a"), nil) }) } From 230be66fa9c2a989399d1ce1975f719f53ddb3f6 Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 10:13:56 +0800 Subject: [PATCH 13/28] update unit test for gring --- g/container/gring/gring_unit_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index eb9eb9a7f..8a17b2303 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -85,8 +85,10 @@ func TestRing_Unlink(t *testing.T) { } // 1 2 3 4 5 // 删除当前位置往后的2个数据,返回被删除的数据 + // 重新计算s len s := r.Unlink(2) // 2 3 gtest.Assert(s.Val(), 2) + gtest.Assert(s.Len(), 1) }) } From 8285c31bf1a974928cb2ffb057e21b783810e49f Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 10:44:40 +0800 Subject: [PATCH 14/28] Update unit test for gring --- g/container/gring/gring_unit_test.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index 8a17b2303..e94588ee6 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -83,7 +83,7 @@ func TestRing_Unlink(t *testing.T) { for i := 0; i< 5; i++ { r.Put(i+1) } - // 1 2 3 4 5 + // 1 2 3 4 // 删除当前位置往后的2个数据,返回被删除的数据 // 重新计算s len s := r.Unlink(2) // 2 3 @@ -118,8 +118,11 @@ func TestRing_Slice(t *testing.T) { gtest.Assert(array3, g.Slice{2,1,5,4}) s := gring.New(ringLen) + for i := 0; i< ringLen; i++ { + s.Put(i+1) + } array4 := s.SlicePrev() // [] - gtest.Assert(array4, g.Slice{}) + gtest.Assert(array4, g.Slice{1,5,4,3,2}) }) } @@ -130,12 +133,15 @@ func TestRing_RLockIterator(t *testing.T) { r := gring.New(ringLen) //ring不存在有值元素 + r.RLockIteratorNext(func(value interface{}) bool { + gtest.Assert(r.Val(), nil) + return false + }) r.RLockIteratorNext(func(value interface{}) bool { gtest.Assert(r.Val(), nil) return true }) - r.RLockIteratorPrev(func(value interface{}) bool { gtest.Assert(r.Val(), nil) return true @@ -166,11 +172,23 @@ func TestRing_LockIterator(t *testing.T) { r := gring.New(ringLen) //不存在有值元素 + r.LockIteratorNext(func(item *ring.Ring) bool { + gtest.Assert(item.Value, nil) + return false + }) + r.LockIteratorNext(func(item *ring.Ring) bool { + gtest.Assert(item.Value, nil) + return false + }) r.LockIteratorNext(func(item *ring.Ring) bool { gtest.Assert(item.Value, nil) return true }) + r.LockIteratorPrev(func(item *ring.Ring) bool { + gtest.Assert(item.Value, nil) + return false + }) r.LockIteratorPrev(func(item *ring.Ring) bool { gtest.Assert(item.Value, nil) return true From ad50ca6e60aa57b633a3b207b6d62a0350f5e2e9 Mon Sep 17 00:00:00 2001 From: aloncn <10946081@qq.com> Date: Wed, 10 Apr 2019 14:26:21 +0800 Subject: [PATCH 15/28] update unit test for gring --- g/container/gring/gring_unit_test.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/g/container/gring/gring_unit_test.go b/g/container/gring/gring_unit_test.go index e94588ee6..4f209d9df 100644 --- a/g/container/gring/gring_unit_test.go +++ b/g/container/gring/gring_unit_test.go @@ -133,17 +133,17 @@ func TestRing_RLockIterator(t *testing.T) { r := gring.New(ringLen) //ring不存在有值元素 - r.RLockIteratorNext(func(value interface{}) bool { - gtest.Assert(r.Val(), nil) + r.RLockIteratorNext(func(v interface{}) bool { + gtest.Assert(v, nil) return false }) - r.RLockIteratorNext(func(value interface{}) bool { - gtest.Assert(r.Val(), nil) + r.RLockIteratorNext(func(v interface{}) bool { + gtest.Assert(v, nil) return true }) - r.RLockIteratorPrev(func(value interface{}) bool { - gtest.Assert(r.Val(), nil) + r.RLockIteratorPrev(func(v interface{}) bool { + gtest.Assert(v, nil) return true }) @@ -151,15 +151,17 @@ func TestRing_RLockIterator(t *testing.T) { r.Put(i+1) } - //回调函数返回true,RLockIteratorNext遍历5次 - r.RLockIteratorNext(func(value interface{}) bool { - gtest.Assert(r.Val(), 1) + //回调函数返回true,RLockIteratorNext遍历5次,期望值分别是1、2、3、4、5 + i := 0 + r.RLockIteratorNext(func(v interface{}) bool { + gtest.Assert(v, i+1) + i++; return true }) - //RLockIteratorPrev遍历3次返回 false,退出遍历 - r.RLockIteratorPrev(func(value interface{}) bool { - gtest.Assert(r.Val(), 1) + //RLockIteratorPrev遍历1次返回 false,退出遍历 + r.RLockIteratorPrev(func(v interface{}) bool { + gtest.Assert(v, 1) return false }) From 9ec15ad2ca5fccf83d705c3378286ac39b8af152 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2019 18:33:12 +0800 Subject: [PATCH 16/28] fix issue in repeated rand value of grand.Intn --- g/util/grand/grand_intn.go | 13 +++++++++---- geg/other/test.go | 13 ++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/g/util/grand/grand_intn.go b/g/util/grand/grand_intn.go index de8d6244c..9677a433e 100644 --- a/g/util/grand/grand_intn.go +++ b/g/util/grand/grand_intn.go @@ -7,8 +7,9 @@ package grand import ( - "crypto/rand" - "encoding/binary" + "crypto/rand" + "encoding/binary" + "os" ) const ( @@ -27,6 +28,7 @@ func init() { for { if n, err := rand.Read(buffer); err != nil { panic(err) + os.Exit(1) } else { // 使用缓冲区数据进行一次完整的随机数生成 for i := 0; i < n - 4; { @@ -35,9 +37,12 @@ func init() { } // 充分利用缓冲区数据,随机索引递增 step = int(buffer[0])%10 + if step == 0 { + step = 2 + } for i := 0; i < n - 4; { - bufferChan <- binary.BigEndian.Uint32(buffer[i : i + 4]) - i += step + bufferChan <- binary.BigEndian.Uint32(buffer[i : i + 4]) + i += step } } } diff --git a/geg/other/test.go b/geg/other/test.go index 20c4a87fc..63996a987 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,12 +1,15 @@ package main import ( - "github.com/gogf/gf/g/test/gtest" + "fmt" + "github.com/gogf/gf/g/util/grand" ) -func test() []byte { - return nil -} + + func main() { - gtest.Assert(test(), nil) + for { + fmt.Println(grand.Intn(100)) + } + } \ No newline at end of file From acac5a2ad61e8822287061f4a0b9689ebbc7fdd1 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2019 18:33:51 +0800 Subject: [PATCH 17/28] version updates --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 0d8a2b6f5..8668f2551 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package gf -const VERSION = "v1.6.0" +const VERSION = "v1.6.1" const AUTHORS = "john" From c7a6a6fff04fed4a5415bf9a36e1413bc2b63ba5 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Apr 2019 23:09:38 +0800 Subject: [PATCH 18/28] improve grand.Intn; README updates --- README.MD | 1 + README_ZH.MD | 1 + g/util/grand/grand_intn.go | 11 ++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.MD b/README.MD index 6059c1ae8..b215dfb70 100644 --- a/README.MD +++ b/README.MD @@ -66,6 +66,7 @@ func main() { # Contributors +- [aloncn](https://github.com/aloncn) - [chenyang351](https://github.com/chenyang351) - [garfieldkwong](https://gitee.com/garfieldkwong) - [hailaz](https://gitee.com/hailaz) diff --git a/README_ZH.MD b/README_ZH.MD index 998f83995..e29248375 100644 --- a/README_ZH.MD +++ b/README_ZH.MD @@ -86,6 +86,7 @@ func main() { # 贡献者 +- [aloncn](https://github.com/aloncn) - [chenyang351](https://github.com/chenyang351) - [garfieldkwong](https://gitee.com/garfieldkwong) - [hailaz](https://gitee.com/hailaz) diff --git a/g/util/grand/grand_intn.go b/g/util/grand/grand_intn.go index 9677a433e..14dcc032e 100644 --- a/g/util/grand/grand_intn.go +++ b/g/util/grand/grand_intn.go @@ -36,10 +36,15 @@ func init() { i ++ } // 充分利用缓冲区数据,随机索引递增 - step = int(buffer[0])%10 - if step == 0 { - step = 2 + for i := 0; i < n; i++ { + step = int(buffer[0])%10 + if step != 0 { + break + } } + if step == 0 { + step = 2 + } for i := 0; i < n - 4; { bufferChan <- binary.BigEndian.Uint32(buffer[i : i + 4]) i += step From 4ac647a2150b337a122faa79f051a8afa6dd9bd1 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Apr 2019 09:05:27 +0800 Subject: [PATCH 19/28] gcmd updates --- g/os/gcmd/gcmd.go | 74 ++++++++++------------------------------ g/os/gcmd/gcmd_option.go | 32 +++++++++++++++++ g/os/gcmd/gcmd_value.go | 32 +++++++++++++++++ 3 files changed, 82 insertions(+), 56 deletions(-) create mode 100644 g/os/gcmd/gcmd_option.go create mode 100644 g/os/gcmd/gcmd_value.go diff --git a/g/os/gcmd/gcmd.go b/g/os/gcmd/gcmd.go index 4fe997010..a5601806f 100644 --- a/g/os/gcmd/gcmd.go +++ b/g/os/gcmd/gcmd.go @@ -6,33 +6,28 @@ // // Package gcmd provides console operations, like options/values reading and command running. -// -// 命令行管理. package gcmd import ( + "github.com/gogf/gf/g/os/glog" "os" - "errors" - "regexp" + "regexp" ) -// 命令行参数列表 +// Console values. type gCmdValue struct { values []string } -// 命令行选项列表 +// Console options. type gCmdOption struct { options map[string]string } -// 终端管理对象(全局) -var Value = &gCmdValue{} // 终端参数-命令参数列表 -var Option = &gCmdOption{} // 终端参数-选项参数列表 -var cmdFuncMap = make(map[string]func()) // 终端命令及函数地址对应表 +var Value = &gCmdValue{} // Console values. +var Option = &gCmdOption{} // Console options. +var cmdFuncMap = make(map[string]func()) // Registered callback functions. -// 检查并初始化console参数,在包加载的时候触发 -// 初始化时执行,不影响运行时性能 func init() { reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`) Option.options = make(map[string]string) @@ -46,67 +41,34 @@ func init() { } } -// 返回所有的命令行参数values -func (c *gCmdValue) GetAll() []string { - return c.values -} - -// 返回所有的命令行参数options -func (c *gCmdOption) GetAll() map[string]string { - return c.options -} - -// 获得一条指定索引位置的value参数 -func (c *gCmdValue) Get(index uint8, def...string) string { - if index < uint8(len(c.values)) { - return c.values[index] - } else if len(def) > 0 { - return def[0] - } - return "" -} - -// 获得一条指定索引位置的option参数; -func (c *gCmdOption) Get(key string, def...string) string { - if option, ok := c.options[key]; ok { - return option - } else if len(def) > 0 { - return def[0] - } - return "" -} - -// 绑定命令行参数及对应的命令函数,注意命令函数参数是函数的内存地址 -// 如果操作失败返回错误信息 -func BindHandle (cmd string, f func()) error { +// BindHandle registers callback function with . +func BindHandle (cmd string, f func()) { if _, ok := cmdFuncMap[cmd]; ok { - return errors.New("duplicated handle for command:" + cmd) + glog.Fatal("duplicated handle for command:" + cmd) } else { cmdFuncMap[cmd] = f - return nil } } -// 执行命令对应的函数 -func RunHandle (cmd string) error { +// RunHandle executes the callback function registered by . +func RunHandle (cmd string) { if handle, ok := cmdFuncMap[cmd]; ok { handle() - return nil } else { - return errors.New("no handle found for command:" + cmd) + glog.Fatal("no handle found for command:" + cmd) } } -// 自动识别命令参数并执行命令参数对应的函数 -func AutoRun () error { +// AutoRun automatically recognizes and executes the callback function +// by value of index 0 (the first console parameter). +func AutoRun () { if cmd := Value.Get(1); cmd != "" { if handle, ok := cmdFuncMap[cmd]; ok { handle() - return nil } else { - return errors.New("no handle found for command:" + cmd) + glog.Fatal("no handle found for command:" + cmd) } } else { - return errors.New("no command found") + glog.Fatal("no command found") } } diff --git a/g/os/gcmd/gcmd_option.go b/g/os/gcmd/gcmd_option.go new file mode 100644 index 000000000..4cc0147f4 --- /dev/null +++ b/g/os/gcmd/gcmd_option.go @@ -0,0 +1,32 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +package gcmd + +import "github.com/gogf/gf/g/container/gvar" + +// GetAll returns all option values as map[string]string. +func (c *gCmdOption) GetAll() map[string]string { + return c.options +} + +// Get returns the option value string specified by , +// if value dose not exist, then returns . +func (c *gCmdOption) Get(key string, def...string) string { + if option, ok := c.options[key]; ok { + return option + } else if len(def) > 0 { + return def[0] + } + return "" +} + +// GetVar returns the option value as gvar.VarRead object specified by , +// if value does not exist, then returns as its default value. +func (c *gCmdOption) GetVar(key string, def...string) gvar.VarRead { + return gvar.NewRead(c.Get(key, def...), true) +} diff --git a/g/os/gcmd/gcmd_value.go b/g/os/gcmd/gcmd_value.go new file mode 100644 index 000000000..b1144b6ac --- /dev/null +++ b/g/os/gcmd/gcmd_value.go @@ -0,0 +1,32 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. +// + +package gcmd + +import "github.com/gogf/gf/g/container/gvar" + +// GetAll returns all values as a slice of string. +func (c *gCmdValue) GetAll() []string { + return c.values +} + +// Get returns value by index as string, +// if value does not exist, then returns . +func (c *gCmdValue) Get(index int, def...string) string { + if index < len(c.values) { + return c.values[index] + } else if len(def) > 0 { + return def[0] + } + return "" +} + +// GetVar returns value by index as gvar.VarRead object, +// if value does not exist, then returns as its default value. +func (c *gCmdValue) GetVar(index int, def...string) gvar.VarRead { + return gvar.NewRead(c.Get(index, def...), true) +} From 0ffe17ee3d200689f7bdb51c1b3dfd460272253d Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Apr 2019 09:26:52 +0800 Subject: [PATCH 20/28] revert SearchArray/InArray functions for gstr --- g/internal/cmdenv/cmdenv.go | 27 +++++++++++++++++++++------ g/text/gstr/gstr.go | 17 +++++++++++++++++ g/text/gstr/gstr_z_unit_basic_test.go | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/g/internal/cmdenv/cmdenv.go b/g/internal/cmdenv/cmdenv.go index 31e7475bc..9dd9a8d08 100644 --- a/g/internal/cmdenv/cmdenv.go +++ b/g/internal/cmdenv/cmdenv.go @@ -7,12 +7,27 @@ package cmdenv import ( - "github.com/gogf/gf/g/container/gvar" - "github.com/gogf/gf/g/os/gcmd" - "github.com/gogf/gf/g/os/genv" - "strings" + "github.com/gogf/gf/g/container/gvar" + "os" + "regexp" + "strings" ) +var ( + // Console options. + cmdOptions = make(map[string]string) +) + +func init() { + reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`) + for i := 0; i < len(os.Args); i++ { + result := reg.FindStringSubmatch(os.Args[i]) + if len(result) > 1 { + cmdOptions[result[1]] = result[2] + } + } +} + // 获取指定名称的命令行参数,当不存在时获取环境变量参数,皆不存在时,返回给定的默认值。 // 规则: // 1、命令行参数以小写字母格式,使用: gf.包名.变量名 传递; @@ -22,11 +37,11 @@ func Get(key string, def...interface{}) gvar.VarRead { if len(def) > 0 { value = def[0] } - if v := gcmd.Option.Get(key); v != "" { + if v, ok := cmdOptions[key]; ok { value = v } else { key = strings.ToUpper(strings.Replace(key, ".", "_", -1)) - if v := genv.Get(key); v != "" { + if v := os.Getenv(key); v != "" { value = v } } diff --git a/g/text/gstr/gstr.go b/g/text/gstr/gstr.go index fc03ce3bc..b1dad21fd 100644 --- a/g/text/gstr/gstr.go +++ b/g/text/gstr/gstr.go @@ -594,4 +594,21 @@ func QuoteMeta(str string) string { buf.WriteRune(char) } return buf.String() +} + +// SearchArray searches string in string slice case-sensitively, +// returns its index in . +// If is not found in , it returns -1. +func SearchArray (a []string, s string) int { + for i, v := range a { + if s == v { + return i + } + } + return -1 +} + +// InArray checks whether string in slice . +func InArray (a []string, s string) bool { + return SearchArray(a, s) != -1 } \ No newline at end of file diff --git a/g/text/gstr/gstr_z_unit_basic_test.go b/g/text/gstr/gstr_z_unit_basic_test.go index b69939236..d15e312db 100644 --- a/g/text/gstr/gstr_z_unit_basic_test.go +++ b/g/text/gstr/gstr_z_unit_basic_test.go @@ -383,3 +383,22 @@ func Test_ContainsAny(t *testing.T) { }) } +func Test_SearchArray(t *testing.T) { + gtest.Case(t, func() { + a := g.SliceStr{"a", "b", "c"} + gtest.AssertEQ(gstr.SearchArray(a, "a"), 0) + gtest.AssertEQ(gstr.SearchArray(a, "b"), 1) + gtest.AssertEQ(gstr.SearchArray(a, "c"), 2) + gtest.AssertEQ(gstr.SearchArray(a, "d"), -1) + }) +} + +func Test_InArray(t *testing.T) { + gtest.Case(t, func() { + a := g.SliceStr{"a", "b", "c"} + gtest.AssertEQ(gstr.InArray(a, "a"), true) + gtest.AssertEQ(gstr.InArray(a, "b"), true) + gtest.AssertEQ(gstr.InArray(a, "c"), true) + gtest.AssertEQ(gstr.InArray(a, "d"), false) + }) +} From f69eb219b5a27a6df20ecfc59467b906f6bd5cfb Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Apr 2019 09:43:17 +0800 Subject: [PATCH 21/28] version updates --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 8668f2551..49e1a370b 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package gf -const VERSION = "v1.6.1" +const VERSION = "v1.6.2" const AUTHORS = "john" From 62ee88bbfa6d5d80d38408c14e2720e882c9726d Mon Sep 17 00:00:00 2001 From: jroam Date: Thu, 11 Apr 2019 14:45:47 +0800 Subject: [PATCH 22/28] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 037ff1e7d..505c72e16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ branches: only: - master - develop + - test_gfile env: - GO111MODULE=on From 5c04befea338ddf17cb3bc1bd204ea492fb5d486 Mon Sep 17 00:00:00 2001 From: jroam Date: Thu, 11 Apr 2019 16:39:20 +0800 Subject: [PATCH 23/28] edit ci yml file --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 505c72e16..7d8dd2329 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ install: script: - cd g + - go get -u github.com/gogf/gf - GOARCH=386 go test -v ./... - GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic From 3a1524ae6d4ed72132f8481c651c7615349ec690 Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Thu, 11 Apr 2019 17:33:52 +0800 Subject: [PATCH 24/28] =?UTF-8?q?Gmap=20=E5=88=9D=E6=B5=8B=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/gmap_z_int_bool_test.go | 87 +++++++++++++++++ g/container/gmap/gmap_z_int_int_test.go | 91 +++++++++++++++++ g/container/gmap/gmap_z_int_interface_test.go | 91 +++++++++++++++++ g/container/gmap/gmap_z_int_string_test.go | 97 +++++++++++++++++++ .../gmap_z_interface_interface_basic_test.go | 1 - g/container/gmap/gmap_z_string_bool_test.go | 85 ++++++++++++++++ g/container/gmap/gmap_z_string_int_test.go | 93 ++++++++++++++++++ .../gmap/gmap_z_string_interface_test.go | 90 +++++++++++++++++ 8 files changed, 634 insertions(+), 1 deletion(-) create mode 100644 g/container/gmap/gmap_z_int_bool_test.go create mode 100644 g/container/gmap/gmap_z_int_int_test.go create mode 100644 g/container/gmap/gmap_z_int_interface_test.go create mode 100644 g/container/gmap/gmap_z_int_string_test.go create mode 100644 g/container/gmap/gmap_z_string_bool_test.go create mode 100644 g/container/gmap/gmap_z_string_int_test.go create mode 100644 g/container/gmap/gmap_z_string_interface_test.go diff --git a/g/container/gmap/gmap_z_int_bool_test.go b/g/container/gmap/gmap_z_int_bool_test.go new file mode 100644 index 000000000..078bd3077 --- /dev/null +++ b/g/container/gmap/gmap_z_int_bool_test.go @@ -0,0 +1,87 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func getBool() bool { + return true +} +func intBoolCallBack(int, bool) bool { + return true +} +func Test_IntBoolMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewIntBoolMap() + m.Set(1, true) + + gtest.Assert(m.Get(1), true) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet(2, false), false) + gtest.Assert(m.SetIfNotExist(2, false), false) + + gtest.Assert(m.SetIfNotExist(3, false), true) + + gtest.Assert(m.Remove(2), false) + gtest.Assert(m.Contains(2), false) + + gtest.AssertIN(3, m.Keys()) + gtest.AssertIN(1, m.Keys()) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewIntBoolMapFrom(map[int]bool{1: true, 2: false}) + gtest.Assert(m2.Map(), map[int]bool{1: true, 2: false}) + m3 := gmap.NewIntBoolMapFromArray([]int{1, 2}, []bool{true, false}) + gtest.Assert(m3.Map(), map[int]bool{1: true, 2: false}) + + }) +} +func Test_IntBoolMap_Set_Fun(t *testing.T) { + m := gmap.NewIntBoolMap() + + m.GetOrSetFunc(1, getBool) + m.GetOrSetFuncLock(2, getBool) + gtest.Assert(m.Get(1), true) + gtest.Assert(m.Get(2), true) + gtest.Assert(m.SetIfNotExistFunc(1, getBool), false) + gtest.Assert(m.SetIfNotExistFuncLock(2, getBool), false) +} + +func Test_IntBoolMap_Batch(t *testing.T) { + m := gmap.NewIntBoolMap() + + m.BatchSet(map[int]bool{1: true, 2: false, 3: true}) + m.Iterator(intBoolCallBack) + gtest.Assert(m.Map(), map[int]bool{1: true, 2: false, 3: true}) + m.BatchRemove([]int{1, 2}) + gtest.Assert(m.Map(), map[int]bool{3: true}) +} + +func Test_IntBoolMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewIntBoolMapFrom(map[int]bool{1: true, 2: false}) + + m_clone := m.Clone() + m.Remove(1) + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN(1, m_clone.Keys()) + + m_clone.Remove(2) + //修改clone map,原 map 不影响 + gtest.AssertIN(2, m.Keys()) +} +func Test_IntBoolMap_Merge(t *testing.T) { + m1 := gmap.NewIntBoolMap() + m2 := gmap.NewIntBoolMap() + m1.Set(1, true) + m2.Set(2, false) + m1.Merge(m2) + gtest.Assert(m1.Map(), map[int]bool{1: true, 2: false}) +} diff --git a/g/container/gmap/gmap_z_int_int_test.go b/g/container/gmap/gmap_z_int_int_test.go new file mode 100644 index 000000000..c7151960e --- /dev/null +++ b/g/container/gmap/gmap_z_int_int_test.go @@ -0,0 +1,91 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func getInt() int { + return 123 +} +func intIntCallBack(int, int) bool { + return true +} +func Test_IntIntMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewIntIntMap() + m.Set(1, 1) + + gtest.Assert(m.Get(1), 1) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet(2, 2), 2) + gtest.Assert(m.SetIfNotExist(2, 2), false) + + gtest.Assert(m.SetIfNotExist(3, 3), true) + + gtest.Assert(m.Remove(2), 2) + gtest.Assert(m.Contains(2), false) + + gtest.AssertIN(3, m.Keys()) + gtest.AssertIN(1, m.Keys()) + gtest.AssertIN(3, m.Values()) + gtest.AssertIN(1, m.Values()) + m.Flip() + gtest.Assert(m.Map(), map[int]int{1: 1, 3: 3}) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2}) + gtest.Assert(m2.Map(), map[int]int{1: 1, 2: 2}) + m3 := gmap.NewIntIntMapFromArray([]int{1, 2}, []int{1, 2}) + gtest.Assert(m3.Map(), map[int]int{1: 1, 2: 2}) + + }) +} +func Test_IntIntMap_Set_Fun(t *testing.T) { + m := gmap.NewIntIntMap() + + m.GetOrSetFunc(1, getInt) + m.GetOrSetFuncLock(2, getInt) + gtest.Assert(m.Get(1), 123) + gtest.Assert(m.Get(2), 123) + gtest.Assert(m.SetIfNotExistFunc(1, getInt), false) + gtest.Assert(m.SetIfNotExistFuncLock(2, getInt), false) +} + +func Test_IntIntMap_Batch(t *testing.T) { + m := gmap.NewIntIntMap() + + m.BatchSet(map[int]int{1: 1, 2: 2, 3: 3}) + m.Iterator(intIntCallBack) + gtest.Assert(m.Map(), map[int]int{1: 1, 2: 2, 3: 3}) + m.BatchRemove([]int{1, 2}) + gtest.Assert(m.Map(), map[int]int{3: 3}) +} + +func Test_IntIntMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2}) + + m_clone := m.Clone() + m.Remove(1) + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN(1, m_clone.Keys()) + + m_clone.Remove(2) + //修改clone map,原 map 不影响 + gtest.AssertIN(2, m.Keys()) +} +func Test_IntIntMap_Merge(t *testing.T) { + m1 := gmap.NewIntIntMap() + m2 := gmap.NewIntIntMap() + m1.Set(1, 1) + m2.Set(2, 2) + m1.Merge(m2) + gtest.Assert(m1.Map(), map[int]int{1: 1, 2: 2}) +} diff --git a/g/container/gmap/gmap_z_int_interface_test.go b/g/container/gmap/gmap_z_int_interface_test.go new file mode 100644 index 000000000..eb5a47598 --- /dev/null +++ b/g/container/gmap/gmap_z_int_interface_test.go @@ -0,0 +1,91 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func getInterface() interface{} { + return 123 +} +func intInterfaceCallBack(int, interface{}) bool { + return true +} +func Test_IntInterfaceMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewIntInterfaceMap() + m.Set(1, 1) + + gtest.Assert(m.Get(1), 1) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet(2, "2"), "2") + gtest.Assert(m.SetIfNotExist(2, "2"), false) + + gtest.Assert(m.SetIfNotExist(3, 3), true) + + gtest.Assert(m.Remove(2), "2") + gtest.Assert(m.Contains(2), false) + + gtest.AssertIN(3, m.Keys()) + gtest.AssertIN(1, m.Keys()) + gtest.AssertIN(3, m.Values()) + gtest.AssertIN(1, m.Values()) + m.Flip() + gtest.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3}) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewIntInterfaceMapFrom(map[int]interface{}{1: 1, 2: "2"}) + gtest.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"}) + m3 := gmap.NewIntInterfaceMapFromArray([]int{1, 2}, []interface{}{1, "2"}) + gtest.Assert(m3.Map(), map[int]interface{}{1: 1, 2: "2"}) + + }) +} +func Test_IntInterfaceMap_Set_Fun(t *testing.T) { + m := gmap.NewIntInterfaceMap() + + m.GetOrSetFunc(1, getInterface) + m.GetOrSetFuncLock(2, getInterface) + gtest.Assert(m.Get(1), 123) + gtest.Assert(m.Get(2), 123) + gtest.Assert(m.SetIfNotExistFunc(1, getInterface), false) + gtest.Assert(m.SetIfNotExistFuncLock(2, getInterface), false) +} + +func Test_IntInterfaceMap_Batch(t *testing.T) { + m := gmap.NewIntInterfaceMap() + + m.BatchSet(map[int]interface{}{1: 1, 2: "2", 3: 3}) + m.Iterator(intInterfaceCallBack) + gtest.Assert(m.Map(), map[int]interface{}{1: 1, 2: "2", 3: 3}) + m.BatchRemove([]int{1, 2}) + gtest.Assert(m.Map(), map[int]interface{}{3: 3}) +} + +func Test_IntInterfaceMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewIntInterfaceMapFrom(map[int]interface{}{1: 1, 2: "2"}) + + m_clone := m.Clone() + m.Remove(1) + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN(1, m_clone.Keys()) + + m_clone.Remove(2) + //修改clone map,原 map 不影响 + gtest.AssertIN(2, m.Keys()) +} +func Test_IntInterfaceMap_Merge(t *testing.T) { + m1 := gmap.NewIntInterfaceMap() + m2 := gmap.NewIntInterfaceMap() + m1.Set(1, 1) + m2.Set(2, "2") + m1.Merge(m2) + gtest.Assert(m1.Map(), map[int]interface{}{1: 1, 2: "2"}) +} diff --git a/g/container/gmap/gmap_z_int_string_test.go b/g/container/gmap/gmap_z_int_string_test.go new file mode 100644 index 000000000..8c1ddb3f5 --- /dev/null +++ b/g/container/gmap/gmap_z_int_string_test.go @@ -0,0 +1,97 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func getString() string { + return "z" +} +func intStringCallBack(int, string) bool { + return true +} +func Test_IntStringMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewIntStringMap() + m.Set(1, "a") + + gtest.Assert(m.Get(1), "a") + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet(2, "b"), "b") + gtest.Assert(m.SetIfNotExist(2, "b"), false) + + gtest.Assert(m.SetIfNotExist(3, "c"), true) + + gtest.Assert(m.Remove(2), "b") + gtest.Assert(m.Contains(2), false) + + gtest.AssertIN(3, m.Keys()) + gtest.AssertIN(1, m.Keys()) + gtest.AssertIN("a", m.Values()) + gtest.AssertIN("c", m.Values()) + + //反转之后不成为以下 map,flip 操作只是翻转原 map + //gtest.Assert(m.Map(), map[string]int{"a": 1, "c": 3}) + m_f := gmap.NewIntStringMap() + m_f.Set(1,"2") + m_f.Flip() + gtest.Assert(m_f.Map(),map[int]string{2:"1"}) + + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewIntStringMapFrom(map[int]string{1: "a", 2: "b"}) + gtest.Assert(m2.Map(), map[int]string{1: "a", 2: "b"}) + m3 := gmap.NewIntStringMapFromArray([]int{1, 2}, []string{"a","b"}) + gtest.Assert(m3.Map(), map[int]string{1: "a", 2: "b"}) + + }) +} +func Test_IntStringMap_Set_Fun(t *testing.T) { + m := gmap.NewIntStringMap() + + m.GetOrSetFunc(1, getString) + m.GetOrSetFuncLock(2, getString) + gtest.Assert(m.Get(1), "z") + gtest.Assert(m.Get(2), "z") + gtest.Assert(m.SetIfNotExistFunc(1, getString), false) + gtest.Assert(m.SetIfNotExistFuncLock(2, getString), false) +} + +func Test_IntStringMap_Batch(t *testing.T) { + m := gmap.NewIntStringMap() + + m.BatchSet(map[int]string{1: "a", 2: "b",3:"c"}) + m.Iterator(intStringCallBack) + gtest.Assert(m.Map(), map[int]string{1: "a", 2: "b"}) + m.BatchRemove([]int{1, 2}) + gtest.Assert(m.Map(), map[int]interface{}{3: "c"}) +} + +func Test_IntStringMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewIntStringMapFrom(map[int]string{1: "a", 2: "b",3:"c"}) + + m_clone := m.Clone() + m.Remove(1) + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN(1, m_clone.Keys()) + + m_clone.Remove(2) + //修改clone map,原 map 不影响 + gtest.AssertIN(2, m.Keys()) +} +func Test_IntStringMap_Merge(t *testing.T) { + m1 := gmap.NewIntStringMap() + m2 := gmap.NewIntStringMap() + m1.Set(1, "a") + m2.Set(2, "b") + m1.Merge(m2) + gtest.Assert(m1.Map(), map[int]string{1: "a", 2: "b"}) +} diff --git a/g/container/gmap/gmap_z_interface_interface_basic_test.go b/g/container/gmap/gmap_z_interface_interface_basic_test.go index 6f23e4155..ead2dae73 100644 --- a/g/container/gmap/gmap_z_interface_interface_basic_test.go +++ b/g/container/gmap/gmap_z_interface_interface_basic_test.go @@ -17,7 +17,6 @@ func Test_Map_Basic(t *testing.T) { m := gmap.New() m.Set("key1", "val1") gtest.Assert(m.Keys(), []interface{}{"key1"}) - gtest.Assert(m.Values(), []interface{}{"val1"}) gtest.Assert(m.Get("key1"), "val1") gtest.Assert(m.Size(), 1) diff --git a/g/container/gmap/gmap_z_string_bool_test.go b/g/container/gmap/gmap_z_string_bool_test.go new file mode 100644 index 000000000..63b251ed3 --- /dev/null +++ b/g/container/gmap/gmap_z_string_bool_test.go @@ -0,0 +1,85 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + + +func StringBoolCallBack( string, bool) bool { + return true +} +func Test_StringBoolMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewStringBoolMap() + m.Set("a", true) + + gtest.Assert(m.Get("a"), true) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet("b", false), false) + gtest.Assert(m.SetIfNotExist("b", false), false) + + gtest.Assert(m.SetIfNotExist("c", false), true) + + gtest.Assert(m.Remove("b"), false) + gtest.Assert(m.Contains("b"), false) + + gtest.AssertIN("c", m.Keys()) + gtest.AssertIN("a", m.Keys()) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewStringBoolMapFrom(map[string]bool{"a": true, "b": false}) + gtest.Assert(m2.Map(), map[string]bool{"a": true, "b": false}) + m3 := gmap.NewStringBoolMapFromArray([]string{"a", "b"}, []bool{true, false}) + gtest.Assert(m3.Map(), map[string]bool{"a": true, "b": false}) + + }) +} +func Test_StringBoolMap_Set_Fun(t *testing.T) { + m := gmap.NewStringBoolMap() + + m.GetOrSetFunc("a", getBool) + m.GetOrSetFuncLock("b", getBool) + gtest.Assert(m.Get("a"), true) + gtest.Assert(m.Get("b"), true) + gtest.Assert(m.SetIfNotExistFunc("a", getBool), false) + gtest.Assert(m.SetIfNotExistFuncLock("b", getBool), false) +} + +func Test_StringBoolMap_Batch(t *testing.T) { + m := gmap.NewStringBoolMap() + + m.BatchSet(map[string]bool{"a": true, "b": false, "c": true}) + m.Iterator(StringBoolCallBack) + gtest.Assert(m.Map(), map[string]bool{"a": true, "b": false, "c": true}) + m.BatchRemove([]string{"a", "b"}) + gtest.Assert(m.Map(), map[string]bool{"c": true}) +} + +func Test_StringBoolMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewStringBoolMapFrom(map[string]bool{"a": true, "b": false}) + + m_clone := m.Clone() + m.Remove("a") + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN("a", m_clone.Keys()) + + m_clone.Remove("b") + //修改clone map,原 map 不影响 + gtest.AssertIN("b", m.Keys()) +} +func Test_StringBoolMap_Merge(t *testing.T) { + m1 := gmap.NewStringBoolMap() + m2 := gmap.NewStringBoolMap() + m1.Set("a", true) + m2.Set("b", false) + m1.Merge(m2) + gtest.Assert(m1.Map(), map[string]bool{"a": true, "b": false}) +} diff --git a/g/container/gmap/gmap_z_string_int_test.go b/g/container/gmap/gmap_z_string_int_test.go new file mode 100644 index 000000000..69892eba1 --- /dev/null +++ b/g/container/gmap/gmap_z_string_int_test.go @@ -0,0 +1,93 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + + +func stringIntCallBack(string, int) bool { + return true +} +func Test_StringIntMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewStringIntMap() + m.Set("a", 1) + + gtest.Assert(m.Get("a"), 1) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet("b", 2), 2) + gtest.Assert(m.SetIfNotExist("b", 2), false) + + gtest.Assert(m.SetIfNotExist("c", 3), true) + + gtest.Assert(m.Remove("b"), 2) + gtest.Assert(m.Contains("b"), false) + + gtest.AssertIN("c", m.Keys()) + gtest.AssertIN("a", m.Keys()) + gtest.AssertIN(3, m.Values()) + gtest.AssertIN(1, m.Values()) + + m_f := gmap.NewStringIntMap() + m_f.Set("1",2) + m_f.Flip() + gtest.Assert(m_f.Map(),map[string]int{"2":1}) + + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewStringIntMapFrom(map[string]int{"a": 1, "b": 2}) + gtest.Assert(m2.Map(), map[string]int{"a": 1, "b": 2}) + m3 := gmap.NewStringIntMapFromArray([]string{"a","b"}, []int{1, 2}) + gtest.Assert(m3.Map(), map[string]int{"a": 1, "b": 2}) + + }) +} +func Test_StringIntMap_Set_Fun(t *testing.T) { + m := gmap.NewStringIntMap() + + m.GetOrSetFunc("a", getInt) + m.GetOrSetFuncLock("b", getInt) + gtest.Assert(m.Get("a"), 123) + gtest.Assert(m.Get("b"), 123) + gtest.Assert(m.SetIfNotExistFunc("a", getInt), false) + gtest.Assert(m.SetIfNotExistFuncLock("b", getInt), false) +} + +func Test_StringIntMap_Batch(t *testing.T) { + m := gmap.NewStringIntMap() + + m.BatchSet(map[string]int{"a": 1, "b": 2,"c":3}) + m.Iterator(stringIntCallBack) + gtest.Assert(m.Map(), map[string]int{"a": 1, "b": 2,"c":3}) + m.BatchRemove([]string{"a","b"}) + gtest.Assert(m.Map(), map[string]int{"c": 3}) +} + +func Test_StringIntMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewStringIntMapFrom(map[string]int{"a": 1, "b": 2,"c":3}) + + m_clone := m.Clone() + m.Remove("a") + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN("a", m_clone.Keys()) + + m_clone.Remove("b") + //修改clone map,原 map 不影响 + gtest.AssertIN("b", m.Keys()) +} +func Test_StringIntMap_Merge(t *testing.T) { + m1 := gmap.NewStringIntMap() + m2 := gmap.NewStringIntMap() + m1.Set("a", 1) + m2.Set("b", 2) + m1.Merge(m2) + gtest.Assert(m1.Map(),map[string]int{"a": 1, "b": 2}) +} diff --git a/g/container/gmap/gmap_z_string_interface_test.go b/g/container/gmap/gmap_z_string_interface_test.go new file mode 100644 index 000000000..45407c186 --- /dev/null +++ b/g/container/gmap/gmap_z_string_interface_test.go @@ -0,0 +1,90 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + + +func stringInterfaceCallBack(string, interface{}) bool { + return true +} +func Test_StringInterfaceMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewStringInterfaceMap() + m.Set("a", 1) + + gtest.Assert(m.Get("a"), 1) + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet("b", "2"), "2") + gtest.Assert(m.SetIfNotExist("b", "2"), false) + + gtest.Assert(m.SetIfNotExist("c", 3), true) + + gtest.Assert(m.Remove("b"), "2") + gtest.Assert(m.Contains("b"), false) + + gtest.AssertIN("c", m.Keys()) + gtest.AssertIN("a", m.Keys()) + gtest.AssertIN(3, m.Values()) + gtest.AssertIN(1, m.Values()) + + m.Flip() + gtest.Assert(m.Map(), map[string]interface{}{"1": "a", "3": "c"}) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewStringInterfaceMapFrom(map[string]interface{}{"a": 1, "b": "2"}) + gtest.Assert(m2.Map(), map[string]interface{}{"a": 1, "b": "2"}) + m3 := gmap.NewStringInterfaceMapFromArray([]string{"a", "b"}, []interface{}{1, "2"}) + gtest.Assert(m3.Map(), map[string]interface{}{"a": 1, "b": "2"}) + + }) +} +func Test_StringInterfaceMap_Set_Fun(t *testing.T) { + m := gmap.NewStringInterfaceMap() + + m.GetOrSetFunc("a", getInterface) + m.GetOrSetFuncLock("b", getInterface) + gtest.Assert(m.Get("a"), 123) + gtest.Assert(m.Get("b"), 123) + gtest.Assert(m.SetIfNotExistFunc("a", getInterface), false) + gtest.Assert(m.SetIfNotExistFuncLock("b", getInterface), false) +} + +func Test_StringInterfaceMap_Batch(t *testing.T) { + m := gmap.NewStringInterfaceMap() + + m.BatchSet(map[string]interface{}{"a": 1, "b": "2","c":3}) + m.Iterator(stringInterfaceCallBack) + gtest.Assert(m.Map(), map[string]interface{}{"a": 1, "b": "2","c":3}) + m.BatchRemove([]string{"a","b"}) + gtest.Assert(m.Map(), map[string]interface{}{"c":3}) +} + +func Test_StringInterfaceMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewStringInterfaceMapFrom(map[string]interface{}{"a": 1, "b": "2"}) + + m_clone := m.Clone() + m.Remove("a") + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN("a", m_clone.Keys()) + + m_clone.Remove("b") + //修改clone map,原 map 不影响 + gtest.AssertIN("b", m.Keys()) +} +func Test_StringInterfaceMap_Merge(t *testing.T) { + m1 := gmap.NewStringInterfaceMap() + m2 := gmap.NewStringInterfaceMap() + m1.Set("a", 1) + m2.Set("b", "2") + m1.Merge(m2) + gtest.Assert(m1.Map(), map[string]interface{}{"a": 1, "b": "2"}) +} From 8e7bf1f908c6bb84e8e5a92ab9120db8534d16e4 Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Thu, 11 Apr 2019 17:46:19 +0800 Subject: [PATCH 25/28] =?UTF-8?q?bug=20=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/gmap_int_string_map.go | 288 +++++++++-------- g/container/gmap/gmap_string_int_map.go | 300 +++++++++--------- g/container/gmap/gmap_string_interface_map.go | 152 ++++----- g/container/gmap/gmap_z_int_string_test.go | 13 +- g/container/gmap/gmap_z_string_int_test.go | 18 +- .../gmap/gmap_z_string_interface_test.go | 9 +- 6 files changed, 387 insertions(+), 393 deletions(-) diff --git a/g/container/gmap/gmap_int_string_map.go b/g/container/gmap/gmap_int_string_map.go index b2bb701c7..f6290f23d 100644 --- a/g/container/gmap/gmap_int_string_map.go +++ b/g/container/gmap/gmap_int_string_map.go @@ -4,12 +4,11 @@ // If a copy of the MIT was not distributed with gm file, // You can obtain one at https://github.com/gogf/gf. - package gmap import ( - "github.com/gogf/gf/g/internal/rwmutex" - "github.com/gogf/gf/g/util/gconv" + "github.com/gogf/gf/g/internal/rwmutex" + "github.com/gogf/gf/g/util/gconv" ) type IntStringMap struct { @@ -20,21 +19,21 @@ type IntStringMap struct { // NewIntStringMap returns an empty IntStringMap object. // The param used to specify whether using map with un-concurrent-safety, // which is false in default, means concurrent-safe. -func NewIntStringMap(unsafe...bool) *IntStringMap { +func NewIntStringMap(unsafe ...bool) *IntStringMap { return &IntStringMap{ - m : make(map[int]string), - mu : rwmutex.New(unsafe...), - } + m: make(map[int]string), + mu: rwmutex.New(unsafe...), + } } // NewIntStringMapFrom returns an IntStringMap object from given map . // Notice that, the param map is a type of pointer, // there might be some concurrent-safe issues when changing the map outside. -func NewIntStringMapFrom(m map[int]string, unsafe...bool) *IntStringMap { - return &IntStringMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewIntStringMapFrom(m map[int]string, unsafe ...bool) *IntStringMap { + return &IntStringMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // NewIntStringMapFromArray returns an IntStringMap object from given array. @@ -43,37 +42,37 @@ func NewIntStringMapFrom(m map[int]string, unsafe...bool) *IntStringMap { // // If length of is greater than that of , // the corresponding overflow map values will be the default value of its type. -func NewIntStringMapFromArray(keys []int, values []string, unsafe...bool) *IntStringMap { - m := make(map[int]string) - l := len(values) - for i, k := range keys { - if i < l { - m[k] = values[i] - } else { - m[k] = "" - } - } - return &IntStringMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewIntStringMapFromArray(keys []int, values []string, unsafe ...bool) *IntStringMap { + m := make(map[int]string) + l := len(values) + for i, k := range keys { + if i < l { + m[k] = values[i] + } else { + m[k] = "" + } + } + return &IntStringMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // Iterator iterates the hash map with custom callback function . // If f returns true, then continue iterating; or false to stop. -func (gm *IntStringMap) Iterator(f func (k int, v string) bool) { - gm.mu.RLock() - defer gm.mu.RUnlock() - for k, v := range gm.m { - if !f(k, v) { - break - } - } +func (gm *IntStringMap) Iterator(f func(k int, v string) bool) { + gm.mu.RLock() + defer gm.mu.RUnlock() + for k, v := range gm.m { + if !f(k, v) { + break + } + } } // Clone returns a new hash map with copy of current map data. func (gm *IntStringMap) Clone() *IntStringMap { - return NewIntStringMapFrom(gm.Map(), !gm.mu.IsSafe()) + return NewIntStringMapFrom(gm.Map(), !gm.mu.IsSafe()) } // Map returns a copy of the data of the hash map. @@ -83,7 +82,7 @@ func (gm *IntStringMap) Map() map[int]string { for k, v := range gm.m { m[k] = v } - gm.mu.RUnlock() + gm.mu.RUnlock() return m } @@ -117,40 +116,40 @@ func (gm *IntStringMap) Get(key int) string { // // It returns value with given . func (gm *IntStringMap) doSetWithLockCheck(key int, value string) string { - gm.mu.Lock() - if v, ok := gm.m[key]; ok { - gm.mu.Unlock() - return v - } - gm.m[key] = value - gm.mu.Unlock() - return value + gm.mu.Lock() + if v, ok := gm.m[key]; ok { + gm.mu.Unlock() + return v + } + gm.m[key] = value + gm.mu.Unlock() + return value } // GetOrSet returns the value by key, // or set value with given if not exist and returns this value. func (gm *IntStringMap) GetOrSet(key int, value string) string { - gm.mu.RLock() - v, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - return gm.doSetWithLockCheck(key, value) - } else { - return v - } + gm.mu.RLock() + v, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + return gm.doSetWithLockCheck(key, value) + } else { + return v + } } // GetOrSetFunc returns the value by key, // or sets value with return value of callback function if not exist and returns this value. func (gm *IntStringMap) GetOrSetFunc(key int, f func() string) string { - gm.mu.RLock() - v, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - return gm.doSetWithLockCheck(key, f()) - } else { - return v - } + gm.mu.RLock() + v, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + return gm.doSetWithLockCheck(key, f()) + } else { + return v + } } // GetOrSetFuncLock returns the value by key, @@ -159,31 +158,31 @@ func (gm *IntStringMap) GetOrSetFunc(key int, f func() string) string { // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function // with mutex.Lock of the hash map. func (gm *IntStringMap) GetOrSetFuncLock(key int, f func() string) string { - gm.mu.RLock() - val, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - gm.mu.Lock() - defer gm.mu.Unlock() - if v, ok := gm.m[key]; ok { - return v - } - val = f() - gm.m[key] = val - return val - } else { - return val - } + gm.mu.RLock() + val, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + gm.mu.Lock() + defer gm.mu.Unlock() + if v, ok := gm.m[key]; ok { + return v + } + val = f() + gm.m[key] = val + return val + } else { + return val + } } // SetIfNotExist sets to the map if the does not exist, then return true. // It returns false if exists, and would be ignored. func (gm *IntStringMap) SetIfNotExist(key int, value string) bool { - if !gm.Contains(key) { - gm.doSetWithLockCheck(key, value) - return true - } - return false + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, value) + return true + } + return false } // SetIfNotExistFunc sets value with return value of callback function , then return true. @@ -213,117 +212,116 @@ func (gm *IntStringMap) SetIfNotExistFuncLock(key int, f func() string) bool { return false } - // BatchRemove batch deletes values of the map by keys. func (gm *IntStringMap) BatchRemove(keys []int) { - gm.mu.Lock() - for _, key := range keys { - delete(gm.m, key) - } - gm.mu.Unlock() + gm.mu.Lock() + for _, key := range keys { + delete(gm.m, key) + } + gm.mu.Unlock() } // Remove deletes value from map by given , and return this deleted value. func (gm *IntStringMap) Remove(key int) string { - gm.mu.Lock() - val, exists := gm.m[key] - if exists { - delete(gm.m, key) - } - gm.mu.Unlock() - return val + gm.mu.Lock() + val, exists := gm.m[key] + if exists { + delete(gm.m, key) + } + gm.mu.Unlock() + return val } // Keys returns all keys of the map as a slice. func (gm *IntStringMap) Keys() []int { - gm.mu.RLock() - keys := make([]int, 0) - for key, _ := range gm.m { - keys = append(keys, key) - } - gm.mu.RUnlock() - return keys + gm.mu.RLock() + keys := make([]int, 0) + for key, _ := range gm.m { + keys = append(keys, key) + } + gm.mu.RUnlock() + return keys } // Values returns all values of the map as a slice. func (gm *IntStringMap) Values() []string { - gm.mu.RLock() - vals := make([]string, 0) - for _, val := range gm.m { - vals = append(vals, val) - } - gm.mu.RUnlock() - return vals + gm.mu.RLock() + vals := make([]string, 0) + for _, val := range gm.m { + vals = append(vals, val) + } + gm.mu.RUnlock() + return vals } // Contains checks whether a key exists. // It returns true if the exists, or else false. func (gm *IntStringMap) Contains(key int) bool { - gm.mu.RLock() - _, exists := gm.m[key] - gm.mu.RUnlock() - return exists + gm.mu.RLock() + _, exists := gm.m[key] + gm.mu.RUnlock() + return exists } // Size returns the size of the map. func (gm *IntStringMap) Size() int { - gm.mu.RLock() - length := len(gm.m) - gm.mu.RUnlock() - return length + gm.mu.RLock() + length := len(gm.m) + gm.mu.RUnlock() + return length } // IsEmpty checks whether the map is empty. // It returns true if map is empty, or else false. func (gm *IntStringMap) IsEmpty() bool { - gm.mu.RLock() - empty := len(gm.m) == 0 - gm.mu.RUnlock() - return empty + gm.mu.RLock() + empty := len(gm.m) == 0 + gm.mu.RUnlock() + return empty } // Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *IntStringMap) Clear() { - gm.mu.Lock() - gm.m = make(map[int]string) - gm.mu.Unlock() + gm.mu.Lock() + gm.m = make(map[int]string) + gm.mu.Unlock() } // LockFunc locks writing with given callback function and mutex.Lock. func (gm *IntStringMap) LockFunc(f func(m map[int]string)) { - gm.mu.Lock() - defer gm.mu.Unlock() - f(gm.m) + gm.mu.Lock() + defer gm.mu.Unlock() + f(gm.m) } // RLockFunc locks reading with given callback function and mutex.RLock. func (gm *IntStringMap) RLockFunc(f func(m map[int]string)) { - gm.mu.RLock() - defer gm.mu.RUnlock() - f(gm.m) + gm.mu.RLock() + defer gm.mu.RUnlock() + f(gm.m) } // Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *IntStringMap) Flip() { - gm.mu.Lock() - defer gm.mu.Unlock() - n := make(map[int]string, len(gm.m)) - for k, v := range gm.m { - n[gconv.Int(v)] = gconv.String(k) - } - gm.m = n + gm.mu.Lock() + defer gm.mu.Unlock() + n := make(map[int]string, len(gm.m)) + for k, v := range gm.m { + n[gconv.Int(v)] = gconv.String(k) + } + gm.m = n } // Merge merges two hash maps. // The map will be merged into the map . func (gm *IntStringMap) Merge(other *IntStringMap) { - gm.mu.Lock() - defer gm.mu.Unlock() - if other != gm { - other.mu.RLock() - defer other.mu.RUnlock() - } - for k, v := range other.m { - gm.m[k] = v - } -} \ No newline at end of file + gm.mu.Lock() + defer gm.mu.Unlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() + } + for k, v := range other.m { + gm.m[k] = v + } +} diff --git a/g/container/gmap/gmap_string_int_map.go b/g/container/gmap/gmap_string_int_map.go index 052d956e3..028f82c74 100644 --- a/g/container/gmap/gmap_string_int_map.go +++ b/g/container/gmap/gmap_string_int_map.go @@ -8,8 +8,8 @@ package gmap import ( - "github.com/gogf/gf/g/internal/rwmutex" - "github.com/gogf/gf/g/util/gconv" + "github.com/gogf/gf/g/internal/rwmutex" + "github.com/gogf/gf/g/util/gconv" ) type StringIntMap struct { @@ -20,21 +20,21 @@ type StringIntMap struct { // NewStringIntMap returns an empty StringIntMap object. // The param used to specify whether using map with un-concurrent-safety, // which is false in default, means concurrent-safe. -func NewStringIntMap(unsafe...bool) *StringIntMap { +func NewStringIntMap(unsafe ...bool) *StringIntMap { return &StringIntMap{ - m : make(map[string]int), - mu : rwmutex.New(unsafe...), - } + m: make(map[string]int), + mu: rwmutex.New(unsafe...), + } } // NewStringIntMapFrom returns an StringIntMap object from given map . // Notice that, the param map is a type of pointer, // there might be some concurrent-safe issues when changing the map outside. -func NewStringIntMapFrom(m map[string]int, unsafe...bool) *StringIntMap { - return &StringIntMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewStringIntMapFrom(m map[string]int, unsafe ...bool) *StringIntMap { + return &StringIntMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // NewStringIntMapFromArray returns an StringIntMap object from given array. @@ -43,48 +43,48 @@ func NewStringIntMapFrom(m map[string]int, unsafe...bool) *StringIntMap { // // If length of is greater than that of , // the corresponding overflow map values will be the default value of its type. -func NewStringIntMapFromArray(keys []string, values []int, unsafe...bool) *StringIntMap { - m := make(map[string]int) - l := len(values) - for i, k := range keys { - if i < l { - m[k] = values[i] - } else { - m[k] = 0 - } - } - return &StringIntMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewStringIntMapFromArray(keys []string, values []int, unsafe ...bool) *StringIntMap { + m := make(map[string]int) + l := len(values) + for i, k := range keys { + if i < l { + m[k] = values[i] + } else { + m[k] = 0 + } + } + return &StringIntMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // Iterator iterates the hash map with custom callback function . // If f returns true, then continue iterating; or false to stop. -func (gm *StringIntMap) Iterator(f func (k string, v int) bool) { - gm.mu.RLock() - defer gm.mu.RUnlock() - for k, v := range gm.m { - if !f(k, v) { - break - } - } +func (gm *StringIntMap) Iterator(f func(k string, v int) bool) { + gm.mu.RLock() + defer gm.mu.RUnlock() + for k, v := range gm.m { + if !f(k, v) { + break + } + } } // Clone returns a new hash map with copy of current map data. func (gm *StringIntMap) Clone() *StringIntMap { - return NewStringIntMapFrom(gm.Map(), !gm.mu.IsSafe()) + return NewStringIntMapFrom(gm.Map(), !gm.mu.IsSafe()) } // Map returns a copy of the data of the hash map. func (gm *StringIntMap) Map() map[string]int { - m := make(map[string]int) - gm.mu.RLock() - for k, v := range gm.m { - m[k] = v - } - gm.mu.RUnlock() - return m + m := make(map[string]int) + gm.mu.RLock() + for k, v := range gm.m { + m[k] = v + } + gm.mu.RUnlock() + return m } // Set sets key-value to the hash map. @@ -107,7 +107,7 @@ func (gm *StringIntMap) BatchSet(m map[string]int) { func (gm *StringIntMap) Get(key string) int { gm.mu.RLock() val, _ := gm.m[key] - gm.mu.RUnlock() + gm.mu.RUnlock() return val } @@ -117,41 +117,41 @@ func (gm *StringIntMap) Get(key string) int { // // It returns value with given . func (gm *StringIntMap) doSetWithLockCheck(key string, value int) int { - gm.mu.Lock() - if v, ok := gm.m[key]; ok { - gm.mu.Unlock() - return v - } - gm.m[key] = value - gm.mu.Unlock() - return value + gm.mu.Lock() + if v, ok := gm.m[key]; ok { + gm.mu.Unlock() + return v + } + gm.m[key] = value + gm.mu.Unlock() + return value } // GetOrSet returns the value by key, // or set value with given if not exist and returns this value. func (gm *StringIntMap) GetOrSet(key string, value int) int { - gm.mu.RLock() - v, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - return gm.doSetWithLockCheck(key, value) - } else { - return v - } + gm.mu.RLock() + v, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + return gm.doSetWithLockCheck(key, value) + } else { + return v + } } // GetOrSetFunc returns the value by key, // or sets value with return value of callback function if not exist // and returns this value. func (gm *StringIntMap) GetOrSetFunc(key string, f func() int) int { - gm.mu.RLock() - v, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - return gm.doSetWithLockCheck(key, f()) - } else { - return v - } + gm.mu.RLock() + v, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + return gm.doSetWithLockCheck(key, f()) + } else { + return v + } } // GetOrSetFuncLock returns the value by key, @@ -161,31 +161,31 @@ func (gm *StringIntMap) GetOrSetFunc(key string, f func() int) int { // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function // with mutex.Lock of the hash map. func (gm *StringIntMap) GetOrSetFuncLock(key string, f func() int) int { - gm.mu.RLock() - val, ok := gm.m[key] - gm.mu.RUnlock() - if !ok { - gm.mu.Lock() - defer gm.mu.Unlock() - if v, ok := gm.m[key]; ok { - return v - } - val = f() - gm.m[key] = val - return val - } else { - return val - } + gm.mu.RLock() + val, ok := gm.m[key] + gm.mu.RUnlock() + if !ok { + gm.mu.Lock() + defer gm.mu.Unlock() + if v, ok := gm.m[key]; ok { + return v + } + val = f() + gm.m[key] = val + return val + } else { + return val + } } // SetIfNotExist sets to the map if the does not exist, then return true. // It returns false if exists, and would be ignored. func (gm *StringIntMap) SetIfNotExist(key string, value int) bool { - if !gm.Contains(key) { - gm.doSetWithLockCheck(key, value) - return true - } - return false + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, value) + return true + } + return false } // SetIfNotExistFunc sets value with return value of callback function , then return true. @@ -217,114 +217,114 @@ func (gm *StringIntMap) SetIfNotExistFuncLock(key string, f func() int) bool { // BatchRemove batch deletes values of the map by keys. func (gm *StringIntMap) BatchRemove(keys []string) { - gm.mu.Lock() - for _, key := range keys { - delete(gm.m, key) - } - gm.mu.Unlock() + gm.mu.Lock() + for _, key := range keys { + delete(gm.m, key) + } + gm.mu.Unlock() } // Remove deletes value from map by given , and return this deleted value. func (gm *StringIntMap) Remove(key string) int { - gm.mu.Lock() - val, exists := gm.m[key] - if exists { - delete(gm.m, key) - } - gm.mu.Unlock() - return val + gm.mu.Lock() + val, exists := gm.m[key] + if exists { + delete(gm.m, key) + } + gm.mu.Unlock() + return val } // Keys returns all keys of the map as a slice. func (gm *StringIntMap) Keys() []string { - gm.mu.RLock() - keys := make([]string, 0) - for key, _ := range gm.m { - keys = append(keys, key) - } - gm.mu.RUnlock() - return keys + gm.mu.RLock() + keys := make([]string, 0) + for key, _ := range gm.m { + keys = append(keys, key) + } + gm.mu.RUnlock() + return keys } // Values returns all values of the map as a slice. func (gm *StringIntMap) Values() []int { - gm.mu.RLock() - vals := make([]int, 0) - for _, val := range gm.m { - vals = append(vals, val) - } - gm.mu.RUnlock() - return vals + gm.mu.RLock() + vals := make([]int, 0) + for _, val := range gm.m { + vals = append(vals, val) + } + gm.mu.RUnlock() + return vals } // Contains checks whether a key exists. // It returns true if the exists, or else false. func (gm *StringIntMap) Contains(key string) bool { - gm.mu.RLock() - _, exists := gm.m[key] - gm.mu.RUnlock() - return exists + gm.mu.RLock() + _, exists := gm.m[key] + gm.mu.RUnlock() + return exists } // Size returns the size of the map. func (gm *StringIntMap) Size() int { - gm.mu.RLock() - length := len(gm.m) - gm.mu.RUnlock() - return length + gm.mu.RLock() + length := len(gm.m) + gm.mu.RUnlock() + return length } // IsEmpty checks whether the map is empty. // It returns true if map is empty, or else false. func (gm *StringIntMap) IsEmpty() bool { - gm.mu.RLock() - empty := len(gm.m) == 0 - gm.mu.RUnlock() - return empty + gm.mu.RLock() + empty := len(gm.m) == 0 + gm.mu.RUnlock() + return empty } // Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringIntMap) Clear() { - gm.mu.Lock() - gm.m = make(map[string]int) - gm.mu.Unlock() + gm.mu.Lock() + gm.m = make(map[string]int) + gm.mu.Unlock() } // LockFunc locks writing with given callback function and mutex.Lock. func (gm *StringIntMap) LockFunc(f func(m map[string]int)) { - gm.mu.Lock() - defer gm.mu.Unlock() - f(gm.m) + gm.mu.Lock() + defer gm.mu.Unlock() + f(gm.m) } // RLockFunc locks reading with given callback function and mutex.RLock. func (gm *StringIntMap) RLockFunc(f func(m map[string]int)) { - gm.mu.RLock() - defer gm.mu.RUnlock() - f(gm.m) + gm.mu.RLock() + defer gm.mu.RUnlock() + f(gm.m) } // Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *StringIntMap) Flip() { - gm.mu.Lock() - defer gm.mu.Unlock() - n := make(map[string]int, len(gm.m)) - for k, v := range gm.m { - n[gconv.String(v)] = gconv.Int(k) - } - gm.m = n + gm.mu.Lock() + defer gm.mu.Unlock() + n := make(map[string]int, len(gm.m)) + for k, v := range gm.m { + n[gconv.String(v)] = gconv.Int(k) + } + gm.m = n } // Merge merges two hash maps. // The map will be merged into the map . func (gm *StringIntMap) Merge(other *StringIntMap) { - gm.mu.Lock() - defer gm.mu.Unlock() - if other != gm { - other.mu.RLock() - defer other.mu.RUnlock() - } - for k, v := range other.m { - gm.m[k] = v - } -} \ No newline at end of file + gm.mu.Lock() + defer gm.mu.Unlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() + } + for k, v := range other.m { + gm.m[k] = v + } +} diff --git a/g/container/gmap/gmap_string_interface_map.go b/g/container/gmap/gmap_string_interface_map.go index 3fab490e9..5c354ea89 100644 --- a/g/container/gmap/gmap_string_interface_map.go +++ b/g/container/gmap/gmap_string_interface_map.go @@ -20,21 +20,21 @@ type StringInterfaceMap struct { // NewStringInterfaceMap returns an empty StringInterfaceMap object. // The param used to specify whether using map with un-concurrent-safety, // which is false in default, means concurrent-safe. -func NewStringInterfaceMap(unsafe...bool) *StringInterfaceMap { +func NewStringInterfaceMap(unsafe ...bool) *StringInterfaceMap { return &StringInterfaceMap{ - m : make(map[string]interface{}), - mu : rwmutex.New(unsafe...), + m: make(map[string]interface{}), + mu: rwmutex.New(unsafe...), } } // NewStringInterfaceMapFrom returns an StringInterfaceMap object from given map . // Notice that, the param map is a type of pointer, // there might be some concurrent-safe issues when changing the map outside. -func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe...bool) *StringInterfaceMap { - return &StringInterfaceMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe ...bool) *StringInterfaceMap { + return &StringInterfaceMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // NewStringInterfaceMapFromArray returns an StringInterfaceMap object from given array. @@ -43,25 +43,25 @@ func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe...bool) *StringI // // If length of is greater than that of , // the corresponding overflow map values will be the default value of its type. -func NewStringInterfaceMapFromArray(keys []string, values []interface{}, unsafe...bool) *StringInterfaceMap { - m := make(map[string]interface{}) - l := len(values) - for i, k := range keys { - if i < l { - m[k] = values[i] - } else { - m[k] = interface{}(nil) - } - } - return &StringInterfaceMap{ - m : m, - mu : rwmutex.New(unsafe...), - } +func NewStringInterfaceMapFromArray(keys []string, values []interface{}, unsafe ...bool) *StringInterfaceMap { + m := make(map[string]interface{}) + l := len(values) + for i, k := range keys { + if i < l { + m[k] = values[i] + } else { + m[k] = interface{}(nil) + } + } + return &StringInterfaceMap{ + m: m, + mu: rwmutex.New(unsafe...), + } } // Iterator iterates the hash map with custom callback function . // If f returns true, then continue iterating; or false to stop. -func (gm *StringInterfaceMap) Iterator(f func (k string, v interface{}) bool) { +func (gm *StringInterfaceMap) Iterator(f func(k string, v interface{}) bool) { gm.mu.RLock() defer gm.mu.RUnlock() for k, v := range gm.m { @@ -73,18 +73,18 @@ func (gm *StringInterfaceMap) Iterator(f func (k string, v interface{}) bool) { // Clone returns a new hash map with copy of current map data. func (gm *StringInterfaceMap) Clone() *StringInterfaceMap { - return NewStringInterfaceMapFrom(gm.Map(), !gm.mu.IsSafe()) + return NewStringInterfaceMapFrom(gm.Map(), !gm.mu.IsSafe()) } // Map returns a copy of the data of the hash map. func (gm *StringInterfaceMap) Map() map[string]interface{} { - m := make(map[string]interface{}) - gm.mu.RLock() - for k, v := range gm.m { - m[k] = v - } - gm.mu.RUnlock() - return m + m := make(map[string]interface{}) + gm.mu.RLock() + for k, v := range gm.m { + m[k] = v + } + gm.mu.RUnlock() + return m } // Set sets key-value to the hash map. @@ -96,11 +96,11 @@ func (gm *StringInterfaceMap) Set(key string, val interface{}) { // BatchSet batch sets key-values to the hash map. func (gm *StringInterfaceMap) BatchSet(m map[string]interface{}) { - gm.mu.Lock() - for k, v := range m { - gm.m[k] = v - } - gm.mu.Unlock() + gm.mu.Lock() + for k, v := range m { + gm.m[k] = v + } + gm.mu.Unlock() } // Get returns the value by given . @@ -123,37 +123,37 @@ func (gm *StringInterfaceMap) Get(key string) interface{} { func (gm *StringInterfaceMap) doSetWithLockCheck(key string, value interface{}) interface{} { gm.mu.Lock() defer gm.mu.Unlock() - if v, ok := gm.m[key]; ok { - return v - } - if f, ok := value.(func() interface {}); ok { - value = f() - } - if value != nil { - gm.m[key] = value - } - return value + if v, ok := gm.m[key]; ok { + return v + } + if f, ok := value.(func() interface{}); ok { + value = f() + } + if value != nil { + gm.m[key] = value + } + return value } // GetOrSet returns the value by key, // or set value with given if not exist and returns this value. func (gm *StringInterfaceMap) GetOrSet(key string, value interface{}) interface{} { - if v := gm.Get(key); v == nil { - return gm.doSetWithLockCheck(key, value) - } else { - return v - } + if v := gm.Get(key); v == nil { + return gm.doSetWithLockCheck(key, value) + } else { + return v + } } // GetOrSetFunc returns the value by key, // or sets value with return value of callback function if not exist // and returns this value. func (gm *StringInterfaceMap) GetOrSetFunc(key string, f func() interface{}) interface{} { - if v := gm.Get(key); v == nil { - return gm.doSetWithLockCheck(key, f()) - } else { - return v - } + if v := gm.Get(key); v == nil { + return gm.doSetWithLockCheck(key, f()) + } else { + return v + } } // GetOrSetFuncLock returns the value by key, @@ -163,21 +163,21 @@ func (gm *StringInterfaceMap) GetOrSetFunc(key string, f func() interface{}) int // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function // with mutex.Lock of the hash map. func (gm *StringInterfaceMap) GetOrSetFuncLock(key string, f func() interface{}) interface{} { - if v := gm.Get(key); v == nil { - return gm.doSetWithLockCheck(key, f) - } else { - return v - } + if v := gm.Get(key); v == nil { + return gm.doSetWithLockCheck(key, f) + } else { + return v + } } // SetIfNotExist sets to the map if the does not exist, then return true. // It returns false if exists, and would be ignored. func (gm *StringInterfaceMap) SetIfNotExist(key string, value interface{}) bool { - if !gm.Contains(key) { - gm.doSetWithLockCheck(key, value) - return true - } - return false + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, value) + return true + } + return false } // SetIfNotExistFunc sets value with return value of callback function , then return true. @@ -205,11 +205,11 @@ func (gm *StringInterfaceMap) SetIfNotExistFuncLock(key string, f func() interfa // BatchRemove batch deletes values of the map by keys. func (gm *StringInterfaceMap) BatchRemove(keys []string) { - gm.mu.Lock() - for _, key := range keys { - delete(gm.m, key) - } - gm.mu.Unlock() + gm.mu.Lock() + for _, key := range keys { + delete(gm.m, key) + } + gm.mu.Unlock() } // Remove deletes value from map by given , and return this deleted value. @@ -230,7 +230,7 @@ func (gm *StringInterfaceMap) Keys() []string { for key, _ := range gm.m { keys = append(keys, key) } - gm.mu.RUnlock() + gm.mu.RUnlock() return keys } @@ -273,9 +273,9 @@ func (gm *StringInterfaceMap) IsEmpty() bool { // Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringInterfaceMap) Clear() { - gm.mu.Lock() - gm.m = make(map[string]interface{}) - gm.mu.Unlock() + gm.mu.Lock() + gm.m = make(map[string]interface{}) + gm.mu.Unlock() } // LockFunc locks writing with given callback function and mutex.Lock. @@ -315,4 +315,4 @@ func (gm *StringInterfaceMap) Merge(other *StringInterfaceMap) { for k, v := range other.m { gm.m[k] = v } -} \ No newline at end of file +} diff --git a/g/container/gmap/gmap_z_int_string_test.go b/g/container/gmap/gmap_z_int_string_test.go index 8c1ddb3f5..386e3a710 100644 --- a/g/container/gmap/gmap_z_int_string_test.go +++ b/g/container/gmap/gmap_z_int_string_test.go @@ -37,10 +37,9 @@ func Test_IntStringMap_Basic(t *testing.T) { //反转之后不成为以下 map,flip 操作只是翻转原 map //gtest.Assert(m.Map(), map[string]int{"a": 1, "c": 3}) m_f := gmap.NewIntStringMap() - m_f.Set(1,"2") + m_f.Set(1, "2") m_f.Flip() - gtest.Assert(m_f.Map(),map[int]string{2:"1"}) - + gtest.Assert(m_f.Map(), map[int]string{2: "1"}) m.Clear() gtest.Assert(m.Size(), 0) @@ -48,7 +47,7 @@ func Test_IntStringMap_Basic(t *testing.T) { m2 := gmap.NewIntStringMapFrom(map[int]string{1: "a", 2: "b"}) gtest.Assert(m2.Map(), map[int]string{1: "a", 2: "b"}) - m3 := gmap.NewIntStringMapFromArray([]int{1, 2}, []string{"a","b"}) + m3 := gmap.NewIntStringMapFromArray([]int{1, 2}, []string{"a", "b"}) gtest.Assert(m3.Map(), map[int]string{1: "a", 2: "b"}) }) @@ -67,16 +66,16 @@ func Test_IntStringMap_Set_Fun(t *testing.T) { func Test_IntStringMap_Batch(t *testing.T) { m := gmap.NewIntStringMap() - m.BatchSet(map[int]string{1: "a", 2: "b",3:"c"}) + m.BatchSet(map[int]string{1: "a", 2: "b", 3: "c"}) m.Iterator(intStringCallBack) - gtest.Assert(m.Map(), map[int]string{1: "a", 2: "b"}) + gtest.Assert(m.Map(), map[int]string{1: "a", 2: "b",3: "c"}) m.BatchRemove([]int{1, 2}) gtest.Assert(m.Map(), map[int]interface{}{3: "c"}) } func Test_IntStringMap_Clone(t *testing.T) { //clone 方法是深克隆 - m := gmap.NewIntStringMapFrom(map[int]string{1: "a", 2: "b",3:"c"}) + m := gmap.NewIntStringMapFrom(map[int]string{1: "a", 2: "b", 3: "c"}) m_clone := m.Clone() m.Remove(1) diff --git a/g/container/gmap/gmap_z_string_int_test.go b/g/container/gmap/gmap_z_string_int_test.go index 69892eba1..7c1050d46 100644 --- a/g/container/gmap/gmap_z_string_int_test.go +++ b/g/container/gmap/gmap_z_string_int_test.go @@ -6,7 +6,6 @@ import ( "testing" ) - func stringIntCallBack(string, int) bool { return true } @@ -33,10 +32,9 @@ func Test_StringIntMap_Basic(t *testing.T) { gtest.AssertIN(1, m.Values()) m_f := gmap.NewStringIntMap() - m_f.Set("1",2) + m_f.Set("1", 2) m_f.Flip() - gtest.Assert(m_f.Map(),map[string]int{"2":1}) - + gtest.Assert(m_f.Map(), map[string]int{"2": 1}) m.Clear() gtest.Assert(m.Size(), 0) @@ -44,7 +42,7 @@ func Test_StringIntMap_Basic(t *testing.T) { m2 := gmap.NewStringIntMapFrom(map[string]int{"a": 1, "b": 2}) gtest.Assert(m2.Map(), map[string]int{"a": 1, "b": 2}) - m3 := gmap.NewStringIntMapFromArray([]string{"a","b"}, []int{1, 2}) + m3 := gmap.NewStringIntMapFromArray([]string{"a", "b"}, []int{1, 2}) gtest.Assert(m3.Map(), map[string]int{"a": 1, "b": 2}) }) @@ -63,16 +61,16 @@ func Test_StringIntMap_Set_Fun(t *testing.T) { func Test_StringIntMap_Batch(t *testing.T) { m := gmap.NewStringIntMap() - m.BatchSet(map[string]int{"a": 1, "b": 2,"c":3}) + m.BatchSet(map[string]int{"a": 1, "b": 2, "c": 3}) m.Iterator(stringIntCallBack) - gtest.Assert(m.Map(), map[string]int{"a": 1, "b": 2,"c":3}) - m.BatchRemove([]string{"a","b"}) + gtest.Assert(m.Map(), map[string]int{"a": 1, "b": 2, "c": 3}) + m.BatchRemove([]string{"a", "b"}) gtest.Assert(m.Map(), map[string]int{"c": 3}) } func Test_StringIntMap_Clone(t *testing.T) { //clone 方法是深克隆 - m := gmap.NewStringIntMapFrom(map[string]int{"a": 1, "b": 2,"c":3}) + m := gmap.NewStringIntMapFrom(map[string]int{"a": 1, "b": 2, "c": 3}) m_clone := m.Clone() m.Remove("a") @@ -89,5 +87,5 @@ func Test_StringIntMap_Merge(t *testing.T) { m1.Set("a", 1) m2.Set("b", 2) m1.Merge(m2) - gtest.Assert(m1.Map(),map[string]int{"a": 1, "b": 2}) + gtest.Assert(m1.Map(), map[string]int{"a": 1, "b": 2}) } diff --git a/g/container/gmap/gmap_z_string_interface_test.go b/g/container/gmap/gmap_z_string_interface_test.go index 45407c186..74e94115d 100644 --- a/g/container/gmap/gmap_z_string_interface_test.go +++ b/g/container/gmap/gmap_z_string_interface_test.go @@ -6,7 +6,6 @@ import ( "testing" ) - func stringInterfaceCallBack(string, interface{}) bool { return true } @@ -60,11 +59,11 @@ func Test_StringInterfaceMap_Set_Fun(t *testing.T) { func Test_StringInterfaceMap_Batch(t *testing.T) { m := gmap.NewStringInterfaceMap() - m.BatchSet(map[string]interface{}{"a": 1, "b": "2","c":3}) + m.BatchSet(map[string]interface{}{"a": 1, "b": "2", "c": 3}) m.Iterator(stringInterfaceCallBack) - gtest.Assert(m.Map(), map[string]interface{}{"a": 1, "b": "2","c":3}) - m.BatchRemove([]string{"a","b"}) - gtest.Assert(m.Map(), map[string]interface{}{"c":3}) + gtest.Assert(m.Map(), map[string]interface{}{"a": 1, "b": "2", "c": 3}) + m.BatchRemove([]string{"a", "b"}) + gtest.Assert(m.Map(), map[string]interface{}{"c": 3}) } func Test_StringInterfaceMap_Clone(t *testing.T) { From 905f46359a0472ba00aeb8b745658e34c8c1fd72 Mon Sep 17 00:00:00 2001 From: Jay <976739120@qq.com> Date: Thu, 11 Apr 2019 17:50:26 +0800 Subject: [PATCH 26/28] =?UTF-8?q?Gmap=20string-string=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/container/gmap/gmap_z_string_string_test.go | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 g/container/gmap/gmap_z_string_string_test.go diff --git a/g/container/gmap/gmap_z_string_string_test.go b/g/container/gmap/gmap_z_string_string_test.go new file mode 100644 index 000000000..443878839 --- /dev/null +++ b/g/container/gmap/gmap_z_string_string_test.go @@ -0,0 +1,90 @@ +package gmap_test + +import ( + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func stringStringCallBack(string, string) bool { + return true +} +func Test_StringStringMap_Basic(t *testing.T) { + gtest.Case(t, func() { + m := gmap.NewStringStringMap() + m.Set("a", "a") + + gtest.Assert(m.Get("a"), "a") + gtest.Assert(m.Size(), 1) + gtest.Assert(m.IsEmpty(), false) + + gtest.Assert(m.GetOrSet("b", "b"), "b") + gtest.Assert(m.SetIfNotExist("b", "b"), false) + + gtest.Assert(m.SetIfNotExist("c", "c"), true) + + gtest.Assert(m.Remove("b"), "b") + gtest.Assert(m.Contains("b"), false) + + gtest.AssertIN("c", m.Keys()) + gtest.AssertIN("a", m.Keys()) + gtest.AssertIN("a", m.Values()) + gtest.AssertIN("c", m.Values()) + + m.Flip() + + gtest.Assert(m.Map(), map[string]string{"a": "a", "c": "c"}) + + m.Clear() + gtest.Assert(m.Size(), 0) + gtest.Assert(m.IsEmpty(), true) + + m2 := gmap.NewStringStringMapFrom(map[string]string{"a": "a", "b": "b"}) + gtest.Assert(m2.Map(), map[string]string{"a": "a", "b": "b"}) + m3 := gmap.NewStringStringMapFromArray([]string{"a", "b"}, []string{"a", "b"}) + gtest.Assert(m3.Map(), map[string]string{"a": "a", "b": "b"}) + + }) +} +func Test_StringStringMap_Set_Fun(t *testing.T) { + m := gmap.NewStringStringMap() + + m.GetOrSetFunc("a", getString) + m.GetOrSetFuncLock("b", getString) + gtest.Assert(m.Get("a"), "z") + gtest.Assert(m.Get("b"), "z") + gtest.Assert(m.SetIfNotExistFunc("a", getString), false) + gtest.Assert(m.SetIfNotExistFuncLock("b", getString), false) +} + +func Test_StringStringMap_Batch(t *testing.T) { + m := gmap.NewStringStringMap() + + m.BatchSet(map[string]string{"a": "a", "b": "b", "c": "c"}) + m.Iterator(stringStringCallBack) + gtest.Assert(m.Map(), map[string]string{"a": "a", "b": "b", "c": "c"}) + m.BatchRemove([]string{"a", "b"}) + gtest.Assert(m.Map(), map[string]string{"c": "c"}) +} + +func Test_StringStringMap_Clone(t *testing.T) { + //clone 方法是深克隆 + m := gmap.NewStringStringMapFrom(map[string]string{"a": "a", "b": "b", "c": "c"}) + + m_clone := m.Clone() + m.Remove("a") + //修改原 map,clone 后的 map 不影响 + gtest.AssertIN("a", m_clone.Keys()) + + m_clone.Remove("b") + //修改clone map,原 map 不影响 + gtest.AssertIN("b", m.Keys()) +} +func Test_StringStringMap_Merge(t *testing.T) { + m1 := gmap.NewStringStringMap() + m2 := gmap.NewStringStringMap() + m1.Set("a", "a") + m2.Set("b", "b") + m1.Merge(m2) + gtest.Assert(m1.Map(), map[string]string{"a": "a", "b": "b"}) +} From 119a11eb8d9d0a306885b823933eb522f6325c84 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Apr 2019 23:07:22 +0800 Subject: [PATCH 27/28] README updates --- README.MD | 1 + README_ZH.MD | 1 + TODO.MD | 1 + geg/os/gtimer/gtimer-batch.go | 17 +++++++++++++++++ 4 files changed, 20 insertions(+) create mode 100644 geg/os/gtimer/gtimer-batch.go diff --git a/README.MD b/README.MD index b215dfb70..7085c7660 100644 --- a/README.MD +++ b/README.MD @@ -73,6 +73,7 @@ func main() { - [johng](https://gitee.com/johng) - [pibigstar](https://github.com/pibigstar) - [qq1054000800](https://gitee.com/qq1054000800) +- [qq976739120](https://github.com/qq976739120) - [wenzi1](https://gitee.com/wenzi1) - [wxkj001](https://github.com/wxkj001) - [ymrjqyy](https://gitee.com/ymrjqyy) diff --git a/README_ZH.MD b/README_ZH.MD index e29248375..5473bfce5 100644 --- a/README_ZH.MD +++ b/README_ZH.MD @@ -93,6 +93,7 @@ func main() { - [johng](https://gitee.com/johng) - [pibigstar](https://github.com/pibigstar) - [qq1054000800](https://gitee.com/qq1054000800) +- [qq976739120](https://github.com/qq976739120) - [wenzi1](https://gitee.com/wenzi1) - [wxkj001](https://github.com/wxkj001) - [ymrjqyy](https://gitee.com/ymrjqyy) diff --git a/TODO.MD b/TODO.MD index a86547377..e456a8c6c 100644 --- a/TODO.MD +++ b/TODO.MD @@ -43,6 +43,7 @@ 1. 添加Save/Replace/BatchSave/BatchReplace方法对sqlite数据库的支持; 1. 添加sqlite数据库的单元测试用例; 1. gredis增加cluster支持; +1. gset.Add/Remove/Contains方法增加批量操作支持; # DONE 1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换; diff --git a/geg/os/gtimer/gtimer-batch.go b/geg/os/gtimer/gtimer-batch.go new file mode 100644 index 000000000..c5d8dcfb9 --- /dev/null +++ b/geg/os/gtimer/gtimer-batch.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + "github.com/gogf/gf/g/os/gtimer" + "time" +) + +func main() { + for i := 0; i < 100000; i++ { + gtimer.Add(time.Second, func() { + + }) + } + fmt.Println("start") + time.Sleep(48*time.Hour) +} From 8a32a8271cea9c9d97f77efcba3345d6c7b53106 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 Apr 2019 00:19:15 +0800 Subject: [PATCH 28/28] fix issue in empty router group error of ghttp.Server --- g/net/ghttp/ghttp_server_router_group.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/g/net/ghttp/ghttp_server_router_group.go b/g/net/ghttp/ghttp_server_router_group.go index cd90806f8..ad3dd3f2d 100644 --- a/g/net/ghttp/ghttp_server_router_group.go +++ b/g/net/ghttp/ghttp_server_router_group.go @@ -26,13 +26,13 @@ type GroupItem = []interface{} // 获取分组路由对象 func (s *Server) Group(prefix...string) *RouterGroup { + group := &RouterGroup{ + server : s, + } if len(prefix) > 0 { - return &RouterGroup{ - server : s, - prefix : prefix[0], - } + group.prefix = prefix[0] } - return &RouterGroup{} + return group } // 获取分组路由对象