helper函数 分层

This commit is contained in:
xing 2023-01-21 19:31:23 +08:00
parent 2188619755
commit 04858e304f
42 changed files with 645 additions and 606 deletions

View File

@ -1,31 +1,14 @@
package helper package helper
import ( import (
"fmt"
"math/rand"
"reflect" "reflect"
"sort"
) )
type IntNumber interface {
~int | ~int64 | ~int32 | ~int8 | ~int16 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
func ToAny[T any](v T) any { func ToAny[T any](v T) any {
return v return v
} }
func IsContainInArr[T comparable](a T, arr []T) bool { func StructColumnToSlice[T any, M any](arr []M, field string) (r []T) {
for _, v := range arr {
if a == v {
return true
}
}
return false
}
func StructColumn[T any, M any](arr []M, field string) (r []T) {
for i := 0; i < len(arr); i++ { for i := 0; i < len(arr); i++ {
v := reflect.ValueOf(arr[i]).FieldByName(field).Interface() v := reflect.ValueOf(arr[i]).FieldByName(field).Interface()
if val, ok := v.(T); ok { if val, ok := v.(T); ok {
@ -34,79 +17,3 @@ func StructColumn[T any, M any](arr []M, field string) (r []T) {
} }
return return
} }
func RandNum[T IntNumber](start, end T) T {
end++
return T(rand.Int63n(int64(end-start))) + start
}
type anyArr[T any] struct {
data []T
fn func(i, j T) bool
}
func (r anyArr[T]) Len() int {
return len(r.data)
}
func (r anyArr[T]) Swap(i, j int) {
r.data[i], r.data[j] = r.data[j], r.data[i]
}
func (r anyArr[T]) Less(i, j int) bool {
return r.fn(r.data[i], r.data[j])
}
func SimpleSort[T any](arr []T, fn func(i, j T) bool) {
slice := anyArr[T]{
data: arr,
fn: fn,
}
sort.Sort(slice)
return
}
func SimpleSortR[T any](arr []T, fn func(i, j T) bool) (r []T) {
r = make([]T, 0, len(arr))
for _, t := range arr {
r = append(r, t)
}
slice := anyArr[T]{
data: r,
fn: fn,
}
sort.Sort(slice)
return
}
func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
min := a[0]
for _, t := range a {
if min > t {
min = t
}
}
return min
}
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
max := a[0]
for _, t := range a {
if max < t {
max = t
}
}
return max
}
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
s := T(0)
for _, t := range a {
s += t
}
return s
}
func NumberToString[T IntNumber | ~float64 | ~float32](n T) string {
return fmt.Sprintf("%v", n)
}

View File

@ -34,17 +34,17 @@ func BenchmarkOr(b *testing.B) {
} }
} }
func BenchmarkStructColumn(b *testing.B) { func BenchmarkStructColumnToSlice(b *testing.B) {
y := getX() y := getX()
fmt.Println(y) fmt.Println(y)
b.ResetTimer() b.ResetTimer()
//b.N = 2 //b.N = 2
for i := 0; i < 1; i++ { for i := 0; i < 1; i++ {
StructColumn[int, *x](y, "Id") StructColumnToSlice[int, *x](y, "Id")
} }
} }
func TestStructColumn(t *testing.T) { func TestStructColumnToSlice(t *testing.T) {
type args struct { type args struct {
arr []x arr []x
field string field string
@ -67,14 +67,14 @@ func TestStructColumn(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if gotR := StructColumn[uint64, x](tt.args.arr, tt.args.field); !reflect.DeepEqual(gotR, tt.wantR) { if gotR := StructColumnToSlice[uint64, x](tt.args.arr, tt.args.field); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("StructColumn() = %v, want %v", gotR, tt.wantR) t.Errorf("StructColumnToSlice() = %v, want %v", gotR, tt.wantR)
} }
}) })
} }
} }
func TestToInterface(t *testing.T) { func TestToAny(t *testing.T) {
type args struct { type args struct {
v int v int
} }
@ -97,239 +97,3 @@ func TestToInterface(t *testing.T) {
}) })
} }
} }
func TestRandNum(t *testing.T) {
type args struct {
start int
end int
}
tests := []struct {
name string
args args
}{
{
name: "t1",
args: args{
start: 1,
end: 2,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := 0; i < 100; i++ {
got := RandNum(tt.args.start, tt.args.end)
if got > tt.args.end || got < tt.args.start {
t.Errorf("RandNum() = %v, range error", got)
}
}
})
}
}
func TestSimpleSort(t *testing.T) {
type xy struct {
x int
y int
}
type args struct {
arr []xy
fn func(i, j xy) bool
}
tests := []struct {
name string
args args
wantR []xy
}{
{
name: "t1",
args: args{
arr: []xy{
{1, 2},
{3, 4},
{1, 3},
{2, 1},
{1, 6},
},
fn: func(i, j xy) bool {
if i.x < j.x {
return true
}
if i.x == j.x && i.y > i.y {
return true
}
return false
},
},
wantR: []xy{
{1, 2},
{1, 3},
{1, 6},
{2, 1},
{3, 4},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if SimpleSort(tt.args.arr, tt.args.fn); !reflect.DeepEqual(tt.args.arr, tt.wantR) {
t.Errorf("SimpleSort() = %v, want %v", tt.args.arr, tt.wantR)
}
})
}
}
func TestMin(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: []int{1, 2, 3}},
want: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Min(tt.args.a...); got != tt.want {
t.Errorf("Min() = %v, want %v", got, tt.want)
}
})
}
}
func TestMax(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: []int{1, 2, 3}},
want: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Max(tt.args.a...); got != tt.want {
t.Errorf("Max() = %v, want %v", got, tt.want)
}
})
}
}
func TestSum(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: RangeSlice(1, 10, 1)},
want: 55,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Sum(tt.args.a...); got != tt.want {
t.Errorf("Sum() = %v, want %v", got, tt.want)
}
})
}
}
func TestNumberToString(t *testing.T) {
type args struct {
n float64
}
tests := []struct {
name string
args args
want string
}{
{
name: "t1",
args: args{n: 111},
want: "111",
},
{
name: "t2",
args: args{n: 111.222222},
want: "111.222222",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NumberToString(tt.args.n); got != tt.want {
t.Errorf("NumberToString() = %v, want %v", got, tt.want)
}
})
}
}
func TestSimpleSortR(t *testing.T) {
type xy struct {
x int
y int
}
type args[T any] struct {
arr []T
fn func(i, j T) bool
}
type testCase[T any] struct {
name string
args args[T]
wantR []T
}
tests := []testCase[xy]{
{
name: "t1",
args: args[xy]{
arr: []xy{
{1, 2},
{3, 4},
{1, 3},
{2, 1},
{1, 6},
},
fn: func(i, j xy) bool {
if i.x < j.x {
return true
}
if i.x == j.x && i.y > i.y {
return true
}
return false
},
},
wantR: []xy{
{1, 2},
{1, 3},
{1, 6},
{2, 1},
{3, 4},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotR := SimpleSortR[xy](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("SimpleSortR() = %v, want %v", gotR, tt.wantR)
}
})
}
}

View File

@ -1,8 +1,9 @@
package helper package html
import ( import (
"fmt" "fmt"
"github.com/dlclark/regexp2" "github.com/dlclark/regexp2"
"github.com/fthvgb1/wp-go/helper/slice"
"regexp" "regexp"
"strings" "strings"
) )
@ -119,7 +120,7 @@ func StripTagsX(str, allowable string) string {
var tagx = regexp.MustCompile(`(</?[a-z0-9]+?)( |>)`) var tagx = regexp.MustCompile(`(</?[a-z0-9]+?)( |>)`)
var selfCloseTags = map[string]string{"area": "", "base": "", "basefont": "", "br": "", "col": "", "command": "", "embed": "", "frame": "", "hr": "", "img": "", "input": "", "isindex": "", "link": "", "meta": "", "param": "", "source": "", "track": "", "wbr": ""} var selfCloseTags = map[string]string{"area": "", "base": "", "basefont": "", "br": "", "col": "", "command": "", "embed": "", "frame": "", "hr": "", "img": "", "input": "", "isindex": "", "link": "", "meta": "", "param": "", "source": "", "track": "", "wbr": ""}
func CloseHtmlTag(str string) string { func CloseTag(str string) string {
tags := tag.FindAllString(str, -1) tags := tag.FindAllString(str, -1)
if len(tags) < 1 { if len(tags) < 1 {
return str return str
@ -135,13 +136,13 @@ func CloseHtmlTag(str string) string {
} }
tagss = append(tagss, ss) tagss = append(tagss, ss)
} }
r := SliceMap(SliceReverse(ClearClosedTag(tagss)), func(s string) string { r := slice.Map(slice.Reverse(UnClosedTag(tagss)), func(s string) string {
return fmt.Sprintf("</%s>", strings.Trim(s, "<>")) return fmt.Sprintf("</%s>", strings.Trim(s, "<>"))
}) })
return strings.Join(r, "") return strings.Join(r, "")
} }
func ClearClosedTag(s []string) []string { func UnClosedTag(s []string) []string {
i := 0 i := 0
for { for {
if len(s[i:]) < 2 { if len(s[i:]) < 2 {

View File

@ -1,4 +1,4 @@
package helper package html
import ( import (
"reflect" "reflect"
@ -183,8 +183,8 @@ func TestCloseHtmlTag(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := CloseHtmlTag(tt.args.str); !reflect.DeepEqual(got, tt.want) { if got := CloseTag(tt.args.str); !reflect.DeepEqual(got, tt.want) {
t.Errorf("CloseHtmlTag() = %v, want %v", got, tt.want) t.Errorf("CloseTag() = %v, want %v", got, tt.want)
} }
}) })
} }
@ -222,8 +222,8 @@ func Test_clearTag(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := ClearClosedTag(tt.args.s); !reflect.DeepEqual(got, tt.want) { if got := UnClosedTag(tt.args.s); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ClearClosedTag() = %v, want %v", got, tt.want) t.Errorf("UnClosedTag() = %v, want %v", got, tt.want)
} }
}) })
} }

