1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35: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)
@@ -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>

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)
@@ -66,7 +72,7 @@ type List[T any] struct {
} }
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
@@ -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

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

View File

@@ -1,4 +1,5 @@
# Netutil # Netutil
Package netutil contains functions to get net information and send http request. Package netutil contains functions to get net information and send http request.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,13 +8,12 @@ Package netutil contains functions to get net information and send http request.
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go) - [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.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/netutil" "github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [ConvertMapToQueryString](#ConvertMapToQueryString) - [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl) - [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp) - [GetInternalIp](#GetInternalIp)
@@ -48,8 +49,8 @@ import (
## Documentation ## Documentation
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span> ### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>Convert map to url query string.</p> <p>Convert map to url query string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -57,6 +58,7 @@ import (
```go ```go
func ConvertMapToQueryString(param map[string]any) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -75,13 +77,13 @@ func main() {
} }
qs := netutil.ConvertMapToQueryString(m) qs := netutil.ConvertMapToQueryString(m)
fmt.Println(qs) //a=1&b=2&c=3 // Output:
// a=1&b=2&c=3
} }
``` ```
### <span id="EncodeUrl">EncodeUrl</span> ### <span id="EncodeUrl">EncodeUrl</span>
<p>Encode url query string values.</p> <p>Encode url query string values.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -89,6 +91,7 @@ func main() {
```go ```go
func EncodeUrl(urlStr string) (string, error) func EncodeUrl(urlStr string) (string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -102,16 +105,20 @@ import (
func main() { func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]" urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr) encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
fmt.Println(encodedUrl)
// Output:
// http://www.lancet.com?a=1&b=%5B2%5D
} }
``` ```
### <span id="GetInternalIp">GetInternalIp</span> ### <span id="GetInternalIp">GetInternalIp</span>
<p>Get internal ip information.</p> <p>Get internal ip information.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -119,6 +126,7 @@ func main() {
```go ```go
func GetInternalIp() string func GetInternalIp() string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -134,13 +142,15 @@ func main() {
internalIp := netutil.GetInternalIp() internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp) ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9 fmt.Println(ip)
// Output:
// 192.168.1.9
} }
``` ```
### <span id="GetIps">GetIps</span> ### <span id="GetIps">GetIps</span>
<p>Get all ipv4 list.</p> <p>Get all ipv4 list.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -148,6 +158,7 @@ func main() {
```go ```go
func GetIps() []string func GetIps() []string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -161,13 +172,15 @@ import (
func main() { func main() {
ips := netutil.GetIps() ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9] fmt.Println(ips)
// Output:
// [192.168.1.9]
} }
``` ```
### <span id="GetMacAddrs">GetMacAddrs</span> ### <span id="GetMacAddrs">GetMacAddrs</span>
<p>Get all mac addresses list.</p> <p>Get all mac addresses list.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -175,6 +188,7 @@ func main() {
```go ```go
func GetMacAddrs() []string { func GetMacAddrs() []string {
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -187,14 +201,16 @@ import (
) )
func main() { func main() {
addrs := netutil.GetMacAddrs() macAddrs := netutil.GetMacAddrs()
fmt.Println(addrs) fmt.Println(macAddrs)
// Output:
// [18:31:bf:09:d1:56 76:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f]
} }
``` ```
### <span id="GetPublicIpInfo">GetPublicIpInfo</span> ### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
<p>Get public ip information.</p> <p>Get public ip information.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -216,6 +232,7 @@ type PublicIpInfo struct {
Ip string `json:"query"` Ip string `json:"query"`
} }
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -236,9 +253,8 @@ func main() {
} }
``` ```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span> ### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>Get http request public ip.</p> <p>Get http request public ip.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -246,6 +262,7 @@ func main() {
```go ```go
func GetRequestPublicIp(req *http.Request) string func GetRequestPublicIp(req *http.Request) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -259,29 +276,23 @@ import (
func main() { func main() {
ip := "36.112.24.10" ip := "36.112.24.10"
request1 := http.Request{ request := http.Request{
Method: "GET", Method: "GET",
Header: http.Header{ Header: http.Header{
"X-Forwarded-For": {ip}, "X-Forwarded-For": {ip},
}, },
} }
publicIp1 := netutil.GetRequestPublicIp(&request1) publicIp := netutil.GetRequestPublicIp(&request)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{ fmt.Println(publicIp)
Method: "GET",
Header: http.Header{ // Output:
"X-Real-Ip": {ip}, // 36.112.24.10
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
} }
``` ```
### <span id="IsPublicIP">IsPublicIP</span> ### <span id="IsPublicIP">IsPublicIP</span>
<p>Checks if an ip is public or not.</p> <p>Checks if an ip is public or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -289,6 +300,7 @@ func main() {
```go ```go
func IsPublicIP(IP net.IP) bool func IsPublicIP(IP net.IP) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -301,18 +313,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("192.168.0.1") ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsPublicIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsPublicIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsPublicIP(ip1)) //false fmt.Println(ip1)
fmt.Println(netutil.IsPublicIP(ip2)) //true fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
} }
``` ```
### <span id="IsInternalIP">IsInternalIP</span> ### <span id="IsInternalIP">IsInternalIP</span>
<p>Checks if an ip is intranet or not.</p> <p>Checks if an ip is intranet or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -320,6 +337,7 @@ func main() {
```go ```go
func IsInternalIP(IP net.IP) bool func IsInternalIP(IP net.IP) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -332,16 +350,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("127.0.0.1") ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsInternalIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsInternalIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsInternalIP(ip1)) //true fmt.Println(ip1)
fmt.Println(netutil.IsInternalIP(ip2)) //false fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
} }
``` ```
### <span id="HttpRequest">HttpRequest</span> ### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest is a struct used to abstract HTTP request entity.</p> <p>HttpRequest is a struct used to abstract HTTP request entity.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -356,6 +381,7 @@ type HttpRequest struct {
Body []byte Body []byte
} }
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -384,8 +410,8 @@ func main() {
} }
``` ```
### <span id="HttpClient">HttpClient</span> ### <span id="HttpClient">HttpClient</span>
<p>HttpClient is a struct used to send HTTP request. It can be instanced with some configurations or none config.</p> <p>HttpClient is a struct used to send HTTP request. It can be instanced with some configurations or none config.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -412,6 +438,7 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -433,9 +460,8 @@ func main() {
} }
``` ```
### <span id="SendRequest">SendRequest</span> ### <span id="SendRequest">SendRequest</span>
<p>Use HttpClient to send HTTP request.</p> <p>Use HttpClient to send HTTP request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -443,6 +469,7 @@ func main() {
```go ```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -464,7 +491,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -475,15 +502,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="DecodeResponse">DecodeResponse</span> ### <span id="DecodeResponse">DecodeResponse</span>
<p>Decode http response into target object.</p> <p>Decode http response into target object.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -491,6 +523,7 @@ func main() {
```go ```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -512,7 +545,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -523,14 +556,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="StructToUrlValues">StructToUrlValues</span> ### <span id="StructToUrlValues">StructToUrlValues</span>
<p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p> <p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -538,6 +577,7 @@ func main() {
```go ```go
func StructToUrlValues(targetStruct any) url.Values func StructToUrlValues(targetStruct any) url.Values
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -551,22 +591,25 @@ import (
func main() { func main() {
type TodoQuery struct { type TodoQuery struct {
Id int `json:"id"` Id int `json:"id"`
UserId int `json:"userId"` Name string `json:"name"`
} }
todoQuery := TodoQuery{ todoQuery := TodoQuery{
Id: 1, Id: 1,
UserId: 2, Name: "Test",
} }
todoValues := netutil.StructToUrlValues(todoQuery) todoValues := netutil.StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id")) //1 fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("userId")) //2 fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
} }
``` ```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>Send http get request.</p> <p>Send http get request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -578,6 +621,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpGet(url string, params ...any) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -606,9 +650,8 @@ func main() {
} }
``` ```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>Send http post request.</p> <p>Send http post request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -620,6 +663,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPost(url string, params ...any) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -655,9 +699,8 @@ func main() {
} }
``` ```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>Send http put request.</p> <p>Send http put request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -669,6 +712,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPut(url string, params ...any) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -705,9 +749,8 @@ func main() {
} }
``` ```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>Send http delete request.</p> <p>Send http delete request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -719,6 +762,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpDelete(url string, params ...any) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -744,9 +788,8 @@ func main() {
} }
``` ```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>Send http patch request.</p> <p>Send http patch request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -758,6 +801,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPatch(url string, params ...any) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -794,9 +838,8 @@ func main() {
} }
``` ```
### <span id="ParseHttpResponse">ParseHttpResponse</span> ### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>Decode http response to specified interface.</p> <p>Decode http response to specified interface.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -804,6 +847,7 @@ func main() {
```go ```go
func ParseHttpResponse(resp *http.Response, obj any) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -844,4 +888,3 @@ func main() {
fmt.Println(toDoResp) fmt.Println(toDoResp)
} }
``` ```

