1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-17 03:02:28 +08:00

Compare commits

...

22 Commits

Author SHA1 Message Date
dudaodong
9cd9d1aeb5 release v2.1.14 2023-02-06 17:42:13 +08:00
dudaodong
71b27c0aa9 feat: add ForEach, Reduce for stream 2023-02-06 17:40:54 +08:00
dudaodong
09a379ec6d feat: add ForEach, Reduce for stream 2023-02-06 17:38:33 +08:00
dudaodong
b4b9b03835 feat: add NoneMatch, AllMatch, AnyMatch for stream 2023-02-06 17:24:17 +08:00
dudaodong
48c7794b01 feat: add Limit method of stream 2023-02-06 17:08:36 +08:00
dudaodong
8e3911833d doc: normalize documents 2023-02-06 11:42:03 +08:00
dudaodong
ebe494051b doc: add doc for some new methods of list 2023-02-06 11:35:32 +08:00
dudaodong
c35bda6a65 feat: add ListToMap for list 2023-02-06 11:06:46 +08:00
dudaodong
1fe4cdc429 feat: add Difference and SymmetricDifference for list 2023-02-06 10:55:42 +08:00
dudaodong
6a79e322e3 Merge branch 'main' into v2 2023-02-06 10:00:02 +08:00
Cai Zhijiang
17e8d2bb6d 部分城市有4位区号+8位号码 (#69) 2023-02-06 09:47:21 +08:00
燕归来
325be0d6a1 feat: add func Iterator, ForEach, RetainAll and DeleteAll for List structure (#71) 2023-02-06 09:46:25 +08:00
dudaodong
ea0f96a8c0 feat: add Skip for stream 2023-01-30 16:56:33 +08:00
dudaodong
82cbb54787 feat: add FromChannel for create stream 2023-01-17 16:47:20 +08:00
dudaodong
585d33cafa feat: add Generate for create stream 2023-01-17 16:31:44 +08:00
dudaodong
bc4cf35e15 feat: add Filter, Map, Count for stream 2023-01-17 14:59:47 +08:00
dudaodong
a3bc20af1d feat: add Distinct 2023-01-17 11:39:05 +08:00
dudaodong
61338b6b46 feat: add Stream package 2023-01-17 11:25:15 +08:00
dudaodong
bc3c080ac3 doc: normalize document 2023-01-15 12:43:00 +08:00
dudaodong
d3fab15af3 refactor: clean structure for netutil package 2023-01-14 14:39:06 +08:00
dudaodong
6e3e411d46 doc: normalize document 2023-01-14 12:48:39 +08:00
dudaodong
f976941e36 doc: normalize document 2023-01-14 12:32:27 +08:00
48 changed files with 6145 additions and 3925 deletions

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.14-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.14-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -51,7 +51,7 @@ lancet 是以包的结构组织代码的,使用时需要导入相应的包名
import "github.com/duke-git/lancet/v2/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
## 例 ##
此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包: 此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包:

View File

@@ -6,6 +6,8 @@ package datastructure
import ( import (
"reflect" "reflect"
"github.com/duke-git/lancet/v2/iterator"
) )
// List is a linear table, implemented with slice. // List is a linear table, implemented with slice.
@@ -316,6 +318,43 @@ func (l *List[T]) Intersection(other *List[T]) *List[T] {
return result return result
} }
// Difference returns the difference between two collections.
// return a list whose element in the original list, not in the given list.
func (l *List[T]) Difference(other *List[T]) *List[T] {
result := NewList(make([]T, 0))
intersectList := l.Intersection(other)
for _, v := range l.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
return result
}
// SymmetricDifference oppoiste operation of intersection function.
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T] {
result := NewList(make([]T, 0))
intersectList := l.Intersection(other)
for _, v := range l.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
for _, v := range other.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
return result
}
// SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive. // SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] { func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
data := l.data[fromIndex:toIndex] data := l.data[fromIndex:toIndex]
@@ -323,3 +362,57 @@ func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
copy(subList, data) copy(subList, data)
return NewList(subList) return NewList(subList)
} }
// ForEach performs the given action for each element of the list.
func (l *List[T]) ForEach(consumer func(T)) {
for _, it := range l.data {
consumer(it)
}
}
// RetainAll retains only the elements in this list that are contained in the given list.
func (l *List[T]) RetainAll(list *List[T]) bool {
return l.batchRemove(list, true)
}
// DeleteAll removes from this list all of its elements that are contained in the given list.
func (l *List[T]) DeleteAll(list *List[T]) bool {
return l.batchRemove(list, false)
}
func (l *List[T]) batchRemove(list *List[T], complement bool) bool {
var (
w = 0
data = l.data
size = len(data)
)
for i := 0; i < size; i++ {
if list.Contain(data[i]) == complement {
data[w] = data[i]
w++
}
}
if w != size {
l.data = data[:w]
return true
}
return false
}
// Iterator returns an iterator over the elements in this list in proper sequence.
func (l *List[T]) Iterator() iterator.Iterator[T] {
return iterator.FromSlice(l.data)
}
// ListToMap convert a list to a map based on iteratee function.
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V {
result := make(map[K]V, list.Size())
for _, item := range list.data {
k, v := iteratee(item)
result[k] = v
}
return result
}

View File

@@ -328,6 +328,28 @@ func TestIntersection(t *testing.T) {
assert.Equal(true, expected.Equal(list3)) assert.Equal(true, expected.Equal(list3))
} }
func TestDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestDifference")
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
expected := NewList([]int{3})
list3 := list1.Difference(list2)
assert.Equal(true, expected.Equal(list3))
}
func TestSymmetricDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestSymmetricDifference")
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
expected := NewList([]int{3, 4})
list3 := list1.SymmetricDifference(list2)
assert.Equal(true, expected.Equal(list3))
}
func TestSubSlice(t *testing.T) { func TestSubSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestSubSlice") assert := internal.NewAssert(t, "TestSubSlice")
@@ -357,3 +379,84 @@ func TestDeleteIf(t *testing.T) {
assert.Equal([]int{2, 3, 4}, list.Data()) assert.Equal([]int{2, 3, 4}, list.Data())
assert.Equal(0, count) assert.Equal(0, count)
} }
func TestForEach(t *testing.T) {
assert := internal.NewAssert(t, "TestForEach")
list := NewList([]int{1, 2, 3, 4})
rs := make([]int, 0)
list.ForEach(func(i int) {
rs = append(rs, i)
})
assert.Equal([]int{1, 2, 3, 4}, rs)
}
func TestRetainAll(t *testing.T) {
assert := internal.NewAssert(t, "TestRetainAll")
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
assert.Equal([]int{1, 2}, list.Data())
assert.Equal([]int{2, 3}, list1.Data())
assert.Equal([]int{1, 2}, list2.Data())
}
func TestDeleteAll(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteAll")
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
assert.Equal([]int{2, 3, 4}, list.Data())
assert.Equal([]int{1, 4}, list1.Data())
assert.Equal([]int{3, 4}, list2.Data())
}
func TestIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestIterator")
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
rs := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
rs = append(rs, item)
}
assert.Equal([]int{1, 2, 3, 4}, rs)
}
func TestListToMap(t *testing.T) {
assert := internal.NewAssert(t, "ListToMap")
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
assert.Equal(expected, result)
}

View File

