From dbb51a93286143df1be51a2006b451250d047911 Mon Sep 17 00:00:00 2001 From: john Date: Thu, 4 Jun 2020 20:13:33 +0800 Subject: [PATCH] improve package glist --- container/glist/glist.go | 166 ++++++++++++++++++++------ container/glist/glist_example_test.go | 28 ++++- container/glist/glist_z_unit_test.go | 19 ++- os/gtime/gtime.go | 2 + util/gconv/gconv.go | 2 + 5 files changed, 174 insertions(+), 43 deletions(-) diff --git a/container/glist/glist.go b/container/glist/glist.go index 30f53581e..d347fbddf 100644 --- a/container/glist/glist.go +++ b/container/glist/glist.go @@ -12,7 +12,6 @@ import ( "bytes" "container/list" "encoding/json" - "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/internal/rwmutex" @@ -23,7 +22,7 @@ type ( // The switch should be set when its initialization and cannot be changed then. List struct { mu rwmutex.RWMutex - list list.List + list *list.List } // Element the item type of the list. Element = list.Element @@ -33,7 +32,7 @@ type ( func New(safe ...bool) *List { return &List{ mu: rwmutex.Create(safe...), - list: list.List{}, + list: list.New(), } } @@ -41,7 +40,7 @@ func New(safe ...bool) *List { // The parameter is used to specify whether using list in concurrent-safety, // which is false in default. func NewFrom(array []interface{}, safe ...bool) *List { - l := list.List{} + l := list.New() for _, v := range array { l.PushBack(v) } @@ -54,6 +53,9 @@ func NewFrom(array []interface{}, safe ...bool) *List { // PushFront inserts a new element with value at the front of list and returns . func (l *List) PushFront(v interface{}) (e *Element) { l.mu.Lock() + if l.list == nil { + l.list = list.New() + } e = l.list.PushFront(v) l.mu.Unlock() return @@ -62,6 +64,9 @@ func (l *List) PushFront(v interface{}) (e *Element) { // PushBack inserts a new element with value at the back of list and returns . func (l *List) PushBack(v interface{}) (e *Element) { l.mu.Lock() + if l.list == nil { + l.list = list.New() + } e = l.list.PushBack(v) l.mu.Unlock() return @@ -70,6 +75,9 @@ func (l *List) PushBack(v interface{}) (e *Element) { // PushFronts inserts multiple new elements with values at the front of list . func (l *List) PushFronts(values []interface{}) { l.mu.Lock() + if l.list == nil { + l.list = list.New() + } for _, v := range values { l.list.PushFront(v) } @@ -79,6 +87,9 @@ func (l *List) PushFronts(values []interface{}) { // PushBacks inserts multiple new elements with values at the back of list . func (l *List) PushBacks(values []interface{}) { l.mu.Lock() + if l.list == nil { + l.list = list.New() + } for _, v := range values { l.list.PushBack(v) } @@ -88,20 +99,28 @@ func (l *List) PushBacks(values []interface{}) { // PopBack removes the element from back of and returns the value of the element. func (l *List) PopBack() (value interface{}) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + return + } if e := l.list.Back(); e != nil { value = l.list.Remove(e) } - l.mu.Unlock() return } // PopFront removes the element from front of and returns the value of the element. func (l *List) PopFront() (value interface{}) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + return + } if e := l.list.Front(); e != nil { value = l.list.Remove(e) } - l.mu.Unlock() return } @@ -109,6 +128,11 @@ func (l *List) PopFront() (value interface{}) { // and returns values of the removed elements as slice. func (l *List) PopBacks(max int) (values []interface{}) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + return + } length := l.list.Len() if length > 0 { if max > 0 && max < length { @@ -119,7 +143,6 @@ func (l *List) PopBacks(max int) (values []interface{}) { values[i] = l.list.Remove(l.list.Back()) } } - l.mu.Unlock() return } @@ -127,6 +150,11 @@ func (l *List) PopBacks(max int) (values []interface{}) { // and returns values of the removed elements as slice. func (l *List) PopFronts(max int) (values []interface{}) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + return + } length := l.list.Len() if length > 0 { if max > 0 && max < length { @@ -137,7 +165,6 @@ func (l *List) PopFronts(max int) (values []interface{}) { values[i] = l.list.Remove(l.list.Front()) } } - l.mu.Unlock() return } @@ -156,6 +183,10 @@ func (l *List) PopFrontAll() []interface{} { // FrontAll copies and returns values of all elements from front of as slice. func (l *List) FrontAll() (values []interface{}) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } length := l.list.Len() if length > 0 { values = make([]interface{}, length) @@ -163,13 +194,16 @@ func (l *List) FrontAll() (values []interface{}) { values[i] = e.Value } } - l.mu.RUnlock() return } // BackAll copies and returns values of all elements from back of as slice. func (l *List) BackAll() (values []interface{}) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } length := l.list.Len() if length > 0 { values = make([]interface{}, length) @@ -177,43 +211,54 @@ func (l *List) BackAll() (values []interface{}) { values[i] = e.Value } } - l.mu.RUnlock() return } // FrontValue returns value of the first element of or nil if the list is empty. func (l *List) FrontValue() (value interface{}) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } if e := l.list.Front(); e != nil { value = e.Value } - l.mu.RUnlock() return } // BackValue returns value of the last element of or nil if the list is empty. func (l *List) BackValue() (value interface{}) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } if e := l.list.Back(); e != nil { value = e.Value } - l.mu.RUnlock() return } // Front returns the first element of list or nil if the list is empty. func (l *List) Front() (e *Element) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } e = l.list.Front() - l.mu.RUnlock() return } // Back returns the last element of list or nil if the list is empty. func (l *List) Back() (e *Element) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } e = l.list.Back() - l.mu.RUnlock() return } @@ -221,8 +266,11 @@ func (l *List) Back() (e *Element) { // The complexity is O(1). func (l *List) Len() (length int) { l.mu.RLock() + defer l.mu.RUnlock() + if l.list == nil { + return + } length = l.list.Len() - l.mu.RUnlock() return } @@ -236,8 +284,11 @@ func (l *List) Size() int { // The element and

must not be nil. func (l *List) MoveBefore(e, p *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } l.list.MoveBefore(e, p) - l.mu.Unlock() } // MoveAfter moves element to its new position after

. @@ -245,8 +296,11 @@ func (l *List) MoveBefore(e, p *Element) { // The element and

must not be nil. func (l *List) MoveAfter(e, p *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } l.list.MoveAfter(e, p) - l.mu.Unlock() } // MoveToFront moves element to the front of list . @@ -254,8 +308,11 @@ func (l *List) MoveAfter(e, p *Element) { // The element must not be nil. func (l *List) MoveToFront(e *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } l.list.MoveToFront(e) - l.mu.Unlock() } // MoveToBack moves element to the back of list . @@ -263,8 +320,11 @@ func (l *List) MoveToFront(e *Element) { // The element must not be nil. func (l *List) MoveToBack(e *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } l.list.MoveToBack(e) - l.mu.Unlock() } // PushBackList inserts a copy of an other list at the back of list . @@ -275,8 +335,11 @@ func (l *List) PushBackList(other *List) { defer other.mu.RUnlock() } l.mu.Lock() - l.list.PushBackList(&other.list) - l.mu.Unlock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } + l.list.PushBackList(other.list) } // PushFrontList inserts a copy of an other list at the front of list . @@ -287,8 +350,11 @@ func (l *List) PushFrontList(other *List) { defer other.mu.RUnlock() } l.mu.Lock() - l.list.PushFrontList(&other.list) - l.mu.Unlock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } + l.list.PushFrontList(other.list) } // InsertAfter inserts a new element with value immediately after

and returns . @@ -296,8 +362,11 @@ func (l *List) PushFrontList(other *List) { // The

must not be nil. func (l *List) InsertAfter(p *Element, v interface{}) (e *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } e = l.list.InsertAfter(v, p) - l.mu.Unlock() return } @@ -306,8 +375,11 @@ func (l *List) InsertAfter(p *Element, v interface{}) (e *Element) { // The

must not be nil. func (l *List) InsertBefore(p *Element, v interface{}) (e *Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } e = l.list.InsertBefore(v, p) - l.mu.Unlock() return } @@ -316,25 +388,31 @@ func (l *List) InsertBefore(p *Element, v interface{}) (e *Element) { // The element must not be nil. func (l *List) Remove(e *Element) (value interface{}) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } value = l.list.Remove(e) - l.mu.Unlock() return } // Removes removes multiple elements from if are elements of list . func (l *List) Removes(es []*Element) { l.mu.Lock() + defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } for _, e := range es { l.list.Remove(e) } - l.mu.Unlock() return } // RemoveAll removes all elements from list . func (l *List) RemoveAll() { l.mu.Lock() - l.list = list.List{} + l.list = list.New() l.mu.Unlock() } @@ -347,14 +425,19 @@ func (l *List) Clear() { func (l *List) RLockFunc(f func(list *list.List)) { l.mu.RLock() defer l.mu.RUnlock() - f(&l.list) + if l.list != nil { + f(l.list) + } } // LockFunc locks writing with given callback function within RWMutex.Lock. func (l *List) LockFunc(f func(list *list.List)) { l.mu.Lock() defer l.mu.Unlock() - f(&l.list) + if l.list == nil { + l.list = list.New() + } + f(l.list) } // Iterator is alias of IteratorAsc. @@ -367,6 +450,9 @@ func (l *List) Iterator(f func(e *Element) bool) { func (l *List) IteratorAsc(f func(e *Element) bool) { l.mu.RLock() defer l.mu.RUnlock() + if l.list == nil { + return + } length := l.list.Len() if length > 0 { for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() { @@ -382,6 +468,9 @@ func (l *List) IteratorAsc(f func(e *Element) bool) { func (l *List) IteratorDesc(f func(e *Element) bool) { l.mu.RLock() defer l.mu.RUnlock() + if l.list == nil { + return + } length := l.list.Len() if length > 0 { for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() { @@ -396,17 +485,14 @@ func (l *List) IteratorDesc(f func(e *Element) bool) { func (l *List) Join(glue string) string { l.mu.RLock() defer l.mu.RUnlock() + if l.list == nil { + return "" + } buffer := bytes.NewBuffer(nil) length := l.list.Len() if length > 0 { - s := "" for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() { - s = gconv.String(e.Value) - if gstr.IsNumeric(s) { - buffer.WriteString(s) - } else { - buffer.WriteString(`"` + gstr.QuoteMeta(s, `"\`) + `"`) - } + buffer.WriteString(gconv.String(e.Value)) if i != length-1 { buffer.WriteString(glue) } @@ -429,6 +515,9 @@ func (l *List) MarshalJSON() ([]byte, error) { func (l *List) UnmarshalJSON(b []byte) error { l.mu.Lock() defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } var array []interface{} if err := json.Unmarshal(b, &array); err != nil { return err @@ -441,6 +530,9 @@ func (l *List) UnmarshalJSON(b []byte) error { func (l *List) UnmarshalValue(value interface{}) (err error) { l.mu.Lock() defer l.mu.Unlock() + if l.list == nil { + l.list = list.New() + } var array []interface{} switch value.(type) { case string, []byte: diff --git a/container/glist/glist_example_test.go b/container/glist/glist_example_test.go index 56d52caec..37fa37f92 100644 --- a/container/glist/glist_example_test.go +++ b/container/glist/glist_example_test.go @@ -10,6 +10,7 @@ import ( "container/list" "fmt" "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/frame/g" "github.com/gogf/gf/container/glist" ) @@ -96,5 +97,30 @@ func Example_iterate() { //10987654321 //12345678910 //10987654321 - //[1,2,3,4,5,"M",7,8,9,10] + //[1,2,3,4,5,M,7,8,9,10] +} + +func Example_popItem() { + l := glist.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9}) + + fmt.Println(l.PopBack()) + fmt.Println(l.PopBacks(2)) + fmt.Println(l.PopFront()) + fmt.Println(l.PopFronts(2)) + + // Output: + // 9 + // [8 7] + // 1 + // [2 3] +} + +func Example_join() { + var l glist.List + l.PushBacks(g.Slice{"a", "b", "c", "d"}) + + fmt.Println(l.Join(",")) + + // Output: + // a,b,c,d } diff --git a/container/glist/glist_z_unit_test.go b/container/glist/glist_z_unit_test.go index cd8b662cc..63b5d1d22 100644 --- a/container/glist/glist_z_unit_test.go +++ b/container/glist/glist_z_unit_test.go @@ -15,7 +15,6 @@ import ( "testing" ) -// 检查链表长度 func checkListLen(t *gtest.T, l *List, len int) bool { if n := l.Len(); n != len { t.Errorf("l.Len() = %d, want %d", n, len) @@ -24,7 +23,6 @@ func checkListLen(t *gtest.T, l *List, len int) bool { return true } -// 检查指针地址 func checkListPointers(t *gtest.T, l *List, es []*Element) { if !checkListLen(t, l, len(es)) { return @@ -605,6 +603,17 @@ func TestList_Removes(t *testing.T) { }) } +func TestList_Pop(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + l := NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9}) + + t.Assert(l.PopBack(), 9) + t.Assert(l.PopBacks(2), []interface{}{8, 7}) + t.Assert(l.PopFront(), 1) + t.Assert(l.PopFronts(2), []interface{}{2, 3}) + }) +} + func TestList_Clear(t *testing.T) { gtest.C(t, func(t *gtest.T) { l := New() @@ -672,15 +681,15 @@ func TestList_Iterator(t *testing.T) { func TestList_Join(t *testing.T) { gtest.C(t, func(t *gtest.T) { l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`}) - t.Assert(l.Join(","), `1,2,"a","\"b\"","\\c"`) - t.Assert(l.Join("."), `1.2."a"."\"b\""."\\c"`) + t.Assert(l.Join(","), `1,2,a,"b",\c`) + t.Assert(l.Join("."), `1.2.a."b".\c`) }) } func TestList_String(t *testing.T) { gtest.C(t, func(t *gtest.T) { l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`}) - t.Assert(l.String(), `[1,2,"a","\"b\"","\\c"]`) + t.Assert(l.String(), `[1,2,a,"b",\c]`) }) } diff --git a/os/gtime/gtime.go b/os/gtime/gtime.go index db64b747f..709aed8aa 100644 --- a/os/gtime/gtime.go +++ b/os/gtime/gtime.go @@ -5,6 +5,8 @@ // You can obtain one at https://github.com/gogf/gf. // Package gtime provides functionality for measuring and displaying time. +// +// This package should keep much less dependencies with other packages. package gtime import ( diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index cfc0bdda0..115fe37f2 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -5,6 +5,8 @@ // You can obtain one at https://github.com/gogf/gf. // Package gconv implements powerful and convenient converting functionality for any types of variables. +// +// This package should keep much less dependencies with other packages. package gconv import (