diff --git a/container/gmap/gmap_z_unit_any_any_test.go b/container/gmap/gmap_z_unit_any_any_test.go index 37520c728..88fd41daa 100644 --- a/container/gmap/gmap_z_unit_any_any_test.go +++ b/container/gmap/gmap_z_unit_any_any_test.go @@ -17,8 +17,34 @@ import ( "github.com/gogf/gf/test/gtest" ) -func anyAnyCallBack(int, interface{}) bool { - return true +func Test_AnyAnyMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.AnyAnyMap + m.Set(1, 1) + + t.Assert(m.Get(1), 1) + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet(2, "2"), "2") + t.Assert(m.SetIfNotExist(2, "2"), false) + + t.Assert(m.SetIfNotExist(3, 3), true) + + t.Assert(m.Remove(2), "2") + t.Assert(m.Contains(2), false) + + t.AssertIN(3, m.Keys()) + t.AssertIN(1, m.Keys()) + t.AssertIN(3, m.Values()) + t.AssertIN(1, m.Values()) + m.Flip() + t.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } func Test_AnyAnyMap_Basic(t *testing.T) { diff --git a/container/gmap/gmap_z_unit_int_any_test.go b/container/gmap/gmap_z_unit_int_any_test.go index 9bf922ed7..125596992 100644 --- a/container/gmap/gmap_z_unit_int_any_test.go +++ b/container/gmap/gmap_z_unit_int_any_test.go @@ -20,9 +20,37 @@ import ( func getAny() interface{} { return 123 } -func intAnyCallBack(int, interface{}) bool { - return true + +func Test_IntAnyMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.IntAnyMap + m.Set(1, 1) + + t.Assert(m.Get(1), 1) + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet(2, "2"), "2") + t.Assert(m.SetIfNotExist(2, "2"), false) + + t.Assert(m.SetIfNotExist(3, 3), true) + + t.Assert(m.Remove(2), "2") + t.Assert(m.Contains(2), false) + + t.AssertIN(3, m.Keys()) + t.AssertIN(1, m.Keys()) + t.AssertIN(3, m.Values()) + t.AssertIN(1, m.Values()) + m.Flip() + t.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } + func Test_IntAnyMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntAnyMap() @@ -55,6 +83,7 @@ func Test_IntAnyMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"}) }) } + func Test_IntAnyMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntAnyMap() diff --git a/container/gmap/gmap_z_unit_int_int_test.go b/container/gmap/gmap_z_unit_int_int_test.go index 5a37ddcc2..ae7092c14 100644 --- a/container/gmap/gmap_z_unit_int_int_test.go +++ b/container/gmap/gmap_z_unit_int_int_test.go @@ -20,9 +20,41 @@ import ( func getInt() int { return 123 } + func intIntCallBack(int, int) bool { return true } + +func Test_IntIntMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.IntIntMap + m.Set(1, 1) + + t.Assert(m.Get(1), 1) + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet(2, 2), 2) + t.Assert(m.SetIfNotExist(2, 2), false) + + t.Assert(m.SetIfNotExist(3, 3), true) + + t.Assert(m.Remove(2), 2) + t.Assert(m.Contains(2), false) + + t.AssertIN(3, m.Keys()) + t.AssertIN(1, m.Keys()) + t.AssertIN(3, m.Values()) + t.AssertIN(1, m.Values()) + m.Flip() + t.Assert(m.Map(), map[int]int{1: 1, 3: 3}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) +} + func Test_IntIntMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntIntMap() @@ -55,6 +87,7 @@ func Test_IntIntMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[int]int{1: 1, 2: 2}) }) } + func Test_IntIntMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntIntMap() diff --git a/container/gmap/gmap_z_unit_int_str_test.go b/container/gmap/gmap_z_unit_int_str_test.go index 47622c24b..1312684ea 100644 --- a/container/gmap/gmap_z_unit_int_str_test.go +++ b/container/gmap/gmap_z_unit_int_str_test.go @@ -20,9 +20,40 @@ import ( func getStr() string { return "z" } -func intStrCallBack(int, string) bool { - return true + +func Test_IntStrMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.IntStrMap + m.Set(1, "a") + + t.Assert(m.Get(1), "a") + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet(2, "b"), "b") + t.Assert(m.SetIfNotExist(2, "b"), false) + + t.Assert(m.SetIfNotExist(3, "c"), true) + + t.Assert(m.Remove(2), "b") + t.Assert(m.Contains(2), false) + + t.AssertIN(3, m.Keys()) + t.AssertIN(1, m.Keys()) + t.AssertIN("a", m.Values()) + t.AssertIN("c", m.Values()) + + m_f := gmap.NewIntStrMap() + m_f.Set(1, "2") + m_f.Flip() + t.Assert(m_f.Map(), map[int]string{2: "1"}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } + func Test_IntStrMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntStrMap() @@ -60,6 +91,7 @@ func Test_IntStrMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[int]string{1: "a", 2: "b"}) }) } + func Test_IntStrMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewIntStrMap() diff --git a/container/gmap/gmap_z_unit_list_map_test.go b/container/gmap/gmap_z_unit_list_map_test.go index ec8feb4c2..564321c1c 100644 --- a/container/gmap/gmap_z_unit_list_map_test.go +++ b/container/gmap/gmap_z_unit_list_map_test.go @@ -17,6 +17,38 @@ import ( "github.com/gogf/gf/test/gtest" ) +func Test_ListMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.ListMap + m.Set("key1", "val1") + t.Assert(m.Keys(), []interface{}{"key1"}) + + t.Assert(m.Get("key1"), "val1") + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet("key2", "val2"), "val2") + t.Assert(m.SetIfNotExist("key2", "val2"), false) + + t.Assert(m.SetIfNotExist("key3", "val3"), true) + t.Assert(m.Remove("key2"), "val2") + t.Assert(m.Contains("key2"), false) + + t.AssertIN("key3", m.Keys()) + t.AssertIN("key1", m.Keys()) + t.AssertIN("val3", m.Values()) + t.AssertIN("val1", m.Values()) + + m.Flip() + + t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) +} + func Test_ListMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewListMap() @@ -51,6 +83,7 @@ func Test_ListMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) }) } + func Test_ListMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewListMap() diff --git a/container/gmap/gmap_z_unit_str_any_test.go b/container/gmap/gmap_z_unit_str_any_test.go index 04965342f..a2159a38c 100644 --- a/container/gmap/gmap_z_unit_str_any_test.go +++ b/container/gmap/gmap_z_unit_str_any_test.go @@ -17,9 +17,37 @@ import ( "github.com/gogf/gf/test/gtest" ) -func stringAnyCallBack(string, interface{}) bool { - return true +func Test_StrAnyMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.StrAnyMap + m.Set("a", 1) + + t.Assert(m.Get("a"), 1) + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet("b", "2"), "2") + t.Assert(m.SetIfNotExist("b", "2"), false) + + t.Assert(m.SetIfNotExist("c", 3), true) + + t.Assert(m.Remove("b"), "2") + t.Assert(m.Contains("b"), false) + + t.AssertIN("c", m.Keys()) + t.AssertIN("a", m.Keys()) + t.AssertIN(3, m.Values()) + t.AssertIN(1, m.Values()) + + m.Flip() + t.Assert(m.Map(), map[string]interface{}{"1": "a", "3": "c"}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } + func Test_StrAnyMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrAnyMap() @@ -53,6 +81,7 @@ func Test_StrAnyMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[string]interface{}{"a": 1, "b": "2"}) }) } + func Test_StrAnyMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrAnyMap() diff --git a/container/gmap/gmap_z_unit_str_int_test.go b/container/gmap/gmap_z_unit_str_int_test.go index b20f23040..22a87e94f 100644 --- a/container/gmap/gmap_z_unit_str_int_test.go +++ b/container/gmap/gmap_z_unit_str_int_test.go @@ -17,9 +17,39 @@ import ( "github.com/gogf/gf/test/gtest" ) -func stringIntCallBack(string, int) bool { - return true +func Test_StrIntMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.StrIntMap + m.Set("a", 1) + + t.Assert(m.Get("a"), 1) + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet("b", 2), 2) + t.Assert(m.SetIfNotExist("b", 2), false) + + t.Assert(m.SetIfNotExist("c", 3), true) + + t.Assert(m.Remove("b"), 2) + t.Assert(m.Contains("b"), false) + + t.AssertIN("c", m.Keys()) + t.AssertIN("a", m.Keys()) + t.AssertIN(3, m.Values()) + t.AssertIN(1, m.Values()) + + m_f := gmap.NewStrIntMap() + m_f.Set("1", 2) + m_f.Flip() + t.Assert(m_f.Map(), map[string]int{"2": 1}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } + func Test_StrIntMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrIntMap() @@ -55,6 +85,7 @@ func Test_StrIntMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[string]int{"a": 1, "b": 2}) }) } + func Test_StrIntMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrIntMap() diff --git a/container/gmap/gmap_z_unit_str_str_test.go b/container/gmap/gmap_z_unit_str_str_test.go index f18ecc98e..d452b1648 100644 --- a/container/gmap/gmap_z_unit_str_str_test.go +++ b/container/gmap/gmap_z_unit_str_str_test.go @@ -17,9 +17,38 @@ import ( "github.com/gogf/gf/test/gtest" ) -func stringStrCallBack(string, string) bool { - return true +func Test_StrStrMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.StrStrMap + m.Set("a", "a") + + t.Assert(m.Get("a"), "a") + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet("b", "b"), "b") + t.Assert(m.SetIfNotExist("b", "b"), false) + + t.Assert(m.SetIfNotExist("c", "c"), true) + + t.Assert(m.Remove("b"), "b") + t.Assert(m.Contains("b"), false) + + t.AssertIN("c", m.Keys()) + t.AssertIN("a", m.Keys()) + t.AssertIN("a", m.Values()) + t.AssertIN("c", m.Values()) + + m.Flip() + + t.Assert(m.Map(), map[string]string{"a": "a", "c": "c"}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) } + func Test_StrStrMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrStrMap() @@ -54,6 +83,7 @@ func Test_StrStrMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[string]string{"a": "a", "b": "b"}) }) } + func Test_StrStrMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewStrStrMap() diff --git a/container/gmap/gmap_z_unit_tree_map_test.go b/container/gmap/gmap_z_unit_tree_map_test.go index 6e623722f..611482d31 100644 --- a/container/gmap/gmap_z_unit_tree_map_test.go +++ b/container/gmap/gmap_z_unit_tree_map_test.go @@ -17,6 +17,39 @@ import ( "github.com/gogf/gf/util/gutil" ) +func Test_TreeMap_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var m gmap.TreeMap + m.SetComparator(gutil.ComparatorString) + m.Set("key1", "val1") + t.Assert(m.Keys(), []interface{}{"key1"}) + + t.Assert(m.Get("key1"), "val1") + t.Assert(m.Size(), 1) + t.Assert(m.IsEmpty(), false) + + t.Assert(m.GetOrSet("key2", "val2"), "val2") + t.Assert(m.SetIfNotExist("key2", "val2"), false) + + t.Assert(m.SetIfNotExist("key3", "val3"), true) + + t.Assert(m.Remove("key2"), "val2") + t.Assert(m.Contains("key2"), false) + + t.AssertIN("key3", m.Keys()) + t.AssertIN("key1", m.Keys()) + t.AssertIN("val3", m.Values()) + t.AssertIN("val1", m.Values()) + + m.Flip() + t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"}) + + m.Clear() + t.Assert(m.Size(), 0) + t.Assert(m.IsEmpty(), true) + }) +} + func Test_TreeMap_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewTreeMap(gutil.ComparatorString) @@ -51,6 +84,7 @@ func Test_TreeMap_Basic(t *testing.T) { t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) }) } + func Test_TreeMap_Set_Fun(t *testing.T) { gtest.C(t, func(t *gtest.T) { m := gmap.NewTreeMap(gutil.ComparatorString) diff --git a/container/gset/gset_any_set.go b/container/gset/gset_any_set.go index 175329546..760af79e8 100644 --- a/container/gset/gset_any_set.go +++ b/container/gset/gset_any_set.go @@ -16,7 +16,7 @@ import ( ) type Set struct { - mu *rwmutex.RWMutex + mu rwmutex.RWMutex data map[interface{}]struct{} } @@ -31,7 +31,7 @@ func New(safe ...bool) *Set { func NewSet(safe ...bool) *Set { return &Set{ data: make(map[interface{}]struct{}), - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), } } @@ -44,7 +44,7 @@ func NewFrom(items interface{}, safe ...bool) *Set { } return &Set{ data: m, - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), } } @@ -64,6 +64,9 @@ func (set *Set) Iterator(f func(v interface{}) bool) *Set { // Add adds one or multiple items to the set. func (set *Set) Add(item ...interface{}) *Set { set.mu.Lock() + if set.data == nil { + set.data = make(map[interface{}]struct{}) + } for _, v := range item { set.data[v] = struct{}{} } @@ -102,6 +105,9 @@ func (set *Set) AddIfNotExistFuncLock(item interface{}, f func() interface{}) *S func (set *Set) doAddWithLockCheck(item interface{}, value interface{}) interface{} { set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[interface{}]struct{}) + } if _, ok := set.data[item]; !ok && value != nil { if f, ok := value.(func() interface{}); ok { item = f() @@ -117,16 +123,21 @@ func (set *Set) doAddWithLockCheck(item interface{}, value interface{}) interfac // Contains checks whether the set contains . func (set *Set) Contains(item interface{}) bool { + var ok bool set.mu.RLock() - _, exists := set.data[item] + if set.data != nil { + _, ok = set.data[item] + } set.mu.RUnlock() - return exists + return ok } // Remove deletes from set. func (set *Set) Remove(item interface{}) *Set { set.mu.Lock() - delete(set.data, item) + if set.data != nil { + delete(set.data, item) + } set.mu.Unlock() return set } @@ -150,8 +161,10 @@ func (set *Set) Clear() *Set { // Slice returns the a of items of the set as slice. func (set *Set) Slice() []interface{} { set.mu.RLock() - i := 0 - ret := make([]interface{}, len(set.data)) + var ( + i = 0 + ret = make([]interface{}, len(set.data)) + ) for item := range set.data { ret[i] = item i++ @@ -164,9 +177,14 @@ func (set *Set) Slice() []interface{} { func (set *Set) Join(glue string) string { set.mu.RLock() defer set.mu.RUnlock() - buffer := bytes.NewBuffer(nil) - l := len(set.data) - i := 0 + if len(set.data) == 0 { + return "" + } + var ( + l = len(set.data) + i = 0 + buffer = bytes.NewBuffer(nil) + ) for k, _ := range set.data { buffer.WriteString(gconv.String(k)) if i != l-1 { @@ -181,11 +199,13 @@ func (set *Set) Join(glue string) string { func (set *Set) String() string { set.mu.RLock() defer set.mu.RUnlock() - buffer := bytes.NewBuffer(nil) + var ( + s = "" + l = len(set.data) + i = 0 + buffer = bytes.NewBuffer(nil) + ) buffer.WriteByte('[') - s := "" - l := len(set.data) - i := 0 for k, _ := range set.data { s = gconv.String(k) if gstr.IsNumeric(s) { @@ -256,7 +276,7 @@ func (set *Set) IsSubsetOf(other *Set) bool { // Union returns a new set which is the union of and . // Which means, all the items in are in or in . func (set *Set) Union(others ...*Set) (newSet *Set) { - newSet = NewSet(true) + newSet = NewSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -282,7 +302,7 @@ func (set *Set) Union(others ...*Set) (newSet *Set) { // Diff returns a new set which is the difference set from to . // Which means, all the items in are in but not in . func (set *Set) Diff(others ...*Set) (newSet *Set) { - newSet = NewSet(true) + newSet = NewSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -303,7 +323,7 @@ func (set *Set) Diff(others ...*Set) (newSet *Set) { // Intersect returns a new set which is the intersection from to . // Which means, all the items in are in and also in . func (set *Set) Intersect(others ...*Set) (newSet *Set) { - newSet = NewSet(true) + newSet = NewSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -328,7 +348,7 @@ func (set *Set) Intersect(others ...*Set) (newSet *Set) { // It returns the difference between and // if the given set is not the full set of . func (set *Set) Complement(full *Set) (newSet *Set) { - newSet = NewSet(true) + newSet = NewSet() set.mu.RLock() defer set.mu.RUnlock() if set != full { @@ -415,12 +435,11 @@ func (set *Set) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. func (set *Set) UnmarshalJSON(b []byte) error { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[interface{}]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[interface{}]struct{}) + } var array []interface{} if err := json.Unmarshal(b, &array); err != nil { return err @@ -433,12 +452,11 @@ func (set *Set) UnmarshalJSON(b []byte) error { // UnmarshalValue is an interface implement which sets any type of value for set. func (set *Set) UnmarshalValue(value interface{}) (err error) { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[interface{}]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[interface{}]struct{}) + } var array []interface{} switch value.(type) { case string, []byte: diff --git a/container/gset/gset_int_set.go b/container/gset/gset_int_set.go index f853700a3..e458b7868 100644 --- a/container/gset/gset_int_set.go +++ b/container/gset/gset_int_set.go @@ -15,7 +15,7 @@ import ( ) type IntSet struct { - mu *rwmutex.RWMutex + mu rwmutex.RWMutex data map[int]struct{} } @@ -24,7 +24,7 @@ type IntSet struct { // which is false in default. func NewIntSet(safe ...bool) *IntSet { return &IntSet{ - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), data: make(map[int]struct{}), } } @@ -36,7 +36,7 @@ func NewIntSetFrom(items []int, safe ...bool) *IntSet { m[v] = struct{}{} } return &IntSet{ - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), data: m, } } @@ -57,6 +57,9 @@ func (set *IntSet) Iterator(f func(v int) bool) *IntSet { // Add adds one or multiple items to the set. func (set *IntSet) Add(item ...int) *IntSet { set.mu.Lock() + if set.data == nil { + set.data = make(map[int]struct{}) + } for _, v := range item { set.data[v] = struct{}{} } @@ -95,6 +98,9 @@ func (set *IntSet) AddIfNotExistFuncLock(item int, f func() int) *IntSet { func (set *IntSet) doAddWithLockCheck(item int, value interface{}) int { set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[int]struct{}) + } if _, ok := set.data[item]; !ok && value != nil { if f, ok := value.(func() int); ok { item = f() @@ -108,16 +114,21 @@ func (set *IntSet) doAddWithLockCheck(item int, value interface{}) int { // Contains checks whether the set contains . func (set *IntSet) Contains(item int) bool { + var ok bool set.mu.RLock() - _, exists := set.data[item] + if set.data != nil { + _, ok = set.data[item] + } set.mu.RUnlock() - return exists + return ok } // Remove deletes from set. func (set *IntSet) Remove(item int) *IntSet { set.mu.Lock() - delete(set.data, item) + if set.data != nil { + delete(set.data, item) + } set.mu.Unlock() return set } @@ -141,8 +152,10 @@ func (set *IntSet) Clear() *IntSet { // Slice returns the a of items of the set as slice. func (set *IntSet) Slice() []int { set.mu.RLock() - ret := make([]int, len(set.data)) - i := 0 + var ( + i = 0 + ret = make([]int, len(set.data)) + ) for k, _ := range set.data { ret[i] = k i++ @@ -155,9 +168,14 @@ func (set *IntSet) Slice() []int { func (set *IntSet) Join(glue string) string { set.mu.RLock() defer set.mu.RUnlock() - buffer := bytes.NewBuffer(nil) - l := len(set.data) - i := 0 + if len(set.data) == 0 { + return "" + } + var ( + l = len(set.data) + i = 0 + buffer = bytes.NewBuffer(nil) + ) for k, _ := range set.data { buffer.WriteString(gconv.String(k)) if i != l-1 { @@ -227,7 +245,7 @@ func (set *IntSet) IsSubsetOf(other *IntSet) bool { // Union returns a new set which is the union of and . // Which means, all the items in are in or in . func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) { - newSet = NewIntSet(true) + newSet = NewIntSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -253,7 +271,7 @@ func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) { // Diff returns a new set which is the difference set from to . // Which means, all the items in are in but not in . func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) { - newSet = NewIntSet(true) + newSet = NewIntSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -274,7 +292,7 @@ func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) { // Intersect returns a new set which is the intersection from to . // Which means, all the items in are in and also in . func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) { - newSet = NewIntSet(true) + newSet = NewIntSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -299,7 +317,7 @@ func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) { // It returns the difference between and // if the given set is not the full set of . func (set *IntSet) Complement(full *IntSet) (newSet *IntSet) { - newSet = NewIntSet(true) + newSet = NewIntSet() set.mu.RLock() defer set.mu.RUnlock() if set != full { @@ -386,12 +404,11 @@ func (set *IntSet) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. func (set *IntSet) UnmarshalJSON(b []byte) error { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[int]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[int]struct{}) + } var array []int if err := json.Unmarshal(b, &array); err != nil { return err @@ -404,12 +421,11 @@ func (set *IntSet) UnmarshalJSON(b []byte) error { // UnmarshalValue is an interface implement which sets any type of value for set. func (set *IntSet) UnmarshalValue(value interface{}) (err error) { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[int]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[int]struct{}) + } var array []int switch value.(type) { case string, []byte: diff --git a/container/gset/gset_str_set.go b/container/gset/gset_str_set.go index cd4ce4723..e7fd5f3ad 100644 --- a/container/gset/gset_str_set.go +++ b/container/gset/gset_str_set.go @@ -16,7 +16,7 @@ import ( ) type StrSet struct { - mu *rwmutex.RWMutex + mu rwmutex.RWMutex data map[string]struct{} } @@ -25,7 +25,7 @@ type StrSet struct { // which is false in default. func NewStrSet(safe ...bool) *StrSet { return &StrSet{ - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), data: make(map[string]struct{}), } } @@ -37,7 +37,7 @@ func NewStrSetFrom(items []string, safe ...bool) *StrSet { m[v] = struct{}{} } return &StrSet{ - mu: rwmutex.New(safe...), + mu: rwmutex.Create(safe...), data: m, } } @@ -58,6 +58,9 @@ func (set *StrSet) Iterator(f func(v string) bool) *StrSet { // Add adds one or multiple items to the set. func (set *StrSet) Add(item ...string) *StrSet { set.mu.Lock() + if set.data == nil { + set.data = make(map[string]struct{}) + } for _, v := range item { set.data[v] = struct{}{} } @@ -96,6 +99,9 @@ func (set *StrSet) AddIfNotExistFuncLock(item string, f func() string) *StrSet { func (set *StrSet) doAddWithLockCheck(item string, value interface{}) string { set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[string]struct{}) + } if _, ok := set.data[item]; !ok && value != nil { if f, ok := value.(func() string); ok { item = f() @@ -111,16 +117,21 @@ func (set *StrSet) doAddWithLockCheck(item string, value interface{}) string { // Contains checks whether the set contains . func (set *StrSet) Contains(item string) bool { + var ok bool set.mu.RLock() - _, exists := set.data[item] + if set.data != nil { + _, ok = set.data[item] + } set.mu.RUnlock() - return exists + return ok } // Remove deletes from set. func (set *StrSet) Remove(item string) *StrSet { set.mu.Lock() - delete(set.data, item) + if set.data != nil { + delete(set.data, item) + } set.mu.Unlock() return set } @@ -144,8 +155,10 @@ func (set *StrSet) Clear() *StrSet { // Slice returns the a of items of the set as slice. func (set *StrSet) Slice() []string { set.mu.RLock() - ret := make([]string, len(set.data)) - i := 0 + var ( + i = 0 + ret = make([]string, len(set.data)) + ) for item := range set.data { ret[i] = item i++ @@ -159,9 +172,14 @@ func (set *StrSet) Slice() []string { func (set *StrSet) Join(glue string) string { set.mu.RLock() defer set.mu.RUnlock() - buffer := bytes.NewBuffer(nil) - l := len(set.data) - i := 0 + if len(set.data) == 0 { + return "" + } + var ( + l = len(set.data) + i = 0 + buffer = bytes.NewBuffer(nil) + ) for k, _ := range set.data { buffer.WriteString(k) if i != l-1 { @@ -176,9 +194,11 @@ func (set *StrSet) Join(glue string) string { func (set *StrSet) String() string { set.mu.RLock() defer set.mu.RUnlock() - buffer := bytes.NewBuffer(nil) - l := len(set.data) - i := 0 + var ( + l = len(set.data) + i = 0 + buffer = bytes.NewBuffer(nil) + ) for k, _ := range set.data { buffer.WriteString(`"` + gstr.QuoteMeta(k, `"\`) + `"`) if i != l-1 { @@ -243,7 +263,7 @@ func (set *StrSet) IsSubsetOf(other *StrSet) bool { // Union returns a new set which is the union of and . // Which means, all the items in are in or in . func (set *StrSet) Union(others ...*StrSet) (newSet *StrSet) { - newSet = NewStrSet(true) + newSet = NewStrSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -269,7 +289,7 @@ func (set *StrSet) Union(others ...*StrSet) (newSet *StrSet) { // Diff returns a new set which is the difference set from to . // Which means, all the items in are in but not in . func (set *StrSet) Diff(others ...*StrSet) (newSet *StrSet) { - newSet = NewStrSet(true) + newSet = NewStrSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -290,7 +310,7 @@ func (set *StrSet) Diff(others ...*StrSet) (newSet *StrSet) { // Intersect returns a new set which is the intersection from to . // Which means, all the items in are in and also in . func (set *StrSet) Intersect(others ...*StrSet) (newSet *StrSet) { - newSet = NewStrSet(true) + newSet = NewStrSet() set.mu.RLock() defer set.mu.RUnlock() for _, other := range others { @@ -315,7 +335,7 @@ func (set *StrSet) Intersect(others ...*StrSet) (newSet *StrSet) { // It returns the difference between and // if the given set is not the full set of . func (set *StrSet) Complement(full *StrSet) (newSet *StrSet) { - newSet = NewStrSet(true) + newSet = NewStrSet() set.mu.RLock() defer set.mu.RUnlock() if set != full { @@ -402,12 +422,11 @@ func (set *StrSet) MarshalJSON() ([]byte, error) { // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. func (set *StrSet) UnmarshalJSON(b []byte) error { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[string]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[string]struct{}) + } var array []string if err := json.Unmarshal(b, &array); err != nil { return err @@ -420,12 +439,11 @@ func (set *StrSet) UnmarshalJSON(b []byte) error { // UnmarshalValue is an interface implement which sets any type of value for set. func (set *StrSet) UnmarshalValue(value interface{}) (err error) { - if set.mu == nil { - set.mu = rwmutex.New() - set.data = make(map[string]struct{}) - } set.mu.Lock() defer set.mu.Unlock() + if set.data == nil { + set.data = make(map[string]struct{}) + } var array []string switch value.(type) { case string, []byte: diff --git a/container/gset/gset_z_unit_any_test.go b/container/gset/gset_z_unit_any_test.go index 583d17332..ac5ecea73 100644 --- a/container/gset/gset_z_unit_any_test.go +++ b/container/gset/gset_z_unit_any_test.go @@ -21,6 +21,26 @@ import ( "testing" ) +func TestSet_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s gset.Set + s.Add(1).Add(1).Add(2) + s.Add([]interface{}{3, 4}...) + t.Assert(s.Size(), 4) + t.AssertIN(1, s.Slice()) + t.AssertIN(2, s.Slice()) + t.AssertIN(3, s.Slice()) + t.AssertIN(4, s.Slice()) + t.AssertNI(0, s.Slice()) + t.Assert(s.Contains(4), true) + t.Assert(s.Contains(5), false) + s.Remove(1) + t.Assert(s.Size(), 3) + s.Clear() + t.Assert(s.Size(), 0) + }) +} + func TestSet_New(t *testing.T) { gtest.C(t, func(t *gtest.T) { s := gset.New() diff --git a/container/gset/gset_z_unit_int_test.go b/container/gset/gset_z_unit_int_test.go index ee36c7805..6180f6228 100644 --- a/container/gset/gset_z_unit_int_test.go +++ b/container/gset/gset_z_unit_int_test.go @@ -20,6 +20,26 @@ import ( "github.com/gogf/gf/test/gtest" ) +func TestIntSet_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s gset.IntSet + s.Add(1).Add(1).Add(2) + s.Add([]int{3, 4}...) + t.Assert(s.Size(), 4) + t.AssertIN(1, s.Slice()) + t.AssertIN(2, s.Slice()) + t.AssertIN(3, s.Slice()) + t.AssertIN(4, s.Slice()) + t.AssertNI(0, s.Slice()) + t.Assert(s.Contains(4), true) + t.Assert(s.Contains(5), false) + s.Remove(1) + t.Assert(s.Size(), 3) + s.Clear() + t.Assert(s.Size(), 0) + }) +} + func TestIntSet_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { s := gset.NewIntSet() diff --git a/container/gset/gset_z_unit_str_test.go b/container/gset/gset_z_unit_str_test.go index 7f0fbb3a6..14acabdfa 100644 --- a/container/gset/gset_z_unit_str_test.go +++ b/container/gset/gset_z_unit_str_test.go @@ -20,6 +20,26 @@ import ( "github.com/gogf/gf/test/gtest" ) +func TestStrSet_Var(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s gset.StrSet + s.Add("1").Add("1").Add("2") + s.Add([]string{"3", "4"}...) + t.Assert(s.Size(), 4) + t.AssertIN("1", s.Slice()) + t.AssertIN("2", s.Slice()) + t.AssertIN("3", s.Slice()) + t.AssertIN("4", s.Slice()) + t.AssertNI("0", s.Slice()) + t.Assert(s.Contains("4"), true) + t.Assert(s.Contains("5"), false) + s.Remove("1") + t.Assert(s.Size(), 3) + s.Clear() + t.Assert(s.Size(), 0) + }) +} + func TestStrSet_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { s := gset.NewStrSet() diff --git a/container/gvar/gvar.go b/container/gvar/gvar.go index fb8349d29..a3e310658 100644 --- a/container/gvar/gvar.go +++ b/container/gvar/gvar.go @@ -54,11 +54,13 @@ func (v *Var) Clone() *Var { // Set sets to , and returns the old value. func (v *Var) Set(value interface{}) (old interface{}) { if v.safe { - old = v.value.(*gtype.Interface).Set(value) - } else { - old = v.value - v.value = value + if t, ok := v.value.(*gtype.Interface); ok { + old = t.Set(value) + return + } } + old = v.value + v.value = value return } @@ -68,7 +70,9 @@ func (v *Var) Val() interface{} { return nil } if v.safe { - return v.value.(*gtype.Interface).Val() + if t, ok := v.value.(*gtype.Interface); ok { + return t.Val() + } } return v.value }