@@ -46,7 +46,7 @@ import (
type Channel[T any] struct type Channel[T any] struct
func NewChannel[T any]() *Channel[T] func NewChannel[T any]() *Channel[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -70,7 +70,7 @@ func main() {
```go ```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -122,7 +122,7 @@ func main() {
```go ```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -161,7 +161,7 @@ func main() {
```go ```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -199,7 +199,7 @@ func main() {
```go ```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -238,7 +238,7 @@ func main() {
```go ```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -279,7 +279,7 @@ func main() {
```go ```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -322,7 +322,7 @@ func main() {
```go ```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -360,7 +360,7 @@ func main() {
```go ```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -406,7 +406,7 @@ func main() {
```go ```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -45,7 +45,7 @@ slices和map的length大于0时返回true否则返回false<br/>
```go ```go
func Bool[T any](value T) bool func Bool[T any](value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -109,7 +109,7 @@ func main() {
```go ```go
func And[T, U any](a T, b U) bool func And[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -135,7 +135,7 @@ func main() {
```go ```go
func Or[T, U any](a T, b U) bool func Or[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -161,7 +161,7 @@ func main() {
```go ```go
func Xor[T, U any](a T, b U) bool func Xor[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -187,7 +187,7 @@ func main() {
```go ```go
func Nor[T, U any](a T, b U) bool func Nor[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -213,7 +213,7 @@ func main() {
```go ```go
func Xnor[T, U any](a T, b U) bool func Xnor[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -239,7 +239,7 @@ func main() {
```go ```go
func Nand[T, U any](a T, b U) bool func Nand[T, U any](a T, b U) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -265,7 +265,7 @@ func main() {
```go ```go
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -46,7 +46,7 @@ import (
func NewHashMap() *HashMap func NewHashMap() *HashMap
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -72,7 +72,7 @@ func main() {
func NewHashMapWithCapacity(size, capacity uint64) *HashMap func NewHashMapWithCapacity(size, capacity uint64) *HashMap
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -98,7 +98,7 @@ func main() {
func (hm *HashMap) Get(key any) any func (hm *HashMap) Get(key any) any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -126,7 +126,7 @@ func main() {
func (hm *HashMap) Put(key any, value any) any func (hm *HashMap) Put(key any, value any) any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -155,7 +155,7 @@ func main() {
func (hm *HashMap) Delete(key any) func (hm *HashMap) Delete(key any)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -187,7 +187,7 @@ func main() {
func (hm *HashMap) Contains(key any) bool func (hm *HashMap) Contains(key any) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -217,7 +217,7 @@ func main() {
func (hm *HashMap) Iterate(iteratee func(key, value any)) func (hm *HashMap) Iterate(iteratee func(key, value any))
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -252,7 +252,7 @@ func main() {
func (hm *HashMap) Keys() []any func (hm *HashMap) Keys() []any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -284,7 +284,7 @@ func main() {
func (hm *HashMap) Values() []any func (hm *HashMap) Values() []any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -48,7 +48,7 @@ type MaxHeap[T any] struct {
} }
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -89,7 +89,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Push(value T) func (h *MaxHeap[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -136,7 +136,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Pop() (T, bool) func (h *MaxHeap[T]) Pop() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -184,7 +184,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Peek() (T, bool) func (h *MaxHeap[T]) Peek() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -232,7 +232,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Data() []T func (h *MaxHeap[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -277,7 +277,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Size() int func (h *MaxHeap[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -323,7 +323,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) PrintStructure() func (h *MaxHeap[T]) PrintStructure()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -81,7 +81,7 @@ type SinglyLink[T any] struct {
} }
func NewSinglyLink[T any]() *SinglyLink[T] func NewSinglyLink[T any]() *SinglyLink[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -107,7 +107,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Values() []T func (link *SinglyLink[T]) Values() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -139,7 +139,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAt(index int, value T) func (link *SinglyLink[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -174,7 +174,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAtHead(value T) func (link *SinglyLink[T]) InsertAtHead(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -206,7 +206,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAtTail(value T) func (link *SinglyLink[T]) InsertAtTail(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -237,7 +237,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAt(index int) func (link *SinglyLink[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -271,7 +271,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAtHead() func (link *SinglyLink[T]) DeleteAtHead()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -306,7 +306,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAtTail() func (link *SinglyLink[T]) DeleteAtTail()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -339,7 +339,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteValue(value T) func (link *SinglyLink[T]) DeleteValue(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -373,7 +373,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Reverse() func (link *SinglyLink[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -405,7 +405,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -437,7 +437,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Size() int func (link *SinglyLink[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -468,7 +468,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) IsEmpty() bool func (link *SinglyLink[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -500,7 +500,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Clear() func (link *SinglyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -533,7 +533,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Clear() func (link *SinglyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -576,7 +576,7 @@ type DoublyLink[T any] struct {
} }
func NewDoublyLink[T any]() *DoublyLink[T] func NewDoublyLink[T any]() *DoublyLink[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -602,7 +602,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Values() []T func (link *DoublyLink[T]) Values() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -634,7 +634,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAt(index int, value T) func (link *DoublyLink[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -669,7 +669,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAtHead(value T) func (link *DoublyLink[T]) InsertAtHead(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -701,7 +701,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAtTail(value T) func (link *DoublyLink[T]) InsertAtTail(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -732,7 +732,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAt(index int) func (link *DoublyLink[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -766,7 +766,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAtHead() func (link *DoublyLink[T]) DeleteAtHead()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -801,7 +801,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAtTail() func (link *DoublyLink[T]) DeleteAtTail()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -835,7 +835,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Reverse() func (link *DoublyLink[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -867,7 +867,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -899,7 +899,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Size() int func (link *DoublyLink[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -930,7 +930,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) IsEmpty() bool func (link *DoublyLink[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -962,7 +962,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Clear() func (link *DoublyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -995,7 +995,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Clear() func (link *DoublyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -47,6 +47,13 @@ import (
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList) - [SubList](#SubList)
- [DeleteIf](#DeleteIf) - [DeleteIf](#DeleteIf)
@@ -62,7 +69,7 @@ NewList function return a list pointer</p>
```go ```go
type List[T any] struct { type List[T any] struct {
data []T data []T
} }
func NewList[T any](data []T) *List[T] func NewList[T any](data []T) *List[T]
``` ```
@@ -671,8 +678,8 @@ import (
) )
func main() { func main() {
data := make([]int, 0, 100) data := make([]int, 0, 100)
li := list.NewList(data) li := list.NewList(data)
fmt.Println(li.Cap()) // 100 fmt.Println(li.Cap()) // 100
@@ -828,6 +835,233 @@ func main() {
### <span id="Difference">Difference</span>
<p>Return a list whose element in the original list, not in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) Difference(other *List[T]) *List[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3
}
```
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>Oppoiste operation of intersection function.</p>
<b>Signature:</b>
```go
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3, 4
}
```
### <span id="RetainAll">RetainAll</span>
<p>Retains only the elements in this list that are contained in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) RetainAll(list *List[T]) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
fmt.Println(list.Data()) //1, 2
fmt.Println(list1.Data()) //2, 3
fmt.Println(list2.Data()) //1, 2
}
```
### <span id="DeleteAll">DeleteAll</span>
<p>Removes from this list all of its elements that are contained in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) DeleteAll(list *List[T]) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
fmt.Println(list.Data()) //2,3,4
fmt.Println(list1.Data()) //1,4
fmt.Println(list2.Data()) //3,4
}
```
### <span id="ForEach">ForEach</span>
<p>Performs the given action for each element of the list.</p>
<b>Signature:</b>
```go
func (l *List[T]) ForEach(consumer func(T))
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := make([]int, 0)
list.ForEach(func(i int) {
result = append(result, i)
})
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="Iterator">Iterator</span>
<p>Returns an iterator over the elements in this list in proper sequence.</p>
<b>Signature:</b>
```go
func (l *List[T]) Iterator() iterator.Iterator[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
result := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
result = append(result, item)
}
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="ListToMap">ListToMap</span>
<p>Converts a list to a map based on iteratee function.</p>
<b>Signature:</b>
```go
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
fmt.Println(result) //map[int]bool{1: false, 2: true, 3: true, 4: true}
}
```
### <span id="SubList">SubList</span> ### <span id="SubList">SubList</span>
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p> <p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p>
@@ -876,9 +1110,9 @@ import (
) )
func main() { func main() {
l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1}) l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12 fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12
fmt.Println(l.Data()) // []int{2, 3, 4} fmt.Println(l.Data()) // []int{2, 3, 4}
} }
``` ```

View File

@@ -34,7 +34,6 @@ import (
- [PopLast](#PopLast) - [PopLast](#PopLast)
- [DeleteAt](#DeleteAt) - [DeleteAt](#DeleteAt)
- [InsertAt](#InsertAt) - [InsertAt](#InsertAt)
- [UpdateAt](#UpdateAt) - [UpdateAt](#UpdateAt)
- [Equal](#Equal) - [Equal](#Equal)
- [IsEmpty](#IsEmpty) - [IsEmpty](#IsEmpty)
@@ -48,6 +47,13 @@ import (
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList) - [SubList](#SubList)
- [DeleteIf](#DeleteIf) - [DeleteIf](#DeleteIf)
@@ -62,11 +68,11 @@ import (
```go ```go
type List[T any] struct { type List[T any] struct {
data []T data []T
} }
func NewList[T any](data []T) *List[T] func NewList[T any](data []T) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -92,7 +98,7 @@ func main() {
```go ```go
func (l *List[T]) Contain(value T) bool func (l *List[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -121,7 +127,7 @@ func main() {
```go ```go
func (l *List[T]) Data() []T func (l *List[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -150,7 +156,7 @@ func main() {
```go ```go
func (l *List[T]) ValueOf(index int) (*T, bool) func (l *List[T]) ValueOf(index int) (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -180,7 +186,7 @@ func main() {
```go ```go
func (l *List[T]) IndexOf(value T) int func (l *List[T]) IndexOf(value T) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -207,7 +213,7 @@ func main() {
```go ```go
func (l *List[T]) LastIndexOf(value T) int func (l *List[T]) LastIndexOf(value T) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -233,7 +239,7 @@ func main() {
```go ```go
func (l *List[T]) IndexOfFunc(f func(T) bool) int func (l *List[T]) IndexOfFunc(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -259,7 +265,7 @@ func main() {
```go ```go
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int func (l *List[T]) LastIndexOfFunc(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -287,7 +293,7 @@ func main() {
```go ```go
func (l *List[T]) Push(value T) func (l *List[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -316,7 +322,7 @@ func main() {
```go ```go
func (l *List[T]) PopFirst() (*T, bool) func (l *List[T]) PopFirst() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -348,7 +354,7 @@ func main() {
```go ```go
func (l *List[T]) PopLast() (*T, bool) func (l *List[T]) PopLast() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -379,7 +385,7 @@ func main() {
```go ```go
func (l *List[T]) DeleteAt(index int) func (l *List[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -417,7 +423,7 @@ func main() {
```go ```go
func (l *List[T]) InsertAt(index int, value T) func (l *List[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -454,7 +460,7 @@ func main() {
```go ```go
func (l *List[T]) UpdateAt(index int, value T) func (l *List[T]) UpdateAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -487,7 +493,7 @@ func main() {
```go ```go
func (l *List[T]) Equal(other *List[T]) bool func (l *List[T]) Equal(other *List[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -517,7 +523,7 @@ func main() {
```go ```go
func (l *List[T]) IsEmpty() bool func (l *List[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -547,7 +553,7 @@ func main() {
```go ```go
func (l *List[T]) Clear() func (l *List[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -575,7 +581,7 @@ func main() {
```go ```go
func (l *List[T]) Clone() *List[T] func (l *List[T]) Clone() *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -604,7 +610,7 @@ func main() {
```go ```go
func (l *List[T]) Merge(other *List[T]) *List[T] func (l *List[T]) Merge(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -633,7 +639,7 @@ func main() {
```go ```go
func (l *List[T]) Size() int func (l *List[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -660,7 +666,7 @@ func main() {
```go ```go
func (l *List[T]) Cap() int func (l *List[T]) Cap() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -671,8 +677,8 @@ import (
) )
func main() { func main() {
data := make([]int, 0, 100) data := make([]int, 0, 100)
li := list.NewList(data) li := list.NewList(data)
fmt.Println(li.Cap()) // 100 fmt.Println(li.Cap()) // 100
@@ -689,7 +695,7 @@ func main() {
```go ```go
func (l *List[T]) Swap(i, j int) func (l *List[T]) Swap(i, j int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -718,7 +724,7 @@ func main() {
```go ```go
func (l *List[T]) Reverse() func (l *List[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -747,7 +753,7 @@ func main() {
```go ```go
func (l *List[T]) Unique() func (l *List[T]) Unique()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -776,7 +782,7 @@ func main() {
```go ```go
func (l *List[T]) Union(other *List[T]) *List[T] func (l *List[T]) Union(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -806,7 +812,7 @@ func main() {
```go ```go
func (l *List[T]) Intersection(other *List[T]) *List[T] func (l *List[T]) Intersection(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -826,16 +832,244 @@ func main() {
``` ```
### <span id="Difference">Difference</span>
<p>差集运算。</p>
<b>函数签名:</b>
```go
func (l *List[T]) Difference(other *List[T]) *List[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3
}
```
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>对称差集运算。</p>
<b>函数签名:</b>
```go
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3, 4
}
```
### <span id="RetainAll">RetainAll</span>
<p>仅保留列表中包含在给定列表中的元素。</p>
<b>函数签名:</b>
```go
func (l *List[T]) RetainAll(list *List[T]) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
fmt.Println(list.Data()) //1, 2
fmt.Println(list1.Data()) //2, 3
fmt.Println(list2.Data()) //1, 2
}
```
### <span id="DeleteAll">DeleteAll</span>
<p>从列表中删除给定列表中包含的所有元素。</p>
<b>函数签名:</b>
```go
func (l *List[T]) DeleteAll(list *List[T]) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
fmt.Println(list.Data()) //2,3,4
fmt.Println(list1.Data()) //1,4
fmt.Println(list2.Data()) //3,4
}
```
### <span id="ForEach">ForEach</span>
<p>对列表的每个元素执行给定的操作。</p>
<b>函数签名:</b>
```go
func (l *List[T]) ForEach(consumer func(T))
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := make([]int, 0)
list.ForEach(func(i int) {
result = append(result, i)
})
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="Iterator">Iterator</span>
<p>按顺序返回列表中元素的迭代器。</p>
<b>函数签名:</b>
```go
func (l *List[T]) Iterator() iterator.Iterator[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
result := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
result = append(result, item)
}
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="ListToMap">ListToMap</span>
<p>基于iteratee函数将列表转换为映射map。</p>
<b>函数签名:</b>
```go
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
fmt.Println(result) //map[int]bool{1: false, 2: true, 3: true, 4: true}
}
```
### <span id="SubList">SubList</span> ### <span id="SubList">SubList</span>
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p> <p>返回指定的fromIndex包含和toIndex不包含之间的原始列表的子列表。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] func (l *List[T]) SubList(fromIndex, toIndex int) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -863,7 +1097,7 @@ func main() {
```go ```go
func (l *List[T]) DeleteIf(f func(T) bool) int func (l *List[T]) DeleteIf(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -874,9 +1108,9 @@ import (
) )
func main() { func main() {
l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1}) l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12 fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12
fmt.Println(l.Data()) // []int{2, 3, 4} fmt.Println(l.Data()) // []int{2, 3, 4}
} }
``` ```

View File

@@ -99,7 +99,7 @@ type ArrayQueue[T any] struct {
size int size int
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -125,7 +125,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Data() []T func (q *ArrayQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -152,7 +152,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Enqueue(item T) bool func (q *ArrayQueue[T]) Enqueue(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -183,7 +183,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Dequeue() (T, bool) func (q *ArrayQueue[T]) Dequeue() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -215,7 +215,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Front() T func (q *ArrayQueue[T]) Front() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -247,7 +247,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Back() T func (q *ArrayQueue[T]) Back() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -278,7 +278,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Size() int func (q *ArrayQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -308,7 +308,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) IsEmpty() bool func (q *ArrayQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -341,7 +341,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) IsFull() bool func (q *ArrayQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -373,7 +373,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Clear() func (q *ArrayQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -404,7 +404,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Contain(value T) bool func (q *ArrayQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -448,7 +448,7 @@ type QueueNode[T any] struct {
Next *QueueNode[T] Next *QueueNode[T]
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -474,7 +474,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Data() []T func (q *LinkedQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -501,7 +501,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Enqueue(value T) func (q *LinkedQueue[T]) Enqueue(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -532,7 +532,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Dequeue() (T, error) func (q *LinkedQueue[T]) Dequeue() (T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -564,7 +564,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Front() (*T, error) func (q *LinkedQueue[T]) Front() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -596,7 +596,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Back() (*T, error) func (q *LinkedQueue[T]) Back() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -627,7 +627,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Size() int func (q *LinkedQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -657,7 +657,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) IsEmpty() bool func (q *LinkedQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -690,7 +690,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Clear() func (q *LinkedQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -721,7 +721,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Contain(value T) bool func (q *LinkedQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -763,7 +763,7 @@ type CircularQueue[T any] struct {
capacity int capacity int
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -789,7 +789,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Data() []T func (q *CircularQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -816,7 +816,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Enqueue(value T) error func (q *CircularQueue[T]) Enqueue(value T) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -847,7 +847,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Dequeue() (*T, bool) func (q *CircularQueue[T]) Dequeue() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -880,7 +880,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Front() T func (q *CircularQueue[T]) Front() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -912,7 +912,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Back() T func (q *CircularQueue[T]) Back() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -943,7 +943,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Size() int func (q *CircularQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -973,7 +973,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) IsEmpty() bool func (q *CircularQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1006,7 +1006,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) IsFull() bool func (q *CircularQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1038,7 +1038,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Clear() func (q *CircularQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1069,7 +1069,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Contain(value T) bool func (q *CircularQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1108,7 +1108,7 @@ type PriorityQueue[T any] struct {
comparator lancetconstraints.Comparator comparator lancetconstraints.Comparator
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1134,7 +1134,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Data() []T func (q *PriorityQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1161,7 +1161,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Enqueue(item T) bool func (q *PriorityQueue[T]) Enqueue(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1207,7 +1207,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Dequeue() (T, bool) func (q *PriorityQueue[T]) Dequeue() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1254,7 +1254,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) IsEmpty() bool func (q *PriorityQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1301,7 +1301,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) IsFull() bool func (q *PriorityQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1348,7 +1348,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Size() int func (q *PriorityQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -55,7 +55,7 @@ import (
type Set[T comparable] map[T]bool type Set[T comparable] map[T]bool
func NewSet[T comparable](items ...T) Set[T] func NewSet[T comparable](items ...T) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -81,7 +81,7 @@ func main() {
```go ```go
func NewSetFromSlice[T comparable](items []T) Set[T] func NewSetFromSlice[T comparable](items []T) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -107,7 +107,7 @@ func main() {
```go ```go
func (s Set[T]) Values() []T func (s Set[T]) Values() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -134,7 +134,7 @@ func main() {
```go ```go
func (s Set[T]) Add(items ...T) func (s Set[T]) Add(items ...T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -161,7 +161,7 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExist(item T) bool func (s Set[T]) AddIfNotExist(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -193,7 +193,7 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -232,7 +232,7 @@ func main() {
```go ```go
func (s Set[T]) Delete(items ...T) func (s Set[T]) Delete(items ...T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -261,7 +261,7 @@ func main() {
```go ```go
func (s Set[T]) Contain(item T) bool func (s Set[T]) Contain(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -291,7 +291,7 @@ func main() {
```go ```go
func (s Set[T]) ContainAll(other Set[T]) bool func (s Set[T]) ContainAll(other Set[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -321,7 +321,7 @@ func main() {
```go ```go
func (s Set[T]) Size() int func (s Set[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -348,7 +348,7 @@ func main() {
```go ```go
func (s Set[T]) Clone() Set[T] func (s Set[T]) Clone() Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -378,7 +378,7 @@ func main() {
```go ```go
func (s Set[T]) Equal(other Set[T]) bool func (s Set[T]) Equal(other Set[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -408,7 +408,7 @@ func main() {
```go ```go
func (s Set[T]) Iterate(fn func(item T)) func (s Set[T]) Iterate(fn func(item T))
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -439,7 +439,7 @@ func main() {
```go ```go
func (s Set[T]) IsEmpty() bool func (s Set[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -468,7 +468,7 @@ func main() {
```go ```go
func (s Set[T]) Union(other Set[T]) Set[T] func (s Set[T]) Union(other Set[T]) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -497,7 +497,7 @@ func main() {
```go ```go
func (s Set[T]) Intersection(other Set[T]) Set[T] func (s Set[T]) Intersection(other Set[T]) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -525,7 +525,7 @@ func main() {
```go ```go
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -556,7 +556,7 @@ func main() {
```go ```go
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -64,7 +64,7 @@ type ArrayStack[T any] struct {
} }
func NewArrayStack[T any]() *ArrayStack[T] func NewArrayStack[T any]() *ArrayStack[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -91,7 +91,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Push(value T) func (s *ArrayStack[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -122,7 +122,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Pop() (*T, error) func (s *ArrayStack[T]) Pop() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -157,7 +157,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Peak() (*T, error) func (s *ArrayStack[T]) Peak() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -192,7 +192,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Data() []T func (s *ArrayStack[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -223,7 +223,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Size() int func (s *ArrayStack[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -254,7 +254,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) IsEmpty() bool func (s *ArrayStack[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -287,7 +287,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Clear() func (s *ArrayStack[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -331,7 +331,7 @@ type LinkedStack[T any] struct {
} }
func NewLinkedStack[T any]() *LinkedStack[T] func NewLinkedStack[T any]() *LinkedStack[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -358,7 +358,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Push(value T) func (s *LinkedStack[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -389,7 +389,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Pop() (*T, error) func (s *LinkedStack[T]) Pop() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -424,7 +424,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Peak() (*T, error) func (s *LinkedStack[T]) Peak() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -459,7 +459,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Data() []T func (s *LinkedStack[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -490,7 +490,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Size() int func (s *LinkedStack[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -521,7 +521,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) IsEmpty() bool func (s *LinkedStack[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -554,7 +554,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Clear() func (s *LinkedStack[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -588,7 +588,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Print() func (s *LinkedStack[T]) Print()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -62,7 +62,7 @@ type TreeNode[T any] struct {
Right *TreeNode[T] Right *TreeNode[T]
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -103,7 +103,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Insert(data T) func (t *BSTree[T]) Insert(data T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -149,7 +149,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Delete(data T) func (t *BSTree[T]) Delete(data T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -197,7 +197,7 @@ func main() {
```go ```go
func (t *BSTree[T]) PreOrderTraverse() []T func (t *BSTree[T]) PreOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -243,7 +243,7 @@ func main() {
```go ```go
func (t *BSTree[T]) InOrderTraverse() []T func (t *BSTree[T]) InOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -289,7 +289,7 @@ func main() {
```go ```go
func (t *BSTree[T]) PostOrderTraverse() []T func (t *BSTree[T]) PostOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -335,7 +335,7 @@ func main() {
```go ```go
func (t *BSTree[T]) LevelOrderTraverse() []T func (t *BSTree[T]) LevelOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -381,7 +381,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Depth() int func (t *BSTree[T]) Depth() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -427,7 +427,7 @@ func main() {
```go ```go
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -479,7 +479,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Print() func (t *BSTree[T]) Print()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -52,7 +52,7 @@ import (
func ClearFile(path string) error func ClearFile(path string) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -80,7 +80,7 @@ func main() {
func CreateFile(path string) bool func CreateFile(path string) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -132,7 +132,7 @@ func main() {
func CopyFile(srcFilePath string, dstFilePath string) error func CopyFile(srcFilePath string, dstFilePath string) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -160,7 +160,7 @@ func main() {
func FileMode(path string) (fs.FileMode, error) func FileMode(path string) (fs.FileMode, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -189,7 +189,7 @@ func main() {
func MiMeType(file any) string func MiMeType(file any) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -220,7 +220,7 @@ func main() {
func IsExist(path string) bool func IsExist(path string) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -247,7 +247,7 @@ func main() {
func IsLink(path string) bool func IsLink(path string) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -273,7 +273,7 @@ func main() {
func IsDir(path string) bool func IsDir(path string) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -302,7 +302,7 @@ func main() {
func ListFileNames(path string) ([]string, error) func ListFileNames(path string) ([]string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -328,7 +328,7 @@ func main() {
func RemoveFile(path string) error func RemoveFile(path string) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -356,7 +356,7 @@ func main() {
func ReadFileToString(path string) (string, error) func ReadFileToString(path string) (string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -389,7 +389,7 @@ func main() {
func ReadFileByLine(path string)([]string, error) func ReadFileByLine(path string)([]string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -423,7 +423,7 @@ func main() {
func Zip(fpath string, destPath string) error func Zip(fpath string, destPath string) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -451,7 +451,7 @@ func main() {
func UnZip(zipFile string, destPath string) error func UnZip(zipFile string, destPath string) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -38,7 +38,7 @@ import (
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -46,7 +46,7 @@ import (
func After(n int, fn any) func(args ...any) []reflect.Value func After(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -79,7 +79,7 @@ func main() {
func Before(n int, fn any) func(args ...any) []reflect.Value func Before(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -117,7 +117,7 @@ type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T func (cf CurryFn[T]) New(val T) func(...T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -156,7 +156,7 @@ func main() {
func Compose[T any](fnList ...func(...T) T) func(...T) T func Compose[T any](fnList ...func(...T) T) func(...T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -194,7 +194,7 @@ func main() {
func Debounced(fn func(), duration time.Duration) func() func Debounced(fn func(), duration time.Duration) func()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -244,7 +244,7 @@ func main() {
func Delay(delay time.Duration, fn any, args ...any) func Delay(delay time.Duration, fn any, args ...any)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -276,7 +276,7 @@ func main() {
func Schedule(d time.Duration, fn any, args ...any) chan bool func Schedule(d time.Duration, fn any, args ...any) chan bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -315,7 +315,7 @@ func main() {
func Pipeline[T any](funcs ...func(T) T) func(T) T func Pipeline[T any](funcs ...func(T) T) func(T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -366,7 +366,7 @@ func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -45,7 +45,7 @@ import (
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -86,7 +86,7 @@ func main() {
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -131,7 +131,7 @@ func main() {
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -186,7 +186,7 @@ func main() {
func Keys[K comparable, V any](m map[K]V) []K func Keys[K comparable, V any](m map[K]V) []K
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -225,7 +225,7 @@ func main() {
func Merge[K comparable, V any](maps ...map[K]V) map[K]V func Merge[K comparable, V any](maps ...map[K]V) map[K]V
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -264,7 +264,7 @@ func main() {
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -306,7 +306,7 @@ func main() {
func Values[K comparable, V any](m map[K]V) []V func Values[K comparable, V any](m map[K]V) []V
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -343,7 +343,7 @@ func main() {
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -49,7 +49,7 @@ import (
func Average[T constraints.Integer | constraints.Float](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -84,7 +84,7 @@ func main() {
func Exponent(x, n int64) int64 func Exponent(x, n int64) int64
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -120,7 +120,7 @@ func main() {
func Fibonacci(first, second, n int) int func Fibonacci(first, second, n int) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -156,7 +156,7 @@ func main() {
func Factorial(x uint) uint func Factorial(x uint) uint
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -192,7 +192,7 @@ func main() {
func Max[T constraints.Integer | constraints.Float](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -225,7 +225,7 @@ func main() {
func MaxBy[T any](slice []T, comparator func(T, T) bool) T func MaxBy[T any](slice []T, comparator func(T, T) bool) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -269,7 +269,7 @@ func main() {
func Min[T constraints.Integer | constraints.Float](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -302,7 +302,7 @@ func main() {
func MinBy[T any](slice []T, comparator func(T, T) bool) T func MinBy[T any](slice []T, comparator func(T, T) bool) T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -346,7 +346,7 @@ func main() {
func Percent(val, total float64, n int) float64 func Percent(val, total float64, n int) float64
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -379,7 +379,7 @@ func main() {
func RoundToFloat(x float64, n int) float64 func RoundToFloat(x float64, n int) float64
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -415,7 +415,7 @@ func main() {
func RoundToString(x float64, n int) string func RoundToString(x float64, n int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -451,7 +451,7 @@ func main() {
func TruncRound(x float64, n int) float64 func TruncRound(x float64, n int) float64
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -56,8 +56,8 @@ import (
) )
func main() { func main() {
randBytes := random.RandBytes(4) randBytes := random.RandBytes(4)
fmt.Println(randBytes) fmt.Println(randBytes)
} }
``` ```
@@ -82,8 +82,8 @@ import (
) )
func main() { func main() {
rInt := random.RandInt(1, 10) rInt := random.RandInt(1, 10)
fmt.Println(rInt) fmt.Println(rInt)
} }
``` ```
@@ -108,8 +108,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //pGWsze fmt.Println(randStr) //pGWsze
} }
``` ```
@@ -134,8 +134,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //PACWGF fmt.Println(randStr) //PACWGF
} }
``` ```
@@ -160,8 +160,8 @@ import (
) )
func main() { func main() {
randStr := random.RandLower(6) randStr := random.RandLower(6)
fmt.Println(randStr) //siqbew fmt.Println(randStr) //siqbew
} }
``` ```
@@ -186,8 +186,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeral(6) randStr := random.RandNumeral(6)
fmt.Println(randStr) //035172 fmt.Println(randStr) //035172
} }
``` ```
@@ -212,8 +212,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeralOrLetter(6) randStr := random.RandNumeralOrLetter(6)
fmt.Println(randStr) //0aW7cQ fmt.Println(randStr) //0aW7cQ
} }
``` ```
@@ -238,10 +238,10 @@ import (
) )
func main() { func main() {
uuid, err := random.UUIdV4() uuid, err := random.UUIdV4()
if err != nil { if err != nil {
return return
} }
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```

View File

@@ -45,7 +45,7 @@ import (
func RandBytes(length int) []byte func RandBytes(length int) []byte
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -56,8 +56,8 @@ import (
) )
func main() { func main() {
randBytes := random.RandBytes(4) randBytes := random.RandBytes(4)
fmt.Println(randBytes) fmt.Println(randBytes)
} }
``` ```
@@ -71,7 +71,7 @@ func main() {
func RandInt(min, max int) int func RandInt(min, max int) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -82,8 +82,8 @@ import (
) )
func main() { func main() {
rInt := random.RandInt(1, 10) rInt := random.RandInt(1, 10)
fmt.Println(rInt) fmt.Println(rInt)
} }
``` ```
@@ -97,7 +97,7 @@ func main() {
func RandString(length int) string func RandString(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -108,8 +108,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //pGWsze fmt.Println(randStr) //pGWsze
} }
``` ```
@@ -123,7 +123,7 @@ func main() {
func RandUpper(length int) string func RandUpper(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -134,8 +134,8 @@ import (
) )
func main() { func main() {
randStr := random.RandString(6) randStr := random.RandString(6)
fmt.Println(randStr) //PACWGF fmt.Println(randStr) //PACWGF
} }
``` ```
@@ -149,7 +149,7 @@ func main() {
func RandLower(length int) string func RandLower(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -160,8 +160,8 @@ import (
) )
func main() { func main() {
randStr := random.RandLower(6) randStr := random.RandLower(6)
fmt.Println(randStr) //siqbew fmt.Println(randStr) //siqbew
} }
``` ```
@@ -175,7 +175,7 @@ func main() {
func RandNumeral(length int) string func RandNumeral(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -186,8 +186,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeral(6) randStr := random.RandNumeral(6)
fmt.Println(randStr) //035172 fmt.Println(randStr) //035172
} }
``` ```
@@ -201,7 +201,7 @@ func main() {
func RandNumeralOrLetter(length int) string func RandNumeralOrLetter(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -212,8 +212,8 @@ import (
) )
func main() { func main() {
randStr := random.RandNumeralOrLetter(6) randStr := random.RandNumeralOrLetter(6)
fmt.Println(randStr) //0aW7cQ fmt.Println(randStr) //0aW7cQ
} }
``` ```
@@ -227,7 +227,7 @@ func main() {
func UUIdV4() (string, error) func UUIdV4() (string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -238,10 +238,10 @@ import (
) )
func main() { func main() {
uuid, err := random.UUIdV4() uuid, err := random.UUIdV4()
if err != nil { if err != nil {
return return
} }
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```

View File

@@ -1,16 +1,17 @@
# Retry # Retry
Package retry is for executing a function repeatedly until it was successful or canceled by the context. Package retry is for executing a function repeatedly until it was successful or canceled by the context.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## Source:
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,18 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Context](#Context)
- [Retry](#Retry) - [Context](#Context)
- [RetryFunc](#RetryFunc) - [Retry](#Retry)
- [RetryDuration](#RetryDuration) - [RetryFunc](#RetryFunc)
- [RetryTimes](#RetryTimes) - [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>Set retry context config, can cancel the retry with context.</p> <p>Set retry context config, can cancel the retry with context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -39,43 +41,46 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
"time" "time"
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
increaseNumber := func() error {
number++
if number > 3 {
cancel()
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, number := 0
retry.RetryDuration(time.Microsecond*50), increaseNumber := func() error {
retry.Context(ctx), number++
) if number > 3 {
cancel()
}
return errors.New("error occurs")
}
if err != nil { duration := retry.RetryDuration(time.Microsecond*50)
fmt.Println(err) //retry is cancelled
} retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
fmt.Println(number)
// Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>Function that retry executes.</p> <p>Function that retry executes.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -83,6 +88,7 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -96,28 +102,31 @@ import (
) )
func main() { func main() {
var number int number := 0
var increaseNumber retry.RetryFunc = func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
increaseNumber := func() error { duration := retry.RetryDuration(time.Microsecond*50)
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>Set times of retry. Default times is 5.</p> <p>Set times of retry. Default times is 5.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -125,6 +134,7 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -138,26 +148,28 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryTimes(2)) err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil { if err != nil {
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1 fmt.Println(err)
} }
// Output:
// function main.main.func1 run failed after 2 times retry
} }
``` ```
### <span id="RetryDuration">RetryDuration</span> ### <span id="RetryDuration">RetryDuration</span>
<p>Set duration of retries. Default duration is 3 second.</p> <p>Set duration of retries. Default duration is 3 second.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -165,6 +177,7 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -178,26 +191,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p> <p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -205,6 +223,7 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -218,20 +237,25 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```

View File

@@ -1,16 +1,17 @@
# Retry # Retry
retry重试执行函数直到函数运行成功或被context cancel。
retry 重试执行函数直到函数运行成功或被 context cancel。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,20 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Context](#Context)
- [Retry](#Retry)
- [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
- [Context](#Context)
- [Retry](#Retry)
- [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Document 文档
## Document文档
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>设置重试context参数</p> <p>设置重试context参数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -41,43 +41,46 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"lancet-demo/retry" "lancet-demo/retry"
"time" "time"
) )
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
increaseNumber := func() error {
number++
if number > 3 {
cancel()
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, number := 0
retry.RetryDuration(time.Microsecond*50), increaseNumber := func() error {
retry.Context(ctx), number++
) if number > 3 {
cancel()
}
return errors.New("error occurs")
}
if err != nil { duration := retry.RetryDuration(time.Microsecond*50)
fmt.Println(err) //retry is cancelled
} retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
fmt.Println(number)
// Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>被重试执行的函数</p> <p>被重试执行的函数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -85,7 +88,8 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -98,27 +102,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { var increaseNumber retry.RetryFunc = func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>设置重试次数默认5</p> <p>设置重试次数默认5</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -126,7 +134,8 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -139,25 +148,28 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryTimes(2)) increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil { if err != nil {
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1 fmt.Println(err)
} }
// Output:
// function main.main.func1 run failed after 2 times retry
} }
``` ```
### <span id="RetryDuration">RetryDuration</span> ### <span id="RetryDuration">RetryDuration</span>
<p>设置重试间隔时间默认3秒</p> <p>设置重试间隔时间默认3秒</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -165,7 +177,8 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -178,26 +191,31 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>重试执行函数retryFunc直到函数运行成功或被context停止</p> <p>重试执行函数retryFunc直到函数运行成功或被context停止</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -205,7 +223,8 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -218,20 +237,25 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
} }
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,17 @@
# System # System
Package system contains some functions about os, runtime, shell command. Package system contains some functions about os, runtime, shell command.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## Source:
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,23 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsWindows](#IsWindows)
- [IsMac](#IsMac) - [IsLinux](#IsLinux)
- [GetOsEnv](#GetOsEnv) - [IsMac](#IsMac)
- [SetOsEnv](#SetOsEnv) - [GetOsEnv](#GetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv) - [SetOsEnv](#SetOsEnv)
- [CompareOsEnv](#CompareOsEnv) - [RemoveOsEnv](#RemoveOsEnv)
- [ExecCommand](#ExecCommand) - [CompareOsEnv](#CompareOsEnv)
- [GetOsBits](#GetOsBits) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>Check if current os is windows.</p> <p>Check if current os is windows.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,24 +45,23 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsWindows := system.IsWindows() isOsWindows := system.IsWindows()
fmt.Println(isOsWindows) fmt.Println(isOsWindows)
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>Check if current os is linux.</p> <p>Check if current os is linux.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,23 +69,23 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsLinux := system.IsLinux() isOsLinux := system.IsLinux()
fmt.Println(isOsLinux) fmt.Println(isOsLinux)
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>Check if current os is macos.</p> <p>Check if current os is macos.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,23 +93,23 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsMac := system.IsMac() isOsMac := system.IsMac()
fmt.Println(isOsMac) fmt.Println(isOsMac)
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>Gets the value of the environment variable named by the key.</p> <p>Gets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,23 +117,29 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>Sets the value of the environment variable named by the key.</p> <p>Sets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,24 +147,29 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
fmt.Println(err) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>Remove a single environment variable.</p> <p>Remove a single environment variable.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,25 +177,37 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} err2 := system.RemoveOsEnv("foo")
result2 := GetOsEnv("foo")
fmt.Println(err1)
fmt.Println(err2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// <nil>
// <nil>
// abc
//
} }
``` ```
### <span id="CompareOsEnv">CompareOsEnv</span> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>Get env named by the key and compare it with comparedEnv.</p> <p>Get env named by the key and compare it with comparedEnv.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,25 +215,32 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">CompareOsEnv</span> ### <span id="ExecCommand">CompareOsEnv</span>
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p> <p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -218,40 +248,39 @@ func main() {
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) func ExecCommand(command string) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
// linux or mac // linux or mac
stdout, stderr, err := system.ExecCommand("ls") stdout, stderr, err := system.ExecCommand("ls")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
assert.Equal("", stderr) assert.Equal("", stderr)
// windows // windows
stdout, stderr, err = system.ExecCommand("dir") stdout, stderr, err = system.ExecCommand("dir")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
// error command // error command
stdout, stderr, err = system.ExecCommand("abc") stdout, stderr, err = system.ExecCommand("abc")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p> <p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
<b>Signature:</b> <b>Signature:</b>
@@ -259,19 +288,17 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```

View File

@@ -1,16 +1,17 @@
# System # System
system包含os, runtime, shell command相关函数。
system 包含 os, runtime, shell command 相关函数。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,23 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsWindows](#IsWindows)
- [IsMac](#IsMac) - [IsLinux](#IsLinux)
- [GetOsEnv](#GetOsEnv) - [IsMac](#IsMac)
- [SetOsEnv](#SetOsEnv) - [GetOsEnv](#GetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv) - [SetOsEnv](#SetOsEnv)
- [CompareOsEnv](#CompareOsEnv) - [RemoveOsEnv](#RemoveOsEnv)
- [ExecCommand](#ExecCommand) - [CompareOsEnv](#CompareOsEnv)
- [GetOsBits](#GetOsBits) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation文档 ## Documentation 文档
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p> <p>检查当前操作系统是否是windows</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,24 +45,23 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsWindows := system.IsWindows() isOsWindows := system.IsWindows()
fmt.Println(isOsWindows) fmt.Println(isOsWindows)
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>检查当前操作系统是否是linux</p> <p>检查当前操作系统是否是linux</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,23 +69,23 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsLinux := system.IsLinux() isOsLinux := system.IsLinux()
fmt.Println(isOsLinux) fmt.Println(isOsLinux)
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>检查当前操作系统是否是macos</p> <p>检查当前操作系统是否是macos</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,23 +93,23 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
isOsMac := system.IsMac() isOsMac := system.IsMac()
fmt.Println(isOsMac) fmt.Println(isOsMac)
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>获取key命名的环境变量的值</p> <p>获取key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,23 +117,29 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>设置由key命名的环境变量的值</p> <p>设置由key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,24 +147,29 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
fmt.Println(err) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>删除单个环境变量</p> <p>删除单个环境变量</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,25 +177,37 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} err2 := system.RemoveOsEnv("foo")
result2 := GetOsEnv("foo")
fmt.Println(err1)
fmt.Println(err2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// <nil>
// <nil>
// abc
//
} }
``` ```
### <span id="CompareOsEnv">CompareOsEnv</span> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>获取key命名的环境变量值并与compareEnv进行比较</p> <p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,25 +215,32 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">ExecCommand</span> ### <span id="ExecCommand">ExecCommand</span>
<p>执行shell命令返回命令的stdout和stderr字符串如果出现错误则返回错误。参数`command`是一个完整的命令字符串如ls-alinuxdirwindowsping 127.0.0.1。在linux中使用/bin/bash-c执行命令在windows中使用powershell.exe执行命令。</p> <p>执行shell命令返回命令的stdout和stderr字符串如果出现错误则返回错误。参数`command`是一个完整的命令字符串如ls-alinuxdirwindowsping 127.0.0.1。在linux中使用/bin/bash-c执行命令在windows中使用powershell.exe执行命令。</p>
<b>Signature:</b> <b>Signature:</b>
@@ -218,40 +248,39 @@ func main() {
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) func ExecCommand(command string) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
// linux or mac // linux or mac
stdout, stderr, err := system.ExecCommand("ls") stdout, stderr, err := system.ExecCommand("ls")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
assert.Equal("", stderr) assert.Equal("", stderr)
// windows // windows
stdout, stderr, err = system.ExecCommand("dir") stdout, stderr, err = system.ExecCommand("dir")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
// error command // error command
stdout, stderr, err = system.ExecCommand("abc") stdout, stderr, err = system.ExecCommand("abc")
fmt.Println("std out: ", stdout) fmt.Println("std out: ", stdout)
fmt.Println("std err: ", stderr) fmt.Println("std err: ", stderr)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数返回32或64</p> <p>获取当前操作系统位数返回32或64</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -259,23 +288,17 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,17 @@
# Xerror # Xerror
Package xerror implements helpers for errors. Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Source: ## Source:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go) - [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Unwrap](#Unwrap)
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Unwrap">Unwrap</span> ### <span id="Unwrap">Unwrap</span>
<p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p> <p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -35,6 +37,7 @@ import (
```go ```go
func Unwrap[T any](val T, err error) T func Unwrap[T any](val T, err error) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -46,20 +49,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error()) result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42
// true // true
} }
``` ```

View File

@@ -1,15 +1,17 @@
# Xerror # Xerror
xerror错误处理逻辑封装
xerror 错误处理逻辑封装
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go) - [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Unwrap](#Unwrap)
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="Unwrap">Unwrap</span> ### <span id="Unwrap">Unwrap</span>
<p>检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。</p> <p>检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -35,7 +37,8 @@ import (
```go ```go
func Unwrap[T any](val T, err error) T func Unwrap[T any](val T, err error) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -46,20 +49,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error()) result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42
// true // true
} }
``` ```

View File

@@ -13,12 +13,21 @@
package netutil package netutil
import ( import (
"bytes"
"crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url"
"reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"time"
"github.com/duke-git/lancet/v2/slice"
) )
// HttpGet send get http request. // HttpGet send get http request.
@@ -78,3 +87,220 @@ func ConvertMapToQueryString(param map[string]any) string {
} }
return build.String() return build.String()
} }
// HttpRequest struct is a composed http request
type HttpRequest struct {
RawURL string
Method string
Headers http.Header
QueryParams url.Values
FormData url.Values
Body []byte
}
// HttpClientConfig contains some configurations for http client
type HttpClientConfig struct {
SSLEnabled bool
TLSConfig *tls.Config
Compressed bool
HandshakeTimeout time.Duration
ResponseTimeout time.Duration
Verbose bool
}
// defaultHttpClientConfig defalut client config
var defaultHttpClientConfig = &HttpClientConfig{
Compressed: false,
HandshakeTimeout: 20 * time.Second,
ResponseTimeout: 40 * time.Second,
}
// HttpClient is used for sending http request
type HttpClient struct {
*http.Client
TLS *tls.Config
Request *http.Request
Config HttpClientConfig
}
// NewHttpClient make a HttpClient instance
func NewHttpClient() *HttpClient {
client := &HttpClient{
Client: &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
DisableCompression: !defaultHttpClientConfig.Compressed,
},
},
Config: *defaultHttpClientConfig,
}
return client
}
// NewHttpClientWithConfig make a HttpClient instance with pass config
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
if config == nil {
config = defaultHttpClientConfig
}
client := &HttpClient{
Client: &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: config.HandshakeTimeout,
ResponseHeaderTimeout: config.ResponseTimeout,
DisableCompression: !config.Compressed,
},
},
Config: *config,
}
if config.SSLEnabled {
client.TLS = config.TLSConfig
}
return client
}
// SendRequest send http request.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
err := validateRequest(request)
if err != nil {
return nil, err
}
rawUrl := request.RawURL
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
if err != nil {
return nil, err
}
client.setTLS(rawUrl)
client.setHeader(req, request.Headers)
err = client.setQueryParam(req, rawUrl, request.QueryParams)
if err != nil {
return nil, err
}
if request.FormData != nil {
client.setFormData(req, request.FormData)
}
client.Request = req
resp, err := client.Client.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}
// DecodeResponse decode response into target object.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
if resp == nil {
return errors.New("invalid target param")
}
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(target)
}
// setTLS set http client transport TLSClientConfig
func (client *HttpClient) setTLS(rawUrl string) {
if strings.HasPrefix(rawUrl, "https") {
if transport, ok := client.Client.Transport.(*http.Transport); ok {
transport.TLSClientConfig = client.TLS
}
}
}
// setHeader set http rquest header
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
if headers == nil {
headers = make(http.Header)
}
if _, ok := headers["Accept"]; !ok {
headers["Accept"] = []string{"*/*"}
}
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
headers["Accept-Encoding"] = []string{"deflate, gzip"}
}
req.Header = headers
}
// setQueryParam set http request query string param
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
if queryParam != nil {
if !strings.Contains(reqUrl, "?") {
reqUrl = reqUrl + "?" + queryParam.Encode()
} else {
reqUrl = reqUrl + "&" + queryParam.Encode()
}
u, err := url.Parse(reqUrl)
if err != nil {
return err
}
req.URL = u
}
return nil
}
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
formData := []byte(values.Encode())
req.Body = io.NopCloser(bytes.NewReader(formData))
req.ContentLength = int64(len(formData))
}
// validateRequest check if a request has url, and valid method.
func validateRequest(req *HttpRequest) error {
if req.RawURL == "" {
return errors.New("invalid request url")
}
// common HTTP methods
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
return errors.New("invalid request method")
}
return nil
}
// StructToUrlValues convert struct to url valuse,
// only convert the field which is exported and has `json` tag.
// Play: https://go.dev/play/p/pFqMkM40w9z
func StructToUrlValues(targetStruct any) url.Values {
rv := reflect.ValueOf(targetStruct)
rt := reflect.TypeOf(targetStruct)
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
}
if rt.Kind() != reflect.Struct {
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
}
result := url.Values{}
fieldNum := rt.NumField()
pattern := `^[A-Z]`
regex := regexp.MustCompile(pattern)
for i := 0; i < fieldNum; i++ {
name := rt.Field(i).Name
tag := rt.Field(i).Tag.Get("json")
if regex.MatchString(name) && tag != "" {
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
}
}
return result
}

View File

@@ -1,235 +0,0 @@
package netutil
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"reflect"
"regexp"
"strings"
"time"
"github.com/duke-git/lancet/v2/slice"
)
// HttpRequest struct is a composed http request
type HttpRequest struct {
RawURL string
Method string
Headers http.Header
QueryParams url.Values
FormData url.Values
Body []byte
}
// HttpClientConfig contains some configurations for http client
type HttpClientConfig struct {
SSLEnabled bool
TLSConfig *tls.Config
Compressed bool
HandshakeTimeout time.Duration
ResponseTimeout time.Duration
Verbose bool
}
// defaultHttpClientConfig defalut client config
var defaultHttpClientConfig = &HttpClientConfig{
Compressed: false,
HandshakeTimeout: 20 * time.Second,
ResponseTimeout: 40 * time.Second,
}
// HttpClient is used for sending http request
type HttpClient struct {
*http.Client
TLS *tls.Config
Request *http.Request
Config HttpClientConfig
}
// NewHttpClient make a HttpClient instance
func NewHttpClient() *HttpClient {
client := &HttpClient{
Client: &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
DisableCompression: !defaultHttpClientConfig.Compressed,
},
},
Config: *defaultHttpClientConfig,
}
return client
}
// NewHttpClientWithConfig make a HttpClient instance with pass config
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
if config == nil {
config = defaultHttpClientConfig
}
client := &HttpClient{
Client: &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: config.HandshakeTimeout,
ResponseHeaderTimeout: config.ResponseTimeout,
DisableCompression: !config.Compressed,
},
},
Config: *config,
}
if config.SSLEnabled {
client.TLS = config.TLSConfig
}
return client
}
// SendRequest send http request.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
err := validateRequest(request)
if err != nil {
return nil, err
}
rawUrl := request.RawURL
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
if err != nil {
return nil, err
}
client.setTLS(rawUrl)
client.setHeader(req, request.Headers)
err = client.setQueryParam(req, rawUrl, request.QueryParams)
if err != nil {
return nil, err
}
if request.FormData != nil {
client.setFormData(req, request.FormData)
}
client.Request = req
resp, err := client.Client.Do(req)
if err != nil {
return nil, err
}
return resp, nil
}
// DecodeResponse decode response into target object.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
if resp == nil {
return errors.New("invalid target param")
}
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(target)
}
// setTLS set http client transport TLSClientConfig
func (client *HttpClient) setTLS(rawUrl string) {
if strings.HasPrefix(rawUrl, "https") {
if transport, ok := client.Client.Transport.(*http.Transport); ok {
transport.TLSClientConfig = client.TLS
}
}
}
// setHeader set http rquest header
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
if headers == nil {
headers = make(http.Header)
}
if _, ok := headers["Accept"]; !ok {
headers["Accept"] = []string{"*/*"}
}
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
headers["Accept-Encoding"] = []string{"deflate, gzip"}
}
req.Header = headers
}
// setQueryParam set http request query string param
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
if queryParam != nil {
if !strings.Contains(reqUrl, "?") {
reqUrl = reqUrl + "?" + queryParam.Encode()
} else {
reqUrl = reqUrl + "&" + queryParam.Encode()
}
u, err := url.Parse(reqUrl)
if err != nil {
return err
}
req.URL = u
}
return nil
}
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
formData := []byte(values.Encode())
req.Body = io.NopCloser(bytes.NewReader(formData))
req.ContentLength = int64(len(formData))
}
// validateRequest check if a request has url, and valid method.
func validateRequest(req *HttpRequest) error {
if req.RawURL == "" {
return errors.New("invalid request url")
}
// common HTTP methods
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
return errors.New("invalid request method")
}
return nil
}
// StructToUrlValues convert struct to url valuse,
// only convert the field which is exported and has `json` tag.
// Play: https://go.dev/play/p/pFqMkM40w9z
func StructToUrlValues(targetStruct any) url.Values {
rv := reflect.ValueOf(targetStruct)
rt := reflect.TypeOf(targetStruct)
if rt.Kind() == reflect.Ptr {
rt = rt.Elem()
}
if rt.Kind() != reflect.Struct {
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
}
result := url.Values{}
fieldNum := rt.NumField()
pattern := `^[A-Z]`
regex := regexp.MustCompile(pattern)
for i := 0; i < fieldNum; i++ {
name := rt.Field(i).Name
tag := rt.Field(i).Tag.Get("json")
if regex.MatchString(name) && tag != "" {
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
}
}
return result
}

View File

@@ -1,98 +0,0 @@
package netutil
import (
"io"
"log"
"net/http"
"net/url"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestHttpClient_Get(t *testing.T) {
assert := internal.NewAssert(t, "TestHttpClient_Get")
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
t.Log(err)
}
assert.Equal(1, todo.Id)
}
func TestHttpClent_Post(t *testing.T) {
header := http.Header{}
header.Add("Content-Type", "multipart/form-data")
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "testItem")
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos",
Method: "POST",
Headers: header,
FormData: postData,
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil {
log.Fatal(err)
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
}
func TestStructToUrlValues(t *testing.T) {
assert := internal.NewAssert(t, "TestStructToUrlValues")
type TodoQuery struct {
Id int `json:"id"`
UserId int `json:"userId"`
}
todoQuery := TodoQuery{
Id: 1,
UserId: 1,
}
todoValues := StructToUrlValues(todoQuery)
assert.Equal("1", todoValues.Get("id"))
assert.Equal("1", todoValues.Get("userId"))
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos",
Method: "GET",
QueryParams: todoValues,
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", string(body))
}

View File

@@ -1,99 +0,0 @@
package netutil
import "fmt"
func ExampleHttpClient_SendRequest() {
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
return
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id)
// Output:
// 1
}
func ExampleHttpClient_DecodeResponse() {
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
return
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id)
// Output:
// 1
}
func ExampleStructToUrlValues() {
type TodoQuery struct {
Id int `json:"id"`
Name string `json:"name"`
}
todoQuery := TodoQuery{
Id: 1,
Name: "Test",
}
todoValues := StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
}
func ExampleConvertMapToQueryString() {
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,
}
qs := ConvertMapToQueryString(m)
fmt.Println(qs)
// Output:
// a=1&b=2&c=3
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"log" "log"
"net/http"
"net/url" "net/url"
"testing" "testing"
@@ -156,3 +157,90 @@ func TestParseResponse(t *testing.T) {
} }
t.Log("response: ", toDoResp) t.Log("response: ", toDoResp)
} }
func TestHttpClient_Get(t *testing.T) {
assert := internal.NewAssert(t, "TestHttpClient_Get")
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
t.Log(err)
}
assert.Equal(1, todo.Id)
}
func TestHttpClent_Post(t *testing.T) {
header := http.Header{}
header.Add("Content-Type", "multipart/form-data")
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "testItem")
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos",
Method: "POST",
Headers: header,
FormData: postData,
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil {
log.Fatal(err)
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
}
func TestStructToUrlValues(t *testing.T) {
assert := internal.NewAssert(t, "TestStructToUrlValues")
type TodoQuery struct {
Id int `json:"id"`
UserId int `json:"userId"`
}
todoQuery := TodoQuery{
Id: 1,
UserId: 1,
}
todoValues := StructToUrlValues(todoQuery)
assert.Equal("1", todoValues.Get("id"))
assert.Equal("1", todoValues.Get("userId"))
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos",
Method: "GET",
QueryParams: todoValues,
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
}
body, _ := io.ReadAll(resp.Body)
t.Log("response: ", string(body))
}

View File

@@ -89,3 +89,68 @@ func ExampleEncodeUrl() {
// Output: // Output:
// http://www.lancet.com?a=1&b=%5B2%5D // http://www.lancet.com?a=1&b=%5B2%5D
} }
func ExampleHttpClient_DecodeResponse() {
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
return
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id)
// Output:
// 1
}
func ExampleStructToUrlValues() {
type TodoQuery struct {
Id int `json:"id"`
Name string `json:"name"`
}
todoQuery := TodoQuery{
Id: 1,
Name: "Test",
}
todoValues := StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
}
func ExampleConvertMapToQueryString() {
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,
}
qs := ConvertMapToQueryString(m)
fmt.Println(qs)
// Output:
// a=1&b=2&c=3
}

View File

@@ -6,7 +6,6 @@ import (
) )
func ExampleRandInt() { func ExampleRandInt() {
result := RandInt(1, 10) result := RandInt(1, 10)
if result >= 1 && result < 10 { if result >= 1 && result < 10 {

261
stream/stream.go Normal file
View File

@@ -0,0 +1,261 @@
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package stream implements a sequence of elements supporting sequential and parallel aggregate operations.
// this package is an experiment to explore if stream in go can work as the way java does. it's complete, but not
// powerful like other libs
package stream
import (
"bytes"
"encoding/gob"
"golang.org/x/exp/constraints"
)
// A stream should implements methods:
// type StreamI[T any] interface {
// // part methods of Java Stream Specification.
// Distinct() StreamI[T]
// Filter(predicate func(item T) bool) StreamI[T]
// FlatMap(mapper func(item T) StreamI[T]) StreamI[T]
// Map(mapper func(item T) T) StreamI[T]
// Peek(consumer func(item T)) StreamI[T]
// Sort(less func(a, b T) bool) StreamI[T]
// Max(less func(a, b T) bool) (T, bool)
// Min(less func(a, b T) bool) (T, bool)
// Limit(maxSize int) StreamI[T]
// Skip(n int) StreamI[T]
// AllMatch(predicate func(item T) bool) bool
// AnyMatch(predicate func(item T) bool) bool
// NoneMatch(predicate func(item T) bool) bool
// ForEach(consumer func(item T))
// Reduce(init T, accumulator func(a, b T) T) T
// Count() int
// FindFirst() (T, bool)
// ToSlice() []T
// // part of methods custom extension
// Reverse() StreamI[T]
// Range(start, end int64) StreamI[T]
// Concat(streams ...StreamI[T]) StreamI[T]
// }
type stream[T any] struct {
source []T
}
// Of creates a stream stream whose elements are the specified values.
func Of[T any](elems ...T) stream[T] {
return FromSlice(elems)
}
// Generate stream where each element is generated by the provided generater function
// generater function: func() func() (item T, ok bool) {}
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
source := make([]T, 0)
var zeroValue T
for next, item, ok := generator(), zeroValue, true; ok; {
item, ok = next()
if ok {
source = append(source, item)
}
}
return FromSlice(source)
}
// FromSlice create stream from slice.
func FromSlice[T any](source []T) stream[T] {
return stream[T]{source: source}
}
// FromChannel create stream from channel.
func FromChannel[T any](source <-chan T) stream[T] {
s := make([]T, 0)
for v := range source {
s = append(s, v)
}
return FromSlice(s)
}
// FromRange create a number stream from start to end. both start and end are included. [start, end]
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
if end < start {
panic("stream.FromRange: param start should be before param end")
} else if step <= 0 {
panic("stream.FromRange: param step should be positive")
}
l := int((end-start)/step) + 1
source := make([]T, l, l)
for i := 0; i < l; i++ {
source[i] = start + (T(i) * step)
}
return FromSlice(source)
}
// Distinct returns a stream that removes the duplicated items.
func (s stream[T]) Distinct() stream[T] {
source := make([]T, 0)
distinct := map[string]bool{}
for _, v := range s.source {
// todo: performance issue
k := hashKey(v)
if _, ok := distinct[k]; !ok {
distinct[k] = true
source = append(source, v)
}
}
return FromSlice(source)
}
func hashKey(data any) string {
buffer := bytes.NewBuffer(nil)
encoder := gob.NewEncoder(buffer)
err := encoder.Encode(data)
if err != nil {
panic("stream.hashKey: get hashkey failed")
}
return buffer.String()
}
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
source := make([]T, 0)
for _, v := range s.source {
if predicate(v) {
source = append(source, v)
}
}
return FromSlice(source)
}
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
source := make([]T, s.Count(), s.Count())
for i, v := range s.source {
source[i] = mapper(v)
}
return FromSlice(source)
}
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
for _, v := range s.source {
consumer(v)
}
return s
}
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
// If this stream contains fewer than n elements then an empty stream will be returned.
func (s stream[T]) Skip(n int) stream[T] {
if n <= 0 {
return s
}
source := make([]T, 0)
l := len(s.source)
if n > l {
return FromSlice(source)
}
for i := n; i < l; i++ {
source = append(source, s.source[i])
}
return FromSlice(source)
}
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
func (s stream[T]) Limit(maxSize int) stream[T] {
if s.source == nil {
return s
}
if maxSize < 0 {
return FromSlice([]T{})
}
source := make([]T, 0, maxSize)
for i := 0; i < len(s.source) && i < maxSize; i++ {
source = append(source, s.source[i])
}
return FromSlice(source)
}
// AllMatch returns whether all elements of this stream match the provided predicate.
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
for _, v := range s.source {
if !predicate(v) {
return false
}
}
return true
}
// AnyMatch returns whether any elements of this stream match the provided predicate.
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
for _, v := range s.source {
if predicate(v) {
return true
}
}
return false
}
// NoneMatch returns whether no elements of this stream match the provided predicate.
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
return !s.AnyMatch(predicate)
}
// ForEach performs an action for each element of this stream.
func (s stream[T]) ForEach(action func(item T)) {
for _, v := range s.source {
action(v)
}
}
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
func (s stream[T]) Reduce(init T, accumulator func(a, b T) T) T {
for _, v := range s.source {
init = accumulator(init, v)
}
return init
}
// Count returns the count of elements in the stream.
func (s stream[T]) Count() int {
return len(s.source)
}
// ToSlice return the elements in the stream.
func (s stream[T]) ToSlice() []T {
return s.source
}

249
stream/stream_test.go Normal file
View File

@@ -0,0 +1,249 @@
package stream
import (
"fmt"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestOf(t *testing.T) {
assert := internal.NewAssert(t, "TestFromSlice")
stream := Of(1, 2, 3)
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
}
func TestGenerate(t *testing.T) {
assert := internal.NewAssert(t, "TestFromSlice")
n := 0
max := 4
generator := func() func() (int, bool) {
return func() (int, bool) {
n++
return n, n < max
}
}
stream := Generate(generator)
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
}
func TestFromSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestFromSlice")
stream := FromSlice([]int{1, 2, 3})
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
}
func TestFromChannel(t *testing.T) {
assert := internal.NewAssert(t, "TestFromChannel")
ch := make(chan int)
go func() {
for i := 1; i < 4; i++ {
ch <- i
}
close(ch)
}()
stream := FromChannel(ch)
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
}
func TestFromRange(t *testing.T) {
assert := internal.NewAssert(t, "TestFromRange")
s1 := FromRange(1, 5, 1)
s2 := FromRange(1.1, 5.0, 1.0)
assert.Equal([]int{1, 2, 3, 4, 5}, s1.ToSlice())
assert.Equal([]float64{1.1, 2.1, 3.1, 4.1}, s2.ToSlice())
}
func TestStream_Distinct(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Distinct")
nums := FromSlice([]int{1, 2, 2, 3, 3, 3})
distinctNums := nums.Distinct()
assert.Equal([]int{1, 2, 2, 3, 3, 3}, nums.ToSlice())
assert.Equal([]int{1, 2, 3}, distinctNums.ToSlice())
type Person struct {
Id string
Name string
Age uint
}
people := []Person{
{Id: "001", Name: "Tom", Age: 10},
{Id: "001", Name: "Tom", Age: 10},
{Id: "002", Name: "Jim", Age: 20},
{Id: "003", Name: "Mike", Age: 30},
}
stream := FromSlice(people)
distinctStream := stream.Distinct()
// {[{001 Tom 10} {001 Tom 10} {002 Jim 20} {003 Mike 30}]}
t.Log(stream)
// {[{001 Tom 10} {002 Jim 20} {003 Mike 30}]}
t.Log(distinctStream)
}
func TestStream_Filter(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Filter")
stream := FromSlice([]int{1, 2, 3, 4, 5})
isEven := func(n int) bool {
return n%2 == 0
}
even := stream.Filter(isEven)
assert.Equal([]int{2, 4}, even.ToSlice())
}
func TestStream_Map(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Map")
stream := FromSlice([]int{1, 2, 3})
addOne := func(n int) int {
return n + 1
}
s := stream.Map(addOne)
assert.Equal([]int{2, 3, 4}, s.ToSlice())
}
func TestStream_Peek(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Peek")
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
result := []string{}
stream = stream.Filter(func(n int) bool {
return n <= 3
}).Peek(func(n int) {
result = append(result, fmt.Sprint("current: ", n))
})
assert.Equal([]int{1, 2, 3}, stream.ToSlice())
assert.Equal([]string{
"current: 1", "current: 2", "current: 3",
}, result)
}
func TestStream_Skip(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Peek")
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
s1 := stream.Skip(-1)
s2 := stream.Skip(0)
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s1.ToSlice())
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s2.ToSlice())
}
func TestStream_Limit(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Limit")
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
s1 := stream.Limit(-1)
s2 := stream.Limit(0)
s3 := stream.Limit(1)
s4 := stream.Limit(6)
assert.Equal([]int{}, s1.ToSlice())
assert.Equal([]int{}, s2.ToSlice())
assert.Equal([]int{1}, s3.ToSlice())
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s4.ToSlice())
}
func TestStream_AllMatch(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_AllMatch")
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
result1 := stream.AllMatch(func(item int) bool {
return item > 0
})
result2 := stream.AllMatch(func(item int) bool {
return item > 1
})
assert.Equal(true, result1)
assert.Equal(false, result2)
}
func TestStream_AnyMatch(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_AnyMatch")
stream := FromSlice([]int{1, 2, 3})
result1 := stream.AnyMatch(func(item int) bool {
return item > 3
})
result2 := stream.AnyMatch(func(item int) bool {
return item > 1
})
assert.Equal(false, result1)
assert.Equal(true, result2)
}
func TestStream_NoneMatch(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_NoneMatch")
stream := FromSlice([]int{1, 2, 3})
result1 := stream.NoneMatch(func(item int) bool {
return item > 3
})
result2 := stream.NoneMatch(func(item int) bool {
return item > 1
})
assert.Equal(true, result1)
assert.Equal(false, result2)
}
func TestStream_ForEach(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_ForEach")
stream := FromSlice([]int{1, 2, 3})
result := 0
stream.ForEach(func(item int) {
result += item
})
assert.Equal(6, result)
}
func TestStream_Reduce(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Reduce")
stream := FromSlice([]int{1, 2, 3})
result := stream.Reduce(0, func(a, b int) int {
return a + b
})
assert.Equal(6, result)
}

View File

@@ -3,10 +3,10 @@ package system
import "fmt" import "fmt"
func ExampleSetOsEnv() { func ExampleSetOsEnv() {
ok := SetOsEnv("foo", "abc") err := SetOsEnv("foo", "abc")
result := GetOsEnv("foo") result := GetOsEnv("foo")
fmt.Println(ok) fmt.Println(err)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// <nil> // <nil>
@@ -25,14 +25,14 @@ func ExampleGetOsEnv() {
} }
func ExampleRemoveOsEnv() { func ExampleRemoveOsEnv() {
ok1 := SetOsEnv("foo", "abc") err1 := SetOsEnv("foo", "abc")
result1 := GetOsEnv("foo") result1 := GetOsEnv("foo")
ok2 := RemoveOsEnv("foo") err2 := RemoveOsEnv("foo")
result2 := GetOsEnv("foo") result2 := GetOsEnv("foo")
fmt.Println(ok1) fmt.Println(err1)
fmt.Println(ok2) fmt.Println(err2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
@@ -49,9 +49,10 @@ func ExampleCompareOsEnv() {
return return
} }
result1 := CompareOsEnv("foo", "abc") result := CompareOsEnv("foo", "abc")
fmt.Println(result)
fmt.Println(result1)
// Output: // Output:
// true // true
} }

View File

@@ -25,7 +25,7 @@ var (
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`) chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`) chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]") chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}`) chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`) creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`) base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
) )

View File

@@ -208,6 +208,7 @@ func TestIsChinesePhone(t *testing.T) {
assert.Equal(true, IsChinesePhone("010-32116675")) assert.Equal(true, IsChinesePhone("010-32116675"))
assert.Equal(true, IsChinesePhone("0464-8756213")) assert.Equal(true, IsChinesePhone("0464-8756213"))
assert.Equal(true, IsChinesePhone("0731-82251545")) //长沙晚报电话
assert.Equal(false, IsChinesePhone("123-87562")) assert.Equal(false, IsChinesePhone("123-87562"))
} }