mirror of
https://gitee.com/johng/gf
synced 2026-07-02 19:31:07 +08:00
fix issue in session expiring for file storage of gsession; add Pop/Pops functions for gset/gmap
This commit is contained in:
@ -9,7 +9,7 @@ import (
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.SetSessionMaxAge(2 * time.Second)
|
||||
s.SetSessionMaxAge(61 * time.Second)
|
||||
s.BindHandler("/set", func(r *ghttp.Request) {
|
||||
r.Session.Set("time", gtime.Second())
|
||||
r.Response.Write("ok")
|
||||
|
||||
@ -141,6 +141,41 @@ func (m *AnyAnyMap) Get(key interface{}) interface{} {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *AnyAnyMap) Pop() (key, value interface{}) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *AnyAnyMap) Pops(size int) map[interface{}]interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[interface{}]interface{}, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -321,10 +356,7 @@ func (m *AnyAnyMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *AnyAnyMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -141,6 +141,41 @@ func (m *IntAnyMap) Get(key int) interface{} {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *IntAnyMap) Pop() (key int, value interface{}) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *IntAnyMap) Pops(size int) map[int]interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[int]interface{}, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -321,10 +356,7 @@ func (m *IntAnyMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *IntAnyMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -139,6 +139,41 @@ func (m *IntIntMap) Get(key int) int {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *IntIntMap) Pop() (key, value int) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *IntIntMap) Pops(size int) map[int]int {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[int]int, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -298,10 +333,7 @@ func (m *IntIntMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *IntIntMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -139,6 +139,41 @@ func (m *IntStrMap) Get(key int) string {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *IntStrMap) Pop() (key int, value string) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *IntStrMap) Pops(size int) map[int]string {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[int]string, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -298,10 +333,7 @@ func (m *IntStrMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *IntStrMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -135,6 +135,41 @@ func (m *StrAnyMap) Get(key string) interface{} {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *StrAnyMap) Pop() (key string, value interface{}) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *StrAnyMap) Pops(size int) map[string]interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[string]interface{}, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -317,10 +352,7 @@ func (m *StrAnyMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *StrAnyMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -139,6 +139,41 @@ func (m *StrIntMap) Get(key string) int {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *StrIntMap) Pop() (key string, value int) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *StrIntMap) Pops(size int) map[string]int {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[string]int, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -300,10 +335,7 @@ func (m *StrIntMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *StrIntMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -139,6 +139,41 @@ func (m *StrStrMap) Get(key string) string {
|
||||
return val
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *StrStrMap) Pop() (key, value string) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for key, value = range m.data {
|
||||
delete(m.data, key)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *StrStrMap) Pops(size int) map[string]string {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[string]string, size)
|
||||
for k, v := range m.data {
|
||||
delete(m.data, k)
|
||||
newMap[k] = v
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
@ -300,10 +335,7 @@ func (m *StrStrMap) Size() int {
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *StrStrMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
|
||||
@ -189,6 +189,45 @@ func (m *ListMap) Get(key interface{}) (value interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
// Pop retrieves and deletes an item from the map.
|
||||
func (m *ListMap) Pop() (key, value interface{}) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
for k, e := range m.data {
|
||||
value = e.Value.(*gListMapNode).value
|
||||
delete(m.data, k)
|
||||
m.list.Remove(e)
|
||||
return k, value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Pops retrieves and deletes <size> items from the map.
|
||||
// It returns all items if size == -1.
|
||||
func (m *ListMap) Pops(size int) map[interface{}]interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if size > len(m.data) || size == -1 {
|
||||
size = len(m.data)
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
newMap := make(map[interface{}]interface{}, size)
|
||||
for k, e := range m.data {
|
||||
value := e.Value.(*gListMapNode).value
|
||||
delete(m.data, k)
|
||||
m.list.Remove(e)
|
||||
newMap[k] = value
|
||||
index++
|
||||
if index == size {
|
||||
break
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"testing"
|
||||
@ -221,3 +222,56 @@ func Test_AnyAnyMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get("k2"), data["k2"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AnyAnyMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AnyAnyMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
"k3": "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -203,3 +204,56 @@ func Test_IntAnyMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get(2), data[2])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntAnyMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
|
||||
1: "v1",
|
||||
2: "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{1, 2})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{1, 2})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntAnyMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
|
||||
1: "v1",
|
||||
2: "v2",
|
||||
3: "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -206,3 +207,56 @@ func Test_IntIntMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get(2), data[2])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntIntMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntIntMapFrom(g.MapIntInt{
|
||||
1: 11,
|
||||
2: 22,
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{1, 2})
|
||||
gtest.AssertIN(v1, g.Slice{11, 22})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{1, 2})
|
||||
gtest.AssertIN(v2, g.Slice{11, 22})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntIntMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntIntMapFrom(g.MapIntInt{
|
||||
1: 11,
|
||||
2: 22,
|
||||
3: 33,
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{11, 22, 33})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{11, 22, 33})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -207,3 +208,56 @@ func Test_IntStrMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get(2), data[2])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntStrMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntStrMapFrom(g.MapIntStr{
|
||||
1: "v1",
|
||||
2: "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{1, 2})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{1, 2})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_IntStrMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewIntStrMapFrom(g.MapIntStr{
|
||||
1: "v1",
|
||||
2: "v2",
|
||||
3: "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{1, 2, 3})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"testing"
|
||||
|
||||
@ -177,3 +178,56 @@ func Test_ListMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get("k2"), data["k2"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ListMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewListMapFrom(g.MapAnyAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ListMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewListMapFrom(g.MapAnyAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
"k3": "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -215,3 +216,56 @@ func Test_StrAnyMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get("k2"), data["k2"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrAnyMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrAnyMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
"k3": "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -218,3 +219,56 @@ func Test_StrIntMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get("k2"), data["k2"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrIntMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrIntMapFrom(g.MapStrInt{
|
||||
"k1": 11,
|
||||
"k2": 22,
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v1, g.Slice{11, 22})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v2, g.Slice{11, 22})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrIntMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrIntMapFrom(g.MapStrInt{
|
||||
"k1": 11,
|
||||
"k2": 22,
|
||||
"k3": 33,
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{11, 22, 33})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{11, 22, 33})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gmap_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
@ -215,3 +216,56 @@ func Test_StrStrMap_Json(t *testing.T) {
|
||||
gtest.Assert(m.Get("k2"), data["k2"])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrStrMap_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrStrMapFrom(g.MapStrStr{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
gtest.Assert(m.Size(), 2)
|
||||
|
||||
k1, v1 := m.Pop()
|
||||
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 1)
|
||||
k2, v2 := m.Pop()
|
||||
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
|
||||
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.AssertNE(k1, k2)
|
||||
gtest.AssertNE(v1, v2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_StrStrMap_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewStrStrMapFrom(g.MapStrStr{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
"k3": "v3",
|
||||
})
|
||||
gtest.Assert(m.Size(), 3)
|
||||
|
||||
kArray := garray.New()
|
||||
vArray := garray.New()
|
||||
for k, v := range m.Pops(1) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 2)
|
||||
for k, v := range m.Pops(2) {
|
||||
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
|
||||
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
|
||||
kArray.Append(k)
|
||||
vArray.Append(v)
|
||||
}
|
||||
gtest.Assert(m.Size(), 0)
|
||||
|
||||
gtest.Assert(kArray.Unique().Len(), 3)
|
||||
gtest.Assert(vArray.Unique().Len(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -373,24 +373,30 @@ func (set *Set) Sum() (sum int) {
|
||||
|
||||
// Pops randomly pops an item from set.
|
||||
func (set *Set) Pop() interface{} {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
return k
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pops randomly pops <size> items from set.
|
||||
// It returns all items if size == -1.
|
||||
func (set *Set) Pops(size int) []interface{} {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
if size > len(set.data) {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if size > len(set.data) || size == -1 {
|
||||
size = len(set.data)
|
||||
}
|
||||
if size <= 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
array := make([]interface{}, size)
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
array[index] = k
|
||||
index++
|
||||
if index == size {
|
||||
|
||||
@ -346,24 +346,30 @@ func (set *IntSet) Sum() (sum int) {
|
||||
|
||||
// Pops randomly pops an item from set.
|
||||
func (set *IntSet) Pop() int {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
return k
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Pops randomly pops <size> items from set.
|
||||
// It returns all items if size == -1.
|
||||
func (set *IntSet) Pops(size int) []int {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
if size > len(set.data) {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if size > len(set.data) || size == -1 {
|
||||
size = len(set.data)
|
||||
}
|
||||
if size <= 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
array := make([]int, size)
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
array[index] = k
|
||||
index++
|
||||
if index == size {
|
||||
|
||||
@ -360,24 +360,30 @@ func (set *StrSet) Sum() (sum int) {
|
||||
|
||||
// Pops randomly pops an item from set.
|
||||
func (set *StrSet) Pop() string {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
return k
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Pops randomly pops <size> items from set.
|
||||
// It returns all items if size == -1.
|
||||
func (set *StrSet) Pops(size int) []string {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
if size > len(set.data) {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if size > len(set.data) || size == -1 {
|
||||
size = len(set.data)
|
||||
}
|
||||
if size <= 0 {
|
||||
return nil
|
||||
}
|
||||
index := 0
|
||||
array := make([]string, size)
|
||||
for k, _ := range set.data {
|
||||
delete(set.data, k)
|
||||
array[index] = k
|
||||
index++
|
||||
if index == size {
|
||||
|
||||
@ -261,19 +261,35 @@ func TestSet_Sum(t *testing.T) {
|
||||
|
||||
func TestSet_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s1 := gset.New(true)
|
||||
s1.Add(1).Add(2).Add(3).Add(4)
|
||||
gtest.AssertIN(s1.Pop(), []int{1, 2, 3, 4})
|
||||
s := gset.New(true)
|
||||
s.Add(1).Add(2).Add(3).Add(4)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.AssertIN(s.Pop(), []int{1, 2, 3, 4})
|
||||
gtest.Assert(s.Size(), 3)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSet_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s1 := gset.New(true)
|
||||
s1.Add(1).Add(2).Add(3).Add(4)
|
||||
gtest.AssertIN(s1.Pops(1), []int{1, 2, 3, 4})
|
||||
gtest.AssertIN(s1.Pops(6), []int{1, 2, 3, 4})
|
||||
gtest.Assert(len(s1.Pops(2)), 2)
|
||||
s := gset.New(true)
|
||||
s.Add(1).Add(2).Add(3).Add(4)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.Assert(s.Pops(0), nil)
|
||||
gtest.AssertIN(s.Pops(1), []int{1, 2, 3, 4})
|
||||
gtest.Assert(s.Size(), 3)
|
||||
a := s.Pops(6)
|
||||
gtest.Assert(len(a), 3)
|
||||
gtest.AssertIN(a, []int{1, 2, 3, 4})
|
||||
gtest.Assert(s.Size(), 0)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.New(true)
|
||||
a := []interface{}{1, 2, 3, 4}
|
||||
s.Add(a...)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.Assert(s.Pops(-2), nil)
|
||||
gtest.AssertIN(s.Pops(-1), a)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -223,11 +223,36 @@ func TestIntSet_Sum(t *testing.T) {
|
||||
|
||||
func TestIntSet_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s1 := gset.NewIntSet()
|
||||
s1.Add(4).Add(2).Add(3)
|
||||
gtest.AssertIN(s1.Pop(), []int{4, 2, 3})
|
||||
gtest.AssertIN(s1.Pop(), []int{4, 2, 3})
|
||||
gtest.Assert(s1.Size(), 3)
|
||||
s := gset.NewIntSet()
|
||||
s.Add(4).Add(2).Add(3)
|
||||
gtest.Assert(s.Size(), 3)
|
||||
gtest.AssertIN(s.Pop(), []int{4, 2, 3})
|
||||
gtest.AssertIN(s.Pop(), []int{4, 2, 3})
|
||||
gtest.Assert(s.Size(), 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntSet_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewIntSet()
|
||||
s.Add(1).Add(4).Add(2).Add(3)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.Assert(s.Pops(0), nil)
|
||||
gtest.AssertIN(s.Pops(1), []int{1, 4, 2, 3})
|
||||
gtest.Assert(s.Size(), 3)
|
||||
a := s.Pops(2)
|
||||
gtest.Assert(len(a), 2)
|
||||
gtest.AssertIN(a, []int{1, 4, 2, 3})
|
||||
gtest.Assert(s.Size(), 1)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewIntSet(true)
|
||||
a := []int{1, 2, 3, 4}
|
||||
s.Add(a...)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.Assert(s.Pops(-2), nil)
|
||||
gtest.AssertIN(s.Pops(-1), a)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -259,20 +259,36 @@ func TestStrSet_Remove(t *testing.T) {
|
||||
|
||||
func TestStrSet_Pop(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
|
||||
str1 := s1.Pop()
|
||||
gtest.Assert(strings.Contains("a,b,c", str1), true)
|
||||
a := []string{"a", "b", "c", "d"}
|
||||
s := gset.NewStrSetFrom(a, true)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.AssertIN(s.Pop(), a)
|
||||
gtest.Assert(s.Size(), 3)
|
||||
gtest.AssertIN(s.Pop(), a)
|
||||
gtest.Assert(s.Size(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrSet_Pops(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
|
||||
strs1 := s1.Pops(2)
|
||||
gtest.AssertIN(strs1, []string{"a", "b", "c"})
|
||||
gtest.Assert(len(strs1), 2)
|
||||
str2 := s1.Pops(7)
|
||||
gtest.AssertIN(str2, []string{"a", "b", "c"})
|
||||
a := []string{"a", "b", "c", "d"}
|
||||
s := gset.NewStrSetFrom(a, true)
|
||||
array := s.Pops(2)
|
||||
gtest.Assert(len(array), 2)
|
||||
gtest.Assert(s.Size(), 2)
|
||||
gtest.AssertIN(array, a)
|
||||
gtest.Assert(s.Pops(0), nil)
|
||||
gtest.AssertIN(s.Pops(2), a)
|
||||
gtest.Assert(s.Size(), 0)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewStrSet(true)
|
||||
a := []string{"1", "2", "3", "4"}
|
||||
s.Add(a...)
|
||||
gtest.Assert(s.Size(), 4)
|
||||
gtest.Assert(s.Pops(-2), nil)
|
||||
gtest.AssertIN(s.Pops(-1), a)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ type Storage interface {
|
||||
RemoveAll() error
|
||||
|
||||
// GetSession returns the session data map for given session id.
|
||||
// The parameter specifies the TTL for this session.
|
||||
// The parameter <ttl> specifies the TTL for this session.
|
||||
// It returns nil if the TTL is exceeded.
|
||||
GetSession(id string, ttl time.Duration) map[string]interface{}
|
||||
// SetSession updates the data map for specified session id.
|
||||
|
||||
@ -72,8 +72,13 @@ func NewStorageFile(path ...string) *StorageFile {
|
||||
cryptoEnabled: DefaultStorageFileCryptoEnabled,
|
||||
updatingIdSet: gset.NewStrSet(true),
|
||||
}
|
||||
// Batch updates the TTL for session ids timely.
|
||||
gtimer.AddSingleton(DefaultStorageFileLoopInterval, func() {
|
||||
for _, id := range s.updatingIdSet.Slice() {
|
||||
id := ""
|
||||
for {
|
||||
if id = s.updatingIdSet.Pop(); id == "" {
|
||||
break
|
||||
}
|
||||
s.doUpdateTTL(id)
|
||||
}
|
||||
})
|
||||
@ -160,7 +165,6 @@ func (s *StorageFile) GetSession(id string, ttl time.Duration) map[string]interf
|
||||
}
|
||||
|
||||
// SetSession updates the content for session id.
|
||||
// Note that the parameter <content> is the serialized bytes for session map.
|
||||
func (s *StorageFile) SetSession(id string, data map[string]interface{}) error {
|
||||
path := s.sessionFilePath(id)
|
||||
content, err := json.Marshal(data)
|
||||
|
||||
Reference in New Issue
Block a user