View File

@@ -1,5 +1,6 @@
# Netutil # Netutil
netutil网络包支持获取ip地址发送http请求。
netutil 网络包支持获取 ip 地址,发送 http 请求。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,13 +8,12 @@ netutil网络包支持获取ip地址发送http请求。
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go) - [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.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/netutil" "github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [ConvertMapToQueryString](#ConvertMapToQueryString) - [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl) - [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp) - [GetInternalIp](#GetInternalIp)
@@ -48,8 +49,8 @@ import (
## 文档 ## 文档
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span> ### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>将map转换成http查询字符串.</p> <p>将map转换成http查询字符串.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -57,7 +58,8 @@ import (
```go ```go
func ConvertMapToQueryString(param map[string]any) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -75,13 +77,15 @@ func main() {
} }
qs := netutil.ConvertMapToQueryString(m) qs := netutil.ConvertMapToQueryString(m)
fmt.Println(qs) //a=1&b=2&c=3 fmt.Println(qs)
// Output:
// a=1&b=2&c=3
} }
``` ```
### <span id="EncodeUrl">EncodeUrl</span> ### <span id="EncodeUrl">EncodeUrl</span>
<p>编码url query string的值</p> <p>编码url query string的值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -89,7 +93,8 @@ func main() {
```go ```go
func EncodeUrl(urlStr string) (string, error) func EncodeUrl(urlStr string) (string, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -102,17 +107,20 @@ import (
func main() { func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]" urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr) encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
fmt.Println(encodedUrl)
// Output:
// http://www.lancet.com?a=1&b=%5B2%5D
} }
``` ```
### <span id="GetInternalIp">GetInternalIp</span> ### <span id="GetInternalIp">GetInternalIp</span>
<p>获取内部ip</p> <p>获取内部ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -120,7 +128,8 @@ func main() {
```go ```go
func GetInternalIp() string func GetInternalIp() string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -135,12 +144,15 @@ func main() {
internalIp := netutil.GetInternalIp() internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp) ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9 fmt.Println(ip)
// Output:
// 192.168.1.9
} }
``` ```
### <span id="GetIps">GetIps</span> ### <span id="GetIps">GetIps</span>
<p>获取ipv4地址列表</p> <p>获取ipv4地址列表</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -148,7 +160,8 @@ func main() {
```go ```go
func GetIps() []string func GetIps() []string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -161,13 +174,15 @@ import (
func main() { func main() {
ips := netutil.GetIps() ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9] fmt.Println(ips)
// Output:
// [192.168.1.9]
} }
``` ```
### <span id="GetMacAddrs">GetMacAddrs</span> ### <span id="GetMacAddrs">GetMacAddrs</span>
<p>获取mac地址列</p> <p>获取mac地址列</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -175,7 +190,8 @@ func main() {
```go ```go
func GetMacAddrs() []string { func GetMacAddrs() []string {
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -187,14 +203,16 @@ import (
) )
func main() { func main() {
addrs := netutil.GetMacAddrs() macAddrs := netutil.GetMacAddrs()
fmt.Println(addrs) fmt.Println(macAddrs)
// Output:
// [18:31:bf:09:d1:56 76:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f]
} }
``` ```
### <span id="GetPublicIpInfo">GetPublicIpInfo</span> ### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
<p>获取公网ip信息</p> <p>获取公网ip信息</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -216,7 +234,8 @@ type PublicIpInfo struct {
Ip string `json:"query"` Ip string `json:"query"`
} }
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -236,9 +255,8 @@ func main() {
} }
``` ```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span> ### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>获取http请求ip</p> <p>获取http请求ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -246,7 +264,8 @@ func main() {
```go ```go
func GetRequestPublicIp(req *http.Request) string func GetRequestPublicIp(req *http.Request) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -259,30 +278,23 @@ import (
func main() { func main() {
ip := "36.112.24.10" ip := "36.112.24.10"
request1 := http.Request{ request := http.Request{
Method: "GET", Method: "GET",
Header: http.Header{ Header: http.Header{
"X-Forwarded-For": {ip}, "X-Forwarded-For": {ip},
}, },
} }
publicIp1 := netutil.GetRequestPublicIp(&request1) publicIp := netutil.GetRequestPublicIp(&request)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{ fmt.Println(publicIp)
Method: "GET",
Header: http.Header{ // Output:
"X-Real-Ip": {ip}, // 36.112.24.10
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
} }
``` ```
### <span id="IsPublicIP">IsPublicIP</span> ### <span id="IsPublicIP">IsPublicIP</span>
<p>判断ip是否是公共ip</p> <p>判断ip是否是公共ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -290,7 +302,8 @@ func main() {
```go ```go
func IsPublicIP(IP net.IP) bool func IsPublicIP(IP net.IP) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -302,17 +315,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("192.168.0.1") ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsPublicIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsPublicIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsPublicIP(ip1)) //false fmt.Println(ip1)
fmt.Println(netutil.IsPublicIP(ip2)) //true fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
} }
``` ```
### <span id="IsInternalIP">IsInternalIP</span> ### <span id="IsInternalIP">IsInternalIP</span>
<p>判断ip是否是局域网ip.</p> <p>判断ip是否是局域网ip.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -320,7 +339,8 @@ func main() {
```go ```go
func IsInternalIP(IP net.IP) bool func IsInternalIP(IP net.IP) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -332,16 +352,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("127.0.0.1") ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsInternalIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsInternalIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsInternalIP(ip1)) //true fmt.Println(ip1)
fmt.Println(netutil.IsInternalIP(ip2)) //false fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
} }
``` ```
### <span id="HttpRequest">HttpRequest</span> ### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest用于抽象HTTP请求实体的结构</p> <p>HttpRequest用于抽象HTTP请求实体的结构</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -356,7 +383,8 @@ type HttpRequest struct {
Body []byte Body []byte
} }
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -384,8 +412,8 @@ func main() {
} }
``` ```
### <span id="HttpClient">HttpClient</span> ### <span id="HttpClient">HttpClient</span>
<p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p> <p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -412,7 +440,8 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -433,9 +462,8 @@ func main() {
} }
``` ```
### <span id="SendRequest">SendRequest</span> ### <span id="SendRequest">SendRequest</span>
<p>HttpClient发送http请求</p> <p>HttpClient发送http请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -443,7 +471,8 @@ func main() {
```go ```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -464,7 +493,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -475,15 +504,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="DecodeResponse">DecodeResponse</span> ### <span id="DecodeResponse">DecodeResponse</span>
<p>解析http响应体到目标结构体</p> <p>解析http响应体到目标结构体</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -491,7 +525,8 @@ func main() {
```go ```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -512,7 +547,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -523,14 +558,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="StructToUrlValues">StructToUrlValues</span> ### <span id="StructToUrlValues">StructToUrlValues</span>
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p> <p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -538,7 +579,8 @@ func main() {
```go ```go
func StructToUrlValues(targetStruct any) url.Values func StructToUrlValues(targetStruct any) url.Values
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -551,22 +593,25 @@ import (
func main() { func main() {
type TodoQuery struct { type TodoQuery struct {
Id int `json:"id"` Id int `json:"id"`
UserId int `json:"userId"` Name string `json:"name"`
} }
todoQuery := TodoQuery{ todoQuery := TodoQuery{
Id: 1, Id: 1,
UserId: 2, Name: "Test",
} }
todoValues := netutil.StructToUrlValues(todoQuery) todoValues := netutil.StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id")) //1 fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("userId")) //2 fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
} }
``` ```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>发送http get请求</p> <p>发送http get请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -578,7 +623,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpGet(url string, params ...any) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -606,9 +652,8 @@ func main() {
} }
``` ```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>发送http post请求</p> <p>发送http post请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -620,7 +665,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPost(url string, params ...any) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -655,9 +701,8 @@ func main() {
} }
``` ```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>发送http put请求</p> <p>发送http put请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -669,7 +714,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPut(url string, params ...any) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -705,9 +751,8 @@ func main() {
} }
``` ```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>发送http delete请求</p> <p>发送http delete请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -719,7 +764,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpDelete(url string, params ...any) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -744,9 +790,8 @@ func main() {
} }
``` ```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>发送http patch请求</p> <p>发送http patch请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -758,7 +803,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPatch(url string, params ...any) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -794,9 +840,8 @@ func main() {
} }
``` ```
### <span id="ParseHttpResponse">ParseHttpResponse</span> ### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>将http请求响应解码成特定struct值</p> <p>将http请求响应解码成特定struct值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -804,7 +849,8 @@ func main() {
```go ```go
func ParseHttpResponse(resp *http.Response, obj any) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -844,4 +890,3 @@ func main() {
fmt.Println(toDoResp) fmt.Println(toDoResp)
} }
``` ```

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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -227,7 +227,7 @@ func main() {
func UUIdV4() (string, error) func UUIdV4() (string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -1,4 +1,5 @@
# 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>
@@ -7,10 +8,10 @@ Package retry is for executing a function repeatedly until it was successful or
- [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,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Context](#Context) - [Context](#Context)
- [Retry](#Retry) - [Retry](#Retry)
- [RetryFunc](#RetryFunc) - [RetryFunc](#RetryFunc)
@@ -30,8 +32,8 @@ import (
## 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,6 +41,7 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -52,7 +55,8 @@ import (
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number > 3 { if number > 3 {
@@ -61,21 +65,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, duration := retry.RetryDuration(time.Microsecond*50)
retry.RetryDuration(time.Microsecond*50),
retry.Retry(increaseNumber,
duration,
retry.Context(ctx), retry.Context(ctx),
) )
if err != nil { fmt.Println(number)
fmt.Println(err) //retry is cancelled
} // 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,9 +102,8 @@ import (
) )
func main() { func main() {
var number int number := 0
var increaseNumber retry.RetryFunc = func() error {
increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
@@ -106,18 +111,22 @@ func main() {
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>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,7 +148,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
@@ -150,14 +160,16 @@ func main() {
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,7 +191,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -187,17 +200,22 @@ func main() {
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,7 +237,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -227,11 +246,16 @@ func main() {
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,5 +1,6 @@
# Retry # Retry
retry重试执行函数直到函数运行成功或被context cancel。
retry 重试执行函数直到函数运行成功或被 context cancel。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ retry重试执行函数直到函数运行成功或被context cancel。
- [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) - [Context](#Context)
- [Retry](#Retry) - [Retry](#Retry)
- [RetryFunc](#RetryFunc) - [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration) - [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes) - [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,7 +41,8 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
@@ -54,7 +55,8 @@ import (
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number > 3 { if number > 3 {
@@ -63,21 +65,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, duration := retry.RetryDuration(time.Microsecond*50)
retry.RetryDuration(time.Microsecond*50),
retry.Retry(increaseNumber,
duration,
retry.Context(ctx), retry.Context(ctx),
) )
if err != nil { fmt.Println(number)
fmt.Println(err) //retry is cancelled
} // 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,8 +102,8 @@ 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
@@ -107,18 +111,22 @@ func main() {
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,7 +148,8 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -150,14 +160,16 @@ func main() {
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>设置重试间隔时间默认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,7 +191,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -187,17 +200,22 @@ func main() {
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,7 +237,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -227,11 +246,16 @@ func main() {
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

View File

@@ -1,4 +1,5 @@
# Strutil # Strutil
Package strutil contains some functions to manipulate string. Package strutil contains some functions to manipulate string.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package strutil contains some functions to manipulate string.
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go) - [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.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/strutil" "github.com/duke-git/lancet/v2/strutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [After](#After) - [After](#After)
- [AfterLast](#AfterLast) - [AfterLast](#AfterLast)
- [Before](#Before) - [Before](#Before)
@@ -41,13 +43,12 @@ import (
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="After">After</span> ### <span id="After">After</span>
<p>Returns the substring after the first occurrence of a specified string in the source string.</p> <p>Returns the substring after the first occurrence of a specified string in the source string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -55,6 +56,7 @@ import (
```go ```go
func After(s, char string) string func After(s, char string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -86,6 +88,7 @@ func main() {
``` ```
### <span id="AfterLast">AfterLast</span> ### <span id="AfterLast">AfterLast</span>
<p>Returns the substring after the last occurrence of a specified string in the source string.</p> <p>Returns the substring after the last occurrence of a specified string in the source string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,6 +96,7 @@ func main() {
```go ```go
func AfterLast(s, char string) string func AfterLast(s, char string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -124,6 +128,7 @@ func main() {
``` ```
### <span id="Before">Before</span> ### <span id="Before">Before</span>
<p>Returns the substring of the source string up to the first occurrence of the specified string.</p> <p>Returns the substring of the source string up to the first occurrence of the specified string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -131,6 +136,7 @@ func main() {
```go ```go
func Before(s, char string) string func Before(s, char string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -159,6 +165,7 @@ func main() {
``` ```
### <span id="BeforeLast">BeforeLast</span> ### <span id="BeforeLast">BeforeLast</span>
<p>Returns the substring of the source string up to the last occurrence of the specified string.</p> <p>Returns the substring of the source string up to the last occurrence of the specified string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,6 +173,7 @@ func main() {
```go ```go
func BeforeLast(s, char string) string func BeforeLast(s, char string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -194,6 +202,7 @@ func main() {
``` ```
### <span id="CamelCase">CamelCase</span> ### <span id="CamelCase">CamelCase</span>
<p>Coverts string to camelCase string, non letters and numbers will be ignored.</p> <p>Coverts string to camelCase string, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -201,6 +210,7 @@ func main() {
```go ```go
func CamelCase(s string) string func CamelCase(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -227,6 +237,7 @@ func main() {
``` ```
### <span id="KebabCase">KebabCase</span> ### <span id="KebabCase">KebabCase</span>
<p>KebabCase covert string to kebab-case, non letters and numbers will be ignored.</p> <p>KebabCase covert string to kebab-case, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -234,6 +245,7 @@ func main() {
```go ```go
func KebabCase(s string) string func KebabCase(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -260,6 +272,7 @@ func main() {
``` ```
### <span id="UpperKebabCase">UpperKebabCase</span> ### <span id="UpperKebabCase">UpperKebabCase</span>
<p>UpperKebabCase covert string to upper KEBAB-CASE, non letters and numbers will be ignored.</p> <p>UpperKebabCase covert string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -267,6 +280,7 @@ func main() {
```go ```go
func UpperKebabCase(s string) string func UpperKebabCase(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -293,6 +307,7 @@ func main() {
``` ```
### <span id="Capitalize">Capitalize</span> ### <span id="Capitalize">Capitalize</span>
<p>Convert the first character of a string to upper case.</p> <p>Convert the first character of a string to upper case.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -300,6 +315,7 @@ func main() {
```go ```go
func Capitalize(s string) string func Capitalize(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -326,6 +342,7 @@ func main() {
``` ```
### <span id="IsString">IsString</span> ### <span id="IsString">IsString</span>
<p>Check if the value's data type is string.</p> <p>Check if the value's data type is string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -333,6 +350,7 @@ func main() {
```go ```go
func IsString(v any) bool func IsString(v any) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -364,6 +382,7 @@ func main() {
``` ```
### <span id="LowerFirst">LowerFirst</span> ### <span id="LowerFirst">LowerFirst</span>
<p>Convert the first character of string to lower case.</p> <p>Convert the first character of string to lower case.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -371,6 +390,7 @@ func main() {
```go ```go
func LowerFirst(s string) string func LowerFirst(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -396,6 +416,7 @@ func main() {
``` ```
### <span id="UpperFirst">UpperFirst</span> ### <span id="UpperFirst">UpperFirst</span>
<p>Convert the first character of string to upper case.</p> <p>Convert the first character of string to upper case.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -403,6 +424,7 @@ func main() {
```go ```go
func UpperFirst(s string) string func UpperFirst(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -428,6 +450,7 @@ func main() {
``` ```
### <span id="PadEnd">PadEnd</span> ### <span id="PadEnd">PadEnd</span>
<p>Pads string on the right side if it's shorter than size.</p> <p>Pads string on the right side if it's shorter than size.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -435,6 +458,7 @@ func main() {
```go ```go
func PadEnd(source string, size int, padStr string) string func PadEnd(source string, size int, padStr string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -472,6 +496,7 @@ func main() {
``` ```
### <span id="PadStart">PadStart</span> ### <span id="PadStart">PadStart</span>
<p>Pads string on the left side if it's shorter than size.</p> <p>Pads string on the left side if it's shorter than size.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -479,6 +504,7 @@ func main() {
```go ```go
func PadStart(source string, size int, padStr string) string func PadStart(source string, size int, padStr string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -516,6 +542,7 @@ func main() {
``` ```
### <span id="Reverse">Reverse</span> ### <span id="Reverse">Reverse</span>
<p>Return string whose char order is reversed to the given string.</p> <p>Return string whose char order is reversed to the given string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -523,6 +550,7 @@ func main() {
```go ```go
func Reverse(s string) string func Reverse(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -545,6 +573,7 @@ func main() {
``` ```
### <span id="SnakeCase">SnakeCase</span> ### <span id="SnakeCase">SnakeCase</span>
<p>Coverts string to snake_case, non letters and numbers will be ignored.</p> <p>Coverts string to snake_case, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -552,6 +581,7 @@ func main() {
```go ```go
func SnakeCase(s string) string func SnakeCase(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -578,6 +608,7 @@ func main() {
``` ```
### <span id="UpperSnakeCase">UpperSnakeCase</span> ### <span id="UpperSnakeCase">UpperSnakeCase</span>
<p>Coverts string to upper KEBAB-CASE, non letters and numbers will be ignored.</p> <p>Coverts string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -585,6 +616,7 @@ func main() {
```go ```go
func SnakeCase(s string) string func SnakeCase(s string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -611,6 +643,7 @@ func main() {
``` ```
### <span id="SplitEx">SplitEx</span> ### <span id="SplitEx">SplitEx</span>
<p>Split a given string whether the result contains empty string.</p> <p>Split a given string whether the result contains empty string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -618,6 +651,7 @@ func main() {
```go ```go
func SplitEx(s, sep string, removeEmptyString bool) []string func SplitEx(s, sep string, removeEmptyString bool) []string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -650,6 +684,7 @@ func main() {
``` ```
### <span id="Substring">Substring</span> ### <span id="Substring">Substring</span>
<p>Returns a substring of the specified length starting at the specified offset position.</p> <p>Returns a substring of the specified length starting at the specified offset position.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -657,6 +692,7 @@ func main() {
```go ```go
func Substring(s string, offset int, length uint) string func Substring(s string, offset int, length uint) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -691,6 +727,7 @@ func main() {
``` ```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>Wrap a string with given string.</p> <p>Wrap a string with given string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -698,6 +735,7 @@ func main() {
```go ```go
func Wrap(str string, wrapWith string) string func Wrap(str string, wrapWith string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -725,8 +763,8 @@ func main() {
} }
``` ```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>Unwrap a given string from anther string. will change source string.</p> <p>Unwrap a given string from anther string. will change source string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -734,6 +772,7 @@ func main() {
```go ```go
func Unwrap(str string, wrapToken string) string func Unwrap(str string, wrapToken string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -763,12 +802,3 @@ func main() {
// *foo* // *foo*
} }
``` ```

View File

@@ -1,5 +1,6 @@
# Strutil # Strutil
strutil包含处理字符串的相关函数。
strutil 包含处理字符串的相关函数。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ strutil包含处理字符串的相关函数。
- [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go) - [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.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/strutil" "github.com/duke-git/lancet/v2/strutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [After](#After) - [After](#After)
- [AfterLast](#AfterLast) - [AfterLast](#AfterLast)
- [Before](#Before) - [Before](#Before)
@@ -41,14 +43,12 @@ import (
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation 文档
## Documentation文档
### <span id="After">After</span> ### <span id="After">After</span>
<p>返回源字符串中特定字符串首次出现时的位置之后的子字符串。</p> <p>返回源字符串中特定字符串首次出现时的位置之后的子字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -56,6 +56,7 @@ import (
```go ```go
func After(s, char string) string func After(s, char string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -87,6 +88,7 @@ func main() {
``` ```
### <span id="AfterLast">AfterLast</span> ### <span id="AfterLast">AfterLast</span>
<p>返回源字符串中指定字符串最后一次出现时的位置之后的子字符串。</p> <p>返回源字符串中指定字符串最后一次出现时的位置之后的子字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -94,6 +96,7 @@ func main() {
```go ```go
func AfterLast(s, char string) string func AfterLast(s, char string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -125,6 +128,7 @@ func main() {
``` ```
### <span id="Before">Before</span> ### <span id="Before">Before</span>
<p>返回源字符串中指定字符串第一次出现时的位置之前的子字符串。</p> <p>返回源字符串中指定字符串第一次出现时的位置之前的子字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -132,6 +136,7 @@ func main() {
```go ```go
func Before(s, char string) string func Before(s, char string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -160,6 +165,7 @@ func main() {
``` ```
### <span id="BeforeLast">BeforeLast</span> ### <span id="BeforeLast">BeforeLast</span>
<p>返回源字符串中指定字符串最后一次出现时的位置之前的子字符串。</p> <p>返回源字符串中指定字符串最后一次出现时的位置之前的子字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -167,6 +173,7 @@ func main() {
```go ```go
func BeforeLast(s, char string) string func BeforeLast(s, char string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -195,6 +202,7 @@ func main() {
``` ```
### <span id="CamelCase">CamelCase</span> ### <span id="CamelCase">CamelCase</span>
<p>将字符串转换为驼峰式字符串, 非字母和数字会被忽略。</p> <p>将字符串转换为驼峰式字符串, 非字母和数字会被忽略。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -202,6 +210,7 @@ func main() {
```go ```go
func CamelCase(s string) string func CamelCase(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -228,6 +237,7 @@ func main() {
``` ```
### <span id="KebabCase">KebabCase</span> ### <span id="KebabCase">KebabCase</span>
<p>将字符串转换为kebab-case, 非字母和数字会被忽略。</p> <p>将字符串转换为kebab-case, 非字母和数字会被忽略。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -235,6 +245,7 @@ func main() {
```go ```go
func KebabCase(s string) string func KebabCase(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -261,6 +272,7 @@ func main() {
``` ```
### <span id="UpperKebabCase">UpperKebabCase</span> ### <span id="UpperKebabCase">UpperKebabCase</span>
<p>将字符串转换为大写KEBAB-CASE, 非字母和数字会被忽略。</p> <p>将字符串转换为大写KEBAB-CASE, 非字母和数字会被忽略。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -268,6 +280,7 @@ func main() {
```go ```go
func UpperKebabCase(s string) string func UpperKebabCase(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -294,6 +307,7 @@ func main() {
``` ```
### <span id="Capitalize">Capitalize</span> ### <span id="Capitalize">Capitalize</span>
<p>将字符串的第一个字符转换为大写。</p> <p>将字符串的第一个字符转换为大写。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -301,6 +315,7 @@ func main() {
```go ```go
func Capitalize(s string) string func Capitalize(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -327,6 +342,7 @@ func main() {
``` ```
### <span id="IsString">IsString</span> ### <span id="IsString">IsString</span>
<p>判断传入参数的数据类型是否为字符串。</p> <p>判断传入参数的数据类型是否为字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -334,6 +350,7 @@ func main() {
```go ```go
func IsString(v any) bool func IsString(v any) bool
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -365,6 +382,7 @@ func main() {
``` ```
### <span id="LowerFirst">LowerFirst</span> ### <span id="LowerFirst">LowerFirst</span>
<p>将字符串的第一个字符转换为小写。</p> <p>将字符串的第一个字符转换为小写。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -372,6 +390,7 @@ func main() {
```go ```go
func LowerFirst(s string) string func LowerFirst(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -397,6 +416,7 @@ func main() {
``` ```
### <span id="UpperFirst">UpperFirst</span> ### <span id="UpperFirst">UpperFirst</span>
<p>将字符串的第一个字符转换为大写形式。</p> <p>将字符串的第一个字符转换为大写形式。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -404,6 +424,7 @@ func main() {
```go ```go
func UpperFirst(s string) string func UpperFirst(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -429,6 +450,7 @@ func main() {
``` ```
### <span id="PadEnd">PadEnd</span> ### <span id="PadEnd">PadEnd</span>
<p>如果字符串长度短于size则在右侧填充字符串。</p> <p>如果字符串长度短于size则在右侧填充字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -436,6 +458,7 @@ func main() {
```go ```go
func PadEnd(source string, size int, padStr string) string func PadEnd(source string, size int, padStr string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -473,6 +496,7 @@ func main() {
``` ```
### <span id="PadStart">PadStart</span> ### <span id="PadStart">PadStart</span>
<p>如果字符串长度短于size则在左侧填充字符串。</p> <p>如果字符串长度短于size则在左侧填充字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -480,6 +504,7 @@ func main() {
```go ```go
func PadStart(source string, size int, padStr string) string func PadStart(source string, size int, padStr string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -517,6 +542,7 @@ func main() {
``` ```
### <span id="Reverse">Reverse</span> ### <span id="Reverse">Reverse</span>
<p>返回字符顺序与给定字符串相反的字符串。</p> <p>返回字符顺序与给定字符串相反的字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -524,6 +550,7 @@ func main() {
```go ```go
func Reverse(s string) string func Reverse(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -546,6 +573,7 @@ func main() {
``` ```
### <span id="SnakeCase">SnakeCase</span> ### <span id="SnakeCase">SnakeCase</span>
<p>将字符串转换为snake_case形式, 非字母和数字会被忽略。</p> <p>将字符串转换为snake_case形式, 非字母和数字会被忽略。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -553,6 +581,7 @@ func main() {
```go ```go
func SnakeCase(s string) string func SnakeCase(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -579,6 +608,7 @@ func main() {
``` ```
### <span id="UpperSnakeCase">UpperSnakeCase</span> ### <span id="UpperSnakeCase">UpperSnakeCase</span>
<p>将字符串转换为大写SNAKE_CASE形式, 非字母和数字会被忽略。</p> <p>将字符串转换为大写SNAKE_CASE形式, 非字母和数字会被忽略。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -586,6 +616,7 @@ func main() {
```go ```go
func SnakeCase(s string) string func SnakeCase(s string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -612,6 +643,7 @@ func main() {
``` ```
### <span id="SplitEx">SplitEx</span> ### <span id="SplitEx">SplitEx</span>
<p>分割字符串为切片removeEmptyString参数指定是否去除空字符串。</p> <p>分割字符串为切片removeEmptyString参数指定是否去除空字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -619,6 +651,7 @@ func main() {
```go ```go
func SplitEx(s, sep string, removeEmptyString bool) []string func SplitEx(s, sep string, removeEmptyString bool) []string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -651,6 +684,7 @@ func main() {
``` ```
### <span id="Substring">Substring</span> ### <span id="Substring">Substring</span>
<p>根据指定的位置和长度截取字符串。</p> <p>根据指定的位置和长度截取字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -658,6 +692,7 @@ func main() {
```go ```go
func Substring(s string, offset int, length uint) string func Substring(s string, offset int, length uint) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -692,6 +727,7 @@ func main() {
``` ```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>用另一个字符串包裹一个字符串。</p> <p>用另一个字符串包裹一个字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -699,6 +735,7 @@ func main() {
```go ```go
func Wrap(str string, wrapWith string) string func Wrap(str string, wrapWith string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go
@@ -726,8 +763,8 @@ func main() {
} }
``` ```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>用另一个字符串解开包裹一个字符串。</p> <p>用另一个字符串解开包裹一个字符串。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -735,6 +772,7 @@ func main() {
```go ```go
func Unwrap(str string, wrapToken string) string func Unwrap(str string, wrapToken string) string
``` ```
<b>示例:</b> <b>示例:</b>
```go ```go

View File

@@ -1,4 +1,5 @@
# 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>
@@ -7,10 +8,10 @@ Package system contains some functions about os, runtime, shell command.
- [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,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [IsWindows](#IsWindows) - [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsLinux](#IsLinux)
- [IsMac](#IsMac) - [IsMac](#IsMac)
@@ -30,13 +32,12 @@ import (
- [ExecCommand](#ExecCommand) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits) - [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,6 +45,7 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -58,10 +60,8 @@ func main() {
} }
``` ```
### <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,6 +69,7 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -83,9 +84,8 @@ func main() {
} }
``` ```
### <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,6 +93,7 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -107,9 +108,8 @@ func main() {
} }
``` ```
### <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,6 +117,7 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -126,14 +127,19 @@ import (
) )
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,6 +147,7 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -150,15 +157,19 @@ import (
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err) 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,6 +177,7 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -175,16 +187,27 @@ import (
) )
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,6 +215,7 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -201,16 +225,22 @@ import (
) )
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,6 +248,7 @@ 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
@@ -248,10 +279,8 @@ func main() {
} }
``` ```
### <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,6 +288,7 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -269,9 +299,6 @@ import (
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```

View File

@@ -1,5 +1,6 @@
# 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>
@@ -7,10 +8,10 @@ system包含os, runtime, shell command相关函数。
- [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,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [IsWindows](#IsWindows) - [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsLinux](#IsLinux)
- [IsMac](#IsMac) - [IsMac](#IsMac)
@@ -30,13 +32,12 @@ import (
- [ExecCommand](#ExecCommand) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits) - [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,6 +45,7 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -58,10 +60,8 @@ func main() {
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>检查当前操作系统是否是linux</p> <p>检查当前操作系统是否是linux</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,6 +69,7 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -83,9 +84,8 @@ func main() {
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>检查当前操作系统是否是macos</p> <p>检查当前操作系统是否是macos</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,6 +93,7 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -107,9 +108,8 @@ func main() {
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>获取key命名的环境变量的值</p> <p>获取key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,6 +117,7 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -126,14 +127,19 @@ import (
) )
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,6 +147,7 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -150,15 +157,19 @@ import (
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err) 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,6 +177,7 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -175,16 +187,27 @@ import (
) )
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,6 +215,7 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -201,16 +225,22 @@ import (
) )
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,6 +248,7 @@ 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
@@ -248,10 +279,8 @@ func main() {
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数返回32或64</p> <p>获取当前操作系统位数返回32或64</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -259,7 +288,8 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
@@ -269,13 +299,6 @@ import (
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,4 +1,5 @@
# 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>
@@ -10,6 +11,7 @@ Package xerror implements helpers for errors.
<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

View File

@@ -1,5 +1,6 @@
# Xerror # Xerror
xerror错误处理逻辑封装
xerror 错误处理逻辑封装
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ xerror错误处理逻辑封装
<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

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"))
} }