From 7bebf062be230dfaee8be46f02b43c3c17012c57 Mon Sep 17 00:00:00 2001
From: hailaz <739476267@qq.com>
Date: Tue, 18 Jun 2019 11:46:43 +0800
Subject: [PATCH 1/3] Improve gmlock unit testing.
---
g/os/gmlock/gmlock_unit_lock_test.go | 300 ++++++++++++++++++-------
g/os/gmlock/gmlock_unit_mutex_test.go | 203 +++++++++++++++++
g/os/gmlock/gmlock_unit_rlock_test.go | 312 ++++++++++++++++++++++----
3 files changed, 683 insertions(+), 132 deletions(-)
create mode 100644 g/os/gmlock/gmlock_unit_mutex_test.go
diff --git a/g/os/gmlock/gmlock_unit_lock_test.go b/g/os/gmlock/gmlock_unit_lock_test.go
index 5d0ca1e63..5ca5c701d 100644
--- a/g/os/gmlock/gmlock_unit_lock_test.go
+++ b/g/os/gmlock/gmlock_unit_lock_test.go
@@ -7,93 +7,227 @@
package gmlock_test
import (
- "github.com/gogf/gf/g/container/garray"
- "github.com/gogf/gf/g/os/gmlock"
- "github.com/gogf/gf/g/test/gtest"
- "testing"
- "time"
+ "testing"
+ "time"
+
+ "github.com/gogf/gf/g/container/garray"
+ "github.com/gogf/gf/g/os/gmlock"
+ "github.com/gogf/gf/g/test/gtest"
)
-func TestLocker_Lock_Unlock(t *testing.T) {
- gtest.Case(t, func() {
- key := "test1"
- array := garray.New()
- go func() {
- gmlock.Lock(key)
- array.Append(1)
- time.Sleep(100*time.Millisecond)
- array.Append(1)
- gmlock.Unlock(key)
- }()
- go func() {
- time.Sleep(10*time.Millisecond)
- gmlock.Lock(key)
- array.Append(1)
- time.Sleep(200*time.Millisecond)
- array.Append(1)
- gmlock.Unlock(key)
- }()
- time.Sleep(50*time.Millisecond)
- gtest.Assert(array.Len(), 1)
- time.Sleep(80*time.Millisecond)
- gtest.Assert(array.Len(), 3)
- time.Sleep(100*time.Millisecond)
- gtest.Assert(array.Len(), 3)
- time.Sleep(100*time.Millisecond)
- gtest.Assert(array.Len(), 4)
- })
+func Test_Locker_Lock(t *testing.T) {
+ //no expire
+ gtest.Case(t, func() {
+ key := "testLock"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ array.Append(1)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ array.Append(1)
+ gmlock.Unlock(key)
+ }()
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(80 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 4)
+ })
+ //expire
+ gtest.Case(t, func() {
+ key := "testLockExpire"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key, 100*time.Millisecond)
+ array.Append(1)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.Lock(key)
+ time.Sleep(100 * time.Millisecond)
+ array.Append(1)
+ gmlock.Unlock(key)
+ }()
+ time.Sleep(150 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(250 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
}
-func TestLocker_Lock_Expire(t *testing.T) {
- gtest.Case(t, func() {
- key := "test2"
- array := garray.New()
- go func() {
- gmlock.Lock(key, 100*time.Millisecond)
- array.Append(1)
- }()
- go func() {
- time.Sleep(10*time.Millisecond)
- gmlock.Lock(key)
- time.Sleep(100*time.Millisecond)
- array.Append(1)
- gmlock.Unlock(key)
- }()
- time.Sleep(150*time.Millisecond)
- gtest.Assert(array.Len(), 1)
- time.Sleep(250*time.Millisecond)
- gtest.Assert(array.Len(), 2)
- })
+func Test_Locker_TryLock(t *testing.T) {
+ gtest.Case(t, func() {
+ key := "testTryLock"
+ array := garray.New()
+ go func() {
+ if gmlock.TryLock(key, 200*time.Millisecond) {
+ array.Append(1)
+ }
+ }()
+ go func() {
+ time.Sleep(100 * time.Millisecond)
+ if !gmlock.TryLock(key) {
+ array.Append(1)
+ } else {
+ gmlock.Unlock(key)
+ }
+ }()
+ go func() {
+ time.Sleep(300 * time.Millisecond)
+ if gmlock.TryLock(key) {
+ array.Append(1)
+ gmlock.Unlock(key)
+ }
+ }()
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(80 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ time.Sleep(350 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
}
-func TestLocker_TryLock_Expire(t *testing.T) {
- gtest.Case(t, func() {
- key := "test3"
- array := garray.New()
- go func() {
- gmlock.Lock(key, 200*time.Millisecond)
- array.Append(1)
- }()
- go func() {
- time.Sleep(100*time.Millisecond)
- if !gmlock.TryLock(key) {
- array.Append(1)
- } else {
- gmlock.Unlock(key)
- }
- }()
- go func() {
- time.Sleep(300*time.Millisecond)
- if gmlock.TryLock(key) {
- array.Append(1)
- gmlock.Unlock(key)
- }
- }()
- time.Sleep(50*time.Millisecond)
- gtest.Assert(array.Len(), 1)
- time.Sleep(80*time.Millisecond)
- gtest.Assert(array.Len(), 2)
- time.Sleep(350*time.Millisecond)
- gtest.Assert(array.Len(), 3)
- })
+func Test_Locker_LockFunc(t *testing.T) {
+ //no expire
+ gtest.Case(t, func() {
+ key := "testLockFunc"
+ array := garray.New()
+ go func() {
+ gmlock.LockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ }) //
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ gmlock.LockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 1) //
+ time.Sleep(350 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+
+ //expire
+ gtest.Case(t, func() {
+ key := "testLockFuncExpire"
+ array := garray.New()
+ go func() {
+ gmlock.LockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ }, 100*time.Millisecond) //
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ gmlock.LockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 2) //
+ time.Sleep(350 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+}
+func Test_Locker_TryLockFunc(t *testing.T) {
+ //no expire
+ gtest.Case(t, func() {
+ key := "testTryLockFunc"
+ array := garray.New()
+ go func() {
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(150 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(200 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+ //expire1
+ gtest.Case(t, func() {
+ key := "testTryLockFuncExpire"
+ array := garray.New()
+ go func() {
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ }, 200*time.Millisecond)
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(150 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ time.Sleep(200 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+
+ //expire2
+ gtest.Case(t, func() {
+ key := "testTryLockFuncExpire"
+ array := garray.New()
+ go func() {
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(300 * time.Millisecond)
+ }, 200*time.Millisecond)
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(150 * time.Millisecond)
+ gmlock.TryLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(100 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(200 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ })
}
diff --git a/g/os/gmlock/gmlock_unit_mutex_test.go b/g/os/gmlock/gmlock_unit_mutex_test.go
new file mode 100644
index 000000000..b1047649e
--- /dev/null
+++ b/g/os/gmlock/gmlock_unit_mutex_test.go
@@ -0,0 +1,203 @@
+// Copyright 2019 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 gmlock_test
+
+import (
+ "testing"
+ "time"
+
+ "github.com/gogf/gf/g/container/garray"
+ "github.com/gogf/gf/g/os/gmlock"
+ "github.com/gogf/gf/g/test/gtest"
+)
+
+func Test_Mutex_Unlock(t *testing.T) {
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ mu.LockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.LockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.LockFunc(func() {
+ array.Append(1)
+ })
+ }()
+
+ go func() {
+ time.Sleep(60 * time.Millisecond)
+ mu.Unlock()
+ mu.Unlock()
+ mu.Unlock()
+ }()
+
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+}
+
+func Test_Mutex_LockFunc(t *testing.T) {
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ mu.LockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.LockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+}
+
+func Test_Mutex_TryLockFunc(t *testing.T) {
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ mu.LockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.TryLockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(110 * time.Millisecond)
+ mu.TryLockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+}
+
+func Test_Mutex_RLockFunc(t *testing.T) {
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ mu.LockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.RLockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.RLockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.RLockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.RLockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ gtest.Assert(array.Len(), 0)
+ time.Sleep(80 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+}
+
+func Test_Mutex_TryRLockFunc(t *testing.T) {
+ gtest.Case(t, func() {
+ mu := gmlock.NewMutex()
+ array := garray.New()
+ go func() {
+ mu.LockFunc(func() {
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(50 * time.Millisecond)
+ mu.TryRLockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(110 * time.Millisecond)
+ mu.TryRLockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(110 * time.Millisecond)
+ mu.TryRLockFunc(func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(50 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+}
diff --git a/g/os/gmlock/gmlock_unit_rlock_test.go b/g/os/gmlock/gmlock_unit_rlock_test.go
index 176d375da..705ff11d0 100644
--- a/g/os/gmlock/gmlock_unit_rlock_test.go
+++ b/g/os/gmlock/gmlock_unit_rlock_test.go
@@ -7,57 +7,271 @@
package gmlock_test
import (
- "github.com/gogf/gf/g/container/garray"
- "github.com/gogf/gf/g/os/gmlock"
- "github.com/gogf/gf/g/test/gtest"
- "testing"
- "time"
+ "testing"
+ "time"
+
+ "github.com/gogf/gf/g/container/garray"
+ "github.com/gogf/gf/g/os/gmlock"
+ "github.com/gogf/gf/g/test/gtest"
)
-func TestLocker_RLock1(t *testing.T) {
- gtest.Case(t, func() {
- key := "test100"
- array := garray.New()
- go func() {
- gmlock.RLock(key)
- array.Append(1)
- time.Sleep(50*time.Millisecond)
- array.Append(1)
- gmlock.RUnlock(key)
- }()
- go func() {
- time.Sleep(10*time.Millisecond)
- gmlock.Lock(key)
- array.Append(1)
- gmlock.Unlock(key)
- }()
- time.Sleep(20*time.Millisecond)
- gtest.Assert(array.Len(), 1)
- time.Sleep(80*time.Millisecond)
- gtest.Assert(array.Len(), 3)
- })
+func Test_Locker_RLock(t *testing.T) {
+ //RLock before Lock
+ gtest.Case(t, func() {
+ key := "testRLockBeforeLock"
+ array := garray.New()
+ go func() {
+ gmlock.RLock(key)
+ array.Append(1)
+ time.Sleep(50 * time.Millisecond)
+ array.Append(1)
+ gmlock.RUnlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.Lock(key)
+ array.Append(1)
+ gmlock.Unlock(key)
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(80 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+
+ //Lock before RLock
+ gtest.Case(t, func() {
+ key := "testLockBeforeRLock"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLock(key)
+ array.Append(1)
+ gmlock.RUnlock(key)
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+
+ //Lock before RLocks
+ gtest.Case(t, func() {
+ key := "testLockBeforeRLocks"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLock(key)
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ gmlock.RUnlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLock(key)
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ gmlock.RUnlock(key)
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
}
-func TestLocker_RLock2(t *testing.T) {
- gtest.Case(t, func() {
- key := "test200"
- array := garray.New()
- go func() {
- gmlock.Lock(key)
- array.Append(1)
- time.Sleep(100*time.Millisecond)
- gmlock.Unlock(key)
- }()
- go func() {
- time.Sleep(10*time.Millisecond)
- gmlock.RLock(key)
- array.Append(1)
- gmlock.RUnlock(key)
- }()
+func Test_Locker_TryRLock(t *testing.T) {
+ //Lock before TryRLock
+ gtest.Case(t, func() {
+ key := "testLockBeforeTryRLock"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ if gmlock.TryRLock(key) {
+ array.Append(1)
+ gmlock.RUnlock(key)
+ }
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ })
- time.Sleep(20*time.Millisecond)
- gtest.Assert(array.Len(), 1)
- time.Sleep(120*time.Millisecond)
- gtest.Assert(array.Len(), 2)
- })
-}
\ No newline at end of file
+ //Lock before TryRLocks
+ gtest.Case(t, func() {
+ key := "testLockBeforeTryRLocks"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ if gmlock.TryRLock(key) {
+ array.Append(1)
+ gmlock.RUnlock(key)
+ }
+ }()
+ go func() {
+ time.Sleep(150 * time.Millisecond)
+ if gmlock.TryRLock(key) {
+ array.Append(1)
+ gmlock.RUnlock(key)
+ }
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(150 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+}
+
+func Test_Locker_RLockFunc(t *testing.T) {
+ //RLockFunc before Lock
+ gtest.Case(t, func() {
+ key := "testRLockFuncBeforeLock"
+ array := garray.New()
+ go func() {
+ gmlock.RLockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(50 * time.Millisecond)
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.Lock(key)
+ array.Append(1)
+ gmlock.Unlock(key)
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(80 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+
+ //Lock before RLockFunc
+ gtest.Case(t, func() {
+ key := "testLockBeforeRLockFunc"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+
+ //Lock before RLockFuncs
+ gtest.Case(t, func() {
+ key := "testLockBeforeRLockFuncs"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ })
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.RLockFunc(key, func() {
+ array.Append(1)
+ time.Sleep(200 * time.Millisecond)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 3)
+ })
+}
+
+func Test_Locker_TryRLockFunc(t *testing.T) {
+ //Lock before TryRLockFunc
+ gtest.Case(t, func() {
+ key := "testLockBeforeTryRLockFunc"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.TryRLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(120 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ })
+
+ //Lock before TryRLockFuncs
+ gtest.Case(t, func() {
+ key := "testLockBeforeTryRLockFuncs"
+ array := garray.New()
+ go func() {
+ gmlock.Lock(key)
+ array.Append(1)
+ time.Sleep(100 * time.Millisecond)
+ gmlock.Unlock(key)
+ }()
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ gmlock.TryRLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ go func() {
+ time.Sleep(150 * time.Millisecond)
+ gmlock.TryRLockFunc(key, func() {
+ array.Append(1)
+ })
+ }()
+ time.Sleep(20 * time.Millisecond)
+ gtest.Assert(array.Len(), 1)
+ time.Sleep(150 * time.Millisecond)
+ gtest.Assert(array.Len(), 2)
+ })
+}
From 3030d7f0323cd229338f54bea90d77318d6dd04e Mon Sep 17 00:00:00 2001
From: hailaz <739476267@qq.com>
Date: Wed, 19 Jun 2019 11:11:00 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=BB=E5=BA=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DONATOR.MD | 1 +
README.MD | 73 +-
g/container/garray/garray.go | 1 -
g/container/garray/garray_func.go | 8 +-
g/container/garray/garray_normal_int.go | 568 +++----
g/container/garray/garray_normal_interface.go | 712 ++++-----
g/container/garray/garray_normal_string.go | 574 +++----
g/container/garray/garray_sorted_int.go | 620 ++++----
g/container/garray/garray_sorted_interface.go | 610 ++++----
g/container/garray/garray_sorted_string.go | 604 ++++----
g/container/garray/garray_z_example_test.go | 152 +-
g/container/gchan/gchan_example_test.go | 30 +-
g/container/glist/glist.go | 320 ++--
g/container/glist/glist_example_test.go | 44 +-
g/container/glist/glist_z_bench_test.go | 49 +-
g/container/gmap/gmap.go | 8 +-
g/container/gmap/gmap_hash_any_any_map.go | 252 +--
g/container/gmap/gmap_hash_int_any_map.go | 238 ++-
g/container/gmap/gmap_hash_int_int_map.go | 240 +--
g/container/gmap/gmap_hash_int_str_map.go | 12 +-
g/container/gmap/gmap_hash_str_any_map.go | 12 +-
g/container/gmap/gmap_hash_str_int_map.go | 12 +-
g/container/gmap/gmap_hash_str_str_map.go | 66 +-
g/container/gmap/gmap_link_map.go | 256 ++--
g/container/gmap/gmap_tree_map.go | 6 +-
g/container/gmap/gmap_z_basic_test.go | 8 +-
g/container/gmap/gmap_z_bench_maps_test.go | 12 +-
g/container/gmap/gmap_z_bench_safe_test.go | 101 +-
g/container/gmap/gmap_z_bench_syncmap_test.go | 44 +-
g/container/gmap/gmap_z_bench_unsafe_test.go | 101 +-
g/container/gmap/gmap_z_example_test.go | 7 +-
g/container/gmap/gmap_z_int_any_test.go | 7 +-
g/container/gmap/gmap_z_int_int_test.go | 8 +-
g/container/gmap/gmap_z_int_str_test.go | 10 +-
g/container/gmap/gmap_z_link_map_test.go | 6 +-
g/container/gmap/gmap_z_str_any_test.go | 2 +-
g/container/gmap/gmap_z_str_int_test.go | 2 +-
g/container/gmap/gmap_z_str_str_test.go | 2 +-
g/container/gmap/gmap_z_tree_map_test.go | 5 +-
g/container/gpool/gpool.go | 169 +-
g/container/gpool/gpool_bench_test.go | 30 +-
g/container/gqueue/gqueue.go | 130 +-
g/container/gqueue/gqueue_bench_test.go | 50 +-
g/container/gring/gring.go | 298 ++--
g/container/gring/gring_test.go | 36 +-
g/container/gring/gring_unit_test.go | 74 +-
g/container/gset/gset.go | 328 ++--
g/container/gset/gset_int_set.go | 228 +--
g/container/gset/gset_string_set.go | 174 +--
g/container/gset/gset_z_bench_test.go | 122 +-
g/container/gtree/gtree_avltree.go | 91 +-
g/container/gtree/gtree_btree.go | 87 +-
g/container/gtree/gtree_redblacktree.go | 123 +-
g/container/gtype/bool.go | 42 +-
g/container/gtype/byte.go | 22 +-
g/container/gtype/bytes.go | 28 +-
g/container/gtype/float32.go | 20 +-
g/container/gtype/float64.go | 20 +-
g/container/gtype/gtype.go | 6 +-
g/container/gtype/gtype_test.go | 206 ++-
g/container/gtype/int.go | 24 +-
g/container/gtype/int32.go | 24 +-
g/container/gtype/int64.go | 24 +-
g/container/gtype/interface.go | 26 +-
g/container/gtype/string.go | 34 +-
g/container/gtype/uint.go | 24 +-
g/container/gtype/uint32.go | 24 +-
g/container/gtype/uint64.go | 24 +-
g/container/gvar/gvar_z_bench_test.go | 132 +-
g/crypto/gaes/gaes.go | 144 +-
g/crypto/gcrc32/gcrc32.go | 4 +-
g/crypto/gdes/gdes.go | 74 +-
g/crypto/gdes/gdes_test.go | 58 +-
g/crypto/gmd5/gmd5.go | 40 +-
g/crypto/gmd5/gmd5_test.go | 5 +-
g/crypto/gsha1/gsha1.go | 38 +-
g/crypto/gsha1/gsha1_test.go | 2 +-
g/database/gdb/gdb.go | 352 ++---
g/database/gdb/gdb_base.go | 883 +++++------
g/database/gdb/gdb_batch_result.go | 6 +-
g/database/gdb/gdb_config.go | 144 +-
g/database/gdb/gdb_func.go | 353 ++---
g/database/gdb/gdb_model.go | 390 ++---
g/database/gdb/gdb_mssql.go | 106 +-
g/database/gdb/gdb_mysql.go | 37 +-
g/database/gdb/gdb_oracle.go | 106 +-
g/database/gdb/gdb_pgsql.go | 53 +-
g/database/gdb/gdb_sqlite.go | 4 +-
g/database/gdb/gdb_structure.go | 122 +-
g/database/gdb/gdb_transaction.go | 175 ++-
g/database/gdb/gdb_type_record.go | 22 +-
g/database/gdb/gdb_type_result.go | 156 +-
g/database/gdb/gdb_unit_basic_test.go | 26 +-
g/database/gdb/gdb_unit_init_test.go | 98 +-
g/database/gdb/gdb_unit_method_test.go | 853 ++++++-----
g/database/gdb/gdb_unit_model_test.go | 1148 +++++++-------
.../gdb/gdb_unit_struct_inherit_test.go | 56 +-
g/database/gdb/gdb_unit_transaction_test.go | 1032 +++++++------
g/database/gredis/gredis.go | 190 ++-
g/database/gredis/gredis_config.go | 61 +-
g/database/gredis/gredis_conn.go | 2 +-
g/encoding/gbase64/gbase64.go | 10 +-
g/encoding/gbase64/gbase64_test.go | 2 +-
g/encoding/gbinary/gbinary.go | 70 +-
g/encoding/gcharset/gcharset.go | 12 +-
g/encoding/gcharset/gcharset_test.go | 3 +-
g/encoding/gcompress/gcompress.go | 55 +-
g/encoding/ghash/ghash.go | 251 ++-
g/encoding/ghash/ghash_test.go | 102 +-
g/encoding/ghash/ghash_z_unit_basic_test.go | 280 ++--
g/encoding/ghtml/ghtml.go | 40 +-
g/encoding/gjson/gjson.go | 556 +++----
g/encoding/gjson/gjson_api.go | 203 ++-
g/encoding/gjson/gjson_api_config.go | 12 +-
g/encoding/gjson/gjson_api_encoding.go | 60 +-
g/encoding/gjson/gjson_api_new_load.go | 244 +--
g/encoding/gjson/gjson_func.go | 2 +-
g/encoding/gjson/gjson_z_bench_test.go | 27 +-
g/encoding/gjson/gjson_z_unit_basic_test.go | 2 +-
g/encoding/gjson/gjson_z_unit_set_test.go | 354 +++--
g/encoding/gparser/gparser.go | 3 +-
g/encoding/gparser/gparser_api.go | 104 +-
g/encoding/gparser/gparser_api_config.go | 2 +-
g/encoding/gparser/gparser_api_encoding.go | 33 +-
g/encoding/gparser/gparser_api_new_load.go | 38 +-
g/encoding/gparser/gparser_unit_set_test.go | 326 ++--
g/encoding/gtoml/gtoml.go | 40 +-
g/encoding/gurl/url.go | 80 +-
g/encoding/gxml/gxml.go | 2 +-
g/encoding/gyaml/gyaml.go | 18 +-
g/frame/gins/gins.go | 349 +++--
g/frame/gins/gins_basic_test.go | 60 +-
g/frame/gins/gins_config_test.go | 221 ++-
g/frame/gins/gins_database_test.go | 51 +-
g/frame/gins/gins_redis_test.go | 67 +-
g/frame/gins/gins_view_test.go | 67 +-
g/frame/gmvc/controller.go | 30 +-
g/frame/gmvc/model.go | 4 +-
g/frame/gmvc/view.go | 110 +-
g/g.go | 40 +-
g/g_func.go | 32 +-
g/g_logger.go | 10 +-
g/g_object.go | 50 +-
g/g_setting.go | 2 +-
g/internal/cmdenv/cmdenv.go | 30 +-
g/internal/cmdenv/cmdenv_test.go | 7 +-
g/internal/empty/empty.go | 95 +-
g/internal/mutex/mutex.go | 38 +-
g/internal/mutex/mutex_z_bench_test.go | 24 +-
g/internal/rwmutex/rwmutex.go | 48 +-
g/internal/rwmutex/rwmutex_z_bench_test.go | 42 +-
g/net/ghttp/ghttp.go | 4 +-
g/net/ghttp/ghttp_client_api.go | 79 +-
g/net/ghttp/ghttp_client_config.go | 66 +-
g/net/ghttp/ghttp_client_request.go | 498 +++---
g/net/ghttp/ghttp_client_response.go | 48 +-
g/net/ghttp/ghttp_controller.go | 5 +-
g/net/ghttp/ghttp_func.go | 28 +-
g/net/ghttp/ghttp_request.go | 262 ++--
g/net/ghttp/ghttp_request_auth.go | 93 +-
g/net/ghttp/ghttp_request_log.go | 6 +-
g/net/ghttp/ghttp_request_params.go | 29 +-
g/net/ghttp/ghttp_request_post.go | 210 +--
g/net/ghttp/ghttp_request_query.go | 226 +--
g/net/ghttp/ghttp_request_request.go | 217 ++-
g/net/ghttp/ghttp_request_router.go | 21 +-
g/net/ghttp/ghttp_response.go | 291 ++--
g/net/ghttp/ghttp_response_cors.go | 66 +-
g/net/ghttp/ghttp_response_gzip.go | 68 +-
g/net/ghttp/ghttp_response_view.go | 66 +-
g/net/ghttp/ghttp_response_writer.go | 31 +-
g/net/ghttp/ghttp_server.go | 902 ++++++-----
g/net/ghttp/ghttp_server_admin.go | 100 +-
g/net/ghttp/ghttp_server_admin_process.go | 390 ++---
g/net/ghttp/ghttp_server_admin_unix.go | 56 +-
g/net/ghttp/ghttp_server_admin_windows.go | 2 +-
g/net/ghttp/ghttp_server_config.go | 470 +++---
g/net/ghttp/ghttp_server_config_cookie.go | 51 +-
g/net/ghttp/ghttp_server_config_logger.go | 84 +-
g/net/ghttp/ghttp_server_config_route.go | 57 +-
g/net/ghttp/ghttp_server_config_session.go | 24 +-
g/net/ghttp/ghttp_server_config_static.go | 183 ++-
g/net/ghttp/ghttp_server_cookie.go | 214 +--
g/net/ghttp/ghttp_server_domain.go | 102 +-
g/net/ghttp/ghttp_server_graceful.go | 263 ++--
g/net/ghttp/ghttp_server_handler.go | 439 +++---
g/net/ghttp/ghttp_server_log.go | 90 +-
g/net/ghttp/ghttp_server_pprof.go | 80 +-
g/net/ghttp/ghttp_server_router.go | 576 ++++---
g/net/ghttp/ghttp_server_router_group.go | 312 ++--
g/net/ghttp/ghttp_server_router_hook.go | 332 ++--
g/net/ghttp/ghttp_server_router_serve.go | 193 ++-
.../ghttp/ghttp_server_service_controller.go | 278 ++--
g/net/ghttp/ghttp_server_service_handler.go | 144 +-
g/net/ghttp/ghttp_server_service_object.go | 340 ++---
g/net/ghttp/ghttp_server_session.go | 248 ++-
g/net/ghttp/ghttp_server_status.go | 48 +-
g/net/ghttp/ghttp_server_websocket.go | 35 +-
g/net/ghttp/ghttp_unit_cookie_test.go | 88 +-
g/net/ghttp/ghttp_unit_init_test.go | 14 +-
g/net/ghttp/ghttp_unit_param_json_test.go | 150 +-
g/net/ghttp/ghttp_unit_param_test.go | 256 ++--
g/net/ghttp/ghttp_unit_router_basic_test.go | 308 ++--
.../ghttp_unit_router_controller_rest_test.go | 117 +-
.../ghttp_unit_router_controller_test.go | 168 +-
.../ghttp_unit_router_domain_basic_test.go | 538 +++----
...unit_router_domain_controller_rest_test.go | 160 +-
...http_unit_router_domain_controller_test.go | 302 ++--
...ttp_unit_router_domain_object_rest_test.go | 154 +-
.../ghttp_unit_router_domain_object_test.go | 295 ++--
g/net/ghttp/ghttp_unit_router_exit_test.go | 200 +--
.../ghttp_unit_router_group_rest_test.go | 194 +--
g/net/ghttp/ghttp_unit_router_group_test.go | 240 +--
g/net/ghttp/ghttp_unit_router_hook_test.go | 185 ++-
g/net/ghttp/ghttp_unit_router_names_test.go | 162 +-
.../ghttp_unit_router_object_rest_test.go | 110 +-
g/net/ghttp/ghttp_unit_router_object_test.go | 163 +-
g/net/ghttp/ghttp_unit_session_test.go | 96 +-
g/net/ghttp/ghttp_unit_static_test.go | 440 +++---
g/net/gipv4/gipv4.go | 248 +--
g/net/gipv6/gipv6.go | 3 +-
g/net/gsmtp/gsmtp.go | 104 +-
g/net/gtcp/gtcp.go | 2 -
g/net/gtcp/gtcp_conn.go | 356 ++---
g/net/gtcp/gtcp_conn_pkg.go | 36 +-
g/net/gtcp/gtcp_func.go | 96 +-
g/net/gtcp/gtcp_func_pkg.go | 10 +-
g/net/gtcp/gtcp_pool.go | 196 +--
g/net/gtcp/gtcp_pool_pkg.go | 90 +-
g/net/gtcp/gtcp_server.go | 117 +-
g/net/gudp/gudp.go | 3 -
g/net/gudp/gudp_conn.go | 342 ++---
g/net/gudp/gudp_func.go | 80 +-
g/net/gudp/gudp_server.go | 103 +-
g/os/gcache/gcache.go | 36 +-
g/os/gcache/gcache_cache.go | 30 +-
g/os/gcache/gcache_mem_cache.go | 505 +++---
g/os/gcache/gcache_mem_cache_item.go | 14 +-
g/os/gcache/gcache_mem_cache_lru.go | 102 +-
g/os/gcache/gcache_z_bench_test.go | 118 +-
g/os/gcfg/gcfg.go | 650 ++++----
g/os/gcfg/gcfg_config.go | 44 +-
g/os/gcfg/gcfg_error.go | 2 +-
g/os/gcfg/gcfg_instance.go | 7 +-
g/os/gcmd/gcmd.go | 6 +-
g/os/gcmd/gcmd_option.go | 18 +-
g/os/gcmd/gcmd_value.go | 18 +-
g/os/gcron/gcron.go | 72 +-
g/os/gcron/gcron_cron.go | 250 +--
g/os/gcron/gcron_entry.go | 149 +-
g/os/gcron/gcron_schedule.go | 422 ++---
g/os/gcron/gcron_unit_1_test.go | 351 +++--
g/os/gcron/gcron_unit_2_test.go | 95 +-
g/os/gcron/gcron_z_bench_test.go | 12 +-
g/os/gcron/gcron_z_example_1_test.go | 17 +-
g/os/genv/genv.go | 20 +-
g/os/gfcache/gfcache.go | 68 +-
g/os/gfile/gfile.go | 472 +++---
g/os/gfile/gfile_contents.go | 154 +-
g/os/gfile/gfile_search.go | 86 +-
g/os/gfile/gfile_size.go | 80 +-
g/os/gfile/gfile_time.go | 22 +-
g/os/gflock/gflock.go | 76 +-
g/os/gfpool/gfpool.go | 229 ++-
g/os/gfpool/gfpool_z_bench_test.go | 54 +-
g/os/gfsnotify/gfsnotify.go | 128 +-
g/os/gfsnotify/gfsnotify_event.go | 12 +-
g/os/gfsnotify/gfsnotify_filefunc.go | 168 +-
g/os/gfsnotify/gfsnotify_watcher.go | 215 ++-
g/os/gfsnotify/gfsnotify_watcher_loop.go | 249 +--
g/os/gfsnotify/gfsnotify_z_unit_test.go | 254 +--
g/os/glog/glog.go | 56 +-
g/os/glog/glog_api.go | 36 +-
g/os/glog/glog_chaining.go | 40 +-
g/os/glog/glog_logger.go | 341 +++--
g/os/glog/glog_logger_api.go | 198 +--
g/os/glog/glog_logger_chaining.go | 168 +-
g/os/glog/glog_logger_writer.go | 2 +-
g/os/gmlock/gmlock.go | 24 +-
g/os/gmlock/gmlock_locker.go | 108 +-
g/os/gmlock/gmlock_mutex.go | 47 +-
g/os/gproc/gproc.go | 177 ++-
g/os/gproc/gproc_comm.go | 27 +-
g/os/gproc/gproc_comm_receive.go | 172 ++-
g/os/gproc/gproc_comm_send.go | 73 +-
g/os/gproc/gproc_manager.go | 108 +-
g/os/gproc/gproc_proccess.go | 159 +-
g/os/grpool/grpool.go | 73 +-
g/os/grpool/grpool_bench_1_test.go | 21 +-
g/os/grpool/grpool_bench_2_test.go | 22 +-
g/os/grpool/grpool_unit_test.go | 27 +-
g/os/gspath/gspath.go | 318 ++--
g/os/gspath/gspath_cache.go | 114 +-
g/os/gtime/gtime.go | 478 +++---
g/os/gtime/gtime_format.go | 159 +-
g/os/gtime/gtime_time.go | 126 +-
g/os/gtime/gtime_z_unit_format_test.go | 3 +-
g/os/gtimer/gtimer.go | 64 +-
g/os/gtimer/gtimer_entry.go | 226 +--
g/os/gtimer/gtimer_loop.go | 116 +-
g/os/gtimer/gtimer_timer.go | 254 +--
g/os/gtimer/gtimer_z_bench_test.go | 27 +-
g/os/gtimer/gtimer_z_example_test.go | 20 +-
g/os/gtimer/gtimer_z_unit_0_test.go | 195 ++-
g/os/gtimer/gtimer_z_unit_1_test.go | 384 +++--
g/os/gtimer/gtimer_z_unit_2_test.go | 101 +-
g/os/gview/gview.go | 325 ++--
g/os/gview/gview_buildin.go | 76 +-
g/os/gview/gview_config.go | 10 +-
g/os/gview/gview_doparse.go | 20 +-
g/os/gview/gview_error.go | 2 +-
g/os/gview/gview_instance.go | 1 +
g/test/gtest/gtest.go | 445 +++---
g/test/gtest/gtest_test.go | 2 +-
g/text/gregex/gregex.go | 88 +-
g/text/gregex/gregex_cache.go | 44 +-
g/text/gregex/gregex_z_bench_test.go | 4 +-
g/text/gstr/gstr.go | 768 +++++-----
g/text/gstr/gstr_levenshtein.go | 90 +-
g/text/gstr/gstr_parse.go | 260 ++--
g/text/gstr/gstr_pos.go | 146 +-
g/text/gstr/gstr_similartext.go | 74 +-
g/text/gstr/gstr_soundex.go | 92 +-
g/text/gstr/gstr_trim.go | 64 +-
g/text/gstr/gstr_z_unit_basic_test.go | 497 +++---
g/text/gstr/gstr_z_unit_parse_test.go | 120 +-
g/text/gstr/gstr_z_unit_pos_test.go | 78 +-
g/text/gstr/gstr_z_unit_trim_test.go | 44 +-
g/util/gconv/gconv.go | 627 ++++----
g/util/gconv/gconv_map.go | 294 ++--
g/util/gconv/gconv_slice.go | 641 ++++----
g/util/gconv/gconv_struct.go | 480 +++---
g/util/gconv/gconv_time.go | 38 +-
g/util/gconv/gconv_z_bench_test.go | 126 +-
g/util/gconv/gconv_z_unit_basic_test.go | 47 +-
g/util/gconv/gconv_z_unit_bool_test.go | 49 +-
g/util/gconv/gconv_z_unit_map_test.go | 213 ++-
g/util/gconv/gconv_z_unit_slice_test.go | 41 +-
g/util/gconv/gconv_z_unit_string_test.go | 73 +-
g/util/gconv/gconv_z_unit_struct_test.go | 608 ++++----
g/util/gconv/gconv_z_unit_time_test.go | 13 +-
g/util/gpage/gpage.go | 470 +++---
g/util/grand/grand.go | 30 +-
g/util/grand/grand_intn.go | 76 +-
g/util/grand/grand_z_bench_test.go | 10 +-
g/util/grand/grand_z_unit_test.go | 197 ++-
g/util/gutil/gutil.go | 104 +-
g/util/gutil/gutil_comparator.go | 14 +-
g/util/gutil/gutil_z_bench_test.go | 16 +-
g/util/gvalid/gvalid.go | 12 +-
g/util/gvalid/gvalid_check.go | 1128 +++++++-------
g/util/gvalid/gvalid_check_map.go | 202 +--
g/util/gvalid/gvalid_check_struct.go | 285 ++--
g/util/gvalid/gvalid_error.go | 181 ++-
g/util/gvalid/gvalid_message.go | 92 +-
g/util/gvalid/gvalid_unit_basic_all_test.go | 1357 ++++++++---------
g/util/gvalid/gvalid_unit_checkmap_test.go | 151 +-
g/util/gvalid/gvalid_unit_checkstruct_test.go | 112 +-
g/util/gvalid/gvalid_unit_customerror_test.go | 124 +-
geg/other/test.go | 2 +-
geg/other/test2.go | 10 +-
361 files changed, 27356 insertions(+), 27290 deletions(-)
diff --git a/DONATOR.MD b/DONATOR.MD
index 741ff45d0..6a9aa30e6 100644
--- a/DONATOR.MD
+++ b/DONATOR.MD
@@ -15,6 +15,7 @@
|潘兄|wechat|¥100.00
|Fly的狐狸|wechat|¥100.00
|土豆相公|alipay|¥66.60
+|蔡蔡|wechat|¥666.00
|上海金保证网络科技|bank|¥2000.00
diff --git a/README.MD b/README.MD
index 2b8740977..f34bcffe6 100644
--- a/README.MD
+++ b/README.MD
@@ -1,44 +1,58 @@
-# GoFrame
+# GoFrame

-[](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories)
-[](https://travis-ci.org/gogf/gf)
+[](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories)
+[](https://travis-ci.org/gogf/gf)
+[](https://goreportcard.com/report/github.com/gogf/gf)
[](https://codecov.io/gh/gogf/gf/branch/master)
[](https://github.com/gogf/gf)
[](https://github.com/gogf/gf)
-`GF(GoFrame)` is a modular, full-featured and production-ready application development framework of golang. Providing a series of core components and dozens of practical modules, such as: memcache, configure, validator, logging, array/queue/set/map containers, timer/timing tasks, file/memory lock, object pool, database ORM, etc. Supporting web server integrated with router, cookie, session, logger, template, https, hooks, rewrites and many more features.
+`GF(Go Frame)`是一款模块化、高性能、生产级Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、
+并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、服务注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。
-# Installation
-```
+# 特点
+* 模块化、松耦合设计;
+* 模块丰富,开箱即用;
+* 详尽的开发文档及示例;
+* 完善的本地中文化支持;
+* 致力于项目的通用方案;
+* 更适合企业及团队使用;
+* 更多请查阅文档及源码;
+
+# 安装
+```html
go get -u github.com/gogf/gf
```
-or use `go.mod`:
+或者
+`go.mod`:
```
require github.com/gogf/gf latest
```
-# Limitation
-```
-golang version >= 1.10
+# 限制
+```shell
+golang版本 >= 1.10
```
-# Documentation
-
-* [APIDoc](https://godoc.org/github.com/gogf/gf)
-* [中文文档](https://goframe.org)
-
-# Architecture
+# 架构
-# Quick Start
+
+# 文档
+
+开发文档:[https://goframe.org](https://goframe.org)
+
+接口文档:[https://godoc.org/github.com/gogf/gf](https://godoc.org/github.com/gogf/gf)
+
+# 使用
```go
package main
@@ -56,26 +70,17 @@ func main() {
}
```
-[View More..](https://goframe.org/start/index)
+[更多..](https://goframe.org/start/index)
-# License
-
-`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
-
-# Donators
-
-We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill. If you like `GF`, why not [buy developer a cup of coffee](DONATOR.MD)?
-
-# Thanks
-
-
-
-
+# 协议
+`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。
+# 捐赠
+如果您喜欢`GF`,要不[给开发者来杯咖啡吧](DONATOR.MD)!
+请在捐赠时备注您的`github`/`gitee`账号名称。
+# 感谢
+
\ No newline at end of file
diff --git a/g/container/garray/garray.go b/g/container/garray/garray.go
index 35f367894..d1ca55d5e 100644
--- a/g/container/garray/garray.go
+++ b/g/container/garray/garray.go
@@ -6,4 +6,3 @@
// Package garray provides concurrent-safe/unsafe arrays.
package garray
-
diff --git a/g/container/garray/garray_func.go b/g/container/garray/garray_func.go
index 7366269d5..ed6ba8a11 100644
--- a/g/container/garray/garray_func.go
+++ b/g/container/garray/garray_func.go
@@ -7,13 +7,13 @@
package garray
type apiSliceInterface interface {
- Slice() []interface{}
+ Slice() []interface{}
}
type apiSliceInt interface {
- Slice() []int
+ Slice() []int
}
type apiSliceString interface {
- Slice() []string
-}
\ No newline at end of file
+ Slice() []string
+}
diff --git a/g/container/garray/garray_normal_int.go b/g/container/garray/garray_normal_int.go
index 21636b16b..2be98a810 100644
--- a/g/container/garray/garray_normal_int.go
+++ b/g/container/garray/garray_normal_int.go
@@ -7,13 +7,13 @@
package garray
import (
- "bytes"
+ "bytes"
"fmt"
"github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
)
type IntArray struct {
@@ -24,40 +24,40 @@ type IntArray struct {
// NewIntArray creates and returns an empty array.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewIntArray(unsafe...bool) *IntArray {
+func NewIntArray(unsafe ...bool) *IntArray {
return NewIntArraySize(0, 0, unsafe...)
}
// NewIntArraySize create and returns an array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewIntArraySize(size int, cap int, unsafe...bool) *IntArray {
- return &IntArray{
- mu : rwmutex.New(unsafe...),
- array : make([]int, size, cap),
- }
+func NewIntArraySize(size int, cap int, unsafe ...bool) *IntArray {
+ return &IntArray{
+ mu: rwmutex.New(unsafe...),
+ array: make([]int, size, cap),
+ }
}
// NewIntArrayFrom creates and returns an array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewIntArrayFrom(array []int, unsafe...bool) *IntArray {
+func NewIntArrayFrom(array []int, unsafe ...bool) *IntArray {
return &IntArray{
- mu : rwmutex.New(unsafe...),
- array : array,
- }
+ mu: rwmutex.New(unsafe...),
+ array: array,
+ }
}
// NewIntArrayFromCopy creates and returns an array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewIntArrayFromCopy(array []int, unsafe...bool) *IntArray {
- newArray := make([]int, len(array))
- copy(newArray, array)
- return &IntArray{
- mu : rwmutex.New(unsafe...),
- array : newArray,
- }
+func NewIntArrayFromCopy(array []int, unsafe ...bool) *IntArray {
+ newArray := make([]int, len(array))
+ copy(newArray, array)
+ return &IntArray{
+ mu: rwmutex.New(unsafe...),
+ array: newArray,
+ }
}
// Get returns the value of the specified index,
@@ -79,83 +79,83 @@ func (a *IntArray) Set(index int, value int) *IntArray {
// SetArray sets the underlying slice array with the given .
func (a *IntArray) SetArray(array []int) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ return a
}
// Replace replaces the array items by given from the beginning of array.
func (a *IntArray) Replace(array []int) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- max := len(array)
- if max > len(a.array) {
- max = len(a.array)
- }
- for i := 0; i < max; i++ {
- a.array[i] = array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ max := len(array)
+ if max > len(a.array) {
+ max = len(a.array)
+ }
+ for i := 0; i < max; i++ {
+ a.array[i] = array[i]
+ }
+ return a
}
// Sum returns the sum of values in an array.
func (a *IntArray) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += v
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += v
+ }
+ return
}
// Sort sorts the array in increasing order.
// The parameter controls whether sort
// in increasing order(default) or decreasing order
-func (a *IntArray) Sort(reverse...bool) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if len(reverse) > 0 && reverse[0] {
- sort.Slice(a.array, func(i, j int) bool {
- if a.array[i] < a.array[j] {
- return false
- }
- return true
- })
- } else {
- sort.Ints(a.array)
- }
- return a
+func (a *IntArray) Sort(reverse ...bool) *IntArray {
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if len(reverse) > 0 && reverse[0] {
+ sort.Slice(a.array, func(i, j int) bool {
+ if a.array[i] < a.array[j] {
+ return false
+ }
+ return true
+ })
+ } else {
+ sort.Ints(a.array)
+ }
+ return a
}
// SortFunc sorts the array by custom function .
func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Slice(a.array, func(i, j int) bool {
- return less(a.array[i], a.array[j])
- })
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Slice(a.array, func(i, j int) bool {
+ return less(a.array[i], a.array[j])
+ })
+ return a
}
// InsertBefore inserts the to the front of .
func (a *IntArray) InsertBefore(index int, value int) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
- rear := append([]int{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
+ rear := append([]int{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
a.array = append(a.array, rear...)
- return a
+ return a
}
// InsertAfter inserts the to the back of .
func (a *IntArray) InsertAfter(index int, value int) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
- rear := append([]int{}, a.array[index + 1:]...)
- a.array = append(a.array[0 : index + 1], value)
+ rear := append([]int{}, a.array[index+1:]...)
+ a.array = append(a.array[0:index+1], value)
a.array = append(a.array, rear...)
- return a
+ return a
}
// Remove removes an item by index.
@@ -164,139 +164,139 @@ func (a *IntArray) Remove(index int) int {
defer a.mu.Unlock()
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
+ value := a.array[0]
+ a.array = a.array[1:]
return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
return value
}
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
return value
}
// PushLeft pushes one or multiple items to the beginning of array.
-func (a *IntArray) PushLeft(value...int) *IntArray {
- a.mu.Lock()
- a.array = append(value, a.array...)
- a.mu.Unlock()
- return a
+func (a *IntArray) PushLeft(value ...int) *IntArray {
+ a.mu.Lock()
+ a.array = append(value, a.array...)
+ a.mu.Unlock()
+ return a
}
// PushRight pushes one or multiple items to the end of array.
// It equals to Append.
-func (a *IntArray) PushRight(value...int) *IntArray {
- a.mu.Lock()
- a.array = append(a.array, value...)
- a.mu.Unlock()
- return a
+func (a *IntArray) PushRight(value ...int) *IntArray {
+ a.mu.Lock()
+ a.array = append(a.array, value...)
+ a.mu.Unlock()
+ return a
}
// PopLeft pops and returns an item from the beginning of array.
func (a *IntArray) PopLeft() int {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *IntArray) PopRight() int {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopRand randomly pops and return an item out of array.
func (a *IntArray) PopRand() int {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *IntArray) PopRands(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]int, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]int, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLefts pops and returns items from the beginning of array.
func (a *IntArray) PopLefts(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *IntArray) PopRights(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *IntArray) Range(start, end int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]int)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]int, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]int)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]int, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// See PushRight.
-func (a *IntArray) Append(value...int) *IntArray {
+func (a *IntArray) Append(value ...int) *IntArray {
a.mu.Lock()
a.array = append(a.array, value...)
- a.mu.Unlock()
- return a
+ a.mu.Unlock()
+ return a
}
// Len returns the length of array.
@@ -325,26 +325,26 @@ func (a *IntArray) Slice() []int {
// Clone returns a new array, which is a copy of current array.
func (a *IntArray) Clone() (newArray *IntArray) {
- a.mu.RLock()
- array := make([]int, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewIntArrayFrom(array, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]int, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewIntArrayFrom(array, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *IntArray) Clear() *IntArray {
a.mu.Lock()
if len(a.array) > 0 {
- a.array = make([]int, 0)
- }
- a.mu.Unlock()
- return a
+ a.array = make([]int, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// Contains checks whether a value exists in the array.
func (a *IntArray) Contains(value int) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
@@ -369,10 +369,10 @@ func (a *IntArray) Search(value int) int {
// Unique uniques the array, clear repeated items.
func (a *IntArray) Unique() *IntArray {
a.mu.Lock()
- for i := 0; i < len(a.array) - 1; i++ {
+ for i := 0; i < len(a.array)-1; i++ {
for j := i + 1; j < len(a.array); j++ {
if a.array[i] == a.array[j] {
- a.array = append(a.array[ : j], a.array[j + 1 : ]...)
+ a.array = append(a.array[:j], a.array[j+1:]...)
}
}
}
@@ -385,7 +385,7 @@ func (a *IntArray) LockFunc(f func(array []int)) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
f(a.array)
- return a
+ return a
}
// RLockFunc locks reading by callback function .
@@ -393,7 +393,7 @@ func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
a.mu.RLock()
defer a.mu.RUnlock()
f(a.array)
- return a
+ return a
}
// Merge merges into current array.
@@ -401,58 +401,64 @@ func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *IntArray) Merge(array interface{}) *IntArray {
- switch v := array.(type) {
- case *Array: a.Append(gconv.Ints(v.Slice())...)
- case *IntArray: a.Append(gconv.Ints(v.Slice())...)
- case *StringArray: a.Append(gconv.Ints(v.Slice())...)
- case *SortedArray: a.Append(gconv.Ints(v.Slice())...)
- case *SortedIntArray: a.Append(gconv.Ints(v.Slice())...)
- case *SortedStringArray: a.Append(gconv.Ints(v.Slice())...)
- default:
- a.Append(gconv.Ints(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Append(gconv.Ints(v.Slice())...)
+ case *IntArray:
+ a.Append(gconv.Ints(v.Slice())...)
+ case *StringArray:
+ a.Append(gconv.Ints(v.Slice())...)
+ case *SortedArray:
+ a.Append(gconv.Ints(v.Slice())...)
+ case *SortedIntArray:
+ a.Append(gconv.Ints(v.Slice())...)
+ case *SortedStringArray:
+ a.Append(gconv.Ints(v.Slice())...)
+ default:
+ a.Append(gconv.Ints(array)...)
+ }
+ return a
}
// Fill fills an array with num entries of the value ,
// keys starting at the parameter.
func (a *IntArray) Fill(startIndex int, num int, value int) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if startIndex < 0 {
- startIndex = 0
- }
- for i := startIndex; i < startIndex + num; i++ {
- if i > len(a.array) - 1 {
- a.array = append(a.array, value)
- } else {
- a.array[i] = value
- }
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if startIndex < 0 {
+ startIndex = 0
+ }
+ for i := startIndex; i < startIndex+num; i++ {
+ if i > len(a.array)-1 {
+ a.array = append(a.array, value)
+ } else {
+ a.array[i] = value
+ }
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *IntArray) Chunk(size int) [][]int {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]int
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]int
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// Pad pads array to the specified length with .
@@ -460,105 +466,105 @@ func (a *IntArray) Chunk(size int) [][]int {
// If the absolute value of is less than or equal to the length of the array
// then no padding takes place.
func (a *IntArray) Pad(size int, value int) *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
- return a
- }
- n := size
- if size < 0 {
- n = -size
- }
- n -= len(a.array)
- tmp := make([]int, n)
- for i := 0; i < n; i++ {
- tmp[i] = value
- }
- if size > 0 {
- a.array = append(a.array, tmp...)
- } else {
- a.array = append(tmp, a.array...)
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
+ return a
+ }
+ n := size
+ if size < 0 {
+ n = -size
+ }
+ n -= len(a.array)
+ tmp := make([]int, n)
+ for i := 0; i < n; i++ {
+ tmp[i] = value
+ }
+ if size > 0 {
+ a.array = append(a.array, tmp...)
+ } else {
+ a.array = append(tmp, a.array...)
+ }
+ return a
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *IntArray) SubSlice(offset, size int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]int, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]int, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *IntArray) Rand() int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *IntArray) Rands(size int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]int, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]int, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Shuffle randomly shuffles the array.
func (a *IntArray) Shuffle() *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, v := range grand.Perm(len(a.array)) {
- a.array[i], a.array[v] = a.array[v], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, v := range grand.Perm(len(a.array)) {
+ a.array[i], a.array[v] = a.array[v], a.array[i]
+ }
+ return a
}
// Reverse makes array with elements in reverse order.
func (a *IntArray) Reverse() *IntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, j := 0, len(a.array) - 1; i < j; i, j = i + 1, j - 1 {
- a.array[i], a.array[j] = a.array[j], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, j := 0, len(a.array)-1; i < j; i, j = i+1, j-1 {
+ a.array[i], a.array[j] = a.array[j], a.array[i]
+ }
+ return a
}
// Join joins array elements with a string .
func (a *IntArray) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
@@ -577,4 +583,4 @@ func (a *IntArray) String() string {
a.mu.RLock()
defer a.mu.RUnlock()
return fmt.Sprint(a.array)
-}
\ No newline at end of file
+}
diff --git a/g/container/garray/garray_normal_interface.go b/g/container/garray/garray_normal_interface.go
index f7a342067..e95048ef2 100644
--- a/g/container/garray/garray_normal_interface.go
+++ b/g/container/garray/garray_normal_interface.go
@@ -7,387 +7,387 @@
package garray
import (
- "bytes"
- "fmt"
- "github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
+ "bytes"
+ "fmt"
+ "github.com/gogf/gf/g/internal/rwmutex"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
)
type Array struct {
- mu *rwmutex.RWMutex
- array []interface{}
+ mu *rwmutex.RWMutex
+ array []interface{}
}
// New creates and returns an empty array.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func New(unsafe...bool) *Array {
- return NewArraySize(0, 0, unsafe...)
+func New(unsafe ...bool) *Array {
+ return NewArraySize(0, 0, unsafe...)
}
// See New.
-func NewArray(unsafe...bool) *Array {
- return NewArraySize(0, 0, unsafe...)
+func NewArray(unsafe ...bool) *Array {
+ return NewArraySize(0, 0, unsafe...)
}
// NewArraySize create and returns an array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewArraySize(size int, cap int, unsafe...bool) *Array {
- return &Array{
- mu : rwmutex.New(unsafe...),
- array : make([]interface{}, size, cap),
- }
+func NewArraySize(size int, cap int, unsafe ...bool) *Array {
+ return &Array{
+ mu: rwmutex.New(unsafe...),
+ array: make([]interface{}, size, cap),
+ }
}
// See NewArrayFrom.
-func NewFrom(array []interface{}, unsafe...bool) *Array {
- return NewArrayFrom(array, unsafe...)
+func NewFrom(array []interface{}, unsafe ...bool) *Array {
+ return NewArrayFrom(array, unsafe...)
}
// See NewArrayFromCopy.
-func NewFromCopy(array []interface{}, unsafe...bool) *Array {
- return NewArrayFromCopy(array, unsafe...)
+func NewFromCopy(array []interface{}, unsafe ...bool) *Array {
+ return NewArrayFromCopy(array, unsafe...)
}
// NewArrayFrom creates and returns an array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewArrayFrom(array []interface{}, unsafe...bool) *Array {
- return &Array{
- mu : rwmutex.New(unsafe...),
- array : array,
- }
+func NewArrayFrom(array []interface{}, unsafe ...bool) *Array {
+ return &Array{
+ mu: rwmutex.New(unsafe...),
+ array: array,
+ }
}
// NewArrayFromCopy creates and returns an array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewArrayFromCopy(array []interface{}, unsafe...bool) *Array {
- newArray := make([]interface{}, len(array))
- copy(newArray, array)
- return &Array{
- mu : rwmutex.New(unsafe...),
- array : newArray,
- }
+func NewArrayFromCopy(array []interface{}, unsafe ...bool) *Array {
+ newArray := make([]interface{}, len(array))
+ copy(newArray, array)
+ return &Array{
+ mu: rwmutex.New(unsafe...),
+ array: newArray,
+ }
}
// Get returns the value of the specified index,
// the caller should notice the boundary of the array.
func (a *Array) Get(index int) interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- value := a.array[index]
- return value
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ value := a.array[index]
+ return value
}
// Set sets value to specified index.
func (a *Array) Set(index int, value interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array[index] = value
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array[index] = value
+ return a
}
// SetArray sets the underlying slice array with the given .
func (a *Array) SetArray(array []interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ return a
}
// Replace replaces the array items by given from the beginning of array.
func (a *Array) Replace(array []interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- max := len(array)
- if max > len(a.array) {
- max = len(a.array)
- }
- for i := 0; i < max; i++ {
- a.array[i] = array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ max := len(array)
+ if max > len(a.array) {
+ max = len(a.array)
+ }
+ for i := 0; i < max; i++ {
+ a.array[i] = array[i]
+ }
+ return a
}
// Sum returns the sum of values in an array.
func (a *Array) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += gconv.Int(v)
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += gconv.Int(v)
+ }
+ return
}
// SortFunc sorts the array by custom function .
func (a *Array) SortFunc(less func(v1, v2 interface{}) bool) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Slice(a.array, func(i, j int) bool {
- return less(a.array[i], a.array[j])
- })
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Slice(a.array, func(i, j int) bool {
+ return less(a.array[i], a.array[j])
+ })
+ return a
}
// InsertBefore inserts the to the front of .
func (a *Array) InsertBefore(index int, value interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- rear := append([]interface{}{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
- a.array = append(a.array, rear...)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ rear := append([]interface{}{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
+ a.array = append(a.array, rear...)
+ return a
}
// InsertAfter inserts the to the back of .
func (a *Array) InsertAfter(index int, value interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- rear := append([]interface{}{}, a.array[index + 1 : ]...)
- a.array = append(a.array[0 : index + 1], value)
- a.array = append(a.array, rear...)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ rear := append([]interface{}{}, a.array[index+1:]...)
+ a.array = append(a.array[0:index+1], value)
+ a.array = append(a.array, rear...)
+ return a
}
// Remove removes an item by index.
func (a *Array) Remove(index int) interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
+ a.mu.Lock()
+ defer a.mu.Unlock()
// Determine array boundaries when deleting to improve deletion efficiency。
- if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
- return value
- }
+ if index == 0 {
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
+ }
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- return value
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ return value
}
// PushLeft pushes one or multiple items to the beginning of array.
-func (a *Array) PushLeft(value...interface{}) *Array {
- a.mu.Lock()
- a.array = append(value, a.array...)
- a.mu.Unlock()
- return a
+func (a *Array) PushLeft(value ...interface{}) *Array {
+ a.mu.Lock()
+ a.array = append(value, a.array...)
+ a.mu.Unlock()
+ return a
}
// PushRight pushes one or multiple items to the end of array.
// It equals to Append.
-func (a *Array) PushRight(value...interface{}) *Array {
- a.mu.Lock()
- a.array = append(a.array, value...)
- a.mu.Unlock()
- return a
+func (a *Array) PushRight(value ...interface{}) *Array {
+ a.mu.Lock()
+ a.array = append(a.array, value...)
+ a.mu.Unlock()
+ return a
}
// PopRand randomly pops and return an item out of array.
func (a *Array) PopRand() interface{} {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *Array) PopRands(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]interface{}, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]interface{}, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLeft pops and returns an item from the beginning of array.
func (a *Array) PopLeft() interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *Array) PopRight() interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopLefts pops and returns items from the beginning of array.
func (a *Array) PopLefts(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *Array) PopRights(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *Array) Range(start, end int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]interface{})(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]interface{}, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]interface{})(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]interface{}, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// See PushRight.
-func (a *Array) Append(value...interface{}) *Array {
- a.PushRight(value...)
- return a
+func (a *Array) Append(value ...interface{}) *Array {
+ a.PushRight(value...)
+ return a
}
// Len returns the length of array.
func (a *Array) Len() int {
- a.mu.RLock()
- length := len(a.array)
- a.mu.RUnlock()
- return length
+ a.mu.RLock()
+ length := len(a.array)
+ a.mu.RUnlock()
+ return length
}
// Slice returns the underlying data of array.
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *Array) Slice() []interface{} {
- array := ([]interface{})(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]interface{}, len(a.array))
- copy(array, a.array)
- } else {
- array = a.array
- }
- return array
+ array := ([]interface{})(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]interface{}, len(a.array))
+ copy(array, a.array)
+ } else {
+ array = a.array
+ }
+ return array
}
// Clone returns a new array, which is a copy of current array.
func (a *Array) Clone() (newArray *Array) {
- a.mu.RLock()
- array := make([]interface{}, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewArrayFrom(array, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]interface{}, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewArrayFrom(array, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *Array) Clear() *Array {
- a.mu.Lock()
- if len(a.array) > 0 {
- a.array = make([]interface{}, 0)
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ if len(a.array) > 0 {
+ a.array = make([]interface{}, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// Contains checks whether a value exists in the array.
func (a *Array) Contains(value interface{}) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
// or returns -1 if not exists.
func (a *Array) Search(value interface{}) int {
- if len(a.array) == 0 {
- return -1
- }
- a.mu.RLock()
- result := -1
- for index, v := range a.array {
- if v == value {
- result = index
- break
- }
- }
- a.mu.RUnlock()
+ if len(a.array) == 0 {
+ return -1
+ }
+ a.mu.RLock()
+ result := -1
+ for index, v := range a.array {
+ if v == value {
+ result = index
+ break
+ }
+ }
+ a.mu.RUnlock()
- return result
+ return result
}
// Unique uniques the array, clear repeated items.
func (a *Array) Unique() *Array {
- a.mu.Lock()
- for i := 0; i < len(a.array) - 1; i++ {
- for j := i + 1; j < len(a.array); j++ {
- if a.array[i] == a.array[j] {
- a.array = append(a.array[ : j], a.array[j + 1 : ]...)
- }
- }
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ for i := 0; i < len(a.array)-1; i++ {
+ for j := i + 1; j < len(a.array); j++ {
+ if a.array[i] == a.array[j] {
+ a.array = append(a.array[:j], a.array[j+1:]...)
+ }
+ }
+ }
+ a.mu.Unlock()
+ return a
}
// LockFunc locks writing by callback function .
func (a *Array) LockFunc(f func(array []interface{})) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- f(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ f(a.array)
+ return a
}
// RLockFunc locks reading by callback function .
func (a *Array) RLockFunc(f func(array []interface{})) *Array {
- a.mu.RLock()
- defer a.mu.RUnlock()
- f(a.array)
- return a
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ f(a.array)
+ return a
}
// Merge merges into current array.
@@ -395,58 +395,64 @@ func (a *Array) RLockFunc(f func(array []interface{})) *Array {
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *Array) Merge(array interface{}) *Array {
- switch v := array.(type) {
- case *Array: a.Append(gconv.Interfaces(v.Slice())...)
- case *IntArray: a.Append(gconv.Interfaces(v.Slice())...)
- case *StringArray: a.Append(gconv.Interfaces(v.Slice())...)
- case *SortedArray: a.Append(gconv.Interfaces(v.Slice())...)
- case *SortedIntArray: a.Append(gconv.Interfaces(v.Slice())...)
- case *SortedStringArray: a.Append(gconv.Interfaces(v.Slice())...)
- default:
- a.Append(gconv.Interfaces(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ case *IntArray:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ case *StringArray:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ case *SortedArray:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ case *SortedIntArray:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ case *SortedStringArray:
+ a.Append(gconv.Interfaces(v.Slice())...)
+ default:
+ a.Append(gconv.Interfaces(array)...)
+ }
+ return a
}
// Fill fills an array with num entries of the value ,
// keys starting at the parameter.
func (a *Array) Fill(startIndex int, num int, value interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- if startIndex < 0 {
- startIndex = 0
- }
- for i := startIndex; i < startIndex + num; i++ {
- if i > len(a.array) - 1 {
- a.array = append(a.array, value)
- } else {
- a.array[i] = value
- }
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if startIndex < 0 {
+ startIndex = 0
+ }
+ for i := startIndex; i < startIndex+num; i++ {
+ if i > len(a.array)-1 {
+ a.array = append(a.array, value)
+ } else {
+ a.array[i] = value
+ }
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *Array) Chunk(size int) [][]interface{} {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]interface{}
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]interface{}
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// Pad pads array to the specified length with .
@@ -454,121 +460,121 @@ func (a *Array) Chunk(size int) [][]interface{} {
// If the absolute value of is less than or equal to the length of the array
// then no padding takes place.
func (a *Array) Pad(size int, val interface{}) *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
- return a
- }
- n := size
- if size < 0 {
- n = -size
- }
- n -= len(a.array)
- tmp := make([]interface{}, n)
- for i := 0; i < n; i++ {
- tmp[i] = val
- }
- if size > 0 {
- a.array = append(a.array, tmp...)
- } else {
- a.array = append(tmp, a.array...)
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
+ return a
+ }
+ n := size
+ if size < 0 {
+ n = -size
+ }
+ n -= len(a.array)
+ tmp := make([]interface{}, n)
+ for i := 0; i < n; i++ {
+ tmp[i] = val
+ }
+ if size > 0 {
+ a.array = append(a.array, tmp...)
+ } else {
+ a.array = append(tmp, a.array...)
+ }
+ return a
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *Array) SubSlice(offset, size int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]interface{}, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]interface{}, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *Array) Rand() interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *Array) Rands(size int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]interface{}, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]interface{}, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Shuffle randomly shuffles the array.
func (a *Array) Shuffle() *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, v := range grand.Perm(len(a.array)) {
- a.array[i], a.array[v] = a.array[v], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, v := range grand.Perm(len(a.array)) {
+ a.array[i], a.array[v] = a.array[v], a.array[i]
+ }
+ return a
}
// Reverse makes array with elements in reverse order.
func (a *Array) Reverse() *Array {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, j := 0, len(a.array) - 1; i < j; i, j = i + 1, j - 1 {
- a.array[i], a.array[j] = a.array[j], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, j := 0, len(a.array)-1; i < j; i, j = i+1, j-1 {
+ a.array[i], a.array[j] = a.array[j], a.array[i]
+ }
+ return a
}
// Join joins array elements with a string .
func (a *Array) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
func (a *Array) CountValues() map[interface{}]int {
- m := make(map[interface{}]int)
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- m[v]++
- }
- return m
+ m := make(map[interface{}]int)
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ m[v]++
+ }
+ return m
}
// String returns current array as a string.
func (a *Array) String() string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return fmt.Sprint(a.array)
-}
\ No newline at end of file
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return fmt.Sprint(a.array)
+}
diff --git a/g/container/garray/garray_normal_string.go b/g/container/garray/garray_normal_string.go
index dee581088..702ecda52 100644
--- a/g/container/garray/garray_normal_string.go
+++ b/g/container/garray/garray_normal_string.go
@@ -7,14 +7,14 @@
package garray
import (
- "bytes"
+ "bytes"
"fmt"
"github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
- "strings"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
+ "strings"
)
type StringArray struct {
@@ -25,40 +25,40 @@ type StringArray struct {
// NewStringArray creates and returns an empty array.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewStringArray(unsafe...bool) *StringArray {
- return NewStringArraySize(0, 0, unsafe...)
+func NewStringArray(unsafe ...bool) *StringArray {
+ return NewStringArraySize(0, 0, unsafe...)
}
// NewStringArraySize create and returns an array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewStringArraySize(size int, cap int, unsafe...bool) *StringArray {
- return &StringArray{
- mu : rwmutex.New(unsafe...),
- array : make([]string, size, cap),
- }
+func NewStringArraySize(size int, cap int, unsafe ...bool) *StringArray {
+ return &StringArray{
+ mu: rwmutex.New(unsafe...),
+ array: make([]string, size, cap),
+ }
}
// NewStringArrayFrom creates and returns an array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewStringArrayFrom(array []string, unsafe...bool) *StringArray {
- return &StringArray {
- mu : rwmutex.New(unsafe...),
- array : array,
+func NewStringArrayFrom(array []string, unsafe ...bool) *StringArray {
+ return &StringArray{
+ mu: rwmutex.New(unsafe...),
+ array: array,
}
}
// NewStringArrayFromCopy creates and returns an array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewStringArrayFromCopy(array []string, unsafe...bool) *StringArray {
- newArray := make([]string, len(array))
- copy(newArray, array)
- return &StringArray{
- mu : rwmutex.New(unsafe...),
- array : newArray,
- }
+func NewStringArrayFromCopy(array []string, unsafe ...bool) *StringArray {
+ newArray := make([]string, len(array))
+ copy(newArray, array)
+ return &StringArray{
+ mu: rwmutex.New(unsafe...),
+ array: newArray,
+ }
}
// Get returns the value of the specified index,
@@ -75,88 +75,88 @@ func (a *StringArray) Set(index int, value string) *StringArray {
a.mu.Lock()
defer a.mu.Unlock()
a.array[index] = value
- return a
+ return a
}
// SetArray sets the underlying slice array with the given .
func (a *StringArray) SetArray(array []string) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ return a
}
// Replace replaces the array items by given from the beginning of array.
func (a *StringArray) Replace(array []string) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- max := len(array)
- if max > len(a.array) {
- max = len(a.array)
- }
- for i := 0; i < max; i++ {
- a.array[i] = array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ max := len(array)
+ if max > len(a.array) {
+ max = len(a.array)
+ }
+ for i := 0; i < max; i++ {
+ a.array[i] = array[i]
+ }
+ return a
}
// Sum returns the sum of values in an array.
func (a *StringArray) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += gconv.Int(v)
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += gconv.Int(v)
+ }
+ return
}
// Sort sorts the array in increasing order.
// The parameter controls whether sort
// in increasing order(default) or decreasing order
-func (a *StringArray) Sort(reverse...bool) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if len(reverse) > 0 && reverse[0] {
- sort.Slice(a.array, func(i, j int) bool {
- if strings.Compare(a.array[i], a.array[j]) < 0 {
- return false
- }
- return true
- })
- } else {
- sort.Strings(a.array)
- }
- return a
+func (a *StringArray) Sort(reverse ...bool) *StringArray {
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if len(reverse) > 0 && reverse[0] {
+ sort.Slice(a.array, func(i, j int) bool {
+ if strings.Compare(a.array[i], a.array[j]) < 0 {
+ return false
+ }
+ return true
+ })
+ } else {
+ sort.Strings(a.array)
+ }
+ return a
}
// SortFunc sorts the array by custom function .
func (a *StringArray) SortFunc(less func(v1, v2 string) bool) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Slice(a.array, func(i, j int) bool {
- return less(a.array[i], a.array[j])
- })
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Slice(a.array, func(i, j int) bool {
+ return less(a.array[i], a.array[j])
+ })
+ return a
}
// InsertBefore inserts the to the front of .
func (a *StringArray) InsertBefore(index int, value string) *StringArray {
a.mu.Lock()
defer a.mu.Unlock()
- rear := append([]string{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
+ rear := append([]string{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
a.array = append(a.array, rear...)
- return a
+ return a
}
// InsertAfter inserts the to the back of .
func (a *StringArray) InsertAfter(index int, value string) *StringArray {
a.mu.Lock()
defer a.mu.Unlock()
- rear := append([]string{}, a.array[index + 1:]...)
- a.array = append(a.array[ 0: index + 1], value)
+ rear := append([]string{}, a.array[index+1:]...)
+ a.array = append(a.array[0:index+1], value)
a.array = append(a.array, rear...)
- return a
+ return a
}
// Remove removes an item by index.
@@ -165,139 +165,139 @@ func (a *StringArray) Remove(index int) string {
defer a.mu.Unlock()
// Determine array boundaries when deleting to improve deletion efficiency。
if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
+ value := a.array[0]
+ a.array = a.array[1:]
return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
return value
}
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
return value
}
// PushLeft pushes one or multiple items to the beginning of array.
-func (a *StringArray) PushLeft(value...string) *StringArray {
- a.mu.Lock()
- a.array = append(value, a.array...)
- a.mu.Unlock()
- return a
+func (a *StringArray) PushLeft(value ...string) *StringArray {
+ a.mu.Lock()
+ a.array = append(value, a.array...)
+ a.mu.Unlock()
+ return a
}
// PushRight pushes one or multiple items to the end of array.
// It equals to Append.
-func (a *StringArray) PushRight(value...string) *StringArray {
- a.mu.Lock()
- a.array = append(a.array, value...)
- a.mu.Unlock()
- return a
+func (a *StringArray) PushRight(value ...string) *StringArray {
+ a.mu.Lock()
+ a.array = append(a.array, value...)
+ a.mu.Unlock()
+ return a
}
// PopLeft pops and returns an item from the beginning of array.
func (a *StringArray) PopLeft() string {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *StringArray) PopRight() string {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopRand randomly pops and return an item out of array.
func (a *StringArray) PopRand() string {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *StringArray) PopRands(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]string, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]string, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLefts pops and returns items from the beginning of array.
func (a *StringArray) PopLefts(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *StringArray) PopRights(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *StringArray) Range(start, end int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]string)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]string, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]string)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]string, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// See PushRight.
-func (a *StringArray) Append(value...string) *StringArray {
+func (a *StringArray) Append(value ...string) *StringArray {
a.mu.Lock()
a.array = append(a.array, value...)
a.mu.Unlock()
- return a
+ return a
}
// Len returns the length of array.
@@ -326,26 +326,26 @@ func (a *StringArray) Slice() []string {
// Clone returns a new array, which is a copy of current array.
func (a *StringArray) Clone() (newArray *StringArray) {
- a.mu.RLock()
- array := make([]string, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewStringArrayFrom(array, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]string, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewStringArrayFrom(array, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *StringArray) Clear() *StringArray {
- a.mu.Lock()
- if len(a.array) > 0 {
- a.array = make([]string, 0)
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ if len(a.array) > 0 {
+ a.array = make([]string, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// Contains checks whether a value exists in the array.
func (a *StringArray) Contains(value string) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
@@ -369,10 +369,10 @@ func (a *StringArray) Search(value string) int {
// Unique uniques the array, clear repeated items.
func (a *StringArray) Unique() *StringArray {
a.mu.Lock()
- for i := 0; i < len(a.array) - 1; i++ {
+ for i := 0; i < len(a.array)-1; i++ {
for j := i + 1; j < len(a.array); j++ {
if a.array[i] == a.array[j] {
- a.array = append(a.array[ : j], a.array[j + 1 : ]...)
+ a.array = append(a.array[:j], a.array[j+1:]...)
}
}
}
@@ -385,7 +385,7 @@ func (a *StringArray) LockFunc(f func(array []string)) *StringArray {
a.mu.Lock()
defer a.mu.Unlock()
f(a.array)
- return a
+ return a
}
// RLockFunc locks reading by callback function .
@@ -393,7 +393,7 @@ func (a *StringArray) RLockFunc(f func(array []string)) *StringArray {
a.mu.RLock()
defer a.mu.RUnlock()
f(a.array)
- return a
+ return a
}
// Merge merges into current array.
@@ -401,58 +401,64 @@ func (a *StringArray) RLockFunc(f func(array []string)) *StringArray {
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *StringArray) Merge(array interface{}) *StringArray {
- switch v := array.(type) {
- case *Array: a.Append(gconv.Strings(v.Slice())...)
- case *IntArray: a.Append(gconv.Strings(v.Slice())...)
- case *StringArray: a.Append(gconv.Strings(v.Slice())...)
- case *SortedArray: a.Append(gconv.Strings(v.Slice())...)
- case *SortedIntArray: a.Append(gconv.Strings(v.Slice())...)
- case *SortedStringArray: a.Append(gconv.Strings(v.Slice())...)
- default:
- a.Append(gconv.Strings(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Append(gconv.Strings(v.Slice())...)
+ case *IntArray:
+ a.Append(gconv.Strings(v.Slice())...)
+ case *StringArray:
+ a.Append(gconv.Strings(v.Slice())...)
+ case *SortedArray:
+ a.Append(gconv.Strings(v.Slice())...)
+ case *SortedIntArray:
+ a.Append(gconv.Strings(v.Slice())...)
+ case *SortedStringArray:
+ a.Append(gconv.Strings(v.Slice())...)
+ default:
+ a.Append(gconv.Strings(array)...)
+ }
+ return a
}
// Fill fills an array with num entries of the value ,
// keys starting at the parameter.
func (a *StringArray) Fill(startIndex int, num int, value string) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if startIndex < 0 {
- startIndex = 0
- }
- for i := startIndex; i < startIndex + num; i++ {
- if i > len(a.array) - 1 {
- a.array = append(a.array, value)
- } else {
- a.array[i] = value
- }
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if startIndex < 0 {
+ startIndex = 0
+ }
+ for i := startIndex; i < startIndex+num; i++ {
+ if i > len(a.array)-1 {
+ a.array = append(a.array, value)
+ } else {
+ a.array[i] = value
+ }
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *StringArray) Chunk(size int) [][]string {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]string
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]string
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// Pad pads array to the specified length with .
@@ -460,105 +466,105 @@ func (a *StringArray) Chunk(size int) [][]string {
// If the absolute value of is less than or equal to the length of the array
// then no padding takes place.
func (a *StringArray) Pad(size int, value string) *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
- return a
- }
- n := size
- if size < 0 {
- n = -size
- }
- n -= len(a.array)
- tmp := make([]string, n)
- for i := 0; i < n; i++ {
- tmp[i] = value
- }
- if size > 0 {
- a.array = append(a.array, tmp...)
- } else {
- a.array = append(tmp, a.array...)
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size == 0 || (size > 0 && size < len(a.array)) || (size < 0 && size > -len(a.array)) {
+ return a
+ }
+ n := size
+ if size < 0 {
+ n = -size
+ }
+ n -= len(a.array)
+ tmp := make([]string, n)
+ for i := 0; i < n; i++ {
+ tmp[i] = value
+ }
+ if size > 0 {
+ a.array = append(a.array, tmp...)
+ } else {
+ a.array = append(tmp, a.array...)
+ }
+ return a
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *StringArray) SubSlice(offset, size int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]string, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]string, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *StringArray) Rand() string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *StringArray) Rands(size int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]string, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]string, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Shuffle randomly shuffles the array.
func (a *StringArray) Shuffle() *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, v := range grand.Perm(len(a.array)) {
- a.array[i], a.array[v] = a.array[v], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, v := range grand.Perm(len(a.array)) {
+ a.array[i], a.array[v] = a.array[v], a.array[i]
+ }
+ return a
}
// Reverse makes array with elements in reverse order.
func (a *StringArray) Reverse() *StringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- for i, j := 0, len(a.array) - 1; i < j; i, j = i + 1, j - 1 {
- a.array[i], a.array[j] = a.array[j], a.array[i]
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for i, j := 0, len(a.array)-1; i < j; i, j = i+1, j-1 {
+ a.array[i], a.array[j] = a.array[j], a.array[i]
+ }
+ return a
}
// Join joins array elements with a string .
func (a *StringArray) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
diff --git a/g/container/garray/garray_sorted_int.go b/g/container/garray/garray_sorted_int.go
index 8cc7a6356..e7f792479 100644
--- a/g/container/garray/garray_sorted_int.go
+++ b/g/container/garray/garray_sorted_int.go
@@ -7,286 +7,286 @@
package garray
import (
- "bytes"
+ "bytes"
"fmt"
"github.com/gogf/gf/g/container/gtype"
- "github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
+ "github.com/gogf/gf/g/internal/rwmutex"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
)
// It's using increasing order in default.
type SortedIntArray struct {
- mu *rwmutex.RWMutex
- array []int
- unique *gtype.Bool // Whether enable unique feature(false)
- comparator func(v1, v2 int) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
+ mu *rwmutex.RWMutex
+ array []int
+ unique *gtype.Bool // Whether enable unique feature(false)
+ comparator func(v1, v2 int) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
}
// NewSortedIntArray creates and returns an empty sorted array.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedIntArray(unsafe...bool) *SortedIntArray {
- return NewSortedIntArraySize(0, unsafe...)
+func NewSortedIntArray(unsafe ...bool) *SortedIntArray {
+ return NewSortedIntArraySize(0, unsafe...)
}
// NewSortedIntArraySize create and returns an sorted array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedIntArraySize(cap int, unsafe...bool) *SortedIntArray {
- return &SortedIntArray {
- mu : rwmutex.New(unsafe...),
- array : make([]int, 0, cap),
- unique : gtype.NewBool(),
- comparator : func(v1, v2 int) int {
- if v1 < v2 {
- return -1
- }
- if v1 > v2 {
- return 1
- }
- return 0
- },
- }
+func NewSortedIntArraySize(cap int, unsafe ...bool) *SortedIntArray {
+ return &SortedIntArray{
+ mu: rwmutex.New(unsafe...),
+ array: make([]int, 0, cap),
+ unique: gtype.NewBool(),
+ comparator: func(v1, v2 int) int {
+ if v1 < v2 {
+ return -1
+ }
+ if v1 > v2 {
+ return 1
+ }
+ return 0
+ },
+ }
}
// NewIntArrayFrom creates and returns an sorted array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedIntArrayFrom(array []int, unsafe...bool) *SortedIntArray {
- a := NewSortedIntArraySize(0, unsafe...)
- a.array = array
- sort.Ints(a.array)
- return a
+func NewSortedIntArrayFrom(array []int, unsafe ...bool) *SortedIntArray {
+ a := NewSortedIntArraySize(0, unsafe...)
+ a.array = array
+ sort.Ints(a.array)
+ return a
}
// NewSortedIntArrayFromCopy creates and returns an sorted array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedIntArrayFromCopy(array []int, unsafe...bool) *SortedIntArray {
- newArray := make([]int, len(array))
- copy(newArray, array)
- return NewSortedIntArrayFrom(newArray, unsafe...)
+func NewSortedIntArrayFromCopy(array []int, unsafe ...bool) *SortedIntArray {
+ newArray := make([]int, len(array))
+ copy(newArray, array)
+ return NewSortedIntArrayFrom(newArray, unsafe...)
}
// SetArray sets the underlying slice array with the given .
func (a *SortedIntArray) SetArray(array []int) *SortedIntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- sort.Ints(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ sort.Ints(a.array)
+ return a
}
// Sort sorts the array in increasing order.
// The parameter controls whether sort
// in increasing order(default) or decreasing order.
func (a *SortedIntArray) Sort() *SortedIntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Ints(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Ints(a.array)
+ return a
}
// Add adds one or multiple values to sorted array, the array always keeps sorted.
-func (a *SortedIntArray) Add(values...int) *SortedIntArray {
- if len(values) == 0 {
- return a
- }
- a.mu.Lock()
- defer a.mu.Unlock()
- for _, value := range values {
- index, cmp := a.binSearch(value, false)
- if a.unique.Val() && cmp == 0 {
- continue
- }
- if index < 0 {
- a.array = append(a.array, value)
- continue
- }
- if cmp > 0 {
- index++
- }
- rear := append([]int{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
- a.array = append(a.array, rear...)
- }
- return a
+func (a *SortedIntArray) Add(values ...int) *SortedIntArray {
+ if len(values) == 0 {
+ return a
+ }
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for _, value := range values {
+ index, cmp := a.binSearch(value, false)
+ if a.unique.Val() && cmp == 0 {
+ continue
+ }
+ if index < 0 {
+ a.array = append(a.array, value)
+ continue
+ }
+ if cmp > 0 {
+ index++
+ }
+ rear := append([]int{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
+ a.array = append(a.array, rear...)
+ }
+ return a
}
// Get returns the value of the specified index,
// the caller should notice the boundary of the array.
func (a *SortedIntArray) Get(index int) int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- value := a.array[index]
- return value
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ value := a.array[index]
+ return value
}
// Remove removes an item by index.
func (a *SortedIntArray) Remove(index int) int {
- a.mu.Lock()
- defer a.mu.Unlock()
+ a.mu.Lock()
+ defer a.mu.Unlock()
// Determine array boundaries when deleting to improve deletion efficiency.
- if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
- return value
- }
+ if index == 0 {
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
+ }
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- return value
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ return value
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedIntArray) PopLeft() int {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *SortedIntArray) PopRight() int {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopRand randomly pops and return an item out of array.
func (a *SortedIntArray) PopRand() int {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *SortedIntArray) PopRands(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]int, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]int, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLefts pops and returns items from the beginning of array.
func (a *SortedIntArray) PopLefts(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *SortedIntArray) PopRights(size int) []int {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedIntArray) Range(start, end int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]int)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]int, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]int)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]int, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// Len returns the length of array.
func (a *SortedIntArray) Len() int {
- a.mu.RLock()
- length := len(a.array)
- a.mu.RUnlock()
- return length
+ a.mu.RLock()
+ length := len(a.array)
+ a.mu.RUnlock()
+ return length
}
// Sum returns the sum of values in an array.
func (a *SortedIntArray) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += v
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += v
+ }
+ return
}
// Slice returns the underlying data of array.
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedIntArray) Slice() []int {
- array := ([]int)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]int, len(a.array))
- copy(array, a.array)
- } else {
- array = a.array
- }
- return array
+ array := ([]int)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]int, len(a.array))
+ copy(array, a.array)
+ } else {
+ array = a.array
+ }
+ return array
}
// Contains checks whether a value exists in the array.
func (a *SortedIntArray) Contains(value int) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
// or returns -1 if not exists.
func (a *SortedIntArray) Search(value int) (index int) {
- if i, r := a.binSearch(value, true); r == 0 {
- return i
- }
- return -1
+ if i, r := a.binSearch(value, true); r == 0 {
+ return i
+ }
+ return -1
}
// Binary search.
@@ -295,93 +295,95 @@ func (a *SortedIntArray) Search(value int) (index int) {
// If lesser than 0, it means the value at is lesser than .
// If greater than 0, it means the value at is greater than .
func (a *SortedIntArray) binSearch(value int, lock bool) (index int, result int) {
- if len(a.array) == 0 {
- return -1, -2
- }
- if lock {
- a.mu.RLock()
- defer a.mu.RUnlock()
- }
- min := 0
- max := len(a.array) - 1
- mid := 0
- cmp := -2
- for min <= max {
- mid = int((min + max) / 2)
- cmp = a.comparator(value, a.array[mid])
- switch {
- case cmp < 0 : max = mid - 1
- case cmp > 0 : min = mid + 1
- default :
- return mid, cmp
- }
- }
- return mid, cmp
+ if len(a.array) == 0 {
+ return -1, -2
+ }
+ if lock {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ }
+ min := 0
+ max := len(a.array) - 1
+ mid := 0
+ cmp := -2
+ for min <= max {
+ mid = int((min + max) / 2)
+ cmp = a.comparator(value, a.array[mid])
+ switch {
+ case cmp < 0:
+ max = mid - 1
+ case cmp > 0:
+ min = mid + 1
+ default:
+ return mid, cmp
+ }
+ }
+ return mid, cmp
}
// SetUnique sets unique mark to the array,
// which means it does not contain any repeated items.
// It also do unique check, remove all repeated items.
func (a *SortedIntArray) SetUnique(unique bool) *SortedIntArray {
- oldUnique := a.unique.Val()
- a.unique.Set(unique)
- if unique && oldUnique != unique {
- a.Unique()
- }
- return a
+ oldUnique := a.unique.Val()
+ a.unique.Set(unique)
+ if unique && oldUnique != unique {
+ a.Unique()
+ }
+ return a
}
// Unique uniques the array, clear repeated items.
func (a *SortedIntArray) Unique() *SortedIntArray {
- a.mu.Lock()
- i := 0
- for {
- if i == len(a.array) - 1 {
- break
- }
- if a.comparator(a.array[i], a.array[i + 1]) == 0 {
- a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...)
- } else {
- i++
- }
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ i := 0
+ for {
+ if i == len(a.array)-1 {
+ break
+ }
+ if a.comparator(a.array[i], a.array[i+1]) == 0 {
+ a.array = append(a.array[:i+1], a.array[i+1+1:]...)
+ } else {
+ i++
+ }
+ }
+ a.mu.Unlock()
+ return a
}
// Clone returns a new array, which is a copy of current array.
func (a *SortedIntArray) Clone() (newArray *SortedIntArray) {
- a.mu.RLock()
- array := make([]int, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewSortedIntArrayFrom(array, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]int, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewSortedIntArrayFrom(array, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *SortedIntArray) Clear() *SortedIntArray {
- a.mu.Lock()
- if len(a.array) > 0 {
- a.array = make([]int, 0)
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ if len(a.array) > 0 {
+ a.array = make([]int, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// LockFunc locks writing by callback function .
func (a *SortedIntArray) LockFunc(f func(array []int)) *SortedIntArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- f(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ f(a.array)
+ return a
}
// RLockFunc locks reading by callback function .
func (a *SortedIntArray) RLockFunc(f func(array []int)) *SortedIntArray {
- a.mu.RLock()
- defer a.mu.RUnlock()
- f(a.array)
- return a
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ f(a.array)
+ return a
}
// Merge merges into current array.
@@ -389,99 +391,105 @@ func (a *SortedIntArray) RLockFunc(f func(array []int)) *SortedIntArray {
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *SortedIntArray) Merge(array interface{}) *SortedIntArray {
- switch v := array.(type) {
- case *Array: a.Add(gconv.Ints(v.Slice())...)
- case *IntArray: a.Add(gconv.Ints(v.Slice())...)
- case *StringArray: a.Add(gconv.Ints(v.Slice())...)
- case *SortedArray: a.Add(gconv.Ints(v.Slice())...)
- case *SortedIntArray: a.Add(gconv.Ints(v.Slice())...)
- case *SortedStringArray: a.Add(gconv.Ints(v.Slice())...)
- default:
- a.Add(gconv.Ints(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Add(gconv.Ints(v.Slice())...)
+ case *IntArray:
+ a.Add(gconv.Ints(v.Slice())...)
+ case *StringArray:
+ a.Add(gconv.Ints(v.Slice())...)
+ case *SortedArray:
+ a.Add(gconv.Ints(v.Slice())...)
+ case *SortedIntArray:
+ a.Add(gconv.Ints(v.Slice())...)
+ case *SortedStringArray:
+ a.Add(gconv.Ints(v.Slice())...)
+ default:
+ a.Add(gconv.Ints(array)...)
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *SortedIntArray) Chunk(size int) [][]int {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]int
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]int
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *SortedIntArray) SubSlice(offset, size int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]int, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]int, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *SortedIntArray) Rand() int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *SortedIntArray) Rands(size int) []int {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]int, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]int, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Join joins array elements with a string .
func (a *SortedIntArray) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
@@ -500,4 +508,4 @@ func (a *SortedIntArray) String() string {
a.mu.RLock()
defer a.mu.RUnlock()
return fmt.Sprint(a.array)
-}
\ No newline at end of file
+}
diff --git a/g/container/garray/garray_sorted_interface.go b/g/container/garray/garray_sorted_interface.go
index e5be83324..cb18f5933 100644
--- a/g/container/garray/garray_sorted_interface.go
+++ b/g/container/garray/garray_sorted_interface.go
@@ -7,22 +7,22 @@
package garray
import (
- "bytes"
+ "bytes"
"fmt"
"github.com/gogf/gf/g/container/gtype"
- "github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
+ "github.com/gogf/gf/g/internal/rwmutex"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
)
// It's using increasing order in default.
type SortedArray struct {
- mu *rwmutex.RWMutex
- array []interface{}
- unique *gtype.Bool // Whether enable unique feature(false)
- comparator func(v1, v2 interface{}) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
+ mu *rwmutex.RWMutex
+ array []interface{}
+ unique *gtype.Bool // Whether enable unique feature(false)
+ comparator func(v1, v2 interface{}) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
}
// NewSortedArray creates and returns an empty sorted array.
@@ -31,254 +31,254 @@ type SortedArray struct {
// if it returns value < 0, means v1 < v2;
// if it returns value = 0, means v1 = v2;
// if it returns value > 0, means v1 > v2;
-func NewSortedArray(comparator func(v1, v2 interface{}) int, unsafe...bool) *SortedArray {
- return NewSortedArraySize(0, comparator, unsafe...)
+func NewSortedArray(comparator func(v1, v2 interface{}) int, unsafe ...bool) *SortedArray {
+ return NewSortedArraySize(0, comparator, unsafe...)
}
// NewSortedArraySize create and returns an sorted array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedArraySize(cap int, comparator func(v1, v2 interface{}) int, unsafe...bool) *SortedArray {
- return &SortedArray{
- mu : rwmutex.New(unsafe...),
- unique : gtype.NewBool(),
- array : make([]interface{}, 0, cap),
- comparator : comparator,
- }
+func NewSortedArraySize(cap int, comparator func(v1, v2 interface{}) int, unsafe ...bool) *SortedArray {
+ return &SortedArray{
+ mu: rwmutex.New(unsafe...),
+ unique: gtype.NewBool(),
+ array: make([]interface{}, 0, cap),
+ comparator: comparator,
+ }
}
// NewSortedArrayFrom creates and returns an sorted array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedArrayFrom(array []interface{}, comparator func(v1, v2 interface{}) int, unsafe...bool) *SortedArray {
- a := NewSortedArraySize(0, comparator, unsafe...)
- a.array = array
- sort.Slice(a.array, func(i, j int) bool {
- return a.comparator(a.array[i], a.array[j]) < 0
- })
- return a
+func NewSortedArrayFrom(array []interface{}, comparator func(v1, v2 interface{}) int, unsafe ...bool) *SortedArray {
+ a := NewSortedArraySize(0, comparator, unsafe...)
+ a.array = array
+ sort.Slice(a.array, func(i, j int) bool {
+ return a.comparator(a.array[i], a.array[j]) < 0
+ })
+ return a
}
// NewSortedArrayFromCopy creates and returns an sorted array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedArrayFromCopy(array []interface{}, comparator func(v1, v2 interface{}) int, unsafe...bool) *SortedArray {
- newArray := make([]interface{}, len(array))
- copy(newArray, array)
- return NewSortedArrayFrom(newArray, comparator, unsafe...)
+func NewSortedArrayFromCopy(array []interface{}, comparator func(v1, v2 interface{}) int, unsafe ...bool) *SortedArray {
+ newArray := make([]interface{}, len(array))
+ copy(newArray, array)
+ return NewSortedArrayFrom(newArray, comparator, unsafe...)
}
// SetArray sets the underlying slice array with the given .
func (a *SortedArray) SetArray(array []interface{}) *SortedArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- sort.Slice(a.array, func(i, j int) bool {
- return a.comparator(a.array[i], a.array[j]) < 0
- })
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ sort.Slice(a.array, func(i, j int) bool {
+ return a.comparator(a.array[i], a.array[j]) < 0
+ })
+ return a
}
// Sort sorts the array in increasing order.
// The parameter controls whether sort
// in increasing order(default) or decreasing order
func (a *SortedArray) Sort() *SortedArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Slice(a.array, func(i, j int) bool {
- return a.comparator(a.array[i], a.array[j]) < 0
- })
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Slice(a.array, func(i, j int) bool {
+ return a.comparator(a.array[i], a.array[j]) < 0
+ })
+ return a
}
// Add adds one or multiple values to sorted array, the array always keeps sorted.
-func (a *SortedArray) Add(values...interface{}) *SortedArray {
- if len(values) == 0 {
- return a
- }
- a.mu.Lock()
- defer a.mu.Unlock()
- for _, value := range values {
- index, cmp := a.binSearch(value, false)
- if a.unique.Val() && cmp == 0 {
- continue
- }
- if index < 0 {
- a.array = append(a.array, value)
- continue
- }
- if cmp > 0 {
- index++
- }
- rear := append([]interface{}{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
- a.array = append(a.array, rear...)
- }
- return a
+func (a *SortedArray) Add(values ...interface{}) *SortedArray {
+ if len(values) == 0 {
+ return a
+ }
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for _, value := range values {
+ index, cmp := a.binSearch(value, false)
+ if a.unique.Val() && cmp == 0 {
+ continue
+ }
+ if index < 0 {
+ a.array = append(a.array, value)
+ continue
+ }
+ if cmp > 0 {
+ index++
+ }
+ rear := append([]interface{}{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
+ a.array = append(a.array, rear...)
+ }
+ return a
}
// Get returns the value of the specified index,
// the caller should notice the boundary of the array.
func (a *SortedArray) Get(index int) interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- value := a.array[index]
- return value
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ value := a.array[index]
+ return value
}
// Remove removes an item by index.
func (a *SortedArray) Remove(index int) interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
+ a.mu.Lock()
+ defer a.mu.Unlock()
// Determine array boundaries when deleting to improve deletion efficiency.
- if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
- return value
- }
+ if index == 0 {
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
+ }
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- return value
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ return value
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedArray) PopLeft() interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *SortedArray) PopRight() interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopRand randomly pops and return an item out of array.
func (a *SortedArray) PopRand() interface{} {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *SortedArray) PopRands(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]interface{}, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]interface{}, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLefts pops and returns items from the beginning of array.
func (a *SortedArray) PopLefts(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *SortedArray) PopRights(size int) []interface{} {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedArray) Range(start, end int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]interface{})(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]interface{}, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]interface{})(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]interface{}, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// Sum returns the sum of values in an array.
func (a *SortedArray) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += gconv.Int(v)
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += gconv.Int(v)
+ }
+ return
}
// Len returns the length of array.
func (a *SortedArray) Len() int {
- a.mu.RLock()
- length := len(a.array)
- a.mu.RUnlock()
- return length
+ a.mu.RLock()
+ length := len(a.array)
+ a.mu.RUnlock()
+ return length
}
// Slice returns the underlying data of array.
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedArray) Slice() []interface{} {
- array := ([]interface{})(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]interface{}, len(a.array))
- copy(array, a.array)
- } else {
- array = a.array
- }
- return array
+ array := ([]interface{})(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]interface{}, len(a.array))
+ copy(array, a.array)
+ } else {
+ array = a.array
+ }
+ return array
}
// Contains checks whether a value exists in the array.
func (a *SortedArray) Contains(value interface{}) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
@@ -295,94 +295,96 @@ func (a *SortedArray) Search(value interface{}) (index int) {
// If equals to 0, it means the value at is equals to .
// If lesser than 0, it means the value at is lesser than .
// If greater than 0, it means the value at is greater than .
-func (a *SortedArray) binSearch(value interface{}, lock bool)(index int, result int) {
- if len(a.array) == 0 {
- return -1, -2
- }
- if lock {
- a.mu.RLock()
- defer a.mu.RUnlock()
- }
- min := 0
- max := len(a.array) - 1
- mid := 0
- cmp := -2
- for min <= max {
- mid = int((min + max) / 2)
- cmp = a.comparator(value, a.array[mid])
- switch {
- case cmp < 0 : max = mid - 1
- case cmp > 0 : min = mid + 1
- default :
- return mid, cmp
- }
- }
- return mid, cmp
+func (a *SortedArray) binSearch(value interface{}, lock bool) (index int, result int) {
+ if len(a.array) == 0 {
+ return -1, -2
+ }
+ if lock {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ }
+ min := 0
+ max := len(a.array) - 1
+ mid := 0
+ cmp := -2
+ for min <= max {
+ mid = int((min + max) / 2)
+ cmp = a.comparator(value, a.array[mid])
+ switch {
+ case cmp < 0:
+ max = mid - 1
+ case cmp > 0:
+ min = mid + 1
+ default:
+ return mid, cmp
+ }
+ }
+ return mid, cmp
}
// SetUnique sets unique mark to the array,
// which means it does not contain any repeated items.
// It also do unique check, remove all repeated items.
func (a *SortedArray) SetUnique(unique bool) *SortedArray {
- oldUnique := a.unique.Val()
- a.unique.Set(unique)
- if unique && oldUnique != unique {
- a.Unique()
- }
- return a
+ oldUnique := a.unique.Val()
+ a.unique.Set(unique)
+ if unique && oldUnique != unique {
+ a.Unique()
+ }
+ return a
}
// Unique uniques the array, clear repeated items.
func (a *SortedArray) Unique() *SortedArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- i := 0
- for {
- if i == len(a.array) - 1 {
- break
- }
- if a.comparator(a.array[i], a.array[i + 1]) == 0 {
- a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...)
- } else {
- i++
- }
- }
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ i := 0
+ for {
+ if i == len(a.array)-1 {
+ break
+ }
+ if a.comparator(a.array[i], a.array[i+1]) == 0 {
+ a.array = append(a.array[:i+1], a.array[i+1+1:]...)
+ } else {
+ i++
+ }
+ }
+ return a
}
// Clone returns a new array, which is a copy of current array.
func (a *SortedArray) Clone() (newArray *SortedArray) {
- a.mu.RLock()
- array := make([]interface{}, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewSortedArrayFrom(array, a.comparator, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]interface{}, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewSortedArrayFrom(array, a.comparator, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *SortedArray) Clear() *SortedArray {
- a.mu.Lock()
- if len(a.array) > 0 {
- a.array = make([]interface{}, 0)
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ if len(a.array) > 0 {
+ a.array = make([]interface{}, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// LockFunc locks writing by callback function .
func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- f(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ f(a.array)
+ return a
}
// RLockFunc locks reading by callback function .
func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray {
- a.mu.RLock()
- defer a.mu.RUnlock()
- f(a.array)
- return a
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ f(a.array)
+ return a
}
// Merge merges into current array.
@@ -390,99 +392,105 @@ func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray {
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *SortedArray) Merge(array interface{}) *SortedArray {
- switch v := array.(type) {
- case *Array: a.Add(gconv.Interfaces(v.Slice())...)
- case *IntArray: a.Add(gconv.Interfaces(v.Slice())...)
- case *StringArray: a.Add(gconv.Interfaces(v.Slice())...)
- case *SortedArray: a.Add(gconv.Interfaces(v.Slice())...)
- case *SortedIntArray: a.Add(gconv.Interfaces(v.Slice())...)
- case *SortedStringArray: a.Add(gconv.Interfaces(v.Slice())...)
- default:
- a.Add(gconv.Interfaces(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ case *IntArray:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ case *StringArray:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ case *SortedArray:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ case *SortedIntArray:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ case *SortedStringArray:
+ a.Add(gconv.Interfaces(v.Slice())...)
+ default:
+ a.Add(gconv.Interfaces(array)...)
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *SortedArray) Chunk(size int) [][]interface{} {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]interface{}
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]interface{}
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *SortedArray) SubSlice(offset, size int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]interface{}, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]interface{}, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *SortedArray) Rand() interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *SortedArray) Rands(size int) []interface{} {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]interface{}, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]interface{}, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Join joins array elements with a string .
func (a *SortedArray) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
@@ -501,4 +509,4 @@ func (a *SortedArray) String() string {
a.mu.RLock()
defer a.mu.RUnlock()
return fmt.Sprint(a.array)
-}
\ No newline at end of file
+}
diff --git a/g/container/garray/garray_sorted_string.go b/g/container/garray/garray_sorted_string.go
index ff34d2791..2092d4f18 100644
--- a/g/container/garray/garray_sorted_string.go
+++ b/g/container/garray/garray_sorted_string.go
@@ -7,272 +7,272 @@
package garray
import (
- "bytes"
+ "bytes"
"fmt"
"github.com/gogf/gf/g/container/gtype"
- "github.com/gogf/gf/g/internal/rwmutex"
- "github.com/gogf/gf/g/util/gconv"
- "github.com/gogf/gf/g/util/grand"
- "math"
- "sort"
- "strings"
+ "github.com/gogf/gf/g/internal/rwmutex"
+ "github.com/gogf/gf/g/util/gconv"
+ "github.com/gogf/gf/g/util/grand"
+ "math"
+ "sort"
+ "strings"
)
// It's using increasing order in default.
type SortedStringArray struct {
- mu *rwmutex.RWMutex
- array []string
- unique *gtype.Bool // Whether enable unique feature(false)
- comparator func(v1, v2 string) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
+ mu *rwmutex.RWMutex
+ array []string
+ unique *gtype.Bool // Whether enable unique feature(false)
+ comparator func(v1, v2 string) int // Comparison function(it returns -1: v1 < v2; 0: v1 == v2; 1: v1 > v2)
}
// NewSortedStringArray creates and returns an empty sorted array.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedStringArray(unsafe...bool) *SortedStringArray {
- return NewSortedStringArraySize(0, unsafe...)
+func NewSortedStringArray(unsafe ...bool) *SortedStringArray {
+ return NewSortedStringArraySize(0, unsafe...)
}
// NewSortedStringArraySize create and returns an sorted array with given size and cap.
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedStringArraySize(cap int, unsafe...bool) *SortedStringArray {
- return &SortedStringArray {
- mu : rwmutex.New(unsafe...),
- array : make([]string, 0, cap),
- unique : gtype.NewBool(),
- comparator : func(v1, v2 string) int {
- return strings.Compare(v1, v2)
- },
- }
+func NewSortedStringArraySize(cap int, unsafe ...bool) *SortedStringArray {
+ return &SortedStringArray{
+ mu: rwmutex.New(unsafe...),
+ array: make([]string, 0, cap),
+ unique: gtype.NewBool(),
+ comparator: func(v1, v2 string) int {
+ return strings.Compare(v1, v2)
+ },
+ }
}
// NewSortedStringArrayFrom creates and returns an sorted array with given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedStringArrayFrom(array []string, unsafe...bool) *SortedStringArray {
- a := NewSortedStringArraySize(0, unsafe...)
- a.array = array
- sort.Strings(a.array)
- return a
+func NewSortedStringArrayFrom(array []string, unsafe ...bool) *SortedStringArray {
+ a := NewSortedStringArraySize(0, unsafe...)
+ a.array = array
+ sort.Strings(a.array)
+ return a
}
// NewSortedStringArrayFromCopy creates and returns an sorted array from a copy of given slice .
// The parameter used to specify whether using array in un-concurrent-safety,
// which is false in default.
-func NewSortedStringArrayFromCopy(array []string, unsafe...bool) *SortedStringArray {
- newArray := make([]string, len(array))
- copy(newArray, array)
- return NewSortedStringArrayFrom(newArray, unsafe...)
+func NewSortedStringArrayFromCopy(array []string, unsafe ...bool) *SortedStringArray {
+ newArray := make([]string, len(array))
+ copy(newArray, array)
+ return NewSortedStringArrayFrom(newArray, unsafe...)
}
// SetArray sets the underlying slice array with the given .
func (a *SortedStringArray) SetArray(array []string) *SortedStringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- a.array = array
- sort.Strings(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ a.array = array
+ sort.Strings(a.array)
+ return a
}
// Sort sorts the array in increasing order.
// The parameter controls whether sort
// in increasing order(default) or decreasing order.
func (a *SortedStringArray) Sort() *SortedStringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- sort.Strings(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ sort.Strings(a.array)
+ return a
}
// Add adds one or multiple values to sorted array, the array always keeps sorted.
-func (a *SortedStringArray) Add(values...string) *SortedStringArray {
- if len(values) == 0 {
- return a
- }
- a.mu.Lock()
- defer a.mu.Unlock()
- for _, value := range values {
- index, cmp := a.binSearch(value, false)
- if a.unique.Val() && cmp == 0 {
- continue
- }
- if index < 0 {
- a.array = append(a.array, value)
- continue
- }
- if cmp > 0 {
- index++
- }
- rear := append([]string{}, a.array[index : ]...)
- a.array = append(a.array[0 : index], value)
- a.array = append(a.array, rear...)
- }
- return a
+func (a *SortedStringArray) Add(values ...string) *SortedStringArray {
+ if len(values) == 0 {
+ return a
+ }
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ for _, value := range values {
+ index, cmp := a.binSearch(value, false)
+ if a.unique.Val() && cmp == 0 {
+ continue
+ }
+ if index < 0 {
+ a.array = append(a.array, value)
+ continue
+ }
+ if cmp > 0 {
+ index++
+ }
+ rear := append([]string{}, a.array[index:]...)
+ a.array = append(a.array[0:index], value)
+ a.array = append(a.array, rear...)
+ }
+ return a
}
// Get returns the value of the specified index,
// the caller should notice the boundary of the array.
func (a *SortedStringArray) Get(index int) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- value := a.array[index]
- return value
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ value := a.array[index]
+ return value
}
// Remove removes an item by index.
func (a *SortedStringArray) Remove(index int) string {
- a.mu.Lock()
- defer a.mu.Unlock()
- // Determine array boundaries when deleting to improve deletion efficiency.
- if index == 0 {
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
- } else if index == len(a.array) - 1 {
- value := a.array[index]
- a.array = a.array[: index]
- return value
- }
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ // Determine array boundaries when deleting to improve deletion efficiency.
+ if index == 0 {
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
+ } else if index == len(a.array)-1 {
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
+ }
// If it is a non-boundary delete,
// it will involve the creation of an array,
// then the deletion is less efficient.
- value := a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- return value
+ value := a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ return value
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedStringArray) PopLeft() string {
- a.mu.Lock()
- defer a.mu.Unlock()
- value := a.array[0]
- a.array = a.array[1 : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ value := a.array[0]
+ a.array = a.array[1:]
+ return value
}
// PopRight pops and returns an item from the end of array.
func (a *SortedStringArray) PopRight() string {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - 1
- value := a.array[index]
- a.array = a.array[: index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - 1
+ value := a.array[index]
+ a.array = a.array[:index]
+ return value
}
// PopRand randomly pops and return an item out of array.
func (a *SortedStringArray) PopRand() string {
- return a.Remove(grand.Intn(len(a.array)))
+ return a.Remove(grand.Intn(len(a.array)))
}
// PopRands randomly pops and returns items out of array.
func (a *SortedStringArray) PopRands(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- array := make([]string, size)
- for i := 0; i < size; i++ {
- index := grand.Intn(len(a.array))
- array[i] = a.array[index]
- a.array = append(a.array[ : index], a.array[index + 1 : ]...)
- }
- return array
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ array := make([]string, size)
+ for i := 0; i < size; i++ {
+ index := grand.Intn(len(a.array))
+ array[i] = a.array[index]
+ a.array = append(a.array[:index], a.array[index+1:]...)
+ }
+ return array
}
// PopLefts pops and returns items from the beginning of array.
func (a *SortedStringArray) PopLefts(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- length := len(a.array)
- if size > length {
- size = length
- }
- value := a.array[0 : size]
- a.array = a.array[size : ]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ length := len(a.array)
+ if size > length {
+ size = length
+ }
+ value := a.array[0:size]
+ a.array = a.array[size:]
+ return value
}
// PopRights pops and returns items from the end of array.
func (a *SortedStringArray) PopRights(size int) []string {
- a.mu.Lock()
- defer a.mu.Unlock()
- index := len(a.array) - size
- if index < 0 {
- index = 0
- }
- value := a.array[index :]
- a.array = a.array[ : index]
- return value
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ index := len(a.array) - size
+ if index < 0 {
+ index = 0
+ }
+ value := a.array[index:]
+ a.array = a.array[:index]
+ return value
}
// Range picks and returns items by range, like array[start:end].
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedStringArray) Range(start, end int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- if start > length || start > end {
- return nil
- }
- if start < 0 {
- start = 0
- }
- if end > length {
- end = length
- }
- array := ([]string)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]string, end - start)
- copy(array, a.array[start : end])
- } else {
- array = a.array[start : end]
- }
- return array
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ if start > length || start > end {
+ return nil
+ }
+ if start < 0 {
+ start = 0
+ }
+ if end > length {
+ end = length
+ }
+ array := ([]string)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]string, end-start)
+ copy(array, a.array[start:end])
+ } else {
+ array = a.array[start:end]
+ }
+ return array
}
// Sum returns the sum of values in an array.
func (a *SortedStringArray) Sum() (sum int) {
- a.mu.RLock()
- defer a.mu.RUnlock()
- for _, v := range a.array {
- sum += gconv.Int(v)
- }
- return
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ for _, v := range a.array {
+ sum += gconv.Int(v)
+ }
+ return
}
// Len returns the length of array.
func (a *SortedStringArray) Len() int {
- a.mu.RLock()
- length := len(a.array)
- a.mu.RUnlock()
- return length
+ a.mu.RLock()
+ length := len(a.array)
+ a.mu.RUnlock()
+ return length
}
// Slice returns the underlying data of array.
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
func (a *SortedStringArray) Slice() []string {
- array := ([]string)(nil)
- if a.mu.IsSafe() {
- a.mu.RLock()
- defer a.mu.RUnlock()
- array = make([]string, len(a.array))
- copy(array, a.array)
- } else {
- array = a.array
- }
- return array
+ array := ([]string)(nil)
+ if a.mu.IsSafe() {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ array = make([]string, len(a.array))
+ copy(array, a.array)
+ } else {
+ array = a.array
+ }
+ return array
}
// Contains checks whether a value exists in the array.
func (a *SortedStringArray) Contains(value string) bool {
- return a.Search(value) != -1
+ return a.Search(value) != -1
}
// Search searches array by , returns the index of ,
@@ -290,93 +290,95 @@ func (a *SortedStringArray) Search(value string) (index int) {
// If lesser than 0, it means the value at is lesser than .
// If greater than 0, it means the value at is greater than .
func (a *SortedStringArray) binSearch(value string, lock bool) (index int, result int) {
- if len(a.array) == 0 {
- return -1, -2
- }
- if lock {
- a.mu.RLock()
- defer a.mu.RUnlock()
- }
- min := 0
- max := len(a.array) - 1
- mid := 0
- cmp := -2
- for min <= max {
- mid = int((min + max) / 2)
- cmp = a.comparator(value, a.array[mid])
- switch {
- case cmp < 0 : max = mid - 1
- case cmp > 0 : min = mid + 1
- default :
- return mid, cmp
- }
- }
- return mid, cmp
+ if len(a.array) == 0 {
+ return -1, -2
+ }
+ if lock {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ }
+ min := 0
+ max := len(a.array) - 1
+ mid := 0
+ cmp := -2
+ for min <= max {
+ mid = int((min + max) / 2)
+ cmp = a.comparator(value, a.array[mid])
+ switch {
+ case cmp < 0:
+ max = mid - 1
+ case cmp > 0:
+ min = mid + 1
+ default:
+ return mid, cmp
+ }
+ }
+ return mid, cmp
}
// SetUnique sets unique mark to the array,
// which means it does not contain any repeated items.
// It also do unique check, remove all repeated items.
func (a *SortedStringArray) SetUnique(unique bool) *SortedStringArray {
- oldUnique := a.unique.Val()
- a.unique.Set(unique)
- if unique && oldUnique != unique {
- a.Unique()
- }
- return a
+ oldUnique := a.unique.Val()
+ a.unique.Set(unique)
+ if unique && oldUnique != unique {
+ a.Unique()
+ }
+ return a
}
// Unique uniques the array, clear repeated items.
func (a *SortedStringArray) Unique() *SortedStringArray {
- a.mu.Lock()
- i := 0
- for {
- if i == len(a.array) - 1 {
- break
- }
- if a.comparator(a.array[i], a.array[i + 1]) == 0 {
- a.array = append(a.array[ : i + 1], a.array[i + 1 + 1 : ]...)
- } else {
- i++
- }
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ i := 0
+ for {
+ if i == len(a.array)-1 {
+ break
+ }
+ if a.comparator(a.array[i], a.array[i+1]) == 0 {
+ a.array = append(a.array[:i+1], a.array[i+1+1:]...)
+ } else {
+ i++
+ }
+ }
+ a.mu.Unlock()
+ return a
}
// Clone returns a new array, which is a copy of current array.
func (a *SortedStringArray) Clone() (newArray *SortedStringArray) {
- a.mu.RLock()
- array := make([]string, len(a.array))
- copy(array, a.array)
- a.mu.RUnlock()
- return NewSortedStringArrayFrom(array, !a.mu.IsSafe())
+ a.mu.RLock()
+ array := make([]string, len(a.array))
+ copy(array, a.array)
+ a.mu.RUnlock()
+ return NewSortedStringArrayFrom(array, !a.mu.IsSafe())
}
// Clear deletes all items of current array.
func (a *SortedStringArray) Clear() *SortedStringArray {
- a.mu.Lock()
- if len(a.array) > 0 {
- a.array = make([]string, 0)
- }
- a.mu.Unlock()
- return a
+ a.mu.Lock()
+ if len(a.array) > 0 {
+ a.array = make([]string, 0)
+ }
+ a.mu.Unlock()
+ return a
}
// LockFunc locks writing by callback function .
func (a *SortedStringArray) LockFunc(f func(array []string)) *SortedStringArray {
- a.mu.Lock()
- defer a.mu.Unlock()
- f(a.array)
- return a
+ a.mu.Lock()
+ defer a.mu.Unlock()
+ f(a.array)
+ return a
}
// RLockFunc locks reading by callback function .
func (a *SortedStringArray) RLockFunc(f func(array []string)) *SortedStringArray {
- a.mu.RLock()
- defer a.mu.RUnlock()
- f(a.array)
- return a
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ f(a.array)
+ return a
}
// Merge merges into current array.
@@ -384,99 +386,105 @@ func (a *SortedStringArray) RLockFunc(f func(array []string)) *SortedStringArray
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *SortedStringArray) Merge(array interface{}) *SortedStringArray {
- switch v := array.(type) {
- case *Array: a.Add(gconv.Strings(v.Slice())...)
- case *IntArray: a.Add(gconv.Strings(v.Slice())...)
- case *StringArray: a.Add(gconv.Strings(v.Slice())...)
- case *SortedArray: a.Add(gconv.Strings(v.Slice())...)
- case *SortedIntArray: a.Add(gconv.Strings(v.Slice())...)
- case *SortedStringArray: a.Add(gconv.Strings(v.Slice())...)
- default:
- a.Add(gconv.Strings(array)...)
- }
- return a
+ switch v := array.(type) {
+ case *Array:
+ a.Add(gconv.Strings(v.Slice())...)
+ case *IntArray:
+ a.Add(gconv.Strings(v.Slice())...)
+ case *StringArray:
+ a.Add(gconv.Strings(v.Slice())...)
+ case *SortedArray:
+ a.Add(gconv.Strings(v.Slice())...)
+ case *SortedIntArray:
+ a.Add(gconv.Strings(v.Slice())...)
+ case *SortedStringArray:
+ a.Add(gconv.Strings(v.Slice())...)
+ default:
+ a.Add(gconv.Strings(array)...)
+ }
+ return a
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by .
// The last chunk may contain less than size elements.
func (a *SortedStringArray) Chunk(size int) [][]string {
- if size < 1 {
- return nil
- }
- a.mu.RLock()
- defer a.mu.RUnlock()
- length := len(a.array)
- chunks := int(math.Ceil(float64(length) / float64(size)))
- var n [][]string
- for i, end := 0, 0; chunks > 0; chunks-- {
- end = (i + 1) * size
- if end > length {
- end = length
- }
- n = append(n, a.array[i*size : end])
- i++
- }
- return n
+ if size < 1 {
+ return nil
+ }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ length := len(a.array)
+ chunks := int(math.Ceil(float64(length) / float64(size)))
+ var n [][]string
+ for i, end := 0, 0; chunks > 0; chunks-- {
+ end = (i + 1) * size
+ if end > length {
+ end = length
+ }
+ n = append(n, a.array[i*size:end])
+ i++
+ }
+ return n
}
// SubSlice returns a slice of elements from the array as specified
// by the and parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
func (a *SortedStringArray) SubSlice(offset, size int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if offset > len(a.array) {
- return nil
- }
- if offset + size > len(a.array) {
- size = len(a.array) - offset
- }
- if a.mu.IsSafe() {
- s := make([]string, size)
- copy(s, a.array[offset:])
- return s
- } else {
- return a.array[offset:]
- }
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if offset > len(a.array) {
+ return nil
+ }
+ if offset+size > len(a.array) {
+ size = len(a.array) - offset
+ }
+ if a.mu.IsSafe() {
+ s := make([]string, size)
+ copy(s, a.array[offset:])
+ return s
+ } else {
+ return a.array[offset:]
+ }
}
// Rand randomly returns one item from array(no deleting).
func (a *SortedStringArray) Rand() string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- return a.array[grand.Intn(len(a.array))]
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ return a.array[grand.Intn(len(a.array))]
}
// Rands randomly returns items from array(no deleting).
func (a *SortedStringArray) Rands(size int) []string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- if size > len(a.array) {
- size = len(a.array)
- }
- n := make([]string, size)
- for i, v := range grand.Perm(len(a.array)) {
- n[i] = a.array[v]
- if i == size - 1 {
- break
- }
- }
- return n
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ if size > len(a.array) {
+ size = len(a.array)
+ }
+ n := make([]string, size)
+ for i, v := range grand.Perm(len(a.array)) {
+ n[i] = a.array[v]
+ if i == size-1 {
+ break
+ }
+ }
+ return n
}
// Join joins array elements with a string .
func (a *SortedStringArray) Join(glue string) string {
- a.mu.RLock()
- defer a.mu.RUnlock()
- buffer := bytes.NewBuffer(nil)
- for k, v := range a.array {
- buffer.WriteString(gconv.String(v))
- if k != len(a.array) - 1 {
- buffer.WriteString(glue)
- }
- }
- return buffer.String()
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+ buffer := bytes.NewBuffer(nil)
+ for k, v := range a.array {
+ buffer.WriteString(gconv.String(v))
+ if k != len(a.array)-1 {
+ buffer.WriteString(glue)
+ }
+ }
+ return buffer.String()
}
// CountValues counts the number of occurrences of all values in the array.
@@ -495,4 +503,4 @@ func (a *SortedStringArray) String() string {
a.mu.RLock()
defer a.mu.RUnlock()
return fmt.Sprint(a.array)
-}
\ No newline at end of file
+}
diff --git a/g/container/garray/garray_z_example_test.go b/g/container/garray/garray_z_example_test.go
index ea1cc3dc1..d32ef72c5 100644
--- a/g/container/garray/garray_z_example_test.go
+++ b/g/container/garray/garray_z_example_test.go
@@ -7,105 +7,105 @@
package garray_test
import (
- "fmt"
- "github.com/gogf/gf/g/container/garray"
+ "fmt"
+ "github.com/gogf/gf/g/container/garray"
)
func Example_basic() {
- // 创建普通的数组,默认并发安全(带锁)
- a := garray.New()
+ // 创建普通的数组,默认并发安全(带锁)
+ a := garray.New()
- // 添加数据项
- for i := 0; i < 10; i++ {
- a.Append(i)
- }
+ // 添加数据项
+ for i := 0; i < 10; i++ {
+ a.Append(i)
+ }
- // 获取当前数组长度
- fmt.Println(a.Len())
+ // 获取当前数组长度
+ fmt.Println(a.Len())
- // 获取当前数据项列表
- fmt.Println(a.Slice())
+ // 获取当前数据项列表
+ fmt.Println(a.Slice())
- // 获取指定索引项
- fmt.Println(a.Get(6))
+ // 获取指定索引项
+ fmt.Println(a.Get(6))
- // 查找指定数据项是否存在
- fmt.Println(a.Contains(6))
- fmt.Println(a.Contains(100))
+ // 查找指定数据项是否存在
+ fmt.Println(a.Contains(6))
+ fmt.Println(a.Contains(100))
- // 在指定索引前插入数据项
- a.InsertAfter(9, 11)
- // 在指定索引后插入数据项
- a.InsertBefore(10, 10)
+ // 在指定索引前插入数据项
+ a.InsertAfter(9, 11)
+ // 在指定索引后插入数据项
+ a.InsertBefore(10, 10)
- fmt.Println(a.Slice())
+ fmt.Println(a.Slice())
- // 修改指定索引的数据项
- a.Set(0, 100)
- fmt.Println(a.Slice())
+ // 修改指定索引的数据项
+ a.Set(0, 100)
+ fmt.Println(a.Slice())
- // 搜索数据项,返回搜索到的索引位置
- fmt.Println(a.Search(5))
+ // 搜索数据项,返回搜索到的索引位置
+ fmt.Println(a.Search(5))
- // 删除指定索引的数据项
- a.Remove(0)
- fmt.Println(a.Slice())
+ // 删除指定索引的数据项
+ a.Remove(0)
+ fmt.Println(a.Slice())
- // 清空数组
- fmt.Println(a.Slice())
- a.Clear()
- fmt.Println(a.Slice())
+ // 清空数组
+ fmt.Println(a.Slice())
+ a.Clear()
+ fmt.Println(a.Slice())
- // Output:
- // 10
- // [0 1 2 3 4 5 6 7 8 9]
- // 6
- // true
- // false
- // [0 1 2 3 4 5 6 7 8 9 10 11]
- // [100 1 2 3 4 5 6 7 8 9 10 11]
- // 5
- // [1 2 3 4 5 6 7 8 9 10 11]
- // [1 2 3 4 5 6 7 8 9 10 11]
- // []
+ // Output:
+ // 10
+ // [0 1 2 3 4 5 6 7 8 9]
+ // 6
+ // true
+ // false
+ // [0 1 2 3 4 5 6 7 8 9 10 11]
+ // [100 1 2 3 4 5 6 7 8 9 10 11]
+ // 5
+ // [1 2 3 4 5 6 7 8 9 10 11]
+ // [1 2 3 4 5 6 7 8 9 10 11]
+ // []
}
func Example_rand() {
- array := garray.NewFrom([]interface{}{1,2,3,4,5,6,7,8,9})
- // 随机返回两个数据项(不删除)
- fmt.Println(array.Rands(2))
- fmt.Println(array.PopRand())
+ array := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9})
+ // 随机返回两个数据项(不删除)
+ fmt.Println(array.Rands(2))
+ fmt.Println(array.PopRand())
}
func Example_pop() {
- array := garray.NewFrom([]interface{}{1,2,3,4,5,6,7,8,9})
- fmt.Println(array.PopLeft())
- fmt.Println(array.PopLefts(2))
- fmt.Println(array.PopRight())
- fmt.Println(array.PopRights(2))
+ array := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9})
+ fmt.Println(array.PopLeft())
+ fmt.Println(array.PopLefts(2))
+ fmt.Println(array.PopRight())
+ fmt.Println(array.PopRights(2))
- // Output:
- // 1
- // [2 3]
- // 9
- // [7 8]
+ // Output:
+ // 1
+ // [2 3]
+ // 9
+ // [7 8]
}
func Example_merge() {
- array1 := garray.NewFrom([]interface{}{1,2})
- array2 := garray.NewFrom([]interface{}{3,4})
- slice1 := []interface{}{5,6}
- slice2 := []int{7,8}
- slice3 := []string{"9","0"}
- fmt.Println(array1.Slice())
- array1.Merge(array1)
- array1.Merge(array2)
- array1.Merge(slice1)
- array1.Merge(slice2)
- array1.Merge(slice3)
- fmt.Println(array1.Slice())
+ array1 := garray.NewFrom([]interface{}{1, 2})
+ array2 := garray.NewFrom([]interface{}{3, 4})
+ slice1 := []interface{}{5, 6}
+ slice2 := []int{7, 8}
+ slice3 := []string{"9", "0"}
+ fmt.Println(array1.Slice())
+ array1.Merge(array1)
+ array1.Merge(array2)
+ array1.Merge(slice1)
+ array1.Merge(slice2)
+ array1.Merge(slice3)
+ fmt.Println(array1.Slice())
- // Output:
- // [1 2]
- // [1 2 1 2 3 4 5 6 7 8 9 0]
-}
\ No newline at end of file
+ // Output:
+ // [1 2]
+ // [1 2 1 2 3 4 5 6 7 8 9 0]
+}
diff --git a/g/container/gchan/gchan_example_test.go b/g/container/gchan/gchan_example_test.go
index acb1cbff9..2545b55e3 100644
--- a/g/container/gchan/gchan_example_test.go
+++ b/g/container/gchan/gchan_example_test.go
@@ -7,23 +7,23 @@
package gchan_test
import (
- "fmt"
- "github.com/gogf/gf/g/container/gchan"
+ "fmt"
+ "github.com/gogf/gf/g/container/gchan"
)
func Example_basic() {
- n := 10
- c := gchan.New(n)
- for i := 0; i < n; i++ {
- c.Push(i)
- }
- fmt.Println(c.Len(), c.Cap())
- for i := 0; i < n; i++ {
- fmt.Print(c.Pop())
- }
- c.Close()
+ n := 10
+ c := gchan.New(n)
+ for i := 0; i < n; i++ {
+ c.Push(i)
+ }
+ fmt.Println(c.Len(), c.Cap())
+ for i := 0; i < n; i++ {
+ fmt.Print(c.Pop())
+ }
+ c.Close()
- // Output:
- //10 10
- //0123456789
+ // Output:
+ //10 10
+ //0123456789
}
diff --git a/g/container/glist/glist.go b/g/container/glist/glist.go
index a3ddd5651..9209408c5 100644
--- a/g/container/glist/glist.go
+++ b/g/container/glist/glist.go
@@ -9,115 +9,115 @@
package glist
import (
- "container/list"
- "github.com/gogf/gf/g/internal/rwmutex"
+ "container/list"
+ "github.com/gogf/gf/g/internal/rwmutex"
)
type (
List struct {
- mu *rwmutex.RWMutex
- list *list.List
+ mu *rwmutex.RWMutex
+ list *list.List
}
Element = list.Element
)
// New creates and returns a new empty doubly linked list.
-func New(unsafe...bool) *List {
- return &List {
- mu : rwmutex.New(unsafe...),
- list : list.New(),
- }
+func New(unsafe ...bool) *List {
+ return &List{
+ mu: rwmutex.New(unsafe...),
+ list: list.New(),
+ }
}
// 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()
- e = l.list.PushFront(v)
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ e = l.list.PushFront(v)
+ l.mu.Unlock()
+ return
}
// 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()
- e = l.list.PushBack(v)
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ e = l.list.PushBack(v)
+ l.mu.Unlock()
+ return
}
// PushFronts inserts multiple new elements with values at the front of list .
func (l *List) PushFronts(values []interface{}) {
- l.mu.Lock()
+ l.mu.Lock()
for _, v := range values {
- l.list.PushFront(v)
+ l.list.PushFront(v)
}
- l.mu.Unlock()
+ l.mu.Unlock()
}
// PushBacks inserts multiple new elements with values at the back of list .
func (l *List) PushBacks(values []interface{}) {
- l.mu.Lock()
- for _, v := range values {
- l.list.PushBack(v)
- }
- l.mu.Unlock()
+ l.mu.Lock()
+ for _, v := range values {
+ l.list.PushBack(v)
+ }
+ l.mu.Unlock()
}
// PopBack removes the element from back of and returns the value of the element.
func (l *List) PopBack() (value interface{}) {
- l.mu.Lock()
+ l.mu.Lock()
if e := l.list.Back(); e != nil {
- value = l.list.Remove(e)
+ value = l.list.Remove(e)
}
- l.mu.Unlock()
+ 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()
- if e := l.list.Front(); e != nil {
- value = l.list.Remove(e)
- }
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ if e := l.list.Front(); e != nil {
+ value = l.list.Remove(e)
+ }
+ l.mu.Unlock()
+ return
}
// PopBacks removes elements from back of
// and returns values of the removed elements as slice.
func (l *List) PopBacks(max int) (values []interface{}) {
- l.mu.Lock()
- length := l.list.Len()
- if length > 0 {
- if max > 0 && max < length {
- length = max
- }
- values = make([]interface{}, length)
- for i := 0; i < length; i++ {
- values[i] = l.list.Remove(l.list.Back())
- }
- }
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ length := l.list.Len()
+ if length > 0 {
+ if max > 0 && max < length {
+ length = max
+ }
+ values = make([]interface{}, length)
+ for i := 0; i < length; i++ {
+ values[i] = l.list.Remove(l.list.Back())
+ }
+ }
+ l.mu.Unlock()
+ return
}
// PopFronts removes elements from front of
// and returns values of the removed elements as slice.
func (l *List) PopFronts(max int) (values []interface{}) {
- l.mu.Lock()
- length := l.list.Len()
- if length > 0 {
- if max > 0 && max < length {
- length = max
- }
- values = make([]interface{}, length)
- for i := 0; i < length; i++ {
- values[i] = l.list.Remove(l.list.Front())
- }
- }
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ length := l.list.Len()
+ if length > 0 {
+ if max > 0 && max < length {
+ length = max
+ }
+ values = make([]interface{}, length)
+ for i := 0; i < length; i++ {
+ values[i] = l.list.Remove(l.list.Front())
+ }
+ }
+ l.mu.Unlock()
+ return
}
// PopBackAll removes all elements from back of
@@ -129,79 +129,79 @@ func (l *List) PopBackAll() []interface{} {
// PopFrontAll removes all elements from front of
// and returns values of the removed elements as slice.
func (l *List) PopFrontAll() []interface{} {
- return l.PopFronts(-1)
+ return l.PopFronts(-1)
}
// FrontAll copies and returns values of all elements from front of as slice.
func (l *List) FrontAll() (values []interface{}) {
- l.mu.RLock()
- length := l.list.Len()
- if length > 0 {
- values = make([]interface{}, length)
- for i, e := 0, l.list.Front(); i < length; i, e = i + 1, e.Next() {
- values[i] = e.Value
- }
- }
- l.mu.RUnlock()
- return
+ l.mu.RLock()
+ length := l.list.Len()
+ if length > 0 {
+ values = make([]interface{}, length)
+ for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
+ 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()
+ l.mu.RLock()
length := l.list.Len()
if length > 0 {
- values = make([]interface{}, length)
- for i, e := 0, l.list.Back(); i < length; i, e = i + 1, e.Prev() {
- values[i] = e.Value
- }
- }
- l.mu.RUnlock()
+ values = make([]interface{}, length)
+ for i, e := 0, l.list.Back(); i < length; i, e = i+1, e.Prev() {
+ 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()
- if e := l.list.Front(); e != nil {
- value = e.Value
- }
- l.mu.RUnlock()
- return
+ l.mu.RLock()
+ 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()
- if e := l.list.Back(); e != nil {
- value = e.Value
- }
- l.mu.RUnlock()
- return
+ l.mu.RLock()
+ 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()
- e = l.list.Front()
- l.mu.RUnlock()
- return
+ l.mu.RLock()
+ 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()
- e = l.list.Back()
- l.mu.RUnlock()
- return
+ l.mu.RLock()
+ e = l.list.Back()
+ l.mu.RUnlock()
+ return
}
// Len returns the number of elements of list .
// The complexity is O(1).
func (l *List) Len() (length int) {
- l.mu.RLock()
- length = l.list.Len()
- l.mu.RUnlock()
+ l.mu.RLock()
+ length = l.list.Len()
+ l.mu.RUnlock()
return
}
@@ -214,107 +214,107 @@ func (l *List) Size() int {
// If or is not an element of , or == , the list is not modified.
// The element and
must not be nil.
func (l *List) MoveBefore(e, p *Element) {
- l.mu.Lock()
- l.list.MoveBefore(e, p)
- l.mu.Unlock()
+ l.mu.Lock()
+ l.list.MoveBefore(e, p)
+ l.mu.Unlock()
}
// MoveAfter moves element to its new position after .
// If or is not an element of , or == , the list is not modified.
// The element and
must not be nil.
func (l *List) MoveAfter(e, p *Element) {
- l.mu.Lock()
- l.list.MoveAfter(e, p)
- l.mu.Unlock()
+ l.mu.Lock()
+ l.list.MoveAfter(e, p)
+ l.mu.Unlock()
}
// MoveToFront moves element to the front of list .
// If is not an element of , the list is not modified.
// The element must not be nil.
func (l *List) MoveToFront(e *Element) {
- l.mu.Lock()
- l.list.MoveToFront(e)
- l.mu.Unlock()
+ l.mu.Lock()
+ l.list.MoveToFront(e)
+ l.mu.Unlock()
}
// MoveToBack moves element to the back of list .
// If is not an element of , the list is not modified.
// The element must not be nil.
func (l *List) MoveToBack(e *Element) {
- l.mu.Lock()
- l.list.MoveToBack(e)
- l.mu.Unlock()
+ l.mu.Lock()
+ l.list.MoveToBack(e)
+ l.mu.Unlock()
}
// PushBackList inserts a copy of an other list at the back of list .
// The lists and may be the same, but they must not be nil.
func (l *List) PushBackList(other *List) {
- if l != other {
- other.mu.RLock()
- defer other.mu.RUnlock()
- }
- l.mu.Lock()
- l.list.PushBackList(other.list)
- l.mu.Unlock()
+ if l != other {
+ other.mu.RLock()
+ defer other.mu.RUnlock()
+ }
+ l.mu.Lock()
+ l.list.PushBackList(other.list)
+ l.mu.Unlock()
}
// PushFrontList inserts a copy of an other list at the front of list .
// The lists and may be the same, but they must not be nil.
func (l *List) PushFrontList(other *List) {
- if l != other {
- other.mu.RLock()
- defer other.mu.RUnlock()
- }
- l.mu.Lock()
- l.list.PushFrontList(other.list)
- l.mu.Unlock()
+ if l != other {
+ other.mu.RLock()
+ defer other.mu.RUnlock()
+ }
+ l.mu.Lock()
+ l.list.PushFrontList(other.list)
+ l.mu.Unlock()
}
// InsertAfter inserts a new element with value immediately after and returns .
// If is not an element of , the list is not modified.
// The must not be nil.
func (l *List) InsertAfter(v interface{}, p *Element) (e *Element) {
- l.mu.Lock()
- e = l.list.InsertAfter(v, p)
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ e = l.list.InsertAfter(v, p)
+ l.mu.Unlock()
+ return
}
// InsertBefore inserts a new element with value immediately before and returns .
// If is not an element of , the list is not modified.
// The must not be nil.
func (l *List) InsertBefore(v interface{}, p *Element) (e *Element) {
- l.mu.Lock()
- e = l.list.InsertBefore(v, p)
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ e = l.list.InsertBefore(v, p)
+ l.mu.Unlock()
+ return
}
// Remove removes from if is an element of list .
// It returns the element value e.Value.
// The element must not be nil.
func (l *List) Remove(e *Element) (value interface{}) {
- l.mu.Lock()
- value = l.list.Remove(e)
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ 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()
- for _, e := range es {
- l.list.Remove(e)
- }
- l.mu.Unlock()
- return
+ l.mu.Lock()
+ 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.New()
- l.mu.Unlock()
+ l.mu.Lock()
+ l.list = list.New()
+ l.mu.Unlock()
}
// See RemoveAll().
@@ -324,30 +324,30 @@ func (l *List) Clear() {
// RLockFunc locks reading with given callback function within RWMutex.RLock.
func (l *List) RLockFunc(f func(list *list.List)) {
- l.mu.RLock()
- defer l.mu.RUnlock()
- f(l.list)
+ l.mu.RLock()
+ defer l.mu.RUnlock()
+ 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)
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ f(l.list)
}
// Iterator is alias of IteratorAsc.
-func (l *List) Iterator(f func (e *Element) bool) {
+func (l *List) Iterator(f func(e *Element) bool) {
l.IteratorAsc(f)
}
// IteratorAsc iterates the list in ascending order with given callback function .
// If returns true, then it continues iterating; or false to stop.
-func (l *List) IteratorAsc(f func (e *Element) bool) {
+func (l *List) IteratorAsc(f func(e *Element) bool) {
l.mu.RLock()
length := l.list.Len()
if length > 0 {
- for i, e := 0, l.list.Front(); i < length; i, e = i + 1, e.Next() {
+ for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
if !f(e) {
break
}
@@ -358,15 +358,15 @@ func (l *List) IteratorAsc(f func (e *Element) bool) {
// IteratorDesc iterates the list in descending order with given callback function