mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve Range/SubSlice functions for garray
This commit is contained in:
@ -9,11 +9,12 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"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"
|
||||
)
|
||||
|
||||
type IntArray struct {
|
||||
@ -266,31 +267,83 @@ func (a *IntArray) PopRights(size int) []int {
|
||||
// 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 {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *IntArray) Range(start int, end ...int) []int {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]int, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *IntArray) SubSlice(offset int, length ...int) []int {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// See PushRight.
|
||||
func (a *IntArray) Append(value ...int) *IntArray {
|
||||
a.mu.Lock()
|
||||
@ -488,27 +541,6 @@ func (a *IntArray) Pad(size int, value int) *IntArray {
|
||||
return a
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *IntArray) Rand() int {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,11 +9,12 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"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"
|
||||
)
|
||||
|
||||
type Array struct {
|
||||
@ -262,31 +263,83 @@ func (a *Array) PopRights(size int) []interface{} {
|
||||
// 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{} {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *Array) Range(start int, end ...int) []interface{} {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]interface{}, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *Array) SubSlice(offset int, length ...int) []interface{} {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// See PushRight.
|
||||
func (a *Array) Append(value ...interface{}) *Array {
|
||||
a.PushRight(value...)
|
||||
@ -482,27 +535,6 @@ func (a *Array) Pad(size int, val interface{}) *Array {
|
||||
return a
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *Array) Rand() interface{} {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,12 +9,13 @@ 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"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"github.com/gogf/gf/g/util/grand"
|
||||
)
|
||||
|
||||
type StringArray struct {
|
||||
@ -267,31 +268,83 @@ func (a *StringArray) PopRights(size int) []string {
|
||||
// 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 {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *StringArray) Range(start int, end ...int) []string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]string, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *StringArray) SubSlice(offset int, length ...int) []string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// See PushRight.
|
||||
func (a *StringArray) Append(value ...string) *StringArray {
|
||||
a.mu.Lock()
|
||||
@ -488,27 +541,6 @@ func (a *StringArray) Pad(size int, value string) *StringArray {
|
||||
return a
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *StringArray) Rand() string {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,12 +9,13 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// It's using increasing order in default.
|
||||
@ -216,31 +217,83 @@ func (a *SortedIntArray) PopRights(size int) []int {
|
||||
// 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 {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *SortedIntArray) Range(start int, end ...int) []int {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]int, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *SortedIntArray) SubSlice(offset int, length ...int) []int {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the length of array.
|
||||
func (a *SortedIntArray) Len() int {
|
||||
a.mu.RLock()
|
||||
@ -433,27 +486,6 @@ func (a *SortedIntArray) Chunk(size int) [][]int {
|
||||
return n
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *SortedIntArray) Rand() int {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,12 +9,13 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// It's using increasing order in default.
|
||||
@ -217,31 +218,83 @@ func (a *SortedArray) PopRights(size int) []interface{} {
|
||||
// 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{} {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *SortedArray) Range(start int, end ...int) []interface{} {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]interface{}, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *SortedArray) SubSlice(offset int, length ...int) []interface{} {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// Sum returns the sum of values in an array.
|
||||
func (a *SortedArray) Sum() (sum int) {
|
||||
a.mu.RLock()
|
||||
@ -434,27 +487,6 @@ func (a *SortedArray) Chunk(size int) [][]interface{} {
|
||||
return n
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *SortedArray) Rand() interface{} {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,13 +9,14 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// It's using increasing order in default.
|
||||
@ -211,31 +212,83 @@ func (a *SortedStringArray) PopRights(size int) []string {
|
||||
// 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 {
|
||||
//
|
||||
// If <end> is negative, then the offset will start from the end of array.
|
||||
// If <end> is omitted, then the sequence will have everything from start up
|
||||
// until the end of the array.
|
||||
func (a *SortedStringArray) Range(start int, end ...int) []string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
length := len(a.array)
|
||||
if start > length || start > end {
|
||||
offsetEnd := len(a.array)
|
||||
if len(end) > 0 && end[0] < offsetEnd {
|
||||
offsetEnd = end[0]
|
||||
}
|
||||
if start > offsetEnd {
|
||||
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])
|
||||
array = make([]string, offsetEnd-start)
|
||||
copy(array, a.array[start:offsetEnd])
|
||||
} else {
|
||||
array = a.array[start:end]
|
||||
array = a.array[start:offsetEnd]
|
||||
}
|
||||
return array
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> parameters.
|
||||
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
|
||||
//
|
||||
// If offset is non-negative, the sequence will start at that offset in the array.
|
||||
// If offset is negative, the sequence will start that far from the end of the array.
|
||||
//
|
||||
// If length is given and is positive, then the sequence will have up to that many elements in it.
|
||||
// If the array is shorter than the length, then only the available array elements will be present.
|
||||
// If length is given and is negative then the sequence will stop that many elements from the end of the array.
|
||||
// If it is omitted, then the sequence will have everything from offset up until the end of the array.
|
||||
//
|
||||
// Any possibility crossing the left border of array, it will fail.
|
||||
func (a *SortedStringArray) SubSlice(offset int, length ...int) []string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
size := len(a.array)
|
||||
if len(length) > 0 {
|
||||
size = length[0]
|
||||
}
|
||||
if offset > len(a.array) {
|
||||
return nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = len(a.array) + offset
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if size < 0 {
|
||||
offset += size
|
||||
size = -size
|
||||
if offset < 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
end := offset + size
|
||||
if end > len(a.array) {
|
||||
end = 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:end]
|
||||
}
|
||||
}
|
||||
|
||||
// Sum returns the sum of values in an array.
|
||||
func (a *SortedStringArray) Sum() (sum int) {
|
||||
a.mu.RLock()
|
||||
@ -428,27 +481,6 @@ func (a *SortedStringArray) Chunk(size int) [][]string {
|
||||
return n
|
||||
}
|
||||
|
||||
// SubSlice returns a slice of elements from the array as specified
|
||||
// by the <offset> and <size> 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:]
|
||||
}
|
||||
}
|
||||
|
||||
// Rand randomly returns one item from array(no deleting).
|
||||
func (a *SortedStringArray) Rand() string {
|
||||
a.mu.RLock()
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
package garray_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_IntArray_Basic(t *testing.T) {
|
||||
@ -100,6 +101,7 @@ func TestIntArray_Range(t *testing.T) {
|
||||
gtest.Assert(array1.Range(0, 1), []int{0})
|
||||
gtest.Assert(array1.Range(1, 2), []int{1})
|
||||
gtest.Assert(array1.Range(0, 2), []int{0, 1})
|
||||
gtest.Assert(array1.Range(10, 2), nil)
|
||||
gtest.Assert(array1.Range(-1, 10), value1)
|
||||
})
|
||||
}
|
||||
@ -151,9 +153,21 @@ func TestIntArray_SubSlice(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
a1 := []int{0, 1, 2, 3, 4, 5, 6}
|
||||
array1 := garray.NewIntArrayFrom(a1)
|
||||
gtest.Assert(array1.SubSlice(6), []int{6})
|
||||
gtest.Assert(array1.SubSlice(5), []int{5, 6})
|
||||
gtest.Assert(array1.SubSlice(8), nil)
|
||||
gtest.Assert(array1.SubSlice(0, 2), []int{0, 1})
|
||||
gtest.Assert(array1.SubSlice(2, 2), []int{2, 3})
|
||||
gtest.Assert(array1.SubSlice(5, 8), []int{5, 6})
|
||||
gtest.Assert(array1.SubSlice(-1, 1), []int{6})
|
||||
gtest.Assert(array1.SubSlice(-1, 9), []int{6})
|
||||
gtest.Assert(array1.SubSlice(-2, 3), []int{5, 6})
|
||||
gtest.Assert(array1.SubSlice(-7, 3), []int{0, 1, 2})
|
||||
gtest.Assert(array1.SubSlice(-8, 3), nil)
|
||||
gtest.Assert(array1.SubSlice(-1, -3), []int{3, 4, 5})
|
||||
gtest.Assert(array1.SubSlice(-9, 3), nil)
|
||||
gtest.Assert(array1.SubSlice(1, -1), []int{0})
|
||||
gtest.Assert(array1.SubSlice(1, -3), nil)
|
||||
})
|
||||
}
|
||||
|
||||
@ -435,7 +449,6 @@ func TestSortedIntArray_Chunk(t *testing.T) {
|
||||
array1 := garray.NewSortedIntArrayFrom(a1)
|
||||
ns1 := array1.Chunk(2) //按每几个元素切成一个数组
|
||||
ns2 := array1.Chunk(-1)
|
||||
t.Log(ns1)
|
||||
gtest.Assert(len(ns1), 3)
|
||||
gtest.Assert(ns1[0], []int{1, 2})
|
||||
gtest.Assert(ns1[2], []int{5})
|
||||
|
||||
@ -10,6 +10,14 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
@ -23,13 +31,6 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"github.com/gogf/gf/third/github.com/gorilla/websocket"
|
||||
"github.com/gogf/gf/third/github.com/olekukonko/tablewriter"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -382,15 +383,14 @@ func (s *Server) GetRouteMap() string {
|
||||
}
|
||||
|
||||
// 阻塞执行监听
|
||||
func (s *Server) Run() error {
|
||||
func (s *Server) Run() {
|
||||
if err := s.Start(); err != nil {
|
||||
return err
|
||||
glog.Fatal(err)
|
||||
}
|
||||
// 阻塞等待服务执行完成
|
||||
<-s.closeChan
|
||||
|
||||
glog.Printf("%d: all servers shutdown", gproc.Pid())
|
||||
return nil
|
||||
}
|
||||
|
||||
// 阻塞等待所有Web Server停止,常用于多Web Server场景,以及需要将Web Server异步运行的场景
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v := gtype.NewInt32(math.MaxInt32)
|
||||
for i := 1; i < 100; i++ {
|
||||
fmt.Println(v.Add(int32(i)))
|
||||
}
|
||||
a2 := []interface{}{0, 1, 2, 3, 4, 5, 6}
|
||||
array3 := garray.NewArrayFrom(a2, true)
|
||||
gtest.Assert(array3.SubSlice(2, 2), []interface{}{2, 3})
|
||||
}
|
||||
|
||||
@ -1,55 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/os/gmutex"
|
||||
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mu := gmutex.New()
|
||||
array := garray.New()
|
||||
glog.Println("step0")
|
||||
go func() {
|
||||
mu.LockFunc(func() {
|
||||
array.Append(1)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
glog.Println("unlocked")
|
||||
})
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
mu.TryRLockFunc(func() {
|
||||
array.Append(1)
|
||||
glog.Println("add1")
|
||||
})
|
||||
}()
|
||||
sum := 1000
|
||||
for index := 1; index < sum; index++ {
|
||||
go func(i int) {
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
//fmt.Println(i*10, mu.IsLocked())
|
||||
if r := mu.TryRLockFunc(func() {
|
||||
array.Append(1)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}); !r {
|
||||
glog.Println(i, r)
|
||||
}
|
||||
}(index)
|
||||
}
|
||||
glog.Println("step1")
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
glog.Println("step2")
|
||||
gtest.Assert(array.Len(), 1)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
glog.Println("step3")
|
||||
gtest.Assert(array.Len(), 1)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
gtest.Assert(array.Len(), sum)
|
||||
type Schedule struct{}
|
||||
|
||||
type Task struct{}
|
||||
|
||||
func (c *Schedule) ListDir(r *ghttp.Request) {
|
||||
r.Response.Writeln("ListDir")
|
||||
}
|
||||
|
||||
func (c *Task) Add(r *ghttp.Request) {
|
||||
r.Response.Writeln("Add")
|
||||
}
|
||||
|
||||
func (c *Task) Task(r *ghttp.Request) {
|
||||
r.Response.Writeln("Task")
|
||||
}
|
||||
|
||||
// 实现权限校验
|
||||
// 通过事件回调,类似于中间件机制,但是可控制的粒度更细,可以精准注册到路由规则
|
||||
func AuthHookHandler(r *ghttp.Request) {
|
||||
// 如果权限校验失败,调用 r.ExitAll() 退出执行流程
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.Group("/schedule").Bind([]ghttp.GroupItem{
|
||||
{"ALL", "*", AuthHookHandler, ghttp.HOOK_BEFORE_SERVE},
|
||||
{"POST", "/schedule", new(Schedule)},
|
||||
{"POST", "/task", new(Task)},
|
||||
})
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user