View File

@ -1,4 +1,4 @@
package helper package maps
import "strings" import "strings"
@ -25,14 +25,14 @@ func GetStrMapAnyVal[T any](key string, v map[string]any) (r T, o bool) {
return return
} }
func GetStrMapAnyValToAny(key string, v map[string]any) (r any, o bool) { func GetStrMapAnyValWithAny(key string, v map[string]any) (r any, o bool) {
k := strings.Split(key, ".") k := strings.Split(key, ".")
if len(k) > 1 { if len(k) > 1 {
val, ok := v[k[0]] val, ok := v[k[0]]
if ok { if ok {
vx, ok := val.(map[string]any) vx, ok := val.(map[string]any)
if ok { if ok {
r, o = GetStrMapAnyValToAny(strings.Join(k[1:], "."), vx) r, o = GetStrMapAnyValWithAny(strings.Join(k[1:], "."), vx)
} }
} }
} else { } else {

View File

@ -1,4 +1,4 @@
package helper package maps
import ( import (
"reflect" "reflect"
@ -65,7 +65,7 @@ func TestGetStrMapAnyVal(t *testing.T) {
} }
} }
func TestGetStrMapAnyValToAny(t *testing.T) { func TestGetStrMapAnyValWithAny(t *testing.T) {
type args struct { type args struct {
key string key string
v map[string]any v map[string]any
@ -113,12 +113,12 @@ func TestGetStrMapAnyValToAny(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
gotR, gotO := GetStrMapAnyValToAny(tt.args.key, tt.args.v) gotR, gotO := GetStrMapAnyValWithAny(tt.args.key, tt.args.v)
if !reflect.DeepEqual(gotR, tt.wantR) { if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("GetStrMapAnyValToAny() gotR = %v, want %v", gotR, tt.wantR) t.Errorf("GetStrMapAnyValWithAny() gotR = %v, want %v", gotR, tt.wantR)
} }
if gotO != tt.wantO { if gotO != tt.wantO {
t.Errorf("GetStrMapAnyValToAny() gotO = %v, want %v", gotO, tt.wantO) t.Errorf("GetStrMapAnyValWithAny() gotO = %v, want %v", gotO, tt.wantO)
} }
}) })
} }

View File

@ -1,4 +1,4 @@
package helper package maps
import "encoding/json" import "encoding/json"
@ -21,7 +21,7 @@ func StructToAnyMap[K comparable, T any](s T) (r map[K]any, err error) {
return return
} }
func MapToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool)) (r []T) { func FilterToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool)) (r []T) {
for k, v := range m { for k, v := range m {
vv, ok := fn(k, v) vv, ok := fn(k, v)
if ok { if ok {
@ -31,15 +31,15 @@ func MapToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool))
return return
} }
// MapAnyAnyToStrAny map[any]any => map[string]any 方便json转换 // AnyAnyToStrAny map[any]any => map[string]any 方便json转换
func MapAnyAnyToStrAny(m map[any]any) (r map[string]any) { func AnyAnyToStrAny(m map[any]any) (r map[string]any) {
r = make(map[string]any) r = make(map[string]any)
for k, v := range m { for k, v := range m {
kk, ok := k.(string) kk, ok := k.(string)
if ok { if ok {
vv, ok := v.(map[any]any) vv, ok := v.(map[any]any)
if ok { if ok {
r[kk] = MapAnyAnyToStrAny(vv) r[kk] = AnyAnyToStrAny(vv)
} else { } else {
r[kk] = v r[kk] = v
} }

View File

@ -1,4 +1,4 @@
package helper package maps
import ( import (
"reflect" "reflect"
@ -118,7 +118,15 @@ func TestStructToAnyMap(t *testing.T) {
t.Errorf("StructToAnyMap() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("StructToAnyMap() error = %v, wantErr %v", err, tt.wantErr)
return return
} }
if !reflect.DeepEqual(gotR, tt.wantR) { gr, err := StrAnyMapToStruct[Me](gotR)
if err != nil {
panic(err)
}
wr, err := StrAnyMapToStruct[Me](tt.wantR)
if err != nil {
panic(err)
}
if !reflect.DeepEqual(gr, wr) {
t.Errorf("StructToAnyMap() gotR = %v, want %v", gotR, tt.wantR) t.Errorf("StructToAnyMap() gotR = %v, want %v", gotR, tt.wantR)
} }
}) })
@ -157,8 +165,8 @@ func TestMapToSlice(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if gotR := MapToSlice(tt.args.m, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) { if gotR := FilterToSlice(tt.args.m, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("MapToSlice() = %v, want %v", gotR, tt.wantR) t.Errorf("FilterToSlice() = %v, want %v", gotR, tt.wantR)
} }
}) })
} }

67
helper/number/number.go Normal file
View File

@ -0,0 +1,67 @@
package number
import (
"fmt"
"math/rand"
)
type IntNumber interface {
~int | ~int64 | ~int32 | ~int8 | ~int16 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}
func Range[T IntNumber](start, end, step T) []T {
if step == 0 {
panic("step can't be 0")
}
l := int((end-start+1)/step + 1)
if l < 0 {
l = 0 - l
}
r := make([]T, 0, l)
for i := start; ; {
r = append(r, i)
i = i + step
if (step > 0 && i > end) || (step < 0 && i < end) {
break
}
}
return r
}
func Rand[T IntNumber](start, end T) T {
end++
return T(rand.Int63n(int64(end-start))) + start
}
func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
min := a[0]
for _, t := range a {
if min > t {
min = t
}
}
return min
}
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
max := a[0]
for _, t := range a {
if max < t {
max = t
}
}
return max
}
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
s := T(0)
for _, t := range a {
s += t
}
return s
}
func ToString[T IntNumber | ~float64 | ~float32](n T) string {
return fmt.Sprintf("%v", n)
}

View File

@ -0,0 +1,193 @@
package number
import (
"reflect"
"testing"
)
func TestRange(t *testing.T) {
type args struct {
start int
end int
step int
}
tests := []struct {
name string
args args
want []int
}{
{
name: "t1",
args: args{
start: 1,
end: 5,
step: 1,
},
want: []int{1, 2, 3, 4, 5},
},
{
name: "t2",
args: args{
start: 0,
end: 5,
step: 2,
},
want: []int{0, 2, 4},
},
{
name: "t3",
args: args{
start: 1,
end: 11,
step: 3,
},
want: []int{1, 4, 7, 10},
},
{
name: "t4",
args: args{
start: 0,
end: -5,
step: -1,
},
want: []int{0, -1, -2, -3, -4, -5},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Range(tt.args.start, tt.args.end, tt.args.step); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Range() = %v, want %v", got, tt.want)
}
})
}
}
func TestMin(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: []int{1, 2, 3}},
want: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Min(tt.args.a...); got != tt.want {
t.Errorf("Min() = %v, want %v", got, tt.want)
}
})
}
}
func TestMax(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: []int{1, 2, 3}},
want: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Max(tt.args.a...); got != tt.want {
t.Errorf("Max() = %v, want %v", got, tt.want)
}
})
}
}
func TestSum(t *testing.T) {
type args struct {
a []int
}
tests := []struct {
name string
args args
want int
}{
{
name: "t1",
args: args{a: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
want: 55,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Sum(tt.args.a...); got != tt.want {
t.Errorf("Sum() = %v, want %v", got, tt.want)
}
})
}
}
func TestToString(t *testing.T) {
type args struct {
n float64
}
tests := []struct {
name string
args args
want string
}{
{
name: "t1",
args: args{n: 111},
want: "111",
},
{
name: "t2",
args: args{n: 111.222222},
want: "111.222222",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ToString(tt.args.n); got != tt.want {
t.Errorf("NumberToString() = %v, want %v", got, tt.want)
}
})
}
}
func TestRand(t *testing.T) {
type args struct {
start int
end int
}
tests := []struct {
name string
args args
}{
{
name: "t1",
args: args{
start: 1,
end: 2,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := 0; i < 100; i++ {
got := Rand(tt.args.start, tt.args.end)
if got > tt.args.end || got < tt.args.start {
t.Errorf("RandNum() = %v, range error", got)
}
}
})
}
}

View File

@ -1,6 +1,6 @@
package helper package slice
func SliceMap[T, R any](arr []T, fn func(T) R) []R { func Map[T, R any](arr []T, fn func(T) R) []R {
r := make([]R, 0, len(arr)) r := make([]R, 0, len(arr))
for _, t := range arr { for _, t := range arr {
r = append(r, fn(t)) r = append(r, fn(t))
@ -8,7 +8,7 @@ func SliceMap[T, R any](arr []T, fn func(T) R) []R {
return r return r
} }
func SliceFilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) { func FilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
for _, t := range arr { for _, t := range arr {
x, ok := fn(t) x, ok := fn(t)
if ok { if ok {
@ -18,7 +18,7 @@ func SliceFilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
return return
} }
func SliceFilter[T any](arr []T, fn func(T) bool) []T { func Filter[T any](arr []T, fn func(T) bool) []T {
var r []T var r []T
for _, t := range arr { for _, t := range arr {
if fn(t) { if fn(t) {
@ -28,14 +28,14 @@ func SliceFilter[T any](arr []T, fn func(T) bool) []T {
return r return r
} }
func SliceReduce[R, T any](arr []T, fn func(T, R) R, r R) R { func Reduce[R, T any](arr []T, fn func(T, R) R, r R) R {
for _, t := range arr { for _, t := range arr {
r = fn(t, r) r = fn(t, r)
} }
return r return r
} }
func SliceReverse[T any](arr []T) []T { func Reverse[T any](arr []T) []T {
var r = make([]T, 0, len(arr)) var r = make([]T, 0, len(arr))
for i := len(arr); i > 0; i-- { for i := len(arr); i > 0; i-- {
r = append(r, arr[i-1]) r = append(r, arr[i-1])
@ -43,7 +43,7 @@ func SliceReverse[T any](arr []T) []T {
return r return r
} }
func SliceSelfReverse[T any](arr []T) []T { func ReverseSelf[T any](arr []T) []T {
l := len(arr) l := len(arr)
half := l / 2 half := l / 2
for i := 0; i < half; i++ { for i := 0; i < half; i++ {
@ -52,13 +52,13 @@ func SliceSelfReverse[T any](arr []T) []T {
return arr return arr
} }
func SimpleSliceToMap[K comparable, V any](arr []V, fn func(V) K) map[K]V { func SimpleToMap[K comparable, V any](arr []V, fn func(V) K) map[K]V {
return SliceToMap(arr, func(v V) (K, V) { return ToMap(arr, func(v V) (K, V) {
return fn(v), v return fn(v), v
}, true) }, true)
} }
func SliceToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev bool) map[K]T { func ToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev bool) map[K]T {
m := make(map[K]T) m := make(map[K]T)
for _, v := range arr { for _, v := range arr {
k, r := fn(v) k, r := fn(v)
@ -72,26 +72,7 @@ func SliceToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev
return m return m
} }
func RangeSlice[T IntNumber](start, end, step T) []T { func Pagination[T any](arr []T, page, pageSize int) []T {
if step == 0 {
panic("step can't be 0")
}
l := int((end-start+1)/step + 1)
if l < 0 {
l = 0 - l
}
r := make([]T, 0, l)
for i := start; ; {
r = append(r, i)
i = i + step
if (step > 0 && i > end) || (step < 0 && i < end) {
break
}
}
return r
}
func SlicePagination[T any](arr []T, page, pageSize int) []T {
start := (page - 1) * pageSize start := (page - 1) * pageSize
l := len(arr) l := len(arr)
if start > l { if start > l {
@ -104,7 +85,7 @@ func SlicePagination[T any](arr []T, page, pageSize int) []T {
return arr[start:end] return arr[start:end]
} }
func SliceChunk[T any](arr []T, size int) [][]T { func Chunk[T any](arr []T, size int) [][]T {
var r [][]T var r [][]T
i := 0 i := 0
for { for {
@ -153,3 +134,13 @@ func Comb[T any](arr []T, m int) (r [][]T) {
} }
return r return r
} }
func IsContained[T comparable](a T, arr []T) bool {
for _, v := range arr {
if a == v {
return true
}
}
return false
}

View File

@ -1,12 +1,13 @@
package helper package slice
import ( import (
"github.com/fthvgb1/wp-go/helper/number"
"reflect" "reflect"
"testing" "testing"
) )
func TestSlicePagination(t *testing.T) { func TestPagination(t *testing.T) {
arr := RangeSlice[int](1, 10, 1) arr := number.Range[int](1, 10, 1)
type args struct { type args struct {
arr []int arr []int
page int page int
@ -24,7 +25,7 @@ func TestSlicePagination(t *testing.T) {
page: 1, page: 1,
pageSize: 2, pageSize: 2,
}, },
want: RangeSlice[int](1, 2, 1), want: number.Range[int](1, 2, 1),
}, { }, {
name: "t2", name: "t2",
args: args{ args: args{
@ -32,7 +33,7 @@ func TestSlicePagination(t *testing.T) {
page: 2, page: 2,
pageSize: 2, pageSize: 2,
}, },
want: RangeSlice[int](3, 4, 1), want: number.Range[int](3, 4, 1),
}, { }, {
name: "t3", name: "t3",
args: args{ args: args{
@ -53,14 +54,14 @@ func TestSlicePagination(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SlicePagination(tt.args.arr, tt.args.page, tt.args.pageSize); !reflect.DeepEqual(got, tt.want) { if got := Pagination(tt.args.arr, tt.args.page, tt.args.pageSize); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SlicePagination() = %v, want %v", got, tt.want) t.Errorf("Pagination() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceReduce(t *testing.T) { func TestReduce(t *testing.T) {
type args struct { type args struct {
arr []int arr []int
fn func(int, int) int fn func(int, int) int
@ -73,7 +74,7 @@ func TestSliceReduce(t *testing.T) {
}{ }{
{ {
name: "t1", name: "t1",
args: args{arr: RangeSlice(1, 10, 1), fn: func(i int, i2 int) int { args: args{arr: number.Range(1, 10, 1), fn: func(i int, i2 int) int {
return i + i2 return i + i2
}}, }},
want: 55, want: 55,
@ -81,14 +82,14 @@ func TestSliceReduce(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceReduce(tt.args.arr, tt.args.fn, tt.args.r); !reflect.DeepEqual(got, tt.want) { if got := Reduce(tt.args.arr, tt.args.fn, tt.args.r); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceReduce() = %v, want %v", got, tt.want) t.Errorf("Reduce() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceFilter(t *testing.T) { func TestFilter(t *testing.T) {
type args struct { type args struct {
arr []int arr []int
fn func(int) bool fn func(int) bool
@ -100,22 +101,22 @@ func TestSliceFilter(t *testing.T) {
}{ }{
{ {
name: "t1", name: "t1",
args: args{arr: RangeSlice(1, 10, 1), fn: func(i int) bool { args: args{arr: number.Range(1, 10, 1), fn: func(i int) bool {
return i > 4 return i > 4
}}, }},
want: RangeSlice(5, 10, 1), want: number.Range(5, 10, 1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceFilter(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) { if got := Filter(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceFilter() = %v, want %v", got, tt.want) t.Errorf("Filter() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceMap(t *testing.T) { func TestMap(t *testing.T) {
type args struct { type args struct {
arr []int8 arr []int8
fn func(int8) int fn func(int8) int
@ -128,24 +129,24 @@ func TestSliceMap(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args{ args: args{
arr: RangeSlice[int8](1, 10, 1), arr: number.Range[int8](1, 10, 1),
fn: func(i int8) int { fn: func(i int8) int {
return int(i) return int(i)
}, },
}, },
want: RangeSlice(1, 10, 1), want: number.Range(1, 10, 1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) { if got := Map(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceMap() = %v, want %v", got, tt.want) t.Errorf("Map() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceReverse(t *testing.T) { func TestReverse(t *testing.T) {
type args struct { type args struct {
arr []int arr []int
} }
@ -156,71 +157,14 @@ func TestSliceReverse(t *testing.T) {
}{ }{
{ {
name: "t1", name: "t1",
args: args{arr: RangeSlice(1, 10, 1)}, args: args{arr: number.Range(1, 10, 1)},
want: RangeSlice(10, 1, -1), want: number.Range(10, 1, -1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceReverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) { if got := Reverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceReverse() = %v, want %v", got, tt.want) t.Errorf("Reverse() = %v, want %v", got, tt.want)
}
})
}
}
func TestRangeSlice(t *testing.T) {
type args struct {
start int
end int
step int
}
tests := []struct {
name string
args args
want []int
}{
{
name: "t1",
args: args{
start: 1,
end: 5,
step: 1,
},
want: []int{1, 2, 3, 4, 5},
},
{
name: "t2",
args: args{
start: 0,
end: 5,
step: 2,
},
want: []int{0, 2, 4},
},
{
name: "t3",
args: args{
start: 1,
end: 11,
step: 3,
},
want: []int{1, 4, 7, 10},
},
{
name: "t4",
args: args{
start: 0,
end: -5,
step: -1,
},
want: []int{0, -1, -2, -3, -4, -5},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := RangeSlice(tt.args.start, tt.args.end, tt.args.step); !reflect.DeepEqual(got, tt.want) {
t.Errorf("RangeSlice() = %v, want %v", got, tt.want)
} }
}) })
} }
@ -240,20 +184,20 @@ func TestSlice(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args{ args: args{
arr: RangeSlice(1, 10, 1), arr: number.Range(1, 10, 1),
offset: 3, offset: 3,
length: 2, length: 2,
}, },
wantR: RangeSlice(4, 5, 1), wantR: number.Range(4, 5, 1),
}, },
{ {
name: "t2", name: "t2",
args: args{ args: args{
arr: RangeSlice(1, 10, 1), arr: number.Range(1, 10, 1),
offset: 3, offset: 3,
length: 0, length: 0,
}, },
wantR: RangeSlice(4, 10, 1), wantR: number.Range(4, 10, 1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -278,7 +222,7 @@ func TestComb(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args{ args: args{
arr: RangeSlice(1, 5, 1), arr: number.Range(1, 5, 1),
m: 2, m: 2,
}, },
wantR: [][]int{ wantR: [][]int{
@ -297,7 +241,7 @@ func TestComb(t *testing.T) {
{ {
name: "t2", name: "t2",
args: args{ args: args{
arr: RangeSlice(1, 5, 1), arr: number.Range(1, 5, 1),
m: 3, m: 3,
}, },
wantR: [][]int{ wantR: [][]int{
@ -316,7 +260,7 @@ func TestComb(t *testing.T) {
{ {
name: "t3", name: "t3",
args: args{ args: args{
arr: RangeSlice(1, 5, 1), arr: number.Range(1, 5, 1),
m: 4, m: 4,
}, },
wantR: [][]int{ wantR: [][]int{
@ -337,7 +281,7 @@ func TestComb(t *testing.T) {
} }
} }
func TestSliceChunk(t *testing.T) { func TestChunk(t *testing.T) {
type args struct { type args struct {
arr []int arr []int
size int size int
@ -350,7 +294,7 @@ func TestSliceChunk(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args{ args: args{
arr: RangeSlice(1, 7, 1), arr: number.Range(1, 7, 1),
size: 2, size: 2,
}, },
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7}}, want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7}},
@ -358,7 +302,7 @@ func TestSliceChunk(t *testing.T) {
{ {
name: "t2", name: "t2",
args: args{ args: args{
arr: RangeSlice(1, 8, 1), arr: number.Range(1, 8, 1),
size: 2, size: 2,
}, },
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}, want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}},
@ -366,8 +310,8 @@ func TestSliceChunk(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceChunk(tt.args.arr, tt.args.size); !reflect.DeepEqual(got, tt.want) { if got := Chunk(tt.args.arr, tt.args.size); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceChunk() = %v, want %v", got, tt.want) t.Errorf("Chunk() = %v, want %v", got, tt.want)
} }
}) })
} }
@ -393,14 +337,14 @@ func TestSimpleSliceToMap(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SimpleSliceToMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) { if got := SimpleToMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SimpleSliceToMap() = %v, want %v", got, tt.want) t.Errorf("SimpleToMap() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceToMap(t *testing.T) { func TestToMap(t *testing.T) {
type ss struct { type ss struct {
id int id int
v string v string
@ -439,14 +383,14 @@ func TestSliceToMap(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceToMap(tt.args.arr, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(got, tt.want) { if got := ToMap(tt.args.arr, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceToMap() = %v, want %v", got, tt.want) t.Errorf("ToMap() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceSelfReverse(t *testing.T) { func TestReverseSelf(t *testing.T) {
type args struct { type args struct {
arr []int arr []int
} }
@ -458,27 +402,27 @@ func TestSliceSelfReverse(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args{ args: args{
arr: RangeSlice(1, 10, 1), arr: number.Range(1, 10, 1),
}, },
want: RangeSlice(10, 1, -1), want: number.Range(10, 1, -1),
}, { }, {
name: "t2", name: "t2",
args: args{ args: args{
arr: RangeSlice(1, 9, 1), arr: number.Range(1, 9, 1),
}, },
want: RangeSlice(9, 1, -1), want: number.Range(9, 1, -1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := SliceSelfReverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) { if got := ReverseSelf(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
t.Errorf("SliceSelfReverse() = %v, want %v", got, tt.want) t.Errorf("ReverseSelf() = %v, want %v", got, tt.want)
} }
}) })
} }
} }
func TestSliceFilterAndMap(t *testing.T) { func TestFilterAndMap(t *testing.T) {
type a struct { type a struct {
x int x int
y string y string
@ -513,8 +457,8 @@ func TestSliceFilterAndMap(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if gotR := SliceFilterAndMap[string](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) { if gotR := FilterAndMap[string](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("SliceFilterAndMap() = %v, want %v", gotR, tt.wantR) t.Errorf("FilterAndMap() = %v, want %v", gotR, tt.wantR)
} }
}) })
} }

42
helper/slice/sort.go Normal file
View File

@ -0,0 +1,42 @@
package slice
import "sort"
type anyArr[T any] struct {
data []T
fn func(i, j T) bool
}
func (r anyArr[T]) Len() int {
return len(r.data)
}
func (r anyArr[T]) Swap(i, j int) {
r.data[i], r.data[j] = r.data[j], r.data[i]
}
func (r anyArr[T]) Less(i, j int) bool {
return r.fn(r.data[i], r.data[j])
}
func SortSelf[T any](arr []T, fn func(i, j T) bool) {
slice := anyArr[T]{
data: arr,
fn: fn,
}
sort.Sort(slice)
return
}
func Sort[T any](arr []T, fn func(i, j T) bool) (r []T) {
r = make([]T, 0, len(arr))
for _, t := range arr {
r = append(r, t)
}
slice := anyArr[T]{
data: r,
fn: fn,
}
sort.Sort(slice)
return
}

112
helper/slice/sort_test.go Normal file
View File

@ -0,0 +1,112 @@
package slice
import (
"reflect"
"testing"
)
func TestSortSelf(t *testing.T) {
type xy struct {
x int
y int
}
type args struct {
arr []xy
fn func(i, j xy) bool
}
tests := []struct {
name string
args args
wantR []xy
}{
{
name: "t1",
args: args{
arr: []xy{
{1, 2},
{3, 4},
{1, 3},
{2, 1},
{1, 6},
},
fn: func(i, j xy) bool {
if i.x < j.x {
return true
}
if i.x == j.x && i.y > i.y {
return true
}
return false
},
},
wantR: []xy{
{1, 2},
{1, 3},
{1, 6},
{2, 1},
{3, 4},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if SortSelf(tt.args.arr, tt.args.fn); !reflect.DeepEqual(tt.args.arr, tt.wantR) {
t.Errorf("SimpleSort() = %v, want %v", tt.args.arr, tt.wantR)
}
})
}
}
func TestSort(t *testing.T) {
type xy struct {
x int
y int
}
type args[T any] struct {
arr []T
fn func(i, j T) bool
}
type testCase[T any] struct {
name string
args args[T]
wantR []T
}
tests := []testCase[xy]{
{
name: "t1",
args: args[xy]{
arr: []xy{
{1, 2},
{3, 4},
{1, 3},
{2, 1},
{1, 6},
},
fn: func(i, j xy) bool {
if i.x < j.x {
return true
}
if i.x == j.x && i.y > i.y {
return true
}
return false
},
},
wantR: []xy{
{1, 2},
{1, 3},
{1, 6},
{2, 1},
{3, 4},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotR := Sort[xy](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("SimpleSortR() = %v, want %v", gotR, tt.wantR)
}
})
}
}

View File

@ -1,4 +1,4 @@
package helper package strings
import ( import (
"crypto/md5" "crypto/md5"
@ -7,7 +7,7 @@ import (
"strings" "strings"
) )
func StrJoin(s ...string) (str string) { func Join(s ...string) (str string) {
if len(s) == 1 { if len(s) == 1 {
return s[0] return s[0]
} else if len(s) > 1 { } else if len(s) > 1 {
@ -20,7 +20,7 @@ func StrJoin(s ...string) (str string) {
return return
} }
func StringMd5(str string) string { func Md5(str string) string {
h := md5.New() h := md5.New()
_, err := io.WriteString(h, str) _, err := io.WriteString(h, str)
if err != nil { if err != nil {

View File

@ -1,4 +1,4 @@
package helper package strings
import "testing" import "testing"
@ -15,8 +15,8 @@ func TestStrJoin(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if gotStr := StrJoin(tt.args.s...); gotStr != tt.wantStr { if gotStr := Join(tt.args.s...); gotStr != tt.wantStr {
t.Errorf("StrJoin() = %v, want %v", gotStr, tt.wantStr) t.Errorf("Join() = %v, want %v", gotStr, tt.wantStr)
} }
}) })
} }

View File

@ -4,7 +4,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/mail" "github.com/fthvgb1/wp-go/internal/mail"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/config" "github.com/fthvgb1/wp-go/internal/pkg/config"
@ -81,7 +81,7 @@ func PostComment(c *gin.Context) {
return return
} }
newReq.Host = home.Host newReq.Host = home.Host
newReq.Header.Set("Cookie", strings.Join(helper.SliceMap(c.Request.Cookies(), func(t *http.Cookie) string { newReq.Header.Set("Cookie", strings.Join(slice.Map(c.Request.Cookies(), func(t *http.Cookie) string {
return fmt.Sprintf("%s=%s", t.Name, t.Value) return fmt.Sprintf("%s=%s", t.Name, t.Value)
}), "; ")) }), "; "))
ress, er := http.DefaultClient.Do(newReq) ress, er := http.DefaultClient.Do(newReq)

View File

@ -2,7 +2,7 @@ package actions
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
@ -49,7 +49,7 @@ func Detail(c *gin.Context) {
if isApproveComment == true { if isApproveComment == true {
return return
} }
c.HTML(status, helper.StrJoin(theme.GetTemplateName(), "/posts/detail.gohtml"), h) c.HTML(status, str.Join(theme.GetTemplateName(), "/posts/detail.gohtml"), h)
}() }()
id := c.Param("id") id := c.Param("id")
Id := 0 Id := 0

View File

@ -1,7 +1,7 @@
package actions package actions
import ( import (
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
@ -11,7 +11,7 @@ import (
var tmp = "Mon, 02 Jan 2006 15:04:05 GMT" var tmp = "Mon, 02 Jan 2006 15:04:05 GMT"
func isCacheExpired(c *gin.Context, lastTime time.Time) bool { func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
eTag := helper.StringMd5(lastTime.Format(tmp)) eTag := str.Md5(lastTime.Format(tmp))
since := c.Request.Header.Get("If-Modified-Since") since := c.Request.Header.Get("If-Modified-Since")
cTag := c.Request.Header.Get("If-None-Match") cTag := c.Request.Header.Get("If-None-Match")
if since != "" && cTag != "" { if since != "" && cTag != "" {
@ -41,7 +41,7 @@ func Feed(c *gin.Context) {
func setFeed(s string, c *gin.Context, t time.Time) { func setFeed(s string, c *gin.Context, t time.Time) {
lastTimeGMT := t.Format(tmp) lastTimeGMT := t.Format(tmp)
eTag := helper.StringMd5(lastTimeGMT) eTag := str.Md5(lastTimeGMT)
c.Header("Content-Type", "application/rss+xml; charset=UTF-8") c.Header("Content-Type", "application/rss+xml; charset=UTF-8")
c.Header("Last-Modified", lastTimeGMT) c.Header("Last-Modified", lastTimeGMT)
c.Header("ETag", eTag) c.Header("ETag", eTag)

View File

@ -2,7 +2,8 @@ package actions
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
dao "github.com/fthvgb1/wp-go/internal/pkg/dao" dao "github.com/fthvgb1/wp-go/internal/pkg/dao"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
@ -83,7 +84,7 @@ func (h *indexHandle) getSearchKey() string {
func (h *indexHandle) parseParams() (err error) { func (h *indexHandle) parseParams() (err error) {
h.order = h.c.Query("order") h.order = h.c.Query("order")
if !helper.IsContainInArr(h.order, []string{"asc", "desc"}) { if !slice.IsContained(h.order, []string{"asc", "desc"}) {
h.order = "asc" h.order = "asc"
} }
year := h.c.Param("year") year := h.c.Param("year")
@ -142,7 +143,7 @@ func (h *indexHandle) parseParams() (err error) {
} }
s := h.c.Query("s") s := h.c.Query("s")
if s != "" && strings.Replace(s, " ", "", -1) != "" { if s != "" && strings.Replace(s, " ", "", -1) != "" {
q := helper.StrJoin("%", s, "%") q := str.Join("%", s, "%")
h.where = append(h.where, []string{ h.where = append(h.where, []string{
"and", "post_title", "like", q, "", "and", "post_title", "like", q, "",
"or", "post_content", "like", q, "", "or", "post_content", "like", q, "",
@ -150,7 +151,7 @@ func (h *indexHandle) parseParams() (err error) {
}, []string{"post_password", ""}) }, []string{"post_password", ""})
h.postType = append(h.postType, "page", "attachment") h.postType = append(h.postType, "page", "attachment")
h.header = fmt.Sprintf("%s的搜索结果", s) h.header = fmt.Sprintf("%s的搜索结果", s)
h.setTitleLR(helper.StrJoin(`"`, s, `"`, "的搜索结果"), wpconfig.Options.Value("blogname")) h.setTitleLR(str.Join(`"`, s, `"`, "的搜索结果"), wpconfig.Options.Value("blogname"))
h.search = s h.search = s
h.scene = plugins.Search h.scene = plugins.Search
} }

View File

@ -2,7 +2,7 @@ package actions
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/phpass" "github.com/fthvgb1/wp-go/internal/phpass"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions"
@ -33,7 +33,7 @@ func Login(c *gin.Context) {
c.Error(err) c.Error(err)
return return
} }
cohash := fmt.Sprintf("wp-postpass_%s", helper.StringMd5(wpconfig.Options.Value("siteurl"))) cohash := fmt.Sprintf("wp-postpass_%s", str.Md5(wpconfig.Options.Value("siteurl")))
c.SetCookie(cohash, pass, 24*3600, "/", "", false, false) c.SetCookie(cohash, pass, 24*3600, "/", "", false, false)
c.Redirect(http.StatusFound, ref) c.Redirect(http.StatusFound, ref)

View File

@ -1,7 +1,7 @@
package middleware package middleware
import ( import (
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
@ -35,7 +35,7 @@ func FlowLimit(maxRequestSleepNum, maxRequestNum int64, sleepTime []time.Duratio
n := atomic.LoadInt64(&flow) n := atomic.LoadInt64(&flow)
if n >= atomic.LoadInt64(&maxRequestSleepNum) && n <= atomic.LoadInt64(&maxRequestNum) { if n >= atomic.LoadInt64(&maxRequestSleepNum) && n <= atomic.LoadInt64(&maxRequestNum) {
ss := s.Load() ss := s.Load()
t := helper.RandNum(ss[0], ss[1]) t := number.Rand(ss[0], ss[1])
time.Sleep(t) time.Sleep(t)
} else if n > atomic.LoadInt64(&maxRequestNum) { } else if n > atomic.LoadInt64(&maxRequestNum) {
c.String(http.StatusForbidden, "请求太多了,服务器君表示压力山大==!, 请稍后访问") c.String(http.StatusForbidden, "请求太多了,服务器君表示压力山大==!, 请稍后访问")

View File

@ -1,14 +1,14 @@
package middleware package middleware
import ( import (
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"strings" "strings"
) )
func SetStaticFileCache(c *gin.Context) { func SetStaticFileCache(c *gin.Context) {
f := strings.Split(strings.TrimLeft(c.FullPath(), "/"), "/") f := strings.Split(strings.TrimLeft(c.FullPath(), "/"), "/")
if len(f) > 0 && helper.IsContainInArr(f[0], []string{"wp-includes", "wp-content", "favicon.ico"}) { if len(f) > 0 && slice.IsContained(f[0], []string{"wp-includes", "wp-content", "favicon.ico"}) {
c.Header("Cache-Control", "private, max-age=86400") c.Header("Cache-Control", "private, max-age=86400")
} }
c.Next() c.Next()

View File

@ -3,7 +3,7 @@ package phpass
import ( import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"io" "io"
"os" "os"
@ -49,7 +49,7 @@ func (p *PasswordHash) getRandomBytes(count int) (r string, err error) {
if len(buf) < count { if len(buf) < count {
r = "" r = ""
for i := 0; i < count; i = i + 16 { for i := 0; i < count; i = i + 16 {
p.randomState = helper.StringMd5(fmt.Sprintf("%d%s", time.Now().UnixMilli(), p.randomState)) p.randomState = str.Md5(fmt.Sprintf("%d%s", time.Now().UnixMilli(), p.randomState))
n, err := md5Raw(p.randomState) n, err := md5Raw(p.randomState)
if err != nil { if err != nil {

View File

@ -3,7 +3,7 @@ package cache
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/plugins" "github.com/fthvgb1/wp-go/internal/plugins"
@ -47,7 +47,7 @@ func PostFeedCache() *cache.MapCache[string, string] {
func feed(arg ...any) (xml []string, err error) { func feed(arg ...any) (xml []string, err error) {
c := arg[0].(*gin.Context) c := arg[0].(*gin.Context)
r := RecentPosts(c, 10) r := RecentPosts(c, 10)
ids := helper.SliceMap(r, func(t models.Posts) uint64 { ids := slice.Map(r, func(t models.Posts) uint64 {
return t.Id return t.Id
}) })
posts, err := GetPostsByIds(c, ids) posts, err := GetPostsByIds(c, ids)
@ -56,7 +56,7 @@ func feed(arg ...any) (xml []string, err error) {
} }
rs := templateRss rs := templateRss
rs.LastBuildDate = time.Now().Format(timeFormat) rs.LastBuildDate = time.Now().Format(timeFormat)
rs.Items = helper.SliceMap(posts, func(t models.Posts) rss2.Item { rs.Items = slice.Map(posts, func(t models.Posts) rss2.Item {
desc := "无法提供摘要。这是一篇受保护的文章。" desc := "无法提供摘要。这是一篇受保护的文章。"
plugins.PasswordProjectTitle(&t) plugins.PasswordProjectTitle(&t)
if t.PostPassword != "" { if t.PostPassword != "" {
@ -138,7 +138,7 @@ func postFeed(arg ...any) (x string, err error) {
} }
} }
} else { } else {
rs.Items = helper.SliceMap(comments, func(t models.Comments) rss2.Item { rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
return rss2.Item{ return rss2.Item{
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor), Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
Link: fmt.Sprintf("%s/p/%d#comment-%d", wpconfig.Options.Value("siteurl"), post.Id, t.CommentId), Link: fmt.Sprintf("%s/p/%d#comment-%d", wpconfig.Options.Value("siteurl"), post.Id, t.CommentId),
@ -161,13 +161,13 @@ func commentsFeed(args ...any) (r []string, err error) {
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.Options.Value("blogname")) rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.Options.Value("blogname"))
rs.LastBuildDate = time.Now().Format(timeFormat) rs.LastBuildDate = time.Now().Format(timeFormat)
rs.AtomLink = fmt.Sprintf("%s/comments/feed", wpconfig.Options.Value("siteurl")) rs.AtomLink = fmt.Sprintf("%s/comments/feed", wpconfig.Options.Value("siteurl"))
com, err := GetCommentByIds(c, helper.SliceMap(commens, func(t models.Comments) uint64 { com, err := GetCommentByIds(c, slice.Map(commens, func(t models.Comments) uint64 {
return t.CommentId return t.CommentId
})) }))
if nil != err { if nil != err {
return []string{}, err return []string{}, err
} }
rs.Items = helper.SliceMap(com, func(t models.Comments) rss2.Item { rs.Items = slice.Map(com, func(t models.Comments) rss2.Item {
post, _ := GetPostById(c, t.CommentPostId) post, _ := GetPostById(c, t.CommentPostId)
plugins.PasswordProjectTitle(&post) plugins.PasswordProjectTitle(&post)
desc := "评论受保护:要查看请输入密码。" desc := "评论受保护:要查看请输入密码。"

View File

@ -3,7 +3,7 @@ package cache
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -67,10 +67,10 @@ func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, o
return return
} }
if order == "desc" { if order == "desc" {
res = helper.SliceReverse(res) res = slice.Reverse(res)
} }
total = len(res) total = len(res)
rr := helper.SlicePagination(res, page, limit) rr := slice.Pagination(res, page, limit)
r, err = GetPostsByIds(ctx, rr) r, err = GetPostsByIds(ctx, rr)
return return
} }

View File

@ -3,6 +3,7 @@ package common
import ( import (
"context" "context"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/model" "github.com/fthvgb1/wp-go/model"
"strconv" "strconv"
@ -36,7 +37,7 @@ func PostComments(args ...any) ([]uint64, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return helper.SliceMap(r, func(t models.Comments) uint64 { return slice.Map(r, func(t models.Comments) uint64 {
return t.CommentId return t.CommentId
}), err }), err
} }
@ -47,11 +48,11 @@ func GetCommentByIds(args ...any) (map[uint64]models.Comments, error) {
m := make(map[uint64]models.Comments) m := make(map[uint64]models.Comments)
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{ r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
{"comment_ID", "in", ""}, {"comment_approved", "1"}, {"comment_ID", "in", ""}, {"comment_approved", "1"},
}, "*", helper.SliceMap(ids, helper.ToAny[uint64])) }, "*", slice.Map(ids, helper.ToAny[uint64]))
if err != nil { if err != nil {
return m, err return m, err
} }
return helper.SimpleSliceToMap(r, func(t models.Comments) uint64 { return slice.SimpleToMap(r, func(t models.Comments) uint64 {
return t.CommentId return t.CommentId
}), err }), err
} }

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/model" "github.com/fthvgb1/wp-go/model"
@ -17,7 +19,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
ids := args[1].([]uint64) ids := args[1].([]uint64)
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{ rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
{"post_id", "in", ""}, {"post_id", "in", ""},
}, "*", "", nil, nil, nil, 0, helper.SliceMap(ids, helper.ToAny[uint64])) }, "*", "", nil, nil, nil, 0, slice.Map(ids, helper.ToAny[uint64]))
if err != nil { if err != nil {
return return
} }
@ -76,7 +78,7 @@ func thumbnail(metadata models.WpAttachmentMetadata, thumbType, host string) (r
r.Width = metadata.Sizes[thumbType].Width r.Width = metadata.Sizes[thumbType].Width
r.Height = metadata.Sizes[thumbType].Height r.Height = metadata.Sizes[thumbType].Height
up := strings.Split(metadata.File, "/") up := strings.Split(metadata.File, "/")
r.Srcset = strings.Join(helper.MapToSlice[string](metadata.Sizes, func(s string, size models.MetaDataFileSize) (r string, ok bool) { r.Srcset = strings.Join(maps.FilterToSlice[string](metadata.Sizes, func(s string, size models.MetaDataFileSize) (r string, ok bool) {
up[2] = size.File up[2] = size.File
if s == "post-thumbnail" { if s == "post-thumbnail" {
return return

View File

@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/fthvgb1/wp-go/model" "github.com/fthvgb1/wp-go/model"
@ -17,7 +18,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
ctx := ids[0].(context.Context) ctx := ids[0].(context.Context)
m = make(map[uint64]models.Posts) m = make(map[uint64]models.Posts)
id := ids[1].([]uint64) id := ids[1].([]uint64)
arg := helper.SliceMap(id, helper.ToAny[uint64]) arg := slice.Map(id, helper.ToAny[uint64])
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{ rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
"Id", "in", "", "Id", "in", "",
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{ }}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{

View File

@ -1,7 +1,7 @@
package models package models
import ( import (
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/leeqvip/gophp" "github.com/leeqvip/gophp"
) )
@ -29,7 +29,7 @@ func (p Postmeta) AttachmentMetadata() (r WpAttachmentMetadata, err error) {
} }
info, ok := unSerialize.(map[string]any) info, ok := unSerialize.(map[string]any)
if ok { if ok {
r, err = helper.StrAnyMapToStruct[WpAttachmentMetadata](info) r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
} }
} }
return return
@ -42,7 +42,7 @@ func AttachmentMetadata(s string) (r WpAttachmentMetadata, err error) {
} }
info, ok := unSerialize.(map[string]any) info, ok := unSerialize.(map[string]any)
if ok { if ok {
r, err = helper.StrAnyMapToStruct[WpAttachmentMetadata](info) r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
} }
return return
} }

View File

@ -2,7 +2,7 @@ package plugins
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/internal/wpconfig" "github.com/fthvgb1/wp-go/internal/wpconfig"
"math/rand" "math/rand"
"net/url" "net/url"
@ -16,7 +16,7 @@ func Gravatar(email string, isTls bool) (u string) {
num := rand.Intn(3) num := rand.Intn(3)
h := "" h := ""
if email != "" { if email != "" {
h = helper.StringMd5(strings.ToLower(email)) h = str.Md5(strings.ToLower(email))
num = int(h[0] % 3) num = int(h[0] % 3)
} }
if isTls { if isTls {

View File

@ -2,7 +2,7 @@ package plugins
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" str "github.com/fthvgb1/wp-go/helper/strings"
"regexp" "regexp"
"strings" "strings"
) )
@ -65,5 +65,5 @@ func (p PageEle) Url(path, query string, page int) string {
if path == "" { if path == "" {
path = "/" path = "/"
} }
return helper.StrJoin(path, query) return str.Join(path, query)
} }

View File

@ -2,7 +2,7 @@ package twentyseventeen
import ( import (
"github.com/elliotchance/phpserialize" "github.com/elliotchance/phpserialize"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/internal/pkg/cache" "github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/logs" "github.com/fthvgb1/wp-go/internal/pkg/logs"
"github.com/fthvgb1/wp-go/internal/pkg/models" "github.com/fthvgb1/wp-go/internal/pkg/models"
@ -86,8 +86,8 @@ func getHeaderMarkup() (r HeaderImageMeta, err error) {
if ok { if ok {
err = phpserialize.Unmarshal([]byte(mods), &rr) err = phpserialize.Unmarshal([]byte(mods), &rr)
if err == nil { if err == nil {
rx := helper.MapAnyAnyToStrAny(rr) rx := maps.AnyAnyToStrAny(rr)
r, err = helper.StrAnyMapToStruct[HeaderImageMeta](rx) r, err = maps.StrAnyMapToStruct[HeaderImageMeta](rx)
} }
} }
return return

View File

@ -2,7 +2,7 @@ package model
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"strconv" "strconv"
"strings" "strings"
) )
@ -25,7 +25,7 @@ func (w SqlBuilder) parseField(ss []string, s *strings.Builder) {
} }
func (w SqlBuilder) parseIn(ss []string, s *strings.Builder, c *int, args *[]any, in *[][]any) (t bool) { func (w SqlBuilder) parseIn(ss []string, s *strings.Builder, c *int, args *[]any, in *[][]any) (t bool) {
if helper.IsContainInArr(ss[1], []string{"in", "not in"}) && len(*in) > 0 { if slice.IsContained(ss[1], []string{"in", "not in"}) && len(*in) > 0 {
s.WriteString(" (") s.WriteString(" (")
for _, p := range (*in)[*c] { for _, p := range (*in)[*c] {
s.WriteString("?,") s.WriteString("?,")
@ -148,7 +148,7 @@ func (w SqlBuilder) ParseWhere(in *[][]any) (string, []any, error) {
func (w SqlBuilder) parseOrderBy() string { func (w SqlBuilder) parseOrderBy() string {
s := strings.Builder{} s := strings.Builder{}
for _, ss := range w { for _, ss := range w {
if len(ss) == 2 && ss[0] != "" && helper.IsContainInArr(ss[1], []string{"asc", "desc"}) { if len(ss) == 2 && ss[0] != "" && slice.IsContained(ss[1], []string{"asc", "desc"}) {
s.WriteString(" ") s.WriteString(" ")
s.WriteString(ss[0]) s.WriteString(ss[0])
s.WriteString(" ") s.WriteString(" ")

View File

@ -3,7 +3,7 @@ package model
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number"
"math/rand" "math/rand"
"strings" "strings"
"time" "time"
@ -87,7 +87,7 @@ func SimplePagination[T Model](ctx context.Context, where ParseWhere, fields, gr
return return
} }
func FindOneById[T Model, I helper.IntNumber](ctx context.Context, id I) (T, error) { func FindOneById[T Model, I number.IntNumber](ctx context.Context, id I) (T, error) {
var r T var r T
sql := fmt.Sprintf("select * from `%s` where `%s`=?", r.Table(), r.PrimaryKey()) sql := fmt.Sprintf("select * from `%s` where `%s`=?", r.Table(), r.PrimaryKey())
err := globalBb.Get(ctx, &r, sql, id) err := globalBb.Get(ctx, &r, sql, id)

View File

@ -4,6 +4,8 @@ import (
"context" "context"
"database/sql" "database/sql"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/helper/slice"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"reflect" "reflect"
@ -497,10 +499,10 @@ func TestSimplePagination(t *testing.T) {
order: nil, order: nil,
join: nil, join: nil,
having: nil, having: nil,
in: [][]any{helper.SliceMap[int, any](helper.RangeSlice(431, 440, 1), helper.ToAny[int])}, in: [][]any{slice.Map[int, any](number.Range(431, 440, 1), helper.ToAny[int])},
}, },
wantR: func() (r []post) { wantR: func() (r []post) {
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", helper.SliceMap[int, any](helper.RangeSlice(431, 435, 1), helper.ToAny[int])...) r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.Map[int, any](number.Range(431, 435, 1), helper.ToAny[int])...)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
panic(err) panic(err)
} else if err == sql.ErrNoRows { } else if err == sql.ErrNoRows {

View File

@ -2,7 +2,8 @@ package digest
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/html"
"github.com/fthvgb1/wp-go/helper/slice"
"regexp" "regexp"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -17,7 +18,7 @@ func ClearHtml(str string) string {
content := removeWpBlock.ReplaceAllString(str, "") content := removeWpBlock.ReplaceAllString(str, "")
content = strings.Trim(content, " \t\n\r\000\x0B") content = strings.Trim(content, " \t\n\r\000\x0B")
content = strings.Replace(content, "]]>", "]]&gt;", -1) content = strings.Replace(content, "]]>", "]]&gt;", -1)
content = helper.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>") content = html.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
return str return str
} }
@ -30,7 +31,7 @@ func Raw(str string, limit int, u string) string {
content := removeWpBlock.ReplaceAllString(str, "") content := removeWpBlock.ReplaceAllString(str, "")
content = strings.Trim(content, " \t\n\r\000\x0B") content = strings.Trim(content, " \t\n\r\000\x0B")
content = strings.Replace(content, "]]>", "]]&gt;", -1) content = strings.Replace(content, "]]>", "]]&gt;", -1)
content = helper.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>") content = html.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
length := utf8.RuneCountInString(content) + 1 length := utf8.RuneCountInString(content) + 1
if length > limit { if length > limit {
index := quto.FindAllStringIndex(content, -1) index := quto.FindAllStringIndex(content, -1)
@ -43,7 +44,7 @@ func Raw(str string, limit int, u string) string {
for { for {
i++ i++
for len(index) > 0 { for len(index) > 0 {
ints := helper.SliceMap(index[0], func(t int) int { ints := slice.Map(index[0], func(t int) int {
return utf8.RuneCountInString(content[:t]) return utf8.RuneCountInString(content[:t])
}) })
if ints[0] <= i { if ints[0] <= i {
@ -75,7 +76,7 @@ func Raw(str string, limit int, u string) string {
} }
content = string(ru[:i]) content = string(ru[:i])
closeTag := helper.CloseHtmlTag(content) closeTag := html.CloseTag(content)
tmp := `%s......%s<p class="read-more"><a href="%s">继续阅读</a></p>` tmp := `%s......%s<p class="read-more"><a href="%s">继续阅读</a></p>`
if strings.Contains(closeTag, "pre") || strings.Contains(closeTag, "code") { if strings.Contains(closeTag, "pre") || strings.Contains(closeTag, "code") {
tmp = `%s%s......<p class="read-more"><a href="%s">继续阅读</a></p>` tmp = `%s%s......<p class="read-more"><a href="%s">继续阅读</a></p>`

View File

@ -2,7 +2,7 @@ package rss2
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"strconv" "strconv"
"strings" "strings"
) )
@ -101,7 +101,7 @@ func (r Rss2) GetXML() (xml string) {
"{$updatePeriod}": r.UpdatePeriod, "{$updatePeriod}": r.UpdatePeriod,
"{$updateFrequency}": fmt.Sprintf("%d", r.UpdateFrequency), "{$updateFrequency}": fmt.Sprintf("%d", r.UpdateFrequency),
"{$generator}": r.Generator, "{$generator}": r.Generator,
"{$items}": strings.Join(helper.SliceMap(r.Items, func(t Item) string { "{$items}": strings.Join(slice.Map(r.Items, func(t Item) string {
return t.GetXml() return t.GetXml()
}), ""), }), ""),
} { } {

View File

@ -2,7 +2,7 @@ package safety
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number"
"testing" "testing"
"time" "time"
) )
@ -20,7 +20,7 @@ func TestSlice_Append(t *testing.T) {
{ {
name: "t1", name: "t1",
r: *NewSlice([]int{}), r: *NewSlice([]int{}),
args: args[int]{helper.RangeSlice(1, 10, 1)}, args: args[int]{number.Range(1, 10, 1)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {

View File

@ -2,7 +2,8 @@ package stream
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/helper/slice"
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
@ -33,8 +34,8 @@ func TestNewSimpleMapStream(t *testing.T) {
} }
} }
var y = helper.RangeSlice(1, 1000, 1) var y = number.Range(1, 1000, 1)
var w = helper.SliceToMap(y, func(v int) (int, int) { var w = slice.ToMap(y, func(v int) (int, int) {
return v, v return v, v
}, true) }, true)
@ -101,7 +102,7 @@ func TestSimpleMapParallelFilterAndMapToMap(t *testing.T) {
}, },
c: 6, c: 6,
}, },
want: NewSimpleMapStream(helper.SliceToMap(y[500:], func(v int) (K, T string) { want: NewSimpleMapStream(slice.ToMap(y[500:], func(v int) (K, T string) {
t := strconv.Itoa(v) t := strconv.Itoa(v)
return t, t return t, t
}, true)), }, true)),
@ -139,7 +140,7 @@ func TestSimpleMapStreamFilterAndMapToMap(t *testing.T) {
return "", "", false return "", "", false
}, },
}, },
wantR: NewSimpleMapStream(helper.SliceToMap(y[500:], func(v int) (K, T string) { wantR: NewSimpleMapStream(slice.ToMap(y[500:], func(v int) (K, T string) {
t := strconv.Itoa(v) t := strconv.Itoa(v)
return t, t return t, t
}, true)), }, true)),
@ -166,7 +167,7 @@ func TestSimpleMapStream_ForEach(t *testing.T) {
tests := []testCase[int, int]{ tests := []testCase[int, int]{
{ {
name: "t1", name: "t1",
r: NewSimpleMapStream(helper.SliceToMap(y[0:10], func(v int) (int, int) { r: NewSimpleMapStream(slice.ToMap(y[0:10], func(v int) (int, int) {
return v, v return v, v
}, true)), }, true)),
args: args[int, int]{ args: args[int, int]{
@ -243,10 +244,10 @@ func TestSimpleMapStream_Result(t *testing.T) {
tests := []testCase[int, int]{ tests := []testCase[int, int]{
{ {
name: "t1", name: "t1",
r: NewSimpleMapStream(helper.SliceToMap(y, func(v int) (int, int) { r: NewSimpleMapStream(slice.ToMap(y, func(v int) (int, int) {
return v, v return v, v
}, true)), }, true)),
want: helper.SliceToMap(y, func(v int) (int, int) { want: slice.ToMap(y, func(v int) (int, int) {
return v, v return v, v
}, true), }, true),
}, },

View File

@ -1,7 +1,7 @@
package stream package stream
import ( import (
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"github.com/fthvgb1/wp-go/taskPools" "github.com/fthvgb1/wp-go/taskPools"
) )
@ -47,7 +47,7 @@ func SimpleSliceFilterAndMapToMap[K comparable, V any, T any](a SimpleSliceStrea
} }
func SimpleStreamFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool)) SimpleSliceStream[R] { func SimpleStreamFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool)) SimpleSliceStream[R] {
return NewSimpleSliceStream(helper.SliceFilterAndMap(a.arr, fn)) return NewSimpleSliceStream(slice.FilterAndMap(a.arr, fn))
} }
func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) SimpleSliceStream[R] { func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) SimpleSliceStream[R] {
@ -59,11 +59,11 @@ func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) Si
return SimpleSliceStream[R]{rr.Load()} return SimpleSliceStream[R]{rr.Load()}
} }
func SimpleStreamMap[R, T any](a SimpleSliceStream[T], fn func(T) R) SimpleSliceStream[R] { func SimpleStreamMap[R, T any](a SimpleSliceStream[T], fn func(T) R) SimpleSliceStream[R] {
return NewSimpleSliceStream(helper.SliceMap(a.arr, fn)) return NewSimpleSliceStream(slice.Map(a.arr, fn))
} }
func Reduce[T any, S any](s SimpleSliceStream[S], fn func(S, T) T, init T) (r T) { func Reduce[T any, S any](s SimpleSliceStream[S], fn func(S, T) T, init T) (r T) {
return helper.SliceReduce(s.arr, fn, init) return slice.Reduce(s.arr, fn, init)
} }
func NewSimpleSliceStream[T any](arr []T) SimpleSliceStream[T] { func NewSimpleSliceStream[T any](arr []T) SimpleSliceStream[T] {
@ -101,7 +101,7 @@ func (r SimpleSliceStream[T]) ParallelFilter(fn func(T) bool, c int) SimpleSlice
return SimpleSliceStream[T]{rr.Load()} return SimpleSliceStream[T]{rr.Load()}
} }
func (r SimpleSliceStream[T]) Filter(fn func(T) bool) SimpleSliceStream[T] { func (r SimpleSliceStream[T]) Filter(fn func(T) bool) SimpleSliceStream[T] {
r.arr = helper.SliceFilter(r.arr, fn) r.arr = slice.Filter(r.arr, fn)
return r return r
} }
@ -114,12 +114,12 @@ func (r SimpleSliceStream[T]) ParallelMap(fn func(T) T, c int) SimpleSliceStream
} }
func (r SimpleSliceStream[T]) Map(fn func(T) T) SimpleSliceStream[T] { func (r SimpleSliceStream[T]) Map(fn func(T) T) SimpleSliceStream[T] {
r.arr = helper.SliceMap(r.arr, fn) r.arr = slice.Map(r.arr, fn)
return r return r
} }
func (r SimpleSliceStream[T]) Sort(fn func(i, j T) bool) SimpleSliceStream[T] { func (r SimpleSliceStream[T]) Sort(fn func(i, j T) bool) SimpleSliceStream[T] {
helper.SimpleSort(r.arr, fn) slice.SortSelf(r.arr, fn)
return r return r
} }
@ -140,7 +140,7 @@ func (r SimpleSliceStream[T]) Limit(limit, offset int) SimpleSliceStream[T] {
} }
func (r SimpleSliceStream[T]) Reverse() SimpleSliceStream[T] { func (r SimpleSliceStream[T]) Reverse() SimpleSliceStream[T] {
helper.SliceSelfReverse(r.arr) slice.ReverseSelf(r.arr)
return r return r
} }

View File

@ -2,13 +2,14 @@ package stream
import ( import (
"fmt" "fmt"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/number"
"github.com/fthvgb1/wp-go/helper/slice"
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
) )
var s = NewSimpleSliceStream(helper.RangeSlice(1, 10, 1)) var s = NewSimpleSliceStream(number.Range(1, 10, 1))
func TestSimpleSliceStream_Filter(t *testing.T) { func TestSimpleSliceStream_Filter(t *testing.T) {
type args[T int] struct { type args[T int] struct {
@ -32,7 +33,7 @@ func TestSimpleSliceStream_Filter(t *testing.T) {
return return
}, },
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(6, 10, 1)}, want: SimpleSliceStream[int]{number.Range(6, 10, 1)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -90,7 +91,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
limit: 3, limit: 3,
offset: 5, offset: 5,
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(6, 8, 1)}, want: SimpleSliceStream[int]{number.Range(6, 8, 1)},
}, },
{ {
name: "t2", name: "t2",
@ -99,7 +100,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
limit: 3, limit: 3,
offset: 9, offset: 9,
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(10, 10, 1)}, want: SimpleSliceStream[int]{number.Range(10, 10, 1)},
}, },
{ {
name: "t3", name: "t3",
@ -139,7 +140,7 @@ func TestSimpleSliceStream_Map(t *testing.T) {
return t * 2 return t * 2
}, },
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(2, 20, 2)}, want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -161,7 +162,7 @@ func TestSimpleSliceStream_Result(t *testing.T) {
{ {
name: "t1", name: "t1",
r: s, r: s,
want: helper.RangeSlice(1, 10, 1), want: number.Range(1, 10, 1),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -192,7 +193,7 @@ func TestSimpleSliceStream_Sort(t *testing.T) {
return i > j return i > j
}, },
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(10, 1, -1)}, want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -254,7 +255,7 @@ func TestSimpleSliceStream_ParallelFilter(t *testing.T) {
}, },
c: 6, c: 6,
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(4, 10, 1)}, want: SimpleSliceStream[int]{number.Range(4, 10, 1)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -289,7 +290,7 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
}, },
c: 6, c: 6,
}, },
want: SimpleSliceStream[int]{helper.RangeSlice(2, 20, 2)}, want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -323,7 +324,7 @@ func TestReduce(t *testing.T) {
}, },
0, 0,
}, },
wantR: helper.Sum(s.Result()...), wantR: number.Sum(s.Result()...),
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -344,8 +345,8 @@ func TestSimpleSliceStream_Reverse(t *testing.T) {
tests := []testCase[int]{ tests := []testCase[int]{
{ {
name: "t1", name: "t1",
r: NewSimpleSliceStream(helper.RangeSlice(1, 10, 1)), r: NewSimpleSliceStream(number.Range(1, 10, 1)),
want: SimpleSliceStream[int]{helper.RangeSlice(10, 1, -1)}, want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -357,7 +358,7 @@ func TestSimpleSliceStream_Reverse(t *testing.T) {
} }
} }
var x = helper.RangeSlice(1, 100000, 1) var x = number.Range(1, 100000, 1)
func TestSimpleStreamMap(t *testing.T) { func TestSimpleStreamMap(t *testing.T) {
type args[T int, R string] struct { type args[T int, R string] struct {
@ -377,7 +378,7 @@ func TestSimpleStreamMap(t *testing.T) {
fn: strconv.Itoa, fn: strconv.Itoa,
}, },
want: SimpleSliceStream[string]{ want: SimpleSliceStream[string]{
helper.SliceMap(x, strconv.Itoa), slice.Map(x, strconv.Itoa),
}, },
}, },
} }
@ -406,7 +407,7 @@ func TestSimpleParallelMap(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args[string, int]{ args: args[string, int]{
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)), a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
fn: func(s string) int { fn: func(s string) int {
i, _ := strconv.Atoi(s) i, _ := strconv.Atoi(s)
return i return i
@ -442,7 +443,7 @@ func TestSimpleParallelFilterAndMap(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args[string, int]{ args: args[string, int]{
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)), a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
fn: func(s string) (int, bool) { fn: func(s string) (int, bool) {
i, _ := strconv.Atoi(s) i, _ := strconv.Atoi(s)
if i > 50000 { if i > 50000 {
@ -480,7 +481,7 @@ func TestSimpleStreamFilterAndMap(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args[string, int]{ args: args[string, int]{
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)), a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
fn: func(s string) (int, bool) { fn: func(s string) (int, bool) {
i, _ := strconv.Atoi(s) i, _ := strconv.Atoi(s)
if i > 50000 { if i > 50000 {
@ -547,7 +548,7 @@ func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
}, },
c: 6, c: 6,
}, },
wantR: NewSimpleMapStream(helper.SliceToMap(x[50000:], func(t int) (int, int) { wantR: NewSimpleMapStream(slice.ToMap(x[50000:], func(t int) (int, int) {
return t, t return t, t
}, true)), }, true)),
}, },
@ -576,7 +577,7 @@ func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
{ {
name: "t1", name: "t1",
args: args[int, int, int]{ args: args[int, int, int]{
a: NewSimpleSliceStream(helper.RangeSlice(1, 10, 1)), a: NewSimpleSliceStream(number.Range(1, 10, 1)),
fn: func(i int) (int, int, bool) { fn: func(i int) (int, int, bool) {
if i > 6 { if i > 6 {
return i, i, true return i, i, true
@ -584,7 +585,7 @@ func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
return 0, 0, false return 0, 0, false
}, },
}, },
wantR: NewSimpleMapStream(helper.SliceToMap(helper.RangeSlice(7, 10, 1), func(t int) (int, int) { wantR: NewSimpleMapStream(slice.ToMap(number.Range(7, 10, 1), func(t int) (int, int) {
return t, t return t, t
}, true)), }, true)),
}, },