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

Compare commits

...

103 Commits

Author SHA1 Message Date
dudaodong 6bba44dc50 feat: add Concat for stream 2023-02-07 10:47:28 +08:00
dudaodong 422022c74d feat: add Range for stream 2023-02-07 10:36:07 +08:00
dudaodong 87fcf97e2d feat: add FindFirst, Reverse for stream 2023-02-07 10:24:19 +08:00
dudaodong 05d1f348d4 refactor: update constant names 2023-02-06 19:39:31 +08:00
dudaodong 6f2f1f3004 fix: IsZeroValue support pointer 2023-02-06 19:36:36 +08:00
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
dudaodong 4c5524354c doc: normalize documents 2023-01-13 14:36:33 +08:00
dudaodong 2c6e9a3fb9 doc: format document 2023-01-13 11:01:22 +08:00
dudaodong 5f2c3edff4 doc: format document 2023-01-13 10:57:40 +08:00
dudaodong b422d98702 doc: format document 2023-01-13 10:48:21 +08:00
dudaodong 6f27e0bfbf doc: format document 2023-01-13 10:47:47 +08:00
dudaodong ce3b6b461e doc: format document 2023-01-13 10:43:16 +08:00
dudaodong 0d6ad4f0d2 doc: format document 2023-01-13 10:41:47 +08:00
dudaodong c875a7f8b8 doc: format document 2023-01-13 10:39:39 +08:00
dudaodong 0c62d117a1 doc: format document 2023-01-13 10:12:37 +08:00
dudaodong c260ce493d doc: normalize documents 2023-01-12 15:44:34 +08:00
dudaodong 9ffe96d3ef update readme file 2023-01-12 11:32:43 +08:00
dudaodong d4bba76dc8 fix: fix ExampleSchedule failed 2023-01-09 11:25:14 +08:00
dudaodong adaa3ebc43 Merge branch 'main' into v2 2023-01-09 11:16:13 +08:00
dudaodong 61d38ae3b8 doc: update doc for algorithm package 2023-01-09 11:15:25 +08:00
dudaodong c85d910044 add playground demo 2023-01-09 11:02:41 +08:00
dudaodong d95a7c6101 fix: fix example function bug in function package 2023-01-08 21:09:41 +08:00
dudaodong bce3641ec6 fix: fix example function bug in datetime package 2023-01-08 21:04:39 +08:00
dudaodong ceb134b2fd fix: fix example function bug in datetime package 2023-01-08 21:01:05 +08:00
dudaodong 4b9b1d32c5 release v2.1.13 2023-01-08 20:45:43 +08:00
dudaodong 395e0883c7 fix: fix example test failed of CreateFile 2023-01-08 20:44:23 +08:00
dudaodong a930511054 test&doc: add example and update doc for xerror package 2023-01-08 20:36:32 +08:00
dudaodong 7380721ccc test&doc: add example and update doc for xerror package 2023-01-08 20:36:17 +08:00
dudaodong 936011dc3b fix: fix bug in file test 2023-01-08 20:25:11 +08:00
dudaodong bc0ee08f38 test&doc: add example and update doc for datetime package 2023-01-08 20:16:04 +08:00
dudaodong f1afd753d4 test&doc: add example and update doc for netutil package 2023-01-08 16:57:03 +08:00
dudaodong b05a0a91c3 test&doc: add example and update doc for netutil package 2023-01-08 16:54:29 +08:00
dudaodong da2eb66657 doc: update doc for datastructure package 2023-01-08 15:42:34 +08:00
dudaodong ad20159de2 doc: update doc for datastructure package 2023-01-08 15:41:59 +08:00
dudaodong 278733d3d1 Todo: add todo for playground demo of function 2023-01-07 18:27:07 +08:00
dudaodong 2f184907ff doc: update document for cryptor package 2023-01-07 18:18:23 +08:00
dudaodong 50fcc718ee test: add example for cryptor package 2023-01-07 17:34:42 +08:00
dudaodong cc68feb52d doc&test: add example and update doc for retry package 2023-01-07 14:22:07 +08:00
dudaodong ca2a51b37e test&doc: add example and update doc for function package 2023-01-06 17:12:32 +08:00
dudaodong be444f521d test: add examples for function package 2023-01-06 16:12:44 +08:00
dudaodong e21dd07d46 doc: update doc for validator package 2023-01-06 14:14:00 +08:00
dudaodong 4044deac70 test: add examples for validator package 2023-01-06 11:31:51 +08:00
dudaodong d9c6294775 fix: fix goline error 2023-01-05 14:55:47 +08:00
dudaodong d8505d1a5f doc: update doc for slice package 2023-01-05 14:49:30 +08:00
dudaodong 6498c7d68a test: add examples for slice package 2023-01-05 11:26:56 +08:00
dudaodong 5f0211f0c4 test: add examples for slice package 2023-01-04 14:44:10 +08:00
dudaodong 1de2e2cedd test: add examples for random package 2023-01-03 15:10:42 +08:00
dudaodong c8f8b1b7d9 doc: update doc for fileutil package 2023-01-03 14:33:29 +08:00
dudaodong 3062eb7789 test: add examples for fileutil package 2023-01-03 11:55:23 +08:00
dudaodong 64d5486cc6 doc: add example and update doc for formatter package 2023-01-02 15:35:09 +08:00
dudaodong 6d57891f66 doc: update document for mathutil package 2023-01-02 15:19:47 +08:00
dudaodong 927245e47f test: add example for mathutil package 2023-01-02 14:59:49 +08:00
dudaodong 31fdbee0b5 doc: update document for maputil function 2023-01-02 14:21:23 +08:00
dudaodong 3712819994 test: add exmaple for maputil package 2023-01-02 14:06:12 +08:00
dudaodong 6d7dec1cea doc: update doc for convertor package 2023-01-01 22:00:23 +08:00
dudaodong 9b6a004dbc test: add example for convertor package 2023-01-01 21:24:24 +08:00
dudaodong 3ad6f4bd9e doc: update doc for condition package 2022-12-31 16:47:18 +08:00
dudaodong b8c6746f31 test: add example for condition package 2022-12-31 16:26:43 +08:00
dudaodong 0bf8bbf4cb doc: add example and update docment for channel 2022-12-31 13:38:52 +08:00
dudaodong a6ba1028c5 doc: add example and update docment for channel 2022-12-31 13:35:44 +08:00
dudaodong cc54dd7ec9 doc: add example and update docment for channel 2022-12-31 13:12:16 +08:00
dudaodong 54834dba4c doc: update doc for system package 2022-12-30 14:28:49 +08:00
dudaodong e996d4c945 test: add examples for system package 2022-12-30 14:14:37 +08:00
dudaodong ae92ae7666 test: add examples for system package 2022-12-30 14:14:22 +08:00
dudaodong 526e568d0e doc: add doc for Substring 2022-12-29 20:03:59 +08:00
dudaodong 1dc5e8ac23 feat: add Substring function 2022-12-29 19:55:40 +08:00
dudaodong b5f7b0e670 doc: update document for algorithm package 2022-12-29 15:32:47 +08:00
dudaodong 39c576248c test: add examples for lrucache 2022-12-29 11:43:14 +08:00
dudaodong eb164d1536 test: add examples for lrucache function 2022-12-29 11:43:04 +08:00
dudaodong 68e170080c test: add examples for sort function 2022-12-28 20:18:05 +08:00
dudaodong 652b09135c test: add examples for search function 2022-12-28 17:58:56 +08:00
dudaodong bff24c89bc doc: update strutil document 2022-12-27 17:26:34 +08:00
dudaodong 49a460eef8 doc: update document and add playgound example for strutil package 2022-12-27 16:57:32 +08:00
dudaodong a58e52e53c test: add example function for strutil package 2022-12-27 15:40:51 +08:00
dudaodong b07356423f fix: update format 2022-12-26 17:57:06 +08:00
dudaodong 005dd9d2ab fix: fix word misspelling 2022-12-26 17:51:30 +08:00
dudaodong 65315dafb1 feat: add take iterator 2022-12-26 17:20:14 +08:00
dudaodong b06fb6736d feat: add reduce for iterator 2022-12-26 16:55:24 +08:00
dudaodong b9f0854950 feat: add join iterator 2022-12-26 15:58:44 +08:00
dudaodong 6a2dd328ad feat: add test for map iterator and filter iterator 2022-12-26 15:13:35 +08:00
dudaodong dd1147f6d0 feat: add Channel iterator 2022-12-26 15:02:28 +08:00
dudaodong 6da7ce64af test: add unit test for RangeIterator 2022-12-26 14:24:23 +08:00
131 changed files with 17978 additions and 8241 deletions
+912 -310
View File
File diff suppressed because it is too large Load Diff
+931 -315
View File
File diff suppressed because it is too large Load Diff
@@ -26,7 +26,7 @@ type LRUCache[K comparable, V any] struct {
length int
}
// NewLRUCache return a LRUCache pointer
// NewLRUCache creates a LRUCache pointer instance.
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
return &LRUCache[K, V]{
cache: make(map[K]*lruNode[K, V], capacity),
@@ -37,7 +37,8 @@ func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
}
}
// Get value of key from lru cache
// Get value of key from lru cache.
// Play: https://go.dev/play/p/iUynEfOP8G0
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
var value V
@@ -50,7 +51,8 @@ func (l *LRUCache[K, V]) Get(key K) (V, bool) {
return value, false
}
// Put value of key into lru cache
// Put value of key into lru cache.
// Play: https://go.dev/play/p/iUynEfOP8G0
func (l *LRUCache[K, V]) Put(key K, value V) {
node, ok := l.cache[key]
if !ok {
@@ -69,6 +71,23 @@ func (l *LRUCache[K, V]) Put(key K, value V) {
l.length = len(l.cache)
}
// Delete item from lru cache.
func (l *LRUCache[K, V]) Delete(key K) bool {
node, ok := l.cache[key]
if ok {
key := l.deleteNode(node)
delete(l.cache, key)
return true
}
return false
}
// Len returns the number of items in the cache.
func (l *LRUCache[K, V]) Len() int {
return l.length
}
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
if l.tail != nil {
l.tail.next = node
+79
View File
@@ -0,0 +1,79 @@
package algorithm
import "fmt"
func ExampleLRUCache_Put() {
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
fmt.Println(result1, ok1)
fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
// Output:
// 1 true
// 2 true
// 0 false
}
func ExampleLRUCache_Get() {
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
fmt.Println(result1, ok1)
fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
// Output:
// 1 true
// 2 true
// 0 false
}
func ExampleLRUCache_Delete() {
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
result1, ok1 := cache.Get(1)
ok2 := cache.Delete(2)
_, ok3 := cache.Get(2)
fmt.Println(result1, ok1)
fmt.Println(ok2)
fmt.Println(ok3)
// Output:
// 1 true
// true
// false
}
func ExampleLRUCache_Len() {
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
result := cache.Len()
fmt.Println(result)
// Output:
// 2
}
@@ -9,13 +9,13 @@ import (
func TestLRUCache(t *testing.T) {
asssert := internal.NewAssert(t, "TestLRUCache")
cache := NewLRUCache[int, int](2)
cache := NewLRUCache[int, int](3)
cache.Put(1, 1)
cache.Put(2, 2)
cache.Put(3, 3)
_, ok := cache.Get(0)
asssert.Equal(false, ok)
asssert.Equal(3, cache.Len())
v, ok := cache.Get(1)
asssert.Equal(true, ok)
@@ -25,12 +25,9 @@ func TestLRUCache(t *testing.T) {
asssert.Equal(true, ok)
asssert.Equal(2, v)
cache.Put(3, 3)
v, ok = cache.Get(1)
asssert.Equal(false, ok)
asssert.NotEqual(1, v)
v, ok = cache.Get(3)
ok = cache.Delete(2)
asssert.Equal(true, ok)
asssert.Equal(3, v)
_, ok = cache.Get(2)
asssert.Equal(false, ok)
}
+12 -9
View File
@@ -1,26 +1,28 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. TODO
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph.
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
// LinearSearch Simple linear search algorithm that iterates over all elements of an slice
// If a target is found, the index of the target is returned. Else the function return -1
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int {
// LinearSearch return the index of target in slice base on equal function.
// If not found return -1
// Play: https://go.dev/play/p/IsS7rgn5s3x
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int {
for i, v := range slice {
if comparator.Compare(v, target) == 0 {
if equal(v, target) {
return i
}
}
return -1
}
// BinarySearch search for target within a sorted slice, recursive call itself.
// If a target is found, the index of the target is returned. Else the function return -1
// BinarySearch return the index of target within a sorted slice, use binary search (recursive call itself).
// If not found return -1.
// Play: https://go.dev/play/p/t6MeGiUSN47
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
if highIndex < lowIndex || len(sortedSlice) == 0 {
return -1
@@ -39,8 +41,9 @@ func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, com
return midIndex
}
// BinaryIterativeSearch search for target within a sorted slice.
// If a target is found, the index of the target is returned. Else the function return -1
// BinaryIterativeSearch return the index of target within a sorted slice, use binary search (no recursive).
// If not found return -1.
// Play: https://go.dev/play/p/Anozfr8ZLH3
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
startIndex := lowIndex
endIndex := highIndex
+51
View File
@@ -0,0 +1,51 @@
package algorithm
import "fmt"
func ExampleLinearSearch() {
numbers := []int{3, 4, 5, 3, 2, 1}
equalFunc := func(a, b int) bool {
return a == b
}
result1 := LinearSearch(numbers, 3, equalFunc)
result2 := LinearSearch(numbers, 6, equalFunc)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// -1
}
func ExampleBinarySearch() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
result1 := BinarySearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := BinarySearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
func ExampleBinaryIterativeSearch() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
result1 := BinaryIterativeSearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := BinaryIterativeSearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
+11 -5
View File
@@ -6,20 +6,24 @@ import (
"github.com/duke-git/lancet/v2/internal"
)
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func TestLinearSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestLinearSearch")
comparator := &intComparator{}
asssert.Equal(4, LinearSearch(sortedNumbers, 5, comparator))
asssert.Equal(-1, LinearSearch(sortedNumbers, 9, comparator))
numbers := []int{3, 4, 5, 3, 2, 1}
equalFunc := func(a, b int) bool {
return a == b
}
asssert.Equal(0, LinearSearch(numbers, 3, equalFunc))
asssert.Equal(-1, LinearSearch(numbers, 6, equalFunc))
}
func TestBinarySearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinarySearch")
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}
@@ -27,7 +31,9 @@ func TestBinarySearch(t *testing.T) {
func TestBinaryIterativeSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinaryIterativeSearch")
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}
+16 -9
View File
@@ -1,12 +1,12 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// BubbleSort use bubble to sort slice.
// BubbleSort applys the bubble sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/GNdv7Jg2Taj
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
for j := 0; j < len(slice)-1-i; j++ {
@@ -18,7 +18,8 @@ func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) {
}
}
// InsertionSort use insertion to sort slice.
// InsertionSort applys the insertion sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/G5LJiWgJJW6
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
for j := i; j > 0; j-- {
@@ -32,7 +33,8 @@ func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
}
}
// SelectionSort use selection to sort slice.
// SelectionSort applys the selection sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/oXovbkekayS
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
min := i
@@ -45,7 +47,8 @@ func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
}
}
// ShellSort shell sort slice.
// ShellSort applys the shell sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/3ibkszpJEu3
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice)
@@ -64,7 +67,8 @@ func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
}
}
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1.
// Play: https://go.dev/play/p/7Y7c1Elk3ax
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) {
quickSort(slice, 0, len(slice)-1, comparator)
}
@@ -93,7 +97,8 @@ func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
return i
}
// HeapSort use heap to sort slice
// HeapSort applys the heap sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/u6Iwa1VZS_f
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice)
@@ -126,7 +131,8 @@ func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraint
slice[i] = temp
}
// MergeSort merge sorting for slice
// MergeSort applys the merge sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/ydinn9YzUJn
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) {
mergeSort(slice, 0, len(slice)-1, comparator)
}
@@ -167,7 +173,8 @@ func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lance
}
}
// CountSort use count sorting for slice
// CountSort applys the count sort algorithm to sort the collection, don't change the original collection data.
// Play: https://go.dev/play/p/tB-Umgm0DrP
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
out := make([]T, size)
+93
View File
@@ -0,0 +1,93 @@
package algorithm
import "fmt"
func ExampleBubbleSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
BubbleSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleCountSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedNumber := CountSort(numbers, comparator)
fmt.Println(numbers)
fmt.Println(sortedNumber)
// Output:
// [2 1 5 3 6 4]
// [1 2 3 4 5 6]
}
func ExampleHeapSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
HeapSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleMergeSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
MergeSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleInsertionSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
InsertionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleSelectionSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
SelectionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleShellSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
ShellSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
func ExampleQuickSort() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
QuickSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
+1
View File
@@ -66,6 +66,7 @@ func TestBubbleSortForStructSlice(t *testing.T) {
func TestBubbleSortForIntSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
BubbleSort(numbers, comparator)
+46 -42
View File
@@ -11,17 +11,18 @@ import (
// Channel is a logic object which can generate or manipulate go channel
// all methods of Channel are in the book tilted《Concurrency in Go》
type Channel struct {
type Channel[T any] struct {
}
// NewChannel return a Channel instance
func NewChannel() *Channel {
return &Channel{}
func NewChannel[T any]() *Channel[T] {
return &Channel[T]{}
}
// Generate a data of type any chan, put param `values` into the chan
func (c *Channel) Generate(ctx context.Context, values ...any) <-chan any {
dataStream := make(chan any)
// Generate creates channel, then put values into the channel.
// Play: https://go.dev/play/p/7aB4KyMMp9A
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T)
go func() {
defer close(dataStream)
@@ -38,9 +39,10 @@ func (c *Channel) Generate(ctx context.Context, values ...any) <-chan any {
return dataStream
}
// Repeat return a data of type any chan, put param `values` into the chan repeatly until cancel the context.
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any {
dataStream := make(chan any)
// Repeat create channel, put values into the channel repeatly until cancel the context.
// Play: https://go.dev/play/p/k5N_ALVmYjE
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T)
go func() {
defer close(dataStream)
@@ -57,10 +59,11 @@ func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any {
return dataStream
}
// RepeatFn return a chan, excutes fn repeatly, and put the result into retruned chan
// until close the `done` channel
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any {
dataStream := make(chan any)
// RepeatFn create a channel, excutes fn repeatly, and put the result into the channel
// until close context.
// Play: https://go.dev/play/p/4J1zAWttP85
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T {
dataStream := make(chan T)
go func() {
defer close(dataStream)
@@ -75,9 +78,10 @@ func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any {
return dataStream
}
// Take return a chan whose values are tahken from another chan
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any {
takeStream := make(chan any)
// Take create a channel whose values are taken from another channel with limit number.
// Play: https://go.dev/play/p/9Utt-1pDr2J
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T {
takeStream := make(chan T)
go func() {
defer close(takeStream)
@@ -94,16 +98,17 @@ func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int)
return takeStream
}
// FanIn merge multiple channels into one channel
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any {
out := make(chan any)
// FanIn merge multiple channels into one channel.
// Play: https://go.dev/play/p/2VYFMexEvTm
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T {
out := make(chan T)
go func() {
var wg sync.WaitGroup
wg.Add(len(channels))
for _, c := range channels {
go func(c <-chan any) {
go func(c <-chan T) {
defer wg.Done()
for v := range c {
select {
@@ -121,10 +126,11 @@ func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
return out
}
// Tee split one chanel into two channels
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any) {
out1 := make(chan any)
out2 := make(chan any)
// Tee split one chanel into two channels, until cancel the context.
// Play: https://go.dev/play/p/3TQPKnCirrP
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) {
out1 := make(chan T)
out2 := make(chan T)
go func() {
defer close(out1)
@@ -147,15 +153,16 @@ func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan an
return out1, out2
}
// Bridge link multiply channels into one channel
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any {
valStream := make(chan any)
// Bridge link multiply channels into one channel.
// Play: https://go.dev/play/p/qmWSy1NVF-Y
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T {
valStream := make(chan T)
go func() {
defer close(valStream)
for {
var stream <-chan any
var stream <-chan T
select {
case maybeStream, ok := <-chanStream:
if !ok {
@@ -178,8 +185,9 @@ func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-ch
return valStream
}
// Or read one or more channels into one channel, will close when any readin channel is closed
func (c *Channel) Or(channels ...<-chan any) <-chan any {
// Or read one or more channels into one channel, will close when any readin channel is closed.
// Play: https://go.dev/play/p/Wqz9rwioPww
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T {
switch len(channels) {
case 0:
return nil
@@ -187,7 +195,7 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
return channels[0]
}
orDone := make(chan any)
orDone := make(chan T)
go func() {
defer close(orDone)
@@ -199,17 +207,12 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
case <-channels[1]:
}
default:
m := len(channels) / 2
select {
case <-c.Or(channels[:m]...):
case <-c.Or(channels[m:]...):
case <-channels[0]:
case <-channels[1]:
case <-channels[2]:
case <-c.Or(append(channels[3:], orDone)...):
}
// select {
// case <-channels[0]:
// case <-channels[1]:
// case <-channels[2]:
// case <-c.Or(append(channels[3:], orDone)...):
// }
}
}()
@@ -217,8 +220,9 @@ func (c *Channel) Or(channels ...<-chan any) <-chan any {
}
// OrDone read a channel into another channel, will close until cancel context.
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any {
valStream := make(chan any)
// Play: https://go.dev/play/p/lm_GoS6aDjo
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T {
valStream := make(chan T)
go func() {
defer close(valStream)
+196
View File
@@ -0,0 +1,196 @@
package concurrency
import (
"context"
"fmt"
"time"
)
func ExampleChannel_Generate() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
func ExampleChannel_Repeat() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 1
// 2
}
func ExampleChannel_RepeatFn() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() string {
return "hello"
}
c := NewChannel[string]()
intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// hello
// hello
// hello
}
func ExampleChannel_Take() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan int, 5)
numbers <- 1
numbers <- 2
numbers <- 3
numbers <- 4
numbers <- 5
defer close(numbers)
c := NewChannel[int]()
intStream := c.Take(ctx, numbers, 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
}
func ExampleChannel_FanIn() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
channels := make([]<-chan int, 2)
for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
}
chs := c.FanIn(ctx, channels...)
for v := range chs {
fmt.Println(v) //1 1 0 0 or 0 0 1 1
}
}
func ExampleChannel_Or() {
sig := func(after time.Duration) <-chan any {
c := make(chan any)
go func() {
defer close(c)
time.Sleep(after)
}()
return c
}
start := time.Now()
c := NewChannel[any]()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
)
if time.Since(start).Seconds() < 2 {
fmt.Println("ok")
}
// Output:
// ok
}
func ExampleChannel_OrDone() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for v := range c.OrDone(ctx, intStream) {
fmt.Println(v)
}
// Output:
// 1
// 1
// 1
}
func ExampleChannel_Tee() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
ch1, ch2 := c.Tee(ctx, intStream)
for v := range ch1 {
fmt.Println(v)
fmt.Println(<-ch2)
}
// Output:
// 1
// 1
// 1
// 1
}
func ExampleChannel_Bridge() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel[int]()
genVals := func() <-chan <-chan int {
out := make(chan (<-chan int))
go func() {
defer close(out)
for i := 1; i <= 5; i++ {
stream := make(chan int, 1)
stream <- i
close(stream)
out <- stream
}
}()
return out
}
for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
// 4
// 5
}
+17 -35
View File
@@ -14,12 +14,9 @@ func TestGenerate(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
c := NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
// for v := range intStream {
// t.Log(v) //1, 2, 3
// }
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(3, <-intStream)
@@ -31,12 +28,9 @@ func TestRepeat(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
// for v := range intStream {
// t.Log(v) //1, 2, 1, 2, 1
// }
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(1, <-intStream)
@@ -50,17 +44,13 @@ func TestRepeatFn(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
fn := func() string {
s := "a"
return s
}
c := NewChannel()
c := NewChannel[string]()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
// for v := range dataStream {
// t.Log(v) //a, a, a
// }
assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream)
@@ -72,7 +62,7 @@ func TestTake(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers := make(chan int, 5)
numbers <- 1
numbers <- 2
numbers <- 3
@@ -80,7 +70,7 @@ func TestTake(t *testing.T) {
numbers <- 5
defer close(numbers)
c := NewChannel()
c := NewChannel[int]()
intStream := c.Take(ctx, numbers, 3)
assert.Equal(1, <-intStream)
@@ -94,8 +84,8 @@ func TestFanIn(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
channels := make([]<-chan any, 3)
c := NewChannel[int]()
channels := make([]<-chan int, 3)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
@@ -124,7 +114,7 @@ func TestOr(t *testing.T) {
start := time.Now()
c := NewChannel()
c := NewChannel[any]()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
@@ -133,9 +123,7 @@ func TestOr(t *testing.T) {
sig(5*time.Second),
)
t.Logf("done after %v", time.Since(start))
assert.Equal(1, 1)
assert.Equal(true, time.Since(start).Seconds() < 2)
}
func TestOrDone(t *testing.T) {
@@ -144,16 +132,12 @@ func TestOrDone(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
c := NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
var res any
for val := range c.OrDone(ctx, intStream) {
t.Logf("%v", val)
res = val
assert.Equal(1, val)
}
assert.Equal(1, res)
}
func TestTee(t *testing.T) {
@@ -162,15 +146,13 @@ func TestTee(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
c := NewChannel[int]()
inStream := c.Take(ctx, c.Repeat(ctx, 1), 4)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
val1 := val
val2 := <-out2
// t.Log("val1 is", val1)
// t.Log("val2 is", val2)
assert.Equal(1, val1)
assert.Equal(1, val2)
}
@@ -182,13 +164,13 @@ func TestBridge(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
c := NewChannel[int]()
genVals := func() <-chan <-chan int {
chanStream := make(chan (<-chan int))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
stream := make(chan int, 1)
stream <- i
close(stream)
chanStream <- stream
+14 -6
View File
@@ -13,6 +13,7 @@ import "reflect"
// If the type has an IsZero() bool method, the opposite value is returned.
// Slices and maps are truthy if they have a length greater than zero.
// All other types are truthy if they are not their zero value.
// Play: https://go.dev/play/p/ETzeDJRSvhm
func Bool[T any](value T) bool {
switch m := any(value).(type) {
case interface{ Bool() bool }:
@@ -34,40 +35,47 @@ func reflectValue(vp any) bool {
}
// And returns true if both a and b are truthy.
// Play: https://go.dev/play/p/W1SSUmt6pvr
func And[T, U any](a T, b U) bool {
return Bool(a) && Bool(b)
}
// Or returns false iff neither a nor b is truthy.
// Or returns false if neither a nor b is truthy.
// Play: https://go.dev/play/p/UlQTxHaeEkq
func Or[T, U any](a T, b U) bool {
return Bool(a) || Bool(b)
}
// Xor returns true iff a or b but not both is truthy.
// Xor returns true if a or b but not both is truthy.
// Play: https://go.dev/play/p/gObZrW7ZbG8
func Xor[T, U any](a T, b U) bool {
valA := Bool(a)
valB := Bool(b)
return (valA || valB) && valA != valB
}
// Nor returns true iff neither a nor b is truthy.
// Nor returns true if neither a nor b is truthy.
// Play: https://go.dev/play/p/g2j08F_zZky
func Nor[T, U any](a T, b U) bool {
return !(Bool(a) || Bool(b))
}
// Xnor returns true iff both a and b or neither a nor b are truthy.
// Xnor returns true if both a and b or neither a nor b are truthy.
// Play: https://go.dev/play/p/OuDB9g51643
func Xnor[T, U any](a T, b U) bool {
valA := Bool(a)
valB := Bool(b)
return (valA && valB) || (!valA && !valB)
}
// Nand returns false iff both a and b are truthy.
// Nand returns false if both a and b are truthy.
// Play: https://go.dev/play/p/vSRMLxLIbq8
func Nand[T, U any](a T, b U) bool {
return !Bool(a) || !Bool(b)
}
// TernaryOperator checks the value of param `isTrue`, if true return ifValue else return elseValue
// TernaryOperator checks the value of param `isTrue`, if true return ifValue else return elseValue.
// Play: https://go.dev/play/p/ElllPZY0guT
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U {
if Bool(isTrue) {
return ifValue
+163
View File
@@ -0,0 +1,163 @@
package condition
import "fmt"
func ExampleBool() {
// bool
result1 := Bool(false)
result2 := Bool(true)
fmt.Println(result1)
fmt.Println(result2)
// integer
result3 := Bool(0)
result4 := Bool(1)
fmt.Println(result3)
fmt.Println(result4)
// string
result5 := Bool("")
result6 := Bool(" ")
fmt.Println(result5)
fmt.Println(result6)
// slice
var nums = []int{}
result7 := Bool(nums)
nums = append(nums, 1, 2)
result8 := Bool(nums)
fmt.Println(result7)
fmt.Println(result8)
// Output:
// false
// true
// false
// true
// false
// true
// false
// true
}
func ExampleAnd() {
result1 := And(0, 1)
result2 := And(0, "")
result3 := And(0, "0")
result4 := And(1, "0")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// false
// true
}
func ExampleOr() {
result1 := Or(0, "")
result2 := Or(0, 1)
result3 := Or(0, "0")
result4 := Or(1, "0")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// true
// true
// true
}
func ExampleXor() {
result1 := Xor(0, 0)
result2 := Xor(1, 1)
result3 := Xor(0, 1)
result4 := Xor(1, 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// true
// true
}
func ExampleNor() {
result1 := Nor(0, 0)
result2 := Nor(1, 1)
result3 := Nor(0, 1)
result4 := Nor(1, 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// false
// false
// false
}
func ExampleXnor() {
result1 := Xnor(0, 0)
result2 := Xnor(1, 1)
result3 := Xnor(0, 1)
result4 := Xnor(1, 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// false
// false
}
func ExampleNand() {
result1 := Nand(0, 0)
result2 := Nand(1, 0)
result3 := Nand(0, 1)
result4 := Nand(1, 1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
func ExampleTernaryOperator() {
conditionTrue := 2 > 1
result1 := TernaryOperator(conditionTrue, 0, 1)
fmt.Println(result1)
conditionFalse := 2 > 3
result2 := TernaryOperator(conditionFalse, 0, 1)
fmt.Println(result2)
// Output:
// 0
// 1
}
+33 -17
View File
@@ -17,12 +17,14 @@ import (
"strings"
)
// ToBool convert string to a boolean
// ToBool convert string to boolean.
// Play: https://go.dev/play/p/ARht2WnGdIN
func ToBool(s string) (bool, error) {
return strconv.ParseBool(s)
}
// ToBytes convert interface to bytes
// ToBytes convert value to byte slice.
// Play: https://go.dev/play/p/fAMXYFDvOvr
func ToBytes(value any) ([]byte, error) {
v := reflect.ValueOf(value)
@@ -63,7 +65,8 @@ func ToBytes(value any) ([]byte, error) {
}
}
// ToChar convert string to char slice
// ToChar convert string to char slice.
// Play: https://go.dev/play/p/JJ1SvbFkVdM
func ToChar(s string) []string {
c := make([]string, 0)
if len(s) == 0 {
@@ -75,7 +78,8 @@ func ToChar(s string) []string {
return c
}
// ToChannel convert a array of elements to a read-only channels
// ToChannel convert a slice of elements to a read-only channel.
// Play: https://go.dev/play/p/hOx_oYZbAnL
func ToChannel[T any](array []T) <-chan T {
ch := make(chan T)
@@ -91,7 +95,8 @@ func ToChannel[T any](array []T) <-chan T {
// ToString convert value to string
// for number, string, []byte, will convert to string
// for other type (slice, map, array, struct) will call json.Marshal
// for other type (slice, map, array, struct) will call json.Marshal.
// Play: https://go.dev/play/p/nF1zOOslpQq
func ToString(value any) string {
if value == nil {
return ""
@@ -140,7 +145,8 @@ func ToString(value any) string {
}
}
// ToJson convert value to a valid json string
// ToJson convert value to a json string.
// Play: https://go.dev/play/p/2rLIkMmXWvR
func ToJson(value any) (string, error) {
result, err := json.Marshal(value)
if err != nil {
@@ -150,7 +156,8 @@ func ToJson(value any) (string, error) {
return string(result), nil
}
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
// ToFloat convert value to float64, if input is not a float return 0.0 and error.
// Play: https://go.dev/play/p/4YTmPCibqHJ
func ToFloat(value any) (float64, error) {
v := reflect.ValueOf(value)
@@ -177,12 +184,13 @@ func ToFloat(value any) (float64, error) {
}
}
// ToInt convert value to a int64, if input is not a numeric format return 0 and error
// ToInt convert value to int64 value, if input is not numerical, return 0 and error.
// Play: https://go.dev/play/p/9_h9vIt-QZ_b
func ToInt(value any) (int64, error) {
v := reflect.ValueOf(value)
var result int64
err := fmt.Errorf("ToInt: invalid interface type %T", value)
err := fmt.Errorf("ToInt: invalid value type %T", value)
switch value.(type) {
case int, int8, int16, int32, int64:
result = v.Int()
@@ -204,12 +212,14 @@ func ToInt(value any) (int64, error) {
}
}
// ToPointer returns a pointer to this value
// ToPointer returns a pointer to passed value.
// Play: https://go.dev/play/p/ASf_etHNlw1
func ToPointer[T any](value T) *T {
return &value
}
// ToMap convert a slice or an array of structs to a map based on iteratee function
// ToMap convert a slice of structs to a map based on iteratee function.
// Play: https://go.dev/play/p/tVFy7E-t24l
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
result := make(map[K]V, len(array))
for _, item := range array {
@@ -221,7 +231,8 @@ func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K
}
// StructToMap convert struct to map, only convert exported struct field
// map key is specified same as struct field tag `json` value
// map key is specified same as struct field tag `json` value.
// Play: https://go.dev/play/p/KYGYJqNUBOI
func StructToMap(value any) (map[string]any, error) {
v := reflect.ValueOf(value)
t := reflect.TypeOf(value)
@@ -250,7 +261,8 @@ func StructToMap(value any) (map[string]any, error) {
return result, nil
}
// MapToSlice convert a map to a slice based on iteratee function
// MapToSlice convert map to slice based on iteratee function.
// Play: https://go.dev/play/p/dmX4Ix5V6Wl
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T {
result := make([]T, 0, len(aMap))
@@ -261,7 +273,8 @@ func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T)
return result
}
// ColorHexToRGB convert hex color to rgb color
// ColorHexToRGB convert hex color to rgb color.
// Play: https://go.dev/play/p/o7_ft-JCJBV
func ColorHexToRGB(colorHex string) (red, green, blue int) {
colorHex = strings.TrimPrefix(colorHex, "#")
color64, err := strconv.ParseInt(colorHex, 16, 32)
@@ -272,7 +285,8 @@ func ColorHexToRGB(colorHex string) (red, green, blue int) {
return color >> 16, (color & 0x00FF00) >> 8, color & 0x0000FF
}
// ColorRGBToHex convert rgb color to hex color
// ColorRGBToHex convert rgb color to hex color.
// Play: https://go.dev/play/p/nzKS2Ro87J1
func ColorRGBToHex(red, green, blue int) string {
r := strconv.FormatInt(int64(red), 16)
g := strconv.FormatInt(int64(green), 16)
@@ -291,7 +305,8 @@ func ColorRGBToHex(red, green, blue int) string {
return "#" + r + g + b
}
// EncodeByte encode data to byte
// EncodeByte encode data to byte slice.
// Play: https://go.dev/play/p/DVmM1G5JfuP
func EncodeByte(data any) ([]byte, error) {
buffer := bytes.NewBuffer(nil)
encoder := gob.NewEncoder(buffer)
@@ -302,7 +317,8 @@ func EncodeByte(data any) ([]byte, error) {
return buffer.Bytes(), nil
}
// DecodeByte decode byte data to target object
// DecodeByte decode byte slice data to target object.
// Play: https://go.dev/play/p/zI6xsmuQRbn
func DecodeByte(data []byte, target any) error {
buffer := bytes.NewBuffer(data)
decoder := gob.NewDecoder(buffer)
+254
View File
@@ -0,0 +1,254 @@
package convertor
import (
"fmt"
"strconv"
)
func ExampleToBool() {
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
for i := 0; i < len(cases); i++ {
result, _ := ToBool(cases[i])
fmt.Println(result)
}
// Output:
// true
// true
// true
// false
// false
// false
// false
// false
// false
}
func ExampleToBytes() {
result1, _ := ToBytes(1)
result2, _ := ToBytes("abc")
result3, _ := ToBytes(true)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// [0 0 0 0 0 0 0 1]
// [97 98 99]
// [116 114 117 101]
}
func ExampleToChar() {
result1 := ToChar("")
result2 := ToChar("abc")
result3 := ToChar("1 2#3")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// []
// [a b c]
// [1 2 # 3]
}
func ExampleToChannel() {
ch := ToChannel([]int{1, 2, 3})
result1 := <-ch
result2 := <-ch
result3 := <-ch
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 3
}
func ExampleToString() {
result1 := ToString("")
result2 := ToString(nil)
result3 := ToString(0)
result4 := ToString(1.23)
result5 := ToString(true)
result6 := ToString(false)
result7 := ToString([]int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
//
//
// 0
// 1.23
// true
// false
// [1,2,3]
}
func ExampleToJson() {
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
result1, err := ToJson(aMap)
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(result1)
// Output:
// {"a":1,"b":2,"c":3}
}
func ExampleToFloat() {
result1, _ := ToFloat("")
result2, _ := ToFloat("abc")
result3, _ := ToFloat("-1")
result4, _ := ToFloat("-.11")
result5, _ := ToFloat("1.23e3")
result6, _ := ToFloat(true)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// 0
// 0
// -1
// -0.11
// 1230
// 0
}
func ExampleToInt() {
result1, _ := ToInt("123")
result2, _ := ToInt("-123")
result3, _ := ToInt(float64(12.3))
result4, _ := ToInt("abc")
result5, _ := ToInt(true)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 123
// -123
// 12
// 0
// 0
}
func ExampleToPointer() {
result := ToPointer(123)
fmt.Println(*result)
// Output:
// 123
}
func ExampleToMap() {
type Message struct {
name string
code int
}
messages := []Message{
{name: "Hello", code: 100},
{name: "Hi", code: 101},
}
result := ToMap(messages, func(msg Message) (int, string) {
return msg.code, msg.name
})
fmt.Println(result)
// Output:
// map[100:Hello 101:Hi]
}
func ExampleStructToMap() {
type People struct {
Name string `json:"name"`
age int
}
p := People{
"test",
100,
}
pm, _ := StructToMap(p)
fmt.Println(pm)
// Output:
// map[name:test]
}
func ExampleMapToSlice() {
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
result := MapToSlice(aMap, func(key string, value int) string {
return key + ":" + strconv.Itoa(value)
})
fmt.Println(result) //[]string{"a:1", "c:3", "b:2"} (random order)
}
func ExampleColorHexToRGB() {
colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex)
fmt.Println(r, g, b)
// Output:
// 0 51 102
}
func ExampleColorRGBToHex() {
r := 0
g := 51
b := 102
colorHex := ColorRGBToHex(r, g, b)
fmt.Println(colorHex)
// Output:
// #003366
}
func ExampleEncodeByte() {
byteData, _ := EncodeByte("abc")
fmt.Println(byteData)
// Output:
// [6 12 0 3 97 98 99]
}
func ExampleDecodeByte() {
var obj string
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
err := DecodeByte(byteData, &obj)
if err != nil {
return
}
fmt.Println(obj)
// Output:
// abc
}
-186
View File
@@ -1,186 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
// Note:
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
package cryptor
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
)
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32
func AesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := aes.NewCipher(generateAesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32
func AesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := aes.NewCipher(generateAesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32
func AesCbcEncrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32
func AesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// AesCtrCrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32
func AesCtrCrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
// len(key) should be 16, 24 or 32
func AesCfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
func AesCfbDecrypt(encrypted, key []byte) []byte {
if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short")
}
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32
func AesOfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, aes.BlockSize)
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32
func AesOfbDecrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:aes.BlockSize]
data = data[aes.BlockSize:]
if len(data)%aes.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
-62
View File
@@ -1,62 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestAesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
assert.Equal(data, string(aesEcbDecrypt))
}
func TestAesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
assert.Equal(data, string(aesCbcDecrypt))
}
func TestAesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCtrCrypt")
assert.Equal(data, string(aesCtrDeCrypt))
}
func TestAesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
assert.Equal(data, string(aesCfbDecrypt))
}
func TestAesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
assert.Equal(data, string(aesOfbDecrypt))
}
+21 -11
View File
@@ -19,25 +19,28 @@ import (
"os"
)
// Base64StdEncode encode string with base64 encoding
// Base64StdEncode encode string with base64 encoding.
// Play: https://go.dev/play/p/VOaUyQUreoK
func Base64StdEncode(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
}
// Base64StdDecode decode a base64 encoded string
// Base64StdDecode decode a base64 encoded string.
// Play: https://go.dev/play/p/RWQylnJVgIe
func Base64StdDecode(s string) string {
b, _ := base64.StdEncoding.DecodeString(s)
return string(b)
}
// Md5String return the md5 value of string
// Md5String return the md5 value of string.
// Play: https://go.dev/play/p/1bLcVetbTOI
func Md5String(s string) string {
h := md5.New()
h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil))
}
// Md5File return the md5 value of file
// Md5File return the md5 value of file.
func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil {
return "", err
@@ -69,49 +72,56 @@ func Md5File(filename string) (string, error) {
return checksum, nil
}
// HmacMd5 return the hmac hash of string use md5
// HmacMd5 return the hmac hash of string use md5.
// Play: https://go.dev/play/p/uef0q1fz53I
func HmacMd5(data, key string) string {
h := hmac.New(md5.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha1 return the hmac hash of string use sha1
// HmacSha1 return the hmac hash of string use sha1.
// Play: https://go.dev/play/p/1UI4oQ4WXKM
func HmacSha1(data, key string) string {
h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha256 return the hmac hash of string use sha256
// HmacSha256 return the hmac hash of string use sha256.
// Play: https://go.dev/play/p/HhpwXxFhhC0
func HmacSha256(data, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha512 return the hmac hash of string use sha512
// HmacSha512 return the hmac hash of string use sha512.
// Play: https://go.dev/play/p/59Od6m4A0Ud
func HmacSha512(data, key string) string {
h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte("")))
}
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
// Play: https://go.dev/play/p/_m_uoD1deMT
func Sha1(data string) string {
sha1 := sha1.New()
sha1.Write([]byte(data))
return hex.EncodeToString(sha1.Sum([]byte("")))
}
// Sha256 return the sha256 value (SHA256 hash algorithm) of string
// Sha256 return the sha256 value (SHA256 hash algorithm) of string.
// Play: https://go.dev/play/p/tU9tfBMIAr1
func Sha256(data string) string {
sha256 := sha256.New()
sha256.Write([]byte(data))
return hex.EncodeToString(sha256.Sum([]byte("")))
}
// Sha512 return the sha512 value (SHA512 hash algorithm) of string
// Sha512 return the sha512 value (SHA512 hash algorithm) of string.
// Play: https://go.dev/play/p/3WsvLYZxsHa
func Sha512(data string) string {
sha512 := sha512.New()
sha512.Write([]byte(data))
+410
View File
@@ -0,0 +1,410 @@
package cryptor
import "fmt"
func ExampleAesEcbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesEcbEncrypt([]byte(data), []byte(key))
decrypted := AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesEcbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesEcbEncrypt([]byte(data), []byte(key))
decrypted := AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCbcEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCbcEncrypt([]byte(data), []byte(key))
decrypted := AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCbcDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCbcEncrypt([]byte(data), []byte(key))
decrypted := AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCtrCrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCtrCrypt([]byte(data), []byte(key))
decrypted := AesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCfbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCfbEncrypt([]byte(data), []byte(key))
decrypted := AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCfbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCfbEncrypt([]byte(data), []byte(key))
decrypted := AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesOfbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesOfbEncrypt([]byte(data), []byte(key))
decrypted := AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesOfbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesOfbEncrypt([]byte(data), []byte(key))
decrypted := AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesEcbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesEcbEncrypt([]byte(data), []byte(key))
decrypted := DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesEcbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesEcbEncrypt([]byte(data), []byte(key))
decrypted := DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCbcEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCbcEncrypt([]byte(data), []byte(key))
decrypted := DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCbcDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCbcEncrypt([]byte(data), []byte(key))
decrypted := DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCtrCrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCtrCrypt([]byte(data), []byte(key))
decrypted := DesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCfbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCfbEncrypt([]byte(data), []byte(key))
decrypted := DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCfbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCfbEncrypt([]byte(data), []byte(key))
decrypted := DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesOfbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesOfbEncrypt([]byte(data), []byte(key))
decrypted := DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesOfbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesOfbEncrypt([]byte(data), []byte(key))
decrypted := DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleGenerateRsaKey() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
fmt.Println("foo")
// Output:
// foo
}
func ExampleRsaEncrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleRsaDecrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleBase64StdEncode() {
base64Str := Base64StdEncode("hello")
fmt.Println(base64Str)
// Output:
// aGVsbG8=
}
func ExampleBase64StdDecode() {
str := Base64StdDecode("aGVsbG8=")
fmt.Println(str)
// Output:
// hello
}
func ExampleHmacMd5() {
str := "hello"
key := "12345"
hms := HmacMd5(str, key)
fmt.Println(hms)
// Output:
// e834306eab892d872525d4918a7a639a
}
func ExampleHmacSha1() {
str := "hello"
key := "12345"
hms := HmacSha1(str, key)
fmt.Println(hms)
// Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
func ExampleHmacSha256() {
str := "hello"
key := "12345"
hms := HmacSha256(str, key)
fmt.Println(hms)
// Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
}
func ExampleHmacSha512() {
str := "hello"
key := "12345"
hms := HmacSha512(str, key)
fmt.Println(hms)
// Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
}
func ExampleMd5String() {
str := "hello"
md5Str := Md5String(str)
fmt.Println(md5Str)
// Output:
// 5d41402abc4b2a76b9719d911017c592
}
func ExampleSha1() {
str := "hello"
result := Sha1(str)
fmt.Println(result)
// Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
}
func ExampleSha256() {
str := "hello"
result := Sha256(str)
fmt.Println(result)
// Output:
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
}
func ExampleSha512() {
str := "hello"
result := Sha512(str)
fmt.Println(result)
// Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
}
-180
View File
@@ -1,180 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
package cryptor
import (
"bytes"
"crypto/cipher"
"crypto/des"
"crypto/rand"
"io"
)
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
// len(key) should be 8
func DesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + des.BlockSize) / des.BlockSize
plain := make([]byte, length*des.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := des.NewCipher(generateDesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
// len(key) should be 8
func DesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := des.NewCipher(generateDesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
// len(key) should be 8
func DesCbcEncrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
// len(key) should be 8
func DesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// DesCtrCrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8
func DesCtrCrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
// len(key) should be 8
func DesCfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 8
func DesCfbDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
if len(encrypted) < des.BlockSize {
panic("encrypted data is too short")
}
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 16, 24 or 32
func DesOfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, des.BlockSize)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
// len(key) should be 8
func DesOfbDecrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:des.BlockSize]
data = data[des.BlockSize:]
if len(data)%des.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
-62
View File
@@ -1,62 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestDesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
assert.Equal(data, string(desEcbDecrypt))
}
func TestDesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
assert.Equal(data, string(desCbcDecrypt))
}
func TestDesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCtrCrypt")
assert.Equal(data, string(desCtrDeCrypt))
}
func TestDesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
assert.Equal(data, string(desCfbDecrypt))
}
func TestDesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
assert.Equal(data, string(desOfbDecrypt))
}
+498
View File
@@ -0,0 +1,498 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
// Note:
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
package cryptor
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"io"
"os"
)
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := aes.NewCipher(generateAesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := aes.NewCipher(generateAesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcEncrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// AesCtrCrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/SpaZO0-5Nsp
func AesCtrCrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbDecrypt(encrypted, key []byte) []byte {
if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short")
}
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, aes.BlockSize)
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbDecrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:aes.BlockSize]
data = data[aes.BlockSize:]
if len(data)%aes.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + des.BlockSize) / des.BlockSize
plain := make([]byte, length*des.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := des.NewCipher(generateDesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := des.NewCipher(generateDesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcEncrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// DesCtrCrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/9-T6OjKpcdw
func DesCtrCrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
if len(encrypted) < des.BlockSize {
panic("encrypted data is too short")
}
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, des.BlockSize)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbDecrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:des.BlockSize]
data = data[des.BlockSize:]
if len(data)%des.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
// GenerateRsaKey create rsa private and public pemo file.
// Play: https://go.dev/play/p/zutRHrDqs0X
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
// private key
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
return err
}
derText := x509.MarshalPKCS1PrivateKey(privateKey)
block := pem.Block{
Type: "rsa private key",
Bytes: derText,
}
file, err := os.Create(priKeyFile)
if err != nil {
panic(err)
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
// public key
publicKey := privateKey.PublicKey
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return err
}
block = pem.Block{
Type: "rsa public key",
Bytes: derpText,
}
file, err = os.Create(pubKeyFile)
if err != nil {
return err
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
return nil
}
// RsaEncrypt encrypt data with ras algorithm.
// Play: https://go.dev/play/p/rDqTT01SPkZ
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
file, err := os.Open(pubKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
defer file.Close()
buf := make([]byte, fileInfo.Size())
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
pubKey := pubInterface.(*rsa.PublicKey)
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
if err != nil {
panic(err)
}
return cipherText
}
// RsaDecrypt decrypt data with ras algorithm.
// Play: https://go.dev/play/p/rDqTT01SPkZ
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
file, err := os.Open(privateKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, fileInfo.Size())
defer file.Close()
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
if err != nil {
panic(err)
}
return plainText
}
+130
View File
@@ -0,0 +1,130 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestAesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
assert.Equal(data, string(aesEcbDecrypt))
}
func TestAesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
assert.Equal(data, string(aesCbcDecrypt))
}
func TestAesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCtrCrypt")
assert.Equal(data, string(aesCtrDeCrypt))
}
func TestAesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
assert.Equal(data, string(aesCfbDecrypt))
}
func TestAesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
assert.Equal(data, string(aesOfbDecrypt))
}
func TestDesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
assert.Equal(data, string(desEcbDecrypt))
}
func TestDesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
assert.Equal(data, string(desCbcDecrypt))
}
func TestDesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCtrCrypt")
assert.Equal(data, string(desCtrDeCrypt))
}
func TestDesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
assert.Equal(data, string(desCfbDecrypt))
}
func TestDesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
assert.Equal(data, string(desOfbDecrypt))
}
func TestRsaEncrypt(t *testing.T) {
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
t.FailNow()
}
data := []byte("hello world")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted))
}
-134
View File
@@ -1,134 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
package cryptor
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
// GenerateRsaKey make a rsa private key, and return key file name
// Generated key file is `rsa_private.pem` and `rsa_public.pem` in current path
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
// private key
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
return err
}
derText := x509.MarshalPKCS1PrivateKey(privateKey)
block := pem.Block{
Type: "rsa private key",
Bytes: derText,
}
//file,err := os.Create("rsa_private.pem")
file, err := os.Create(priKeyFile)
if err != nil {
panic(err)
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
// public key
publicKey := privateKey.PublicKey
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return err
}
block = pem.Block{
Type: "rsa public key",
Bytes: derpText,
}
file, err = os.Create(pubKeyFile)
if err != nil {
return err
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
return nil
}
// RsaEncrypt encrypt data with ras algorithm
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
file, err := os.Open(pubKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
defer file.Close()
buf := make([]byte, fileInfo.Size())
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
pubKey := pubInterface.(*rsa.PublicKey)
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
if err != nil {
panic(err)
}
return cipherText
}
// RsaDecrypt decrypt data with ras algorithm
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
file, err := os.Open(privateKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, fileInfo.Size())
defer file.Close()
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
if err != nil {
panic(err)
}
return plainText
}
-20
View File
@@ -1,20 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestRsaEncrypt(t *testing.T) {
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
t.FailNow()
}
data := []byte("hello world")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted))
}
+119 -26
View File
@@ -6,19 +6,21 @@ package datastructure
import (
"reflect"
"github.com/duke-git/lancet/v2/iterator"
)
// List is a linear table, implemented with slice
// List is a linear table, implemented with slice.
type List[T any] struct {
data []T
}
// NewList return a pointer of List
// NewList return a pointer of List.
func NewList[T any](data []T) *List[T] {
return &List[T]{data: data}
}
// Data return list data
// Data return list data.
func (l *List[T]) Data() []T {
return l.data
}
@@ -31,7 +33,7 @@ func (l *List[T]) ValueOf(index int) (*T, bool) {
return &l.data[index], true
}
// IndexOf returns the index of value. if not found return -1
// IndexOf returns the index of value. if not found return -1.
func (l *List[T]) IndexOf(value T) int {
index := -1
data := l.data
@@ -45,7 +47,7 @@ func (l *List[T]) IndexOf(value T) int {
}
// LastIndexOf returns the index of the last occurrence of the value in this list.
// if not found return -1
// if not found return -1.
func (l *List[T]) LastIndexOf(value T) int {
index := -1
data := l.data
@@ -59,7 +61,7 @@ func (l *List[T]) LastIndexOf(value T) int {
}
// IndexOfFunc returns the first index satisfying f(v)
// if not found return -1
// if not found return -1.
func (l *List[T]) IndexOfFunc(f func(T) bool) int {
index := -1
data := l.data
@@ -73,7 +75,7 @@ func (l *List[T]) IndexOfFunc(f func(T) bool) int {
}
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying f(data[i])
// if not found return -1
// if not found return -1.
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int {
index := -1
data := l.data
@@ -86,7 +88,7 @@ func (l *List[T]) LastIndexOfFunc(f func(T) bool) int {
return index
}
// Contain checks if the value in the list or not
// Contain checks if the value in the list or not.
func (l *List[T]) Contain(value T) bool {
data := l.data
for _, v := range data {
@@ -97,22 +99,22 @@ func (l *List[T]) Contain(value T) bool {
return false
}
// Push append value to the list data
// Push append value to the list data.
func (l *List[T]) Push(value T) {
l.data = append(l.data, value)
}
// InsertAtFirst insert value into list at first index
// InsertAtFirst insert value into list at first index.
func (l *List[T]) InsertAtFirst(value T) {
l.InsertAt(0, value)
}
// InsertAtLast insert value into list at last index
// InsertAtLast insert value into list at last index.
func (l *List[T]) InsertAtLast(value T) {
l.InsertAt(len(l.data), value)
}
// InsertAt insert value into list at index
// InsertAt insert value into list at index.
func (l *List[T]) InsertAt(index int, value T) {
data := l.data
size := len(data)
@@ -123,7 +125,7 @@ func (l *List[T]) InsertAt(index int, value T) {
l.data = append(data[:index], append([]T{value}, data[index:]...)...)
}
// PopFirst delete the first value of list and return it
// PopFirst delete the first value of list and return it.
func (l *List[T]) PopFirst() (*T, bool) {
if len(l.data) == 0 {
return nil, false
@@ -135,7 +137,7 @@ func (l *List[T]) PopFirst() (*T, bool) {
return &v, true
}
// PopLast delete the last value of list and return it
// PopLast delete the last value of list and return it.
func (l *List[T]) PopLast() (*T, bool) {
size := len(l.data)
if size == 0 {
@@ -148,7 +150,7 @@ func (l *List[T]) PopLast() (*T, bool) {
return &v, true
}
// DeleteAt delete the value of list at index
// DeleteAt delete the value of list at index.
func (l *List[T]) DeleteAt(index int) {
data := l.data
size := len(data)
@@ -199,7 +201,7 @@ func (l *List[T]) UpdateAt(index int, value T) {
l.data = append(data[:index], append([]T{value}, data[index+1:]...)...)
}
// Equal compare list to other list, use reflect.DeepEqual
// Equal compare list to other list, use reflect.DeepEqual.
func (l *List[T]) Equal(other *List[T]) bool {
if len(l.data) != len(other.data) {
return false
@@ -214,17 +216,17 @@ func (l *List[T]) Equal(other *List[T]) bool {
return true
}
// IsEmpty check if the list is empty or not
// IsEmpty check if the list is empty or not.
func (l *List[T]) IsEmpty() bool {
return len(l.data) == 0
}
// Clear the data of list
// Clear the data of list.
func (l *List[T]) Clear() {
l.data = make([]T, 0)
}
// Clone return a copy of list
// Clone return a copy of list.
func (l *List[T]) Clone() *List[T] {
cl := NewList(make([]T, len(l.data)))
copy(cl.data, l.data)
@@ -232,7 +234,7 @@ func (l *List[T]) Clone() *List[T] {
return cl
}
// Merge two list, return new list, don't change original list
// Merge two list, return new list, don't change original list.
func (l *List[T]) Merge(other *List[T]) *List[T] {
l1, l2 := len(l.data), len(other.data)
ml := NewList(make([]T, l1+l2))
@@ -243,17 +245,17 @@ func (l *List[T]) Merge(other *List[T]) *List[T] {
return ml
}
// Size return number of list data items
// Size return number of list data items.
func (l *List[T]) Size() int {
return len(l.data)
}
// Cap return cap of the inner data
// Cap return cap of the inner data.
func (l *List[T]) Cap() int {
return cap(l.data)
}
// Swap the value of index i and j in list
// Swap the value of index i and j in list.
func (l *List[T]) Swap(i, j int) {
size := len(l.data)
if i < 0 || i >= size || j < 0 || j >= size {
@@ -262,14 +264,14 @@ func (l *List[T]) Swap(i, j int) {
l.data[i], l.data[j] = l.data[j], l.data[i]
}
// Reverse the item order of list
// Reverse the item order of list.
func (l *List[T]) Reverse() {
for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 {
l.data[i], l.data[j] = l.data[j], l.data[i]
}
}
// Unique remove duplicate items in list
// Unique remove duplicate items in list.
func (l *List[T]) Unique() {
data := l.data
size := len(data)
@@ -303,7 +305,7 @@ func (l *List[T]) Union(other *List[T]) *List[T] {
return result
}
// Intersection creates a new list whose element both be contained in list l and other
// Intersection creates a new list whose element both be contained in list l and other.
func (l *List[T]) Intersection(other *List[T]) *List[T] {
result := NewList(make([]T, 0))
@@ -316,6 +318,43 @@ func (l *List[T]) Intersection(other *List[T]) *List[T] {
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.
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
data := l.data[fromIndex:toIndex]
@@ -323,3 +362,57 @@ func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
copy(subList, data)
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
}
+103
View File
@@ -328,6 +328,28 @@ func TestIntersection(t *testing.T) {
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) {
assert := internal.NewAssert(t, "TestSubSlice")
@@ -357,3 +379,84 @@ func TestDeleteIf(t *testing.T) {
assert.Equal([]int{2, 3, 4}, list.Data())
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)
}
+16 -8
View File
@@ -9,17 +9,20 @@ type theTime struct {
unix int64
}
// NewUnixNow return unix timestamp of current time
// NewUnixNow return unix timestamp of current time.
// Play: https://go.dev/play/p/U4PPx-9D0oz
func NewUnixNow() *theTime {
return &theTime{unix: time.Now().Unix()}
}
// NewUnix return unix timestamp of specified time
// NewUnix return unix timestamp of specified time.
// Play: https://go.dev/play/p/psoSuh_kLRt
func NewUnix(unix int64) *theTime {
return &theTime{unix: unix}
}
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss"
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".
// Play: https://go.dev/play/p/VkW08ZOaXPZ
func NewFormat(t string) (*theTime, error) {
timeLayout := "2006-01-02 15:04:05"
loc := time.FixedZone("CST", 8*3600)
@@ -30,7 +33,8 @@ func NewFormat(t string) (*theTime, error) {
return &theTime{unix: tt.Unix()}, nil
}
// NewISO8601 return unix timestamp of specified iso8601 time string
// NewISO8601 return unix timestamp of specified iso8601 time string.
// Play: https://go.dev/play/p/mkhOHQkdeA2
func NewISO8601(iso8601 string) (*theTime, error) {
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
if err != nil {
@@ -39,22 +43,26 @@ func NewISO8601(iso8601 string) (*theTime, error) {
return &theTime{unix: t.Unix()}, nil
}
// ToUnix return unix timestamp
// ToUnix return unix timestamp.
// Play: https://go.dev/play/p/_LUiwAdocjy
func (t *theTime) ToUnix() int64 {
return t.unix
}
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time.
// Play: https://go.dev/play/p/VkW08ZOaXPZ
func (t *theTime) ToFormat() string {
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
}
// ToFormatForTpl return the time string which format is specified tpl
// ToFormatForTpl return the time string which format is specified tpl.
// Play: https://go.dev/play/p/nyXxXcQJ8L5
func (t *theTime) ToFormatForTpl(tpl string) string {
return time.Unix(t.unix, 0).Format(tpl)
}
// ToFormatForTpl return iso8601 time string
// ToFormatForTpl return iso8601 time string.
// Play: https://go.dev/play/p/mkhOHQkdeA2
func (t *theTime) ToIso8601() string {
return time.Unix(t.unix, 0).Format(time.RFC3339)
}
-3
View File
@@ -19,9 +19,6 @@ func TestToUnix(t *testing.T) {
func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
+44 -22
View File
@@ -54,54 +54,64 @@ func init() {
}
}
// AddMinute add or sub minute to the time
// AddMinute add or sub minute to the time.
// Play: https://go.dev/play/p/nT1heB1KUUK
func AddMinute(t time.Time, minute int64) time.Time {
return t.Add(time.Minute * time.Duration(minute))
}
// AddHour add or sub hour to the time
// AddHour add or sub hour to the time.
// Play: https://go.dev/play/p/rcMjd7OCsi5
func AddHour(t time.Time, hour int64) time.Time {
return t.Add(time.Hour * time.Duration(hour))
}
// AddDay add or sub day to the time
// AddDay add or sub day to the time.
// Play: https://go.dev/play/p/dIGbs_uTdFa
func AddDay(t time.Time, day int64) time.Time {
return t.Add(24 * time.Hour * time.Duration(day))
}
// GetNowDate return format yyyy-mm-dd of current date
// GetNowDate return format yyyy-mm-dd of current date.
// Play: https://go.dev/play/p/PvfkPpcpBBf
func GetNowDate() string {
return time.Now().Format("2006-01-02")
}
// GetNowTime return format hh-mm-ss of current time
// GetNowTime return format hh-mm-ss of current time.
// Play: https://go.dev/play/p/l7BNxCkTmJS
func GetNowTime() string {
return time.Now().Format("15:04:05")
}
// GetNowDateTime return format yyyy-mm-dd hh-mm-ss of current datetime
// GetNowDateTime return format yyyy-mm-dd hh-mm-ss of current datetime.
// Play: https://go.dev/play/p/pI4AqngD0al
func GetNowDateTime() string {
return time.Now().Format("2006-01-02 15:04:05")
}
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00)
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
// Play: https://go.dev/play/p/QmL2oIaGE3q
func GetZeroHourTimestamp() int64 {
ts := time.Now().Format("2006-01-02")
t, _ := time.Parse("2006-01-02", ts)
return t.UTC().Unix() - 8*3600
}
// GetNightTimestamp return timestamp of zero hour (timestamp of 23:59)
// GetNightTimestamp return timestamp of zero hour (timestamp of 23:59).
// Play: https://go.dev/play/p/UolysR3MYP1
func GetNightTimestamp() int64 {
return GetZeroHourTimestamp() + 86400 - 1
}
// FormatTimeToStr convert time to string
// FormatTimeToStr convert time to string.
// Play: https://go.dev/play/p/_Ia7M8H_OvE
func FormatTimeToStr(t time.Time, format string) string {
return t.Format(timeFormat[format])
}
// FormatStrToTime convert string to time
// FormatStrToTime convert string to time.
// Play: https://go.dev/play/p/1h9FwdU8ql4
func FormatStrToTime(str, format string) (time.Time, error) {
v, ok := timeFormat[format]
if !ok {
@@ -111,43 +121,50 @@ func FormatStrToTime(str, format string) (time.Time, error) {
return time.Parse(v, str)
}
// BeginOfMinute return beginning minute time of day
// BeginOfMinute return beginning minute time of day.
// Play: https://go.dev/play/p/ieOLVJ9CiFT
func BeginOfMinute(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), 0, 0, t.Location())
}
// EndOfMinute return end minute time of day
// EndOfMinute return end minute time of day.
// Play: https://go.dev/play/p/yrL5wGzPj4z
func EndOfMinute(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), 59, int(time.Second-time.Nanosecond), t.Location())
}
// BeginOfHour return beginning hour time of day
// BeginOfHour return beginning hour time of day.
// Play: https://go.dev/play/p/GhdGFnDWpYs
func BeginOfHour(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location())
}
// EndOfHour return end hour time of day
// EndOfHour return end hour time of day.
// Play: https://go.dev/play/p/6ce3j_6cVqN
func EndOfHour(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location())
}
// BeginOfDay return beginning hour time of day
// BeginOfDay return beginning hour time of day.
// Play: https://go.dev/play/p/94m_UT6cWs9
func BeginOfDay(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
}
// EndOfDay return end time of day
// EndOfDay return end time of day.
// Play: https://go.dev/play/p/eMBOvmq5Ih1
func EndOfDay(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
}
// BeginOfWeek return beginning week, default week begin from Sunday
// BeginOfWeek return beginning week, default week begin from Sunday.
// Play: https://go.dev/play/p/ynjoJPz7VNV
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time {
var beginFromWeekday = time.Sunday
if len(beginFrom) > 0 {
@@ -161,7 +178,8 @@ func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time {
return beginOfWeek
}
// EndOfWeek return end week time, default week end with Saturday
// EndOfWeek return end week time, default week end with Saturday.
// Play: https://go.dev/play/p/i08qKXD9flf
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time {
var endWithWeekday = time.Saturday
if len(endWith) > 0 {
@@ -175,24 +193,28 @@ func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time {
return endWithWeek
}
// BeginOfMonth return beginning of month
// BeginOfMonth return beginning of month.
// Play: https://go.dev/play/p/bWXVFsmmzwL
func BeginOfMonth(t time.Time) time.Time {
y, m, _ := t.Date()
return time.Date(y, m, 1, 0, 0, 0, 0, t.Location())
}
// EndOfMonth return end of month
// EndOfMonth return end of month.
// Play: https://go.dev/play/p/_GWh10B3Nqi
func EndOfMonth(t time.Time) time.Time {
return BeginOfMonth(t).AddDate(0, 1, 0).Add(-time.Nanosecond)
}
// BeginOfYear return beginning of year
// BeginOfYear return the date time at the begin of year.
// Play: https://go.dev/play/p/i326DSwLnV8
func BeginOfYear(t time.Time) time.Time {
y, _, _ := t.Date()
return time.Date(y, time.January, 1, 0, 0, 0, 0, t.Location())
}
// EndOfYear return end of year
// EndOfYear return the date time at the end of year.
// Play: https://go.dev/play/p/G01cKlMCvNm
func EndOfYear(t time.Time) time.Time {
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
}
+323
View File
@@ -0,0 +1,323 @@
package datetime
import (
"fmt"
"reflect"
"time"
)
func ExampleAddDay() {
now := time.Now()
tomorrow := AddDay(now, 1)
diff1 := tomorrow.Sub(now)
yesterday := AddDay(now, -1)
diff2 := yesterday.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 24h0m0s
// -24h0m0s
}
func ExampleAddHour() {
now := time.Now()
after2Hours := AddHour(now, 2)
diff1 := after2Hours.Sub(now)
before2Hours := AddHour(now, -2)
diff2 := before2Hours.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2h0m0s
// -2h0m0s
}
func ExampleAddMinute() {
now := time.Now()
after2Minutes := AddMinute(now, 2)
diff1 := after2Minutes.Sub(now)
before2Minutes := AddMinute(now, -2)
diff2 := before2Minutes.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2m0s
// -2m0s
}
func ExampleGetNowDate() {
result := GetNowDate()
expected := time.Now().Format("2006-01-02")
fmt.Println(result == expected)
// Output:
// true
}
func ExampleGetNowTime() {
result := GetNowTime()
expected := time.Now().Format("15:04:05")
fmt.Println(result == expected)
// Output:
// true
}
func ExampleGetNowDateTime() {
result := GetNowDateTime()
expected := time.Now().Format("2006-01-02 15:04:05")
fmt.Println(result == expected)
// Output:
// true
}
// func ExampleGetZeroHourTimestamp() {
// ts := GetZeroHourTimestamp()
// fmt.Println(ts)
// // Output:
// // 1673107200
// }
// func ExampleGetNightTimestamp() {
// ts := GetNightTimestamp()
// fmt.Println(ts)
// // Output:
// // 1673193599
// }
func ExampleFormatTimeToStr() {
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08
// 2021-01-02
// 02-01-21 16:04:08
}
func ExampleFormatStrToTime() {
result1, _ := FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss")
result2, _ := FormatStrToTime("2021-01-02", "yyyy-mm-dd")
result3, _ := FormatStrToTime("02-01-21 16:04:08", "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08 +0000 UTC
// 2021-01-02 00:00:00 +0000 UTC
// 2021-01-02 16:04:08 +0000 UTC
}
func ExampleBeginOfMinute() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:00 +0000 UTC
}
func ExampleEndOfMinute() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:59.999999999 +0000 UTC
}
func ExampleBeginOfHour() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:00:00 +0000 UTC
}
func ExampleEndOfHour() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:59:59.999999999 +0000 UTC
}
func ExampleBeginOfDay() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
func ExampleEndOfDay() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfWeek() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
func ExampleEndOfWeek() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-14 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfMonth() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
func ExampleEndOfMonth() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-31 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfYear() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfYear(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
func ExampleEndOfYear() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfYear(input)
fmt.Println(result)
// Output:
// 2023-12-31 23:59:59.999999999 +0000 UTC
}
func ExampleNewUnix() {
result := NewUnix(1647597438)
fmt.Println(result)
// Output:
// &{1647597438}
}
func ExampleNewUnixNow() {
tm1 := NewUnixNow()
unixTimestamp := tm1.ToUnix()
tm2 := NewUnix(unixTimestamp)
fmt.Println(reflect.DeepEqual(tm1, tm2))
// Output:
// true
}
// func ExampleNewFormat() {
// tm, err := NewFormat("2022-03-18 17:04:05")
// if err != nil {
// return
// }
// result := tm.ToFormat()
// fmt.Println(result)
// // Output:
// // 2022-03-18 17:04:05
// }
// func ExampleNewISO8601() {
// tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
// if err != nil {
// return
// }
// result := tm.ToIso8601()
// fmt.Println(result)
// // Output:
// // 2006-01-02T23:04:05+08:00
// }
+2 -3
View File
@@ -52,8 +52,8 @@ func TestGetNowDate(t *testing.T) {
assert.Equal(expected, GetNowDate())
}
func TestGetNotTime(t *testing.T) {
assert := internal.NewAssert(t, "TestGetNotTime")
func TestGetNowTime(t *testing.T) {
assert := internal.NewAssert(t, "TestGetNowTime")
expected := time.Now().Format("15:04:05")
assert.Equal(expected, GetNowTime())
}
@@ -81,7 +81,6 @@ func TestFormatTimeToStr(t *testing.T) {
for i := 0; i < len(cases); i++ {
actual := FormatTimeToStr(datetime, cases[i])
assert.Equal(expected[i], actual)
}
}
+147 -106
View File
@@ -1,4 +1,5 @@
# Algorithm
Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div>
@@ -12,6 +13,7 @@ Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div>
## Usage
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
@@ -35,14 +37,12 @@ import (
- [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="BubbleSort">BubbleSort</span>
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -50,6 +50,7 @@ import (
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -60,7 +61,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -76,18 +76,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.BubbleSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -95,6 +98,7 @@ func main() {
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -105,7 +109,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
@@ -125,34 +128,32 @@ func main() {
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
return 0
}
var peoples = []people{
func main() {
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator)
fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
fmt.Println(peoples)
// Output:
// [{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -160,6 +161,7 @@ func main() {
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -170,7 +172,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -186,18 +187,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.SelectionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="ShellSort">ShellSort</span>
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -205,6 +209,7 @@ func main() {
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -215,7 +220,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -231,18 +235,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.ShellSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="QuickSort">QuickSort</span>
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -250,6 +257,7 @@ func main() {
```go
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -260,7 +268,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -276,18 +283,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.QuickSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.QuickSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="HeapSort">HeapSort</span>
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -295,6 +305,7 @@ func main() {
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -305,7 +316,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -321,18 +331,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.HeapSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="MergeSort">MergeSort</span>
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -340,6 +353,7 @@ func main() {
```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
@@ -350,7 +364,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -366,17 +379,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.MergeSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="CountSort">CountSort</span>
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
@@ -384,6 +401,7 @@ func main() {
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
@@ -394,7 +412,7 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -410,18 +428,21 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
sortedNums := algorithm.CountSort(numbers, comparator)
fmt.Println(sortedNums)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
@@ -429,6 +450,7 @@ func main() {
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
@@ -439,7 +461,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -455,19 +476,24 @@ func main() {
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
result1 := algorithm.BinarySearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := algorithm.BinarySearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
@@ -475,6 +501,7 @@ func main() {
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
@@ -485,7 +512,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -501,27 +527,32 @@ func main() {
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
result1 := algorithm.BinaryIterativeSearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := algorithm.BinaryIterativeSearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>LinearSearch Simple linear search algorithm that iterates over all elements of an slice. If a target is found, the index of the target is returned. Else the function return -1.</p>
<p>return the index of target in slice base on equal function.If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
```
<b>Example:</b>
```go
@@ -533,35 +564,26 @@ import (
)
func main() {
type intComparator struct{}
numbers := []int{3, 4, 5, 3, 2, 1}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
equalFunc := func(a, b int) bool {
return a == b
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
result1 := algorithm.LinearSearch(numbers, 3, equalFunc)
result2 := algorithm.LinearSearch(numbers, 6, equalFunc)
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// -1
}
```
### <span id="LRUCache">LRUCache</span>
<p>LRUCache implements mem cache with lru.</p>
<b>Signature:</b>
@@ -570,7 +592,10 @@ func main() {
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int
```
<b>Example:</b>
```go
@@ -587,9 +612,25 @@ func main() {
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
v, ok := cache.Get(1) // v->1, ok->true
fmt.Println(result1, ok1)
fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
fmt.Println(cache.Len())
ok := cache.Delete(2)
fmt.Println(ok)
// Output:
// 1 true
// 2 true
// 0 false
// 2
// true
}
```
+172 -131
View File
@@ -1,4 +1,5 @@
# Algorithm
algorithm 算法包实现一些基本算法,sortsearchlrucache。
<div STYLE="page-break-after: always;"></div>
@@ -12,6 +13,7 @@ algorithm算法包实现一些基本算法,sortsearchlrucache。
<div STYLE="page-break-after: always;"></div>
## 用法
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
@@ -35,22 +37,21 @@ import (
- [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="BubbleSort">BubbleSort</span>
<p>冒泡排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>冒泡排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -60,7 +61,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -76,26 +76,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.BubbleSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>插入排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>插入排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -105,7 +109,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
@@ -125,42 +128,41 @@ func main() {
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
return 0
}
var peoples = []people{
func main() {
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator)
fmt.Println(intSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
fmt.Println(peoples)
// Output:
// [{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>选择排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>选择排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -170,7 +172,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -186,26 +187,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.SelectionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="ShellSort">ShellSort</span>
<p>希尔排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>希尔排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -215,7 +220,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -231,26 +235,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.ShellSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="QuickSort">QuickSort</span>
<p>快速排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>快速排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -260,7 +268,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -276,26 +283,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.QuickSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.QuickSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="HeapSort">HeapSort</span>
<p>堆排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>堆排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -305,7 +316,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -321,26 +331,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.HeapSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="MergeSort">MergeSort</span>
<p>归并排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>归并排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -350,7 +364,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -366,25 +379,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
algorithm.MergeSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="CountSort">CountSort</span>
<p>计数排序,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>计数排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -394,7 +412,7 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -410,26 +428,30 @@ func main() {
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
func main() {
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
sortedNums := algorithm.CountSort(numbers, comparator)
fmt.Println(sortedNums)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>二分递归查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>二分递归查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -439,7 +461,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -455,27 +476,33 @@ func main() {
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
result1 := algorithm.BinarySearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := algorithm.BinarySearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>二分迭代查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>二分迭代查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b>
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -485,7 +512,6 @@ import (
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -501,28 +527,33 @@ func main() {
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
result1 := algorithm.BinaryIterativeSearch(numbers, 5, 0, len(numbers)-1, comparator)
result2 := algorithm.BinaryIterativeSearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>线性查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator</p>
<p>基于传入的相等函数线性查找元素,返回元素索引,未找到元素返回-1。</p>
<b>函数签名:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -533,36 +564,27 @@ import (
)
func main() {
type intComparator struct{}
numbers := []int{3, 4, 5, 3, 2, 1}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
equalFunc := func(a, b int) bool {
return a == b
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
result1 := algorithm.LinearSearch(numbers, 3, equalFunc)
result2 := algorithm.LinearSearch(numbers, 6, equalFunc)
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// -1
}
```
### <span id="LRUCache">LRUCache</span>
<p>lru实现缓存</p>
<p>lru算法实现缓存。</p>
<b>函数签名:</b>
@@ -570,8 +592,11 @@ func main() {
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int
```
<b>Example:</b>
<b>示例:</b>
```go
package main
@@ -587,9 +612,25 @@ func main() {
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
v, ok := cache.Get(1) // v->1, ok->true
fmt.Println(result1, ok1)
fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
fmt.Println(cache.Len())
ok := cache.Delete(2)
fmt.Println(ok)
// Output:
// 1 true
// 2 true
// 0 false
// 2
// true
}
```
+129 -78
View File
@@ -38,13 +38,13 @@ import (
## Channel
### <span id="NewChannel">NewChannel</span>
<p>return a Channel pointer instance.</p>
<p>Create a Channel pointer instance.</p>
<b>Signature:</b>
```go
type Channel struct {}
func NewChannel() *Channel
type Channel[T any] struct
func NewChannel[T any]() *Channel[T]
```
<b>Example:</b>
@@ -57,12 +57,10 @@ import (
)
func main() {
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
}
```
### <span id="Bridge">Bridge</span>
<p>Link multiple channels into one channel until cancel the context.</p>
@@ -70,7 +68,7 @@ func main() {
<b>Signature:</b>
```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
```
<b>Example:</b>
@@ -87,39 +85,42 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
c := concurrency.NewChannel[int]()
genVals := func() <-chan <-chan int {
out := make(chan (<-chan int))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
defer close(out)
for i := 1; i <= 5; i++ {
stream := make(chan int, 1)
stream <- i
close(stream)
chanStream <- stream
out <- stream
}
}()
return chanStream
return out
}
index := 0
for val := range c.Bridge(ctx, genVals()) {
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
// 4
// 5
}
```
### <span id="FanIn">FanIn</span>
<p>merge multiple channels into one channel until cancel the context.</p>
<p>Merge multiple channels into one channel until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
```
<b>Example:</b>
@@ -136,30 +137,29 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
channels := make([]<-chan any, 3)
c := concurrency.NewChannel[int]()
channels := make([]<-chan int, 2)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
}
mergedChannel := c.FanIn(ctx, channels...)
chs := c.FanIn(ctx, channels...)
for val := range mergedChannel {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure)
for v := range chs {
fmt.Println(v) //1 1 0 0 or 0 0 1 1
}
}
```
### <span id="Repeat">Repeat</span>
<p>Return a chan, put param `values` into the chan repeatly until cancel the context.</p>
<p>Create channel, put values into the channel repeatly until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
```
<b>Example:</b>
@@ -176,26 +176,67 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1
fmt.Println(v)
}
// Output:
// 1
// 2
// 1
// 2
}
```
### <span id="Generate">Generate</span>
<p>Creates a channel, then put values into the channel.</p>
<b>Signature:</b>
```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
```
### <span id="RepeatFn">RepeatFn</span>
<p>Return a chan, excutes fn repeatly, and put the result into retruned chan until cancel context.</p>
<p>Create a channel, excutes fn repeatly, and put the result into the channel, until close context.</p>
<b>Signature:</b>
```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
```
<b>Example:</b>
@@ -212,21 +253,24 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
fn := func() string {
return "hello"
}
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream {
fmt.Println(v) //a, a, a
c := concurrency.NewChannel[string]()
intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// hello
// hello
// hello
}
```
### <span id="Or">Or</span>
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
@@ -234,7 +278,7 @@ func main() {
<b>Signature:</b>
```go
func (c *Channel) Or(channels ...<-chan any) <-chan any
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
```
<b>Example:</b>
@@ -249,7 +293,7 @@ import (
func main() {
sig := func(after time.Duration) <-chan any {
c := make(chan interface{})
c := make(chan any)
go func() {
defer close(c)
time.Sleep(after)
@@ -259,22 +303,17 @@ func main() {
start := time.Now()
c := concurrency.NewChannel()
c := concurrency.NewChannel[any]()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
)
fmt.Println("done after %v", time.Since(start)) //1.003s
}
```
### <span id="OrDone">OrDone</span>
<p>Read a channel into another channel, will close until cancel context.</p>
@@ -282,7 +321,7 @@ func main() {
<b>Signature:</b>
```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
```
<b>Example:</b>
@@ -299,26 +338,28 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1
for v := range c.OrDone(ctx, intStream) {
fmt.Println(v)
}
// Output:
// 1
// 1
// 1
}
```
### <span id="Take">Take</span>
<p>Return a chan whose values are tahken from another chan until cancel context.</p>
<p>Create a channel whose values are taken from another channel with limit number.</p>
<b>Signature:</b>
```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
```
<b>Example:</b>
@@ -335,7 +376,7 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers := make(chan int, 5)
numbers <- 1
numbers <- 2
numbers <- 3
@@ -343,25 +384,28 @@ func main() {
numbers <- 5
defer close(numbers)
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, numbers, 3)
for val := range intStream {
fmt.Println(val) //1, 2, 3
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
}
```
### <span id="Tee">Tee</span>
<p>Split one chanel into two channels until cancel context.</p>
<p>Split one chanel into two channels, until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any)
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
```
<b>Example:</b>
@@ -378,13 +422,20 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
fmt.Println(val) //1
fmt.Println(<-out2) //1
ch1, ch2 := c.Tee(ctx, intStream)
for v := range ch1 {
fmt.Println(v)
fmt.Println(<-ch2)
}
// Output:
// 1
// 1
// 1
// 1
}
```
+140 -91
View File
@@ -43,10 +43,10 @@ import (
<b>函数签名:</b>
```go
type Channel struct {}
func NewChannel() *Channel
type Channel[T any] struct
func NewChannel[T any]() *Channel[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -57,22 +57,20 @@ import (
)
func main() {
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
}
```
### <span id="Bridge">Bridge</span>
<p>将多个通道链接到一个通道,直到取消上下文。</p>
<p>将多个channel链接到一个channel,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -87,41 +85,44 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
c := concurrency.NewChannel[int]()
genVals := func() <-chan <-chan int {
out := make(chan (<-chan int))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
defer close(out)
for i := 1; i <= 5; i++ {
stream := make(chan int, 1)
stream <- i
close(stream)
chanStream <- stream
out <- stream
}
}()
return chanStream
return out
}
index := 0
for val := range c.Bridge(ctx, genVals()) {
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
// 4
// 5
}
```
### <span id="FanIn">FanIn</span>
<p>将多个通道合并为一个通道,直到取消上下文</p>
<p>将多个channel合并为一个channel,直到取消上下文</p>
<b>函数签名:</b>
```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -136,32 +137,69 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
channels := make([]<-chan any, 3)
c := concurrency.NewChannel[int]()
channels := make([]<-chan int, 2)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
for i := 0; i < 2; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 2)
}
mergedChannel := c.FanIn(ctx, channels...)
chs := c.FanIn(ctx, channels...)
for val := range mergedChannel {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure)
for v := range chs {
fmt.Println(v) //1 1 0 0 or 0 0 1 1
}
}
```
### <span id="Generate">Generate</span>
<p>根据传入的值,生成channel.</p>
<b>函数签名:</b>
```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>示例:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
```
### <span id="Repeat">Repeat</span>
<p>返回一个chan,将参数`values`重复放入chan,直到取消上下文。</p>
<p>返回一个channel,将参数`values`重复放入channel,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -176,28 +214,31 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1
fmt.Println(v)
}
// Output:
// 1
// 2
// 1
// 2
}
```
### <span id="RepeatFn">RepeatFn</span>
<p>返回一个chan,重复执行函数fn,并将结果放入返回的chan,直到取消上下文。</p>
<p>返回一个channel,重复执行函数fn,并将结果放入返回的channel,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -212,31 +253,33 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
fn := func() string {
return "hello"
}
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream {
fmt.Println(v) //a, a, a
c := concurrency.NewChannel[string]()
intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// hello
// hello
// hello
}
```
### <span id="Or">Or</span>
<p>将一个或多个通道读取到一个通道中,当任何读取通道关闭时将结束读取。</p>
<p>将一个或多个channel读取到一个channel中,当任何读取channel关闭时将结束读取。</p>
<b>函数签名:</b>
```go
func (c *Channel) Or(channels ...<-chan any) <-chan any
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -249,7 +292,7 @@ import (
func main() {
sig := func(after time.Duration) <-chan any {
c := make(chan interface{})
c := make(chan any)
go func() {
defer close(c)
time.Sleep(after)
@@ -259,32 +302,27 @@ func main() {
start := time.Now()
c := concurrency.NewChannel()
c := concurrency.NewChannel[any]()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
)
fmt.Println("done after %v", time.Since(start)) //1.003s
}
```
### <span id="OrDone">OrDone</span>
<p>将一个通道读入另一个通道,直到取消上下文。</p>
<p>将一个channel读入另一个channel,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -299,28 +337,30 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1
for v := range c.OrDone(ctx, intStream) {
fmt.Println(v)
}
// Output:
// 1
// 1
// 1
}
```
### <span id="Take">Take</span>
<p>返回一个chan,其值从另一个chan获取,直到取消上下文。</p>
<p>返回一个channel,其值从另一个channel获取,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -335,7 +375,7 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers := make(chan int, 5)
numbers <- 1
numbers <- 2
numbers <- 3
@@ -343,27 +383,30 @@ func main() {
numbers <- 5
defer close(numbers)
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, numbers, 3)
for val := range intStream {
fmt.Println(val) //1, 2, 3
for v := range intStream {
fmt.Println(v)
}
// Output:
// 1
// 2
// 3
}
```
### <span id="Tee">Tee</span>
<p>将一个通道分成两个通道,直到取消上下文。</p>
<p>将一个channel分成两个channel,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any)
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -378,13 +421,19 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
c := concurrency.NewChannel[int]()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 2)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
fmt.Println(val) //1
fmt.Println(<-out2) //1
ch1, ch2 := c.Tee(ctx, intStream)
for v := range ch1 {
fmt.Println(v)
fmt.Println(<-ch2)
}
// Output:
// 1
// 1
// 1
// 1
}
```
+75 -29
View File
@@ -25,6 +25,7 @@ import (
- [Or](#Or)
- [Xor](#Generate)
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [TernaryOperator](#TernaryOperator)
@@ -57,40 +58,51 @@ import (
func main() {
// bool
fmt.Println(condition.Bool(false)) // false
fmt.Println(condition.Bool(true)) // true
result1 := condition.Bool(false)
result2 := condition.Bool(true)
fmt.Println(result1) // false
fmt.Println(result2) // true
// integer
fmt.Println(condition.Bool(0)) // false
fmt.Println(condition.Bool(1)) // true
// float
fmt.Println(condition.Bool(0.0)) // false
fmt.Println(condition.Bool(0.1)) // true
result3 := condition.Bool(0)
result4 := condition.Bool(1)
fmt.Println(result3) // false
fmt.Println(result4) // true
// string
fmt.Println(condition.Bool("")) // false
fmt.Println(condition.Bool(" ")) // true
fmt.Println(condition.Bool("0")) // true
result5 := condition.Bool("")
result6 := condition.Bool(" ")
fmt.Println(result5) // false
fmt.Println(result6) // true
// slice
var nums [2]int
fmt.Println(condition.Bool(nums)) // false
nums = [2]int{0, 1}
fmt.Println(condition.Bool(nums)) // true
nums := []int{}
result7 := condition.Bool(nums)
// map
fmt.Println(condition.Bool(map[string]string{})) // false
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true
nums = append(nums, 1, 2)
result8 := condition.Bool(nums)
fmt.Println(result7) // false
fmt.Println(result8) // true
// struct
fmt.Println(condition.Bool(struct{}{})) // false
fmt.Println(condition.Bool(time.Now())) // true
result9 = condition.Bool(struct{}{})
fmt.Println(result8) // false
// Output:
// false
// true
// false
// true
// false
// true
// false
// true
// false
}
```
### <span id="And">And</span>
<p>Returns true if both a and b are truthy.</p>
@@ -120,7 +132,7 @@ func main() {
### <span id="Or">Or</span>
<p>Returns false iff neither a nor b is truthy.</p>
<p>Returns false if neither a nor b is truthy.</p>
<b>Signature:</b>
@@ -148,7 +160,7 @@ func main() {
### <span id="Xor">Xor</span>
<p>Returns true iff a or b but not both is truthy.</p>
<p>Returns true if a or b but not both is truthy.</p>
<b>Signature:</b>
@@ -176,7 +188,7 @@ func main() {
### <span id="Nor">Nor</span>
<p>Returns true iff neither a nor b is truthy.</p>
<p>Returns true if neither a nor b is truthy.</p>
<b>Signature:</b>
@@ -197,14 +209,40 @@ func main() {
fmt.Println(condition.Nor(0, 0)) // true
fmt.Println(condition.Nor(0, 1)) // false
fmt.Println(condition.Nor(1, 0)) // false
fmt.Println(condition.Nor(1, 1)) // true
fmt.Println(condition.Nor(1, 1)) // false
}
```
### <span id="Xnor">Xnor</span>
<p>Returns true if both a and b or neither a nor b are truthy.</p>
<b>Signature:</b>
```go
func Xnor[T, U any](a T, b U) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/condition"
)
func main() {
fmt.Println(condition.Xnor(0, 0)) // true
fmt.Println(condition.Xnor(0, 1)) // false
fmt.Println(condition.Xnor(1, 0)) // false
fmt.Println(condition.Xnor(1, 1)) // true
}
```
### <span id="Nand">Nand</span>
<p>Returns false iff both a and b are truthy</p>
<p>Returns false if both a and b are truthy</p>
<b>Signature:</b>
@@ -250,10 +288,18 @@ import (
)
func main() {
trueValue := "1"
falseValue := "0"
conditionTrue := 2 > 1
result1 := condition.TernaryOperator(conditionTrue, 0, 1)
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1"
conditionFalse := 2 > 3
result2 := condition.TernaryOperator(conditionFalse, 0, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// 1
}
```
+76 -41
View File
@@ -25,6 +25,7 @@ import (
- [Or](#Or)
- [Xor](#Generate)
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [TernaryOperator](#TernaryOperator)
@@ -44,7 +45,7 @@ slices和map的length大于0时,返回true,否则返回false<br/>
```go
func Bool[T any](value T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -56,40 +57,50 @@ import (
func main() {
// bool
fmt.Println(condition.Bool(false)) // false
fmt.Println(condition.Bool(true)) // true
result1 := condition.Bool(false)
result2 := condition.Bool(true)
fmt.Println(result1) // false
fmt.Println(result2) // true
// integer
fmt.Println(condition.Bool(0)) // false
fmt.Println(condition.Bool(1)) // true
// float
fmt.Println(condition.Bool(0.0)) // false
fmt.Println(condition.Bool(0.1)) // true
result3 := condition.Bool(0)
result4 := condition.Bool(1)
fmt.Println(result3) // false
fmt.Println(result4) // true
// string
fmt.Println(condition.Bool("")) // false
fmt.Println(condition.Bool(" ")) // true
fmt.Println(condition.Bool("0")) // true
result5 := condition.Bool("")
result6 := condition.Bool(" ")
fmt.Println(result5) // false
fmt.Println(result6) // true
// slice
var nums [2]int
fmt.Println(condition.Bool(nums)) // false
nums = [2]int{0, 1}
fmt.Println(condition.Bool(nums)) // true
nums := []int{}
result7 := condition.Bool(nums)
// map
fmt.Println(condition.Bool(map[string]string{})) // false
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true
nums = append(nums, 1, 2)
result8 := condition.Bool(nums)
fmt.Println(result7) // false
fmt.Println(result8) // true
// struct
fmt.Println(condition.Bool(struct{}{})) // false
fmt.Println(condition.Bool(time.Now())) // true
result9 = condition.Bool(struct{}{})
fmt.Println(result8) // false
// Output:
// false
// true
// false
// true
// false
// true
// false
// true
// false
}
```
### <span id="And">And</span>
<p>逻辑且操作,当切仅当a和b都为true时返回true</p>
@@ -98,7 +109,7 @@ func main() {
```go
func And[T, U any](a T, b U) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -116,8 +127,6 @@ func main() {
}
```
### <span id="Or">Or</span>
<p>逻辑或操作,当切仅当a和b都为false时返回false</p>
@@ -126,7 +135,7 @@ func main() {
```go
func Or[T, U any](a T, b U) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -144,8 +153,6 @@ func main() {
}
```
### <span id="Xor">Xor</span>
<p>逻辑异或操作,a和b相同返回falsea和b不相同返回true</p>
@@ -154,7 +161,7 @@ func main() {
```go
func Xor[T, U any](a T, b U) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -172,8 +179,6 @@ func main() {
}
```
### <span id="Nor">Nor</span>
<p>异或的取反操作</p>
@@ -182,7 +187,7 @@ func main() {
```go
func Nor[T, U any](a T, b U) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -196,11 +201,35 @@ func main() {
fmt.Println(condition.Nor(0, 0)) // true
fmt.Println(condition.Nor(0, 1)) // false
fmt.Println(condition.Nor(1, 0)) // false
fmt.Println(condition.Nor(1, 1)) // true
fmt.Println(condition.Nor(1, 1)) // false
}
```
### <span id="Xnor">Xnor</span>
<p>如果a和b都是真的或a和b均是假的,则返回true。</p>
<b>函数签名:</b>
```go
func Xnor[T, U any](a T, b U) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/condition"
)
func main() {
fmt.Println(condition.Xnor(0, 0)) // true
fmt.Println(condition.Xnor(0, 1)) // false
fmt.Println(condition.Xnor(1, 0)) // false
fmt.Println(condition.Xnor(1, 1)) // true
}
```
### <span id="Nand">Nand</span>
<p>如果a和b都为真,返回false,否则返回true</p>
@@ -210,7 +239,7 @@ func main() {
```go
func Nand[T, U any](a T, b U) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -228,8 +257,6 @@ func main() {
}
```
### <span id="TernaryOperator">TernaryOperator</span>
<p>三元运算符</p>
@@ -238,7 +265,7 @@ func main() {
```go
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -249,10 +276,18 @@ import (
)
func main() {
trueValue := "1"
falseValue := "0"
conditionTrue := 2 > 1
result1 := condition.TernaryOperator(conditionTrue, 0, 1)
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1"
conditionFalse := 2 > 3
result2 := condition.TernaryOperator(conditionFalse, 0, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// 1
}
```
+156 -89
View File
@@ -40,8 +40,6 @@ import (
## Documentation
### <span id="ColorHexToRGB">ColorHexToRGB</span>
<p>Convert color hex to color rgb.</p>
@@ -63,12 +61,14 @@ import (
func main() {
colorHex := "#003366"
r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
fmt.Println(r, g, b)
// Output:
// 0 51 102
}
```
### <span id="ColorRGBToHex">ColorRGBToHex</span>
<p>Convert color rgb to color hex.</p>
@@ -92,17 +92,18 @@ func main() {
r := 0
g := 51
b := 102
colorHex := convertor.ColorRGBToHex(r, g, b)
colorHex := ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366
fmt.Println(colorHex)
// Output:
// #003366
}
```
### <span id="ToBool">ToBool</span>
<p>Convert string to a boolean value. Use strconv.ParseBool</p>
<p>Convert string to bool. Use strconv.ParseBool.</p>
<b>Signature:</b>
@@ -120,25 +121,29 @@ import (
)
func main() {
v1, _ := convertor.ToBool("1")
fmt.Println(v1) //true
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
v2, _ := convertor.ToBool("true")
fmt.Println(v2) //true
for i := 0; i < len(cases); i++ {
result, _ := convertor.ToBool(cases[i])
fmt.Println(result)
}
v3, _ := convertor.ToBool("True")
fmt.Println(v3) //true
v4, _ := convertor.ToBool("123")
fmt.Println(v4) //false
// Output:
// true
// true
// true
// false
// false
// false
// false
// false
// false
}
```
### <span id="ToBytes">ToBytes</span>
<p>Convert interface to byte slice.</p>
<p>Convert value to byte slice.</p>
<b>Signature:</b>
@@ -156,16 +161,18 @@ import (
)
func main() {
bytesData, err := convertor.ToBytes("0")
bytesData, err := convertor.ToBytes("abc")
if err != nil {
fmt.Println(err)
}
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
fmt.Println(bytesData)
// Output:
// [97 98 99]
}
```
### <span id="ToChar">ToChar</span>
<p>Convert string to char slice.</p>
@@ -186,21 +193,24 @@ import (
)
func main() {
chars := convertor.ToChar("")
fmt.Println(chars) //[]string{""}
result1 := convertor.ToChar("")
result2 := convertor.ToChar("abc")
result3 := convertor.ToChar("1 2#3")
chars = convertor.ToChar("abc")
fmt.Println(chars) //[]string{"a", "b", "c"}
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
chars = convertor.ToChar("1 2#3")
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"}
// Output:
// []
// [a b c]
// [1 2 # 3]
}
```
### <span id="ToChannel">ToChannel</span>
<p>Convert a collection of elements to a read-only channels.</p>
<p>Convert a collection of elements to a read-only channel.</p>
<b>Signature:</b>
@@ -219,26 +229,24 @@ import (
func main() {
ch := convertor.ToChannel([]int{1, 2, 3})
result1 := <-ch
result2 := <-ch
result3 := <-ch
val1, _ := <-ch
fmt.Println(val1) //1
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
val2, _ := <-ch
fmt.Println(val2) //2
val3, _ := <-ch
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
// Output:
// 1
// 2
// 3
}
```
### <span id="ToFloat">ToFloat</span>
<p>Convert interface to a float64 value. If param is a invalid floatable, will return 0 and error. </p>
<p>Convert value to a float64 value. If param is a invalid floatable, will return 0.0 and error. </p>
<b>Signature:</b>
@@ -256,22 +264,33 @@ import (
)
func main() {
v, err := convertor.ToFloat("")
if err != nil {
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax
}
fmt.Println(v) //0
result1, _ := convertor.ToFloat("")
result2, err := convertor.ToFloat("abc")
result3, _ := convertor.ToFloat("-1")
result4, _ := convertor.ToFloat("-.11")
result5, _ := convertor.ToFloat("1.23e3")
result6, _ := convertor.ToFloat(true)
v, _ = convertor.ToFloat("-.11")
fmt.Println(v) //-0.11
fmt.Println(result1)
fmt.Println(result2, err)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// 0
// 0 strconv.ParseFloat: parsing "": invalid syntax
// -1
// -0.11
// 1230
// 0
}
```
### <span id="ToInt">ToInt</span>
<p>Convert interface to a int64 value. If param is a invalid intable, will return 0 and error. </p>
<p>Convert value to a int64 value. If param is a invalid intable, will return 0 and error. </p>
<b>Signature:</b>
@@ -289,19 +308,27 @@ import (
)
func main() {
v, err := convertor.ToInt("")
if err != nil {
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax
}
fmt.Println(v) //0
result1, _ := convertor.ToInt("123")
result2, _ := convertor.ToInt("-123")
result3, _ := convertor.ToInt(float64(12.3))
result4, err := convertor.ToInt("abc")
result5, _ := convertor.ToInt(true)
v, _ = convertor.ToFloat(1.12)
fmt.Println(v) //1
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4, err)
fmt.Println(result5)
// Output:
// 123
// -123
// 12
// 0 strconv.ParseInt: parsing "": invalid syntax
// 0
}
```
### <span id="ToJson">ToJson</span>
<p>Convert interface to json string. If param can't be converted, will return "" and error. </p>
@@ -322,17 +349,23 @@ import (
)
func main() {
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
jsonStr, _ := convertor.ToJson(aMap)
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
result, err := ToJson(aMap)
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(result)
// Output:
// {"a":1,"b":2,"c":3}
}
```
### <span id="ToMap">ToMap</span>
<p>Convert a slice or an array of structs to a map based on iteratee function. </p>
<p>Convert a slice of structs to a map based on iteratee function. </p>
<b>Signature:</b>
@@ -358,16 +391,18 @@ func main() {
{name: "Hello", code: 100},
{name: "Hi", code: 101},
}
result := convertor.ToMap(messages, func(msg Message) (int, string) {
return msg.code, msg.name
})
fmt.Println(result) //{100: "Hello", 101: "Hi"}
fmt.Println(result)
// Output:
// map[100:Hello 101:Hi]
}
```
### <span id="ToPointer">ToPointer</span>
<p>Returns a pointer to passed value. </p>
@@ -389,11 +424,13 @@ import (
func main() {
result := convertor.ToPointer(123)
fmt.Println(*result) //123
fmt.Println(*result)
// Output:
// 123
}
```
### <span id="ToString">ToString</span>
<p>ToString convert value to string, for number, string, []byte, will convert to string. For other type (slice, map, array, struct) will call json.Marshal</p>
@@ -414,13 +451,33 @@ import (
)
func main() {
fmt.Printf("%q", convertor.ToString(1)) //"1"
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
result1 := convertor.ToString("")
result2 := convertor.ToString(nil)
result3 := convertor.ToString(0)
result4 := convertor.ToString(1.23)
result5 := convertor.ToString(true)
result6 := convertor.ToString(false)
result7 := convertor.ToString([]int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
//
//
// 0
// 1.23
// true
// false
// [1,2,3]
}
```
### <span id="StructToMap">StructToMap</span>
<p>Convert struct to map, only convert exported field, struct field tag `json` should be set.</p>
@@ -451,12 +508,13 @@ func main() {
}
pm, _ := convertor.StructToMap(p)
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
fmt.Println(pm)
// Output:
// map[name:test]
}
```
### <span id="MapToSlice">MapToSlice</span>
<p>Convert a map to a slice based on iteratee function.</p>
@@ -508,12 +566,13 @@ import (
func main() {
byteData, _ := convertor.EncodeByte("abc")
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99}
fmt.Println(byteData)
// Output:
// [6 12 0 3 97 98 99]
}
```
### <span id="DecodeByte">DecodeByte</span>
<p>Decode byte data to target object. target should be a pointer instance.</p>
@@ -536,7 +595,15 @@ import (
func main() {
var result string
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
convertor.DecodeByte(byteData, &result)
fmt.Println(result) //"abc"
err := convertor.DecodeByte(byteData, &result)
if err != nil {
return
}
fmt.Println(result)
// Output:
// abc
}
```
+182 -119
View File
@@ -43,16 +43,15 @@ import (
## 文档
### <span id="ColorHexToRGB">ColorHexToRGB</span>
<p>颜色值十六进制转rgb</p>
<p>颜色值十六进制转rgb</p>
<b>函数签名:</b>
```go
func ColorHexToRGB(colorHex string) (red, green, blue int)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -65,22 +64,24 @@ import (
func main() {
colorHex := "#003366"
r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
fmt.Println(r, g, b)
// Output:
// 0 51 102
}
```
### <span id="ColorRGBToHex">ColorRGBToHex</span>
<p>颜色值rgb转十六进制</p>
<p>颜色值rgb转十六进制</p>
<b>函数签名:</b>
```go
func ColorRGBToHex(red, green, blue int) string
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -94,24 +95,25 @@ func main() {
r := 0
g := 51
b := 102
colorHex := convertor.ColorRGBToHex(r, g, b)
colorHex := ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366
fmt.Println(colorHex)
// Output:
// #003366
}
```
### <span id="ToBool">ToBool</span>
<p>字符串转布尔类型,使用strconv.ParseBool</p>
<p>字符串转布尔类型,使用strconv.ParseBool</p>
<b>函数签名:</b>
```go
func ToBool(s string) (bool, error)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -122,32 +124,36 @@ import (
)
func main() {
v1, _ := convertor.ToBool("1")
fmt.Println(v1) //true
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
v2, _ := convertor.ToBool("true")
fmt.Println(v2) //true
for i := 0; i < len(cases); i++ {
result, _ := convertor.ToBool(cases[i])
fmt.Println(result)
}
v3, _ := convertor.ToBool("True")
fmt.Println(v3) //true
v4, _ := convertor.ToBool("123")
fmt.Println(v4) //false
// Output:
// true
// true
// true
// false
// false
// false
// false
// false
// false
}
```
### <span id="ToBytes">ToBytes</span>
<p>interface转字节切片.</p>
<p>Interface转字节切片</p>
<b>函数签名:</b>
```go
func ToBytes(data any) ([]byte, error)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -158,26 +164,28 @@ import (
)
func main() {
bytesData, err := convertor.ToBytes("0")
bytesData, err := convertor.ToBytes("abc")
if err != nil {
fmt.Println(err)
}
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
fmt.Println(bytesData)
// Output:
// [97 98 99]
}
```
### <span id="ToChar">ToChar</span>
<p>字符串转字符切片</p>
<p>字符串转字符切片</p>
<b>函数签名:</b>
```go
func ToChar(s string) []string
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -188,29 +196,31 @@ import (
)
func main() {
chars := convertor.ToChar("")
fmt.Println(chars) //[]string{""}
result1 := convertor.ToChar("")
result2 := convertor.ToChar("abc")
result3 := convertor.ToChar("1 2#3")
chars = convertor.ToChar("abc")
fmt.Println(chars) //[]string{"a", "b", "c"}
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
chars = convertor.ToChar("1 2#3")
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"}
// Output:
// []
// [a b c]
// [1 2 # 3]
}
```
### <span id="ToChannel">ToChannel</span>
<p>将切片转为只读channel</p>
<p>将切片转为只读channel</p>
<b>函数签名:</b>
```go
func ToChannel[T any](array []T) <-chan T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -222,33 +232,31 @@ import (
func main() {
ch := convertor.ToChannel([]int{1, 2, 3})
result1 := <-ch
result2 := <-ch
result3 := <-ch
val1, _ := <-ch
fmt.Println(val1) //1
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
val2, _ := <-ch
fmt.Println(val2) //2
val3, _ := <-ch
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
// Output:
// 1
// 2
// 3
}
```
### <span id="ToFloat">ToFloat</span>
<p>将interface转成float64类型,如果参数无法转换,会返回0和error</p>
<p>将interface转成float64类型,如果参数无法转换,会返回0和error</p>
<b>函数签名:</b>
```go
func ToFloat(value any) (float64, error)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -259,29 +267,40 @@ import (
)
func main() {
v, err := convertor.ToFloat("")
if err != nil {
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax
}
fmt.Println(v) //0
result1, _ := convertor.ToFloat("")
result2, err := convertor.ToFloat("abc")
result3, _ := convertor.ToFloat("-1")
result4, _ := convertor.ToFloat("-.11")
result5, _ := convertor.ToFloat("1.23e3")
result6, _ := convertor.ToFloat(true)
v, _ = convertor.ToFloat("-.11")
fmt.Println(v) //-0.11
fmt.Println(result1)
fmt.Println(result2, err)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// 0
// 0 strconv.ParseFloat: parsing "": invalid syntax
// -1
// -0.11
// 1230
// 0
}
```
### <span id="ToInt">ToInt</span>
<p>将interface转成int64类型,如果参数无法转换,会返回0和error</p>
<p>将interface转成int64类型,如果参数无法转换,会返回0和error</p>
<b>函数签名:</b>
```go
func ToInt(value any) (int64, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -292,29 +311,37 @@ import (
)
func main() {
v, err := convertor.ToInt("")
if err != nil {
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax
}
fmt.Println(v) //0
result1, _ := convertor.ToInt("123")
result2, _ := convertor.ToInt("-123")
result3, _ := convertor.ToInt(float64(12.3))
result4, err := convertor.ToInt("abc")
result5, _ := convertor.ToInt(true)
v, _ = convertor.ToFloat(1.12)
fmt.Println(v) //1
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4, err)
fmt.Println(result5)
// Output:
// 123
// -123
// 12
// 0 strconv.ParseInt: parsing "": invalid syntax
// 0
}
```
### <span id="ToJson">ToJson</span>
<p>将interface转成json字符串,如果参数无法转换,会返回""和error</p>
<p>将interface转成json字符串,如果参数无法转换,会返回""和error</p>
<b>函数签名:</b>
```go
func ToJson(value any) (string, error)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -325,24 +352,30 @@ import (
)
func main() {
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
jsonStr, _ := convertor.ToJson(aMap)
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
result, err := ToJson(aMap)
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(result)
// Output:
// {"a":1,"b":2,"c":3}
}
```
### <span id="ToMap">ToMap</span>
<p>将切片转为map</p>
<p>将切片转为map</p>
<b>函数签名:</b>
```go
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -361,26 +394,28 @@ func main() {
{name: "Hello", code: 100},
{name: "Hi", code: 101},
}
result := convertor.ToMap(messages, func(msg Message) (int, string) {
return msg.code, msg.name
})
fmt.Println(result) //{100: "Hello", 101: "Hi"}
fmt.Println(result)
// Output:
// map[100:Hello 101:Hi]
}
```
### <span id="ToPointer">ToPointer</span>
<p>返回传入值的指针</p>
<p>返回传入值的指针</p>
<b>函数签名:</b>
```go
func ToPointer[T any](value T) *T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -392,22 +427,23 @@ import (
func main() {
result := convertor.ToPointer(123)
fmt.Println(*result) //123
fmt.Println(*result)
// Output:
// 123
}
```
### <span id="ToString">ToString</span>
<p>将值转换为字符串,对于数字、字符串、[]byte,将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal</p>
<p>将值转换为字符串,对于数字、字符串、[]byte,将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal</p>
<b>函数签名:</b>
```go
func ToString(value any) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -418,24 +454,43 @@ import (
)
func main() {
fmt.Printf("%q", convertor.ToString(1)) //"1"
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
result1 := convertor.ToString("")
result2 := convertor.ToString(nil)
result3 := convertor.ToString(0)
result4 := convertor.ToString(1.23)
result5 := convertor.ToString(true)
result6 := convertor.ToString(false)
result7 := convertor.ToString([]int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
//
//
// 0
// 1.23
// true
// false
// [1,2,3]
}
```
### <span id="StructToMap">StructToMap</span>
<p>将struct转成map,只会转换struct中可导出的字段。struct中导出字段需要设置json tag标记</p>
<p>将struct转成map,只会转换struct中可导出的字段。struct中导出字段需要设置json tag标记</p>
<b>函数签名:</b>
```go
func StructToMap(value any) (map[string]any, error)
```
<b>列子:</b>
<b>示例:</b>
```go
package main
@@ -456,22 +511,23 @@ func main() {
}
pm, _ := convertor.StructToMap(p)
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
fmt.Println(pm)
// Output:
// map[name:test]
}
```
### <span id="MapToSlice">MapToSlice</span>
<p>map中key和value执行函数iteratee后,转为切片</p>
<p>map中key和value执行函数iteratee后,转为切片</p>
<b>函数签名:</b>
```go
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -491,18 +547,16 @@ func main() {
}
```
### <span id="EncodeByte">EncodeByte</span>
<p>将data编码成字节切片</p>
<p>将data编码成字节切片</p>
<b>函数签名:</b>
```go
func EncodeByte(data any) ([]byte, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -514,22 +568,23 @@ import (
func main() {
byteData, _ := convertor.EncodeByte("abc")
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99}
fmt.Println(byteData)
// Output:
// [6 12 0 3 97 98 99]
}
```
### <span id="DecodeByte">DecodeByte</span>
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p>
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p>
<b>函数签名:</b>
```go
func DecodeByte(data []byte, target any) error
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -542,7 +597,15 @@ import (
func main() {
var result string
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
convertor.DecodeByte(byteData, &result)
fmt.Println(result) //"abc"
err := convertor.DecodeByte(byteData, &result)
if err != nil {
return
}
fmt.Println(result)
// Output:
// abc
}
```
+220 -146
View File
@@ -5,10 +5,10 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Source:
- [https://github.com/duke-git/lancet/blob/main/cryptor/aes.go](https://github.com/duke-git/lancet/blob/main/cryptor/aes.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/des.go](https://github.com/duke-git/lancet/blob/main/cryptor/des.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
<div STYLE="page-break-after: always;"></div>
@@ -61,8 +61,6 @@ import (
## Documentation
### <span id="AesEcbEncrypt">AesEcbEncrypt</span>
<p>Encrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -83,16 +81,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesEcbDecrypt">AesEcbDecrypt</span>
<p>Decrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -113,16 +114,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCbcEncrypt">AesCbcEncrypt</span>
<p>Encrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -143,16 +147,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCbcDecrypt">AesCbcDecrypt</span>
<p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -174,16 +181,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCtrCrypt">AesCtrCrypt</span>
<p>Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -205,17 +215,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCfbEncrypt">AesCfbEncrypt</span>
<p>Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -237,15 +249,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCfbDecrypt">AesCfbDecrypt</span>
<p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -267,16 +283,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesOfbEncrypt">AesOfbEncrypt</span>
<p>Enecrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -298,15 +317,18 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCfbDecrypt">AesOfbDecrypt</span>
<p>Decrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -328,17 +350,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="Base64StdEncode">Base64StdEncode</span>
<p>Encode string with base64 encoding.</p>
@@ -359,13 +383,13 @@ import (
)
func main() {
base64Str := cryptor.Base64StdEncode("hello world")
fmt.Println(base64Str) //aGVsbG8gd29ybGQ=
base64Str := cryptor.Base64StdEncode("hello")
fmt.Println(base64Str)
// Output:
// aGVsbG8=
}
```
### <span id="Base64StdDecode">Base64StdDecode</span>
<p>Decode a base64 encoded string.</p>
@@ -387,13 +411,14 @@ import (
)
func main() {
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=")
fmt.Println(str) //hello world
str := cryptor.Base64StdDecode("aGVsbG8=")
fmt.Println(str)
// Output:
// hello
}
```
### <span id="DesEcbEncrypt">DesEcbEncrypt</span>
<p>Encrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p>
@@ -415,16 +440,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesEcbDecrypt">DesEcbDecrypt</span>
<p>Decrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p>
@@ -446,17 +474,20 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCbcEncrypt">DesCbcEncrypt</span>
<p>Encrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -478,16 +509,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
fmt.Println(string(encrypted))
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCbcDecrypt">DesCbcDecrypt</span>
<p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -509,17 +543,18 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCtrCrypt">DesCtrCrypt</span>
<p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
@@ -541,17 +576,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCfbEncrypt">DesCfbEncrypt</span>
<p>Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.</p>
@@ -573,15 +610,18 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
fmt.Println(string(encrypted))
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCfbDecrypt">DesCfbDecrypt</span>
<p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -603,16 +643,18 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesOfbEncrypt">DesOfbEncrypt</span>
<p>Enecrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
@@ -634,15 +676,18 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted))
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesOfbDecrypt">DesOfbDecrypt</span>
<p>Decrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
@@ -664,17 +709,19 @@ import (
)
func main() {
data := "hello world"
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="HmacMd5">HmacMd5</span>
<p>Get the md5 hmac hash of string.</p>
@@ -696,13 +743,16 @@ import (
)
func main() {
s := cryptor.HmacMd5("hello world", "12345"))
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d
str := "hello"
key := "12345"
hms := cryptor.HmacMd5(str, key)
fmt.Println(hms)
// Output:
// e834306eab892d872525d4918a7a639a
}
```
### <span id="HmacSha1">HmacSha1</span>
<p>Get the sha1 hmac hash of string.</p>
@@ -724,13 +774,16 @@ import (
)
func main() {
s := cryptor.HmacSha1("hello world", "12345"))
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
str := "hello"
key := "12345"
hms := cryptor.HmacSha1(str, key)
fmt.Println(hms)
// Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
```
### <span id="HmacSha256">HmacSha256</span>
<p>Get the sha256 hmac hash of string</p>
@@ -752,13 +805,17 @@ import (
)
func main() {
s := cryptor.HmacSha256("hello world", "12345"))
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
str := "hello"
key := "12345"
hms := cryptor.HmacSha256(str, key)
fmt.Println(hms)
// Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
}
```
### <span id="HmacSha512">HmacSha512</span>
<p>Get the sha512 hmac hash of string.</p>
@@ -780,14 +837,18 @@ import (
)
func main() {
s := cryptor.HmacSha512("hello world", "12345"))
fmt.Println(s)
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
str := "hello"
key := "12345"
hms := cryptor.HmacSha512(str, key)
fmt.Println(hms)
// Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
}
```
### <span id="Md5String">Md5String</span>
<p>Get the md5 value of string.</p>
@@ -809,13 +870,16 @@ import (
)
func main() {
s := cryptor.Md5String("hello"))
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
str := "hello"
md5Str := cryptor.Md5String(str)
fmt.Println(md5Str)
// Output:
// 5d41402abc4b2a76b9719d911017c592
}
```
### <span id="Md5File">Md5File</span>
<p>Get the md5 value of file.</p>
@@ -842,8 +906,6 @@ func main() {
}
```
### <span id="Sha1">Sha1</span>
<p>Get the sha1 value of string.</p>
@@ -865,13 +927,16 @@ import (
)
func main() {
s := cryptor.Sha1("hello world"))
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
str := "hello"
result := cryptor.Sha1(str)
fmt.Println(result)
// Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
}
```
### <span id="Sha256">Sha256</span>
<p>Get the sha256 value of string.</p>
@@ -893,13 +958,16 @@ import (
)
func main() {
s := cryptor.Sha256("hello world"))
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
str := "hello"
result := cryptor.Sha256(str)
fmt.Println(result)
// Output:
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
}
```
### <span id="Sha512">Sha512</span>
<p>Get the sha512 value of string.</p>
@@ -921,13 +989,16 @@ import (
)
func main() {
s := cryptor.Sha512("hello world"))
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
str := "hello"
result := cryptor.Sha512(str)
fmt.Println(result)
// Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
}
```
### <span id="GenerateRsaKey">GenerateRsaKey</span>
<p>Create the rsa public and private key file in current directory.</p>
@@ -956,8 +1027,6 @@ func main() {
}
```
### <span id="RsaEncrypt">RsaEncrypt</span>
<p>Encrypt data with public key file useing ras algorithm.</p>
@@ -981,19 +1050,21 @@ import (
func main() {
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
fmt.Println(err)
return
}
data := []byte("hello world")
data := []byte("hello")
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="RsaDecrypt">RsaDecrypt</span>
<p>Decrypt data with private key file useing ras algorithm.</p>
@@ -1017,14 +1088,17 @@ import (
func main() {
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
fmt.Println(err)
return
}
data := []byte("hello world")
data := []byte("hello")
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
}
```
+281 -205
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -46,7 +46,7 @@ import (
func NewHashMap() *HashMap
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -72,7 +72,7 @@ func main() {
func NewHashMapWithCapacity(size, capacity uint64) *HashMap
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -98,7 +98,7 @@ func main() {
func (hm *HashMap) Get(key any) any
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -126,7 +126,7 @@ func main() {
func (hm *HashMap) Put(key any, value any) any
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -155,7 +155,7 @@ func main() {
func (hm *HashMap) Delete(key any)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -187,7 +187,7 @@ func main() {
func (hm *HashMap) Contains(key any) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -217,7 +217,7 @@ func main() {
func (hm *HashMap) Iterate(iteratee func(key, value any))
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -252,7 +252,7 @@ func main() {
func (hm *HashMap) Keys() []any
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -284,7 +284,7 @@ func main() {
func (hm *HashMap) Values() []any
```
<b>例:</b>
<b>例:</b>
```go
package main
+7 -7
View File
@@ -48,7 +48,7 @@ type MaxHeap[T any] struct {
}
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -89,7 +89,7 @@ func main() {
```go
func (h *MaxHeap[T]) Push(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -136,7 +136,7 @@ func main() {
```go
func (h *MaxHeap[T]) Pop() (T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -184,7 +184,7 @@ func main() {
```go
func (h *MaxHeap[T]) Peek() (T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -232,7 +232,7 @@ func main() {
```go
func (h *MaxHeap[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -277,7 +277,7 @@ func main() {
```go
func (h *MaxHeap[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -323,7 +323,7 @@ func main() {
```go
func (h *MaxHeap[T]) PrintStructure()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -81,7 +81,7 @@ type SinglyLink[T any] struct {
}
func NewSinglyLink[T any]() *SinglyLink[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -107,7 +107,7 @@ func main() {
```go
func (link *SinglyLink[T]) Values() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -139,7 +139,7 @@ func main() {
```go
func (link *SinglyLink[T]) InsertAt(index int, value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -174,7 +174,7 @@ func main() {
```go
func (link *SinglyLink[T]) InsertAtHead(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -206,7 +206,7 @@ func main() {
```go
func (link *SinglyLink[T]) InsertAtTail(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -237,7 +237,7 @@ func main() {
```go
func (link *SinglyLink[T]) DeleteAt(index int)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -271,7 +271,7 @@ func main() {
```go
func (link *SinglyLink[T]) DeleteAtHead()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -306,7 +306,7 @@ func main() {
```go
func (link *SinglyLink[T]) DeleteAtTail()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -339,7 +339,7 @@ func main() {
```go
func (link *SinglyLink[T]) DeleteValue(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -373,7 +373,7 @@ func main() {
```go
func (link *SinglyLink[T]) Reverse()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -405,7 +405,7 @@ func main() {
```go
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -437,7 +437,7 @@ func main() {
```go
func (link *SinglyLink[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -468,7 +468,7 @@ func main() {
```go
func (link *SinglyLink[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -500,7 +500,7 @@ func main() {
```go
func (link *SinglyLink[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -533,7 +533,7 @@ func main() {
```go
func (link *SinglyLink[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -576,7 +576,7 @@ type DoublyLink[T any] struct {
}
func NewDoublyLink[T any]() *DoublyLink[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -602,7 +602,7 @@ func main() {
```go
func (link *DoublyLink[T]) Values() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -634,7 +634,7 @@ func main() {
```go
func (link *DoublyLink[T]) InsertAt(index int, value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -669,7 +669,7 @@ func main() {
```go
func (link *DoublyLink[T]) InsertAtHead(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -701,7 +701,7 @@ func main() {
```go
func (link *DoublyLink[T]) InsertAtTail(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -732,7 +732,7 @@ func main() {
```go
func (link *DoublyLink[T]) DeleteAt(index int)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -766,7 +766,7 @@ func main() {
```go
func (link *DoublyLink[T]) DeleteAtHead()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -801,7 +801,7 @@ func main() {
```go
func (link *DoublyLink[T]) DeleteAtTail()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -835,7 +835,7 @@ func main() {
```go
func (link *DoublyLink[T]) Reverse()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -867,7 +867,7 @@ func main() {
```go
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -899,7 +899,7 @@ func main() {
```go
func (link *DoublyLink[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -930,7 +930,7 @@ func main() {
```go
func (link *DoublyLink[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -962,7 +962,7 @@ func main() {
```go
func (link *DoublyLink[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -995,7 +995,7 @@ func main() {
```go
func (link *DoublyLink[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
+234
View File
@@ -47,6 +47,13 @@ import (
- [Unique](#Unique)
- [Union](#Union)
- [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList)
- [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>
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p>
+264 -30
View File
@@ -34,7 +34,6 @@ import (
- [PopLast](#PopLast)
- [DeleteAt](#DeleteAt)
- [InsertAt](#InsertAt)
- [UpdateAt](#UpdateAt)
- [Equal](#Equal)
- [IsEmpty](#IsEmpty)
@@ -48,6 +47,13 @@ import (
- [Unique](#Unique)
- [Union](#Union)
- [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList)
- [DeleteIf](#DeleteIf)
@@ -66,7 +72,7 @@ type List[T any] struct {
}
func NewList[T any](data []T) *List[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -92,7 +98,7 @@ func main() {
```go
func (l *List[T]) Contain(value T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -121,7 +127,7 @@ func main() {
```go
func (l *List[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -150,7 +156,7 @@ func main() {
```go
func (l *List[T]) ValueOf(index int) (*T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -180,7 +186,7 @@ func main() {
```go
func (l *List[T]) IndexOf(value T) int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -207,7 +213,7 @@ func main() {
```go
func (l *List[T]) LastIndexOf(value T) int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -233,7 +239,7 @@ func main() {
```go
func (l *List[T]) IndexOfFunc(f func(T) bool) int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -259,7 +265,7 @@ func main() {
```go
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -287,7 +293,7 @@ func main() {
```go
func (l *List[T]) Push(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -316,7 +322,7 @@ func main() {
```go
func (l *List[T]) PopFirst() (*T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -348,7 +354,7 @@ func main() {
```go
func (l *List[T]) PopLast() (*T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -379,7 +385,7 @@ func main() {
```go
func (l *List[T]) DeleteAt(index int)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -417,7 +423,7 @@ func main() {
```go
func (l *List[T]) InsertAt(index int, value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -454,7 +460,7 @@ func main() {
```go
func (l *List[T]) UpdateAt(index int, value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -487,7 +493,7 @@ func main() {
```go
func (l *List[T]) Equal(other *List[T]) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -517,7 +523,7 @@ func main() {
```go
func (l *List[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -547,7 +553,7 @@ func main() {
```go
func (l *List[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -575,7 +581,7 @@ func main() {
```go
func (l *List[T]) Clone() *List[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -604,7 +610,7 @@ func main() {
```go
func (l *List[T]) Merge(other *List[T]) *List[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -633,7 +639,7 @@ func main() {
```go
func (l *List[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -660,7 +666,7 @@ func main() {
```go
func (l *List[T]) Cap() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -689,7 +695,7 @@ func main() {
```go
func (l *List[T]) Swap(i, j int)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -718,7 +724,7 @@ func main() {
```go
func (l *List[T]) Reverse()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -747,7 +753,7 @@ func main() {
```go
func (l *List[T]) Unique()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -776,7 +782,7 @@ func main() {
```go
func (l *List[T]) Union(other *List[T]) *List[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -806,7 +812,7 @@ func main() {
```go
func (l *List[T]) Intersection(other *List[T]) *List[T]
```
<b>例:</b>
<b>例:</b>
```go
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>
<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>
```go
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -863,7 +1097,7 @@ func main() {
```go
func (l *List[T]) DeleteIf(f func(T) bool) int
```
<b>例:</b>
<b>例:</b>
```go
package main
+39 -39
View File
@@ -99,7 +99,7 @@ type ArrayQueue[T any] struct {
size int
}
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -125,7 +125,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -152,7 +152,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Enqueue(item T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -183,7 +183,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Dequeue() (T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -215,7 +215,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Front() T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -247,7 +247,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Back() T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -278,7 +278,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -308,7 +308,7 @@ func main() {
```go
func (q *ArrayQueue[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -341,7 +341,7 @@ func main() {
```go
func (q *ArrayQueue[T]) IsFull() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -373,7 +373,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -404,7 +404,7 @@ func main() {
```go
func (q *ArrayQueue[T]) Contain(value T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -448,7 +448,7 @@ type QueueNode[T any] struct {
Next *QueueNode[T]
}
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -474,7 +474,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -501,7 +501,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Enqueue(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -532,7 +532,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Dequeue() (T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -564,7 +564,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Front() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -596,7 +596,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Back() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -627,7 +627,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -657,7 +657,7 @@ func main() {
```go
func (q *LinkedQueue[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -690,7 +690,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -721,7 +721,7 @@ func main() {
```go
func (q *LinkedQueue[T]) Contain(value T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -763,7 +763,7 @@ type CircularQueue[T any] struct {
capacity int
}
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -789,7 +789,7 @@ func main() {
```go
func (q *CircularQueue[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -816,7 +816,7 @@ func main() {
```go
func (q *CircularQueue[T]) Enqueue(value T) error
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -847,7 +847,7 @@ func main() {
```go
func (q *CircularQueue[T]) Dequeue() (*T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -880,7 +880,7 @@ func main() {
```go
func (q *CircularQueue[T]) Front() T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -912,7 +912,7 @@ func main() {
```go
func (q *CircularQueue[T]) Back() T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -943,7 +943,7 @@ func main() {
```go
func (q *CircularQueue[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -973,7 +973,7 @@ func main() {
```go
func (q *CircularQueue[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1006,7 +1006,7 @@ func main() {
```go
func (q *CircularQueue[T]) IsFull() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1038,7 +1038,7 @@ func main() {
```go
func (q *CircularQueue[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1069,7 +1069,7 @@ func main() {
```go
func (q *CircularQueue[T]) Contain(value T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1108,7 +1108,7 @@ type PriorityQueue[T any] struct {
comparator lancetconstraints.Comparator
}
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1134,7 +1134,7 @@ func main() {
```go
func (q *PriorityQueue[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1161,7 +1161,7 @@ func main() {
```go
func (q *PriorityQueue[T]) Enqueue(item T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1207,7 +1207,7 @@ func main() {
```go
func (q *PriorityQueue[T]) Dequeue() (T, bool)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1254,7 +1254,7 @@ func main() {
```go
func (q *PriorityQueue[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1301,7 +1301,7 @@ func main() {
```go
func (q *PriorityQueue[T]) IsFull() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -1348,7 +1348,7 @@ func main() {
```go
func (q *PriorityQueue[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
+18 -18
View File
@@ -55,7 +55,7 @@ import (
type Set[T comparable] map[T]bool
func NewSet[T comparable](items ...T) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -81,7 +81,7 @@ func main() {
```go
func NewSetFromSlice[T comparable](items []T) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -107,7 +107,7 @@ func main() {
```go
func (s Set[T]) Values() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -134,7 +134,7 @@ func main() {
```go
func (s Set[T]) Add(items ...T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -161,7 +161,7 @@ func main() {
```go
func (s Set[T]) AddIfNotExist(item T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -193,7 +193,7 @@ func main() {
```go
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -232,7 +232,7 @@ func main() {
```go
func (s Set[T]) Delete(items ...T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -261,7 +261,7 @@ func main() {
```go
func (s Set[T]) Contain(item T) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -291,7 +291,7 @@ func main() {
```go
func (s Set[T]) ContainAll(other Set[T]) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -321,7 +321,7 @@ func main() {
```go
func (s Set[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -348,7 +348,7 @@ func main() {
```go
func (s Set[T]) Clone() Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -378,7 +378,7 @@ func main() {
```go
func (s Set[T]) Equal(other Set[T]) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -408,7 +408,7 @@ func main() {
```go
func (s Set[T]) Iterate(fn func(item T))
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -439,7 +439,7 @@ func main() {
```go
func (s Set[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -468,7 +468,7 @@ func main() {
```go
func (s Set[T]) Union(other Set[T]) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -497,7 +497,7 @@ func main() {
```go
func (s Set[T]) Intersection(other Set[T]) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -525,7 +525,7 @@ func main() {
```go
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -556,7 +556,7 @@ func main() {
```go
func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
+17 -17
View File
@@ -64,7 +64,7 @@ type ArrayStack[T any] struct {
}
func NewArrayStack[T any]() *ArrayStack[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -91,7 +91,7 @@ func main() {
```go
func (s *ArrayStack[T]) Push(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -122,7 +122,7 @@ func main() {
```go
func (s *ArrayStack[T]) Pop() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -157,7 +157,7 @@ func main() {
```go
func (s *ArrayStack[T]) Peak() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -192,7 +192,7 @@ func main() {
```go
func (s *ArrayStack[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -223,7 +223,7 @@ func main() {
```go
func (s *ArrayStack[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -254,7 +254,7 @@ func main() {
```go
func (s *ArrayStack[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -287,7 +287,7 @@ func main() {
```go
func (s *ArrayStack[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -331,7 +331,7 @@ type LinkedStack[T any] struct {
}
func NewLinkedStack[T any]() *LinkedStack[T]
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -358,7 +358,7 @@ func main() {
```go
func (s *LinkedStack[T]) Push(value T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -389,7 +389,7 @@ func main() {
```go
func (s *LinkedStack[T]) Pop() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -424,7 +424,7 @@ func main() {
```go
func (s *LinkedStack[T]) Peak() (*T, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -459,7 +459,7 @@ func main() {
```go
func (s *LinkedStack[T]) Data() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -490,7 +490,7 @@ func main() {
```go
func (s *LinkedStack[T]) Size() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -521,7 +521,7 @@ func main() {
```go
func (s *LinkedStack[T]) IsEmpty() bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -554,7 +554,7 @@ func main() {
```go
func (s *LinkedStack[T]) Clear()
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -588,7 +588,7 @@ func main() {
```go
func (s *LinkedStack[T]) Print()
```
<b>例:</b>
<b>例:</b>
```go
package main
+10 -10
View File
@@ -62,7 +62,7 @@ type TreeNode[T any] struct {
Right *TreeNode[T]
}
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -103,7 +103,7 @@ func main() {
```go
func (t *BSTree[T]) Insert(data T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -149,7 +149,7 @@ func main() {
```go
func (t *BSTree[T]) Delete(data T)
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -197,7 +197,7 @@ func main() {
```go
func (t *BSTree[T]) PreOrderTraverse() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -243,7 +243,7 @@ func main() {
```go
func (t *BSTree[T]) InOrderTraverse() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -289,7 +289,7 @@ func main() {
```go
func (t *BSTree[T]) PostOrderTraverse() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -335,7 +335,7 @@ func main() {
```go
func (t *BSTree[T]) LevelOrderTraverse() []T
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -381,7 +381,7 @@ func main() {
```go
func (t *BSTree[T]) Depth() int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -427,7 +427,7 @@ func main() {
```go
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -479,7 +479,7 @@ func main() {
```go
func (t *BSTree[T]) Print()
```
<b>例:</b>
<b>例:</b>
```go
package main
+268 -100
View File
@@ -1,4 +1,5 @@
# Datetime
Package datetime supports date and time format and compare.
<div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ Package datetime supports date and time format and compare.
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/datetime"
@@ -20,6 +22,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [AddDay](#AddDay)
- [AddHour](#AddHour)
- [AddMinute](#AddMinute)
@@ -51,14 +54,14 @@ import (
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div>
## Documentation
## Note:
1. 'format' string param in func FormatTimeToStr and FormatStrToTime function should be one of flows:
- yyyy-mm-dd hh:mm:ss
- yyyy-mm-dd hh:mm
- yyyy-mm-dd hh
@@ -78,8 +81,8 @@ import (
- hh:mm:ss
- mm:ss
### <span id="AddDay">AddDay</span>
<p>Add or sub days to time.</p>
<b>Signature:</b>
@@ -87,6 +90,7 @@ import (
```go
func AddDay(t time.Time, day int64) time.Time
```
<b>Example:</b>
```go
@@ -100,15 +104,24 @@ import (
func main() {
now := time.Now()
after2Days := datetime.AddDay(now, 2)
before2Days := datetime.AddDay(now, -2)
fmt.Println(after2Days, before2Days)
tomorrow := datetime.AddDay(now, 1)
diff1 := tomorrow.Sub(now)
yesterday := datetime.AddDay(now, -1)
diff2 := yesterday.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 24h0m0s
// -24h0m0s
}
```
### <span id="AddHour">AddHour</span>
<p>Add or sub hours to time.</p>
<b>Signature:</b>
@@ -116,6 +129,7 @@ func main() {
```go
func AddHour(t time.Time, hour int64) time.Time
```
<b>Example:</b>
```go
@@ -129,14 +143,24 @@ import (
func main() {
now := time.Now()
after2Hours := datetime.AddHour(now, 2)
before2Hours := datetime.AddHour(now, -2)
fmt.Println(after2Hours, after2Hours)
after2Hours := datetime.AddHour(now, 2)
diff1 := after2Hours.Sub(now)
before2Hours := datetime.AddHour(now, -2)
diff2 := before2Hours.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2h0m0s
// -2h0m0s
}
```
### <span id="AddMinute">AddMinute</span>
<p>Add or sub minutes to time.</p>
<b>Signature:</b>
@@ -144,6 +168,7 @@ func main() {
```go
func AddMinute(t time.Time, minute int64) time.Time
```
<b>Example:</b>
```go
@@ -157,14 +182,24 @@ import (
func main() {
now := time.Now()
after2Minute := datetime.AddMinute(now, 2)
before2Minute := datetime.AddMinute(now, -2)
fmt.Println(after2Minute, before2Minute)
after2Minutes := datetime.AddMinute(now, 2)
diff1 := after2Minutes.Sub(now)
before2Minutes := datetime.AddMinute(now, -2)
diff2 := before2Minutes.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2m0s
// -2m0s
}
```
### <span id="BeginOfMinute">BeginOfMinute</span>
<p>Return beginning minute time of day.</p>
<b>Signature:</b>
@@ -172,6 +207,7 @@ func main() {
```go
func BeginOfMinute(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -184,13 +220,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfMinute(td)
fmt.Println(bm) //2022-02-15 15:48:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:00 +0000 UTC
}
```
### <span id="BeginOfHour">BeginOfHour</span>
<p>Return zero time of day.</p>
<b>Signature:</b>
@@ -198,6 +239,7 @@ func main() {
```go
func BeginOfHour(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -210,13 +252,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfHour(td)
fmt.Println(bm) //2022-02-15 15:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:00:00 +0000 UTC
}
```
### <span id="BeginOfDay">BeginOfDay</span>
<p>Return begin time of day.</p>
<b>Signature:</b>
@@ -224,6 +271,7 @@ func main() {
```go
func BeginOfDay(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -236,15 +284,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfDay(td)
fmt.Println(bm) //2022-02-15 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
```
### <span id="BeginOfWeek">BeginOfWeek</span>
<p>Return beginning time of week, week begin from Sunday.</p>
<b>Signature:</b>
@@ -252,6 +303,7 @@ func main() {
```go
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
```
<b>Example:</b>
```go
@@ -264,15 +316,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfWeek(td)
fmt.Println(bm) //2022-02-13 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
```
### <span id="BeginOfMonth">BeginOfMonth</span>
<p>Return beginning time of month</p>
<b>Signature:</b>
@@ -280,6 +335,7 @@ func main() {
```go
func BeginOfMonth(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -292,14 +348,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfMonth(td)
fmt.Println(bm) //2022-02-01 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
```
### <span id="BeginOfYear">BeginOfYear</span>
<p>Return beginning time of year.</p>
<b>Signature:</b>
@@ -307,6 +367,7 @@ func main() {
```go
func BeginOfYear(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -319,15 +380,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfYear(td)
fmt.Println(bm) //2022-01-01 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfYear(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
```
### <span id="EndOfMinute">EndOfMinute</span>
<p>Return end time minute of day.</p>
<b>Signature:</b>
@@ -335,6 +399,7 @@ func main() {
```go
func EndOfMinute(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -347,13 +412,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfMinute(td)
fmt.Println(bm) //2022-02-15 15:48:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:59.999999999 +0000 UTC
}
```
### <span id="EndOfHour">EndOfHour</span>
<p>Return end time hour of day.</p>
<b>Signature:</b>
@@ -361,6 +431,7 @@ func main() {
```go
func EndOfHour(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -373,13 +444,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfHour(td)
fmt.Println(bm) //2022-02-15 15:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfDay">EndOfDay</span>
<p>Return end time hour of day.</p>
<b>Signature:</b>
@@ -387,6 +463,7 @@ func main() {
```go
func EndOfDay(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -399,15 +476,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfDay(td)
fmt.Println(bm) //2022-02-15 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfWeek">EndOfWeek</span>
<p>Return end time of week, week end with Saturday.</p>
<b>Signature:</b>
@@ -415,6 +495,7 @@ func main() {
```go
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
```
<b>Example:</b>
```go
@@ -427,15 +508,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfWeek(td)
fmt.Println(bm) //2022-02-19 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-14 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfMonth">EndOfMonth</span>
<p>Return end time of month</p>
<b>Signature:</b>
@@ -443,6 +527,7 @@ func main() {
```go
func EndOfMonth(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -455,14 +540,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfMonth(td)
fmt.Println(bm) //2022-02-28 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-31 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfYear">EndOfYear</span>
<p>Return beginning time of year.</p>
<b>Signature:</b>
@@ -470,6 +559,7 @@ func main() {
```go
func EndOfYear(t time.Time) time.Time
```
<b>Example:</b>
```go
@@ -482,14 +572,18 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfYear(td)
fmt.Println(bm) //2022-12-31 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfYear(input)
fmt.Println(result)
// Output:
// 2023-12-31 23:59:59.999999999 +0000 UTC
}
```
### <span id="GetNowDate">GetNowDate</span>
<p>Get current date string, format is yyyy-mm-dd.</p>
<b>Signature:</b>
@@ -497,6 +591,7 @@ func main() {
```go
func GetNowDate() string
```
<b>Example:</b>
```go
@@ -511,12 +606,16 @@ import (
func main() {
now := time.Now()
currentDate := datetime.GetNowDate()
fmt.Println(currentDate) // 2022-01-28
fmt.Println(currentDate)
// Output:
// 2022-01-28
}
```
### <span id="GetNowTime">GetNowTime</span>
<p>Get current time string, format is hh:mm:ss.</p>
<b>Signature:</b>
@@ -524,6 +623,7 @@ func main() {
```go
func GetNowTime() string
```
<b>Example:</b>
```go
@@ -538,12 +638,16 @@ import (
func main() {
now := time.Now()
currentTime := datetime.GetNowTime()
fmt.Println(currentDate) // 15:57:33
fmt.Println(currentTime) // 15:57:33
// Output:
// 15:57:33
}
```
### <span id="GetNowDateTime">GetNowDateTime</span>
<p>Get current date time string, format is yyyy-mm-dd hh:mm:ss.</p>
<b>Signature:</b>
@@ -551,6 +655,7 @@ func main() {
```go
func GetNowDateTime() string
```
<b>Example:</b>
```go
@@ -565,12 +670,16 @@ import (
func main() {
now := time.Now()
current := datetime.GetNowDateTime()
fmt.Println(current) // 2022-01-28 15:59:33
fmt.Println(current)
// Output:
// 2022-01-28 15:59:33
}
```
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>Return timestamp of zero hour (timestamp of 00:00).</p>
<b>Signature:</b>
@@ -578,6 +687,7 @@ func main() {
```go
func GetZeroHourTimestamp() int64
```
<b>Example:</b>
```go
@@ -592,12 +702,16 @@ import (
func main() {
now := time.Now()
zeroTime := datetime.GetZeroHourTimestamp()
fmt.Println(zeroTime) // 1643299200
fmt.Println(zeroTime)
// Output:
// 1643299200
}
```
### <span id="GetNightTimestamp">GetNightTimestamp</span>
<p>Return timestamp of zero hour (timestamp of 23:59).</p>
<b>Signature:</b>
@@ -605,6 +719,7 @@ func main() {
```go
func GetNightTimestamp() int64
```
<b>Example:</b>
```go
@@ -619,11 +734,16 @@ import (
func main() {
now := time.Now()
nightTime := datetime.GetNightTimestamp()
fmt.Println(nightTime) // 1643385599
fmt.Println(nightTime)
// Output:
// 1643385599
}
```
### <span id="FormatTimeToStr">FormatTimeToStr</span>
<p>Format time to string, `format` param specification see note 1.</p>
<b>Signature:</b>
@@ -631,6 +751,7 @@ func main() {
```go
func FormatTimeToStr(t time.Time, format string) string
```
<b>Example:</b>
```go
@@ -643,14 +764,25 @@ import (
)
func main() {
now := time.Now()
timeStr := datetime.FormatTimeToStr(now, "yyyy/mm/dd hh:mm:ss")
fmt.Println(timeStr) //2022/01/28 16:07:44
t, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
result1 := datetime.FormatTimeToStr(t, "yyyy-mm-dd hh:mm:ss")
result2 := datetime.FormatTimeToStr(t, "yyyy-mm-dd")
result3 := datetime.FormatTimeToStr(t, "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08
// 2021-01-02
// 02-01-21 16:04:08
}
```
### <span id="FormatStrToTime">FormatStrToTime</span>
<p>Format string to time, `format` param specification see note 1.</p>
<b>Signature:</b>
@@ -658,6 +790,7 @@ func main() {
```go
func FormatStrToTime(str, format string) (time.Time, error)
```
<b>Example:</b>
```go
@@ -669,14 +802,23 @@ import (
)
func main() {
time := datetime.FormatStrToTime("2006-01-02 15:04:05", "yyyy/mm/dd hh:mm:ss")
fmt.Println(time)
result1, _ := datetime.FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss")
result2, _ := datetime.FormatStrToTime("2021-01-02", "yyyy-mm-dd")
result3, _ := datetime.FormatStrToTime("02-01-21 16:04:08", "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08 +0000 UTC
// 2021-01-02 00:00:00 +0000 UTC
// 2021-01-02 16:04:08 +0000 UTC
}
```
### <span id="NewUnixNow">NewUnixNow</span>
<p>Return unix timestamp of current time</p>
<b>Signature:</b>
@@ -687,6 +829,7 @@ type theTime struct {
}
func NewUnixNow() *theTime
```
<b>Example:</b>
```go
@@ -699,12 +842,15 @@ import (
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
fmt.Println(tm)
// Output:
// &{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>Return unix timestamp of specified int64 value.</p>
<b>Signature:</b>
@@ -715,6 +861,7 @@ type theTime struct {
}
func NewUnix(unix int64) *theTime
```
<b>Example:</b>
```go
@@ -727,13 +874,15 @@ import (
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
fmt.Println(tm)
// Output:
// &{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>Return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".</p>
<b>Signature:</b>
@@ -744,6 +893,7 @@ type theTime struct {
}
func NewFormat(t string) (*theTime, error)
```
<b>Example:</b>
```go
@@ -756,14 +906,15 @@ import (
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
fmt.Println(tm)
// Output:
// &{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>Return unix timestamp of specified iso8601 time string.</p>
<b>Signature:</b>
@@ -774,6 +925,7 @@ type theTime struct {
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>Example:</b>
```go
@@ -786,13 +938,15 @@ import (
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
fmt.Println(tm)
// Output:
// &{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>Return unix timestamp.</p>
<b>Signature:</b>
@@ -800,6 +954,7 @@ func main() {
```go
func (t *theTime) ToUnix() int64
```
<b>Example:</b>
```go
@@ -812,13 +967,15 @@ import (
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
fmt.Println(tm.ToUnix())
// Output:
// 1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>Return time string 'yyyy-mm-dd hh:mm:ss'.</p>
<b>Signature:</b>
@@ -826,6 +983,7 @@ func main() {
```go
func (t *theTime) ToFormat() string
```
<b>Example:</b>
```go
@@ -838,13 +996,15 @@ import (
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
fmt.Println(tm.ToFormat())
// Output:
// 2022-03-18 17:04:05
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>Return the time string which format is specified tpl.</p>
<b>Signature:</b>
@@ -852,6 +1012,7 @@ func main() {
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>Example:</b>
```go
@@ -865,12 +1026,15 @@ import (
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
fmt.Println(ts)
// Output:
// 2022/03/18 17:04:05
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>Return iso8601 time string.</p>
<b>Signature:</b>
@@ -878,6 +1042,7 @@ func main() {
```go
func (t *theTime) ToIso8601() string
```
<b>Example:</b>
```go
@@ -891,6 +1056,9 @@ import (
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
fmt.Println(ts)
// Output:
// 2006-01-02T23:04:05+08:00
}
```
+351 -184
View File
@@ -77,14 +77,16 @@ import (
### <span id="AddDay">AddDay</span>
<p>将日期加/减天数</p>
<b>函数签名:</b>
<p>将日期加/减天数。</p>
<b>Signature:</b>
```go
func AddDay(t time.Time, day int64) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -97,23 +99,33 @@ import (
func main() {
now := time.Now()
after2Days := datetime.AddDay(now, 2)
before2Days := datetime.AddDay(now, -2)
fmt.Println(after2Days, before2Days)
tomorrow := datetime.AddDay(now, 1)
diff1 := tomorrow.Sub(now)
yesterday := datetime.AddDay(now, -1)
diff2 := yesterday.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 24h0m0s
// -24h0m0s
}
```
### <span id="AddHour">AddHour</span>
<p>将日期加/减小时数</p>
<b>函数签名:</b>
<p>将日期加/减小时数。</p>
<b>Signature:</b>
```go
func AddHour(t time.Time, hour int64) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -126,22 +138,33 @@ import (
func main() {
now := time.Now()
after2Hours := datetime.AddHour(now, 2)
before2Hours := datetime.AddHour(now, -2)
fmt.Println(after2Hours, after2Hours)
after2Hours := datetime.AddHour(now, 2)
diff1 := after2Hours.Sub(now)
before2Hours := datetime.AddHour(now, -2)
diff2 := before2Hours.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2h0m0s
// -2h0m0s
}
```
### <span id="AddMinute">AddMinute</span>
<p>将日期加/减分钟数</p>
<b>函数签名:</b>
<p>将日期加/减分钟数。</p>
<b>Signature:</b>
```go
func AddMinute(t time.Time, minute int64) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -154,22 +177,33 @@ import (
func main() {
now := time.Now()
after2Minute := datetime.AddMinute(now, 2)
before2Minute := datetime.AddMinute(now, -2)
fmt.Println(after2Minute, before2Minute)
after2Minutes := datetime.AddMinute(now, 2)
diff1 := after2Minutes.Sub(now)
before2Minutes := datetime.AddMinute(now, -2)
diff2 := before2Minutes.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2m0s
// -2m0s
}
```
### <span id="BeginOfMinute">BeginOfMinute</span>
<p>返回指定时间的分钟开始时间</p>
<b>函数签名:</b>
<p>返回指定时间的分钟开始时间。</p>
<b>Signature:</b>
```go
func BeginOfMinute(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -181,21 +215,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfMinute(td)
fmt.Println(bm) //2022-02-15 15:48:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:00 +0000 UTC
}
```
### <span id="BeginOfHour">BeginOfHour</span>
<p>返回指定时间的小时开始时间</p>
<b>函数签名:</b>
<p>返回指定时间的小时开始时间。</p>
<b>Signature:</b>
```go
func BeginOfHour(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -207,21 +247,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfHour(td)
fmt.Println(bm) //2022-02-15 15:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:00:00 +0000 UTC
}
```
### <span id="BeginOfDay">BeginOfDay</span>
<p>返回指定时间的当天开始时间</p>
<b>函数签名:</b>
<p>返回指定时间的当天开始时间。</p>
<b>Signature:</b>
```go
func BeginOfDay(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -233,23 +279,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfDay(td)
fmt.Println(bm) //2022-02-15 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
```
### <span id="BeginOfWeek">BeginOfWeek</span>
<p>返回指定时间的每周开始时间,默认开始时间星期日</p>
<b>函数签名:</b>
<p>返回指定时间的每周开始时间,默认开始时间星期日。</p>
<b>Signature:</b>
```go
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -261,23 +311,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfWeek(td)
fmt.Println(bm) //2022-02-13 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
```
### <span id="BeginOfMonth">BeginOfMonth</span>
<p>返回指定时间的当月开始时间</p>
<b>函数签名:</b>
<p>返回指定时间的当月开始时间。</p>
<b>Signature:</b>
```go
func BeginOfMonth(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -289,22 +343,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfMonth(td)
fmt.Println(bm) //2022-02-01 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
```
### <span id="BeginOfYear">BeginOfYear</span>
<p>返回指定时间的当年开始时间</p>
<b>函数签名:</b>
<b>Signature:</b>
```go
func BeginOfYear(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -316,23 +375,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.BeginOfYear(td)
fmt.Println(bm) //2022-01-01 00:00:00 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.BeginOfYear(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
```
### <span id="EndOfMinute">EndOfMinute</span>
<p>返回指定时间的分钟结束时间</p>
<b>函数签名:</b>
<p>返回指定时间的分钟结束时间。</p>
<b>Signature:</b>
```go
func EndOfMinute(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -344,21 +407,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfMinute(td)
fmt.Println(bm) //2022-02-15 15:48:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:59.999999999 +0000 UTC
}
```
### <span id="EndOfHour">EndOfHour</span>
<p>返回指定时间的小时结束时间</p>
<b>函数签名:</b>
<p>返回指定时间的小时结束时间。</p>
<b>Signature:</b>
```go
func EndOfHour(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -370,21 +439,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfHour(td)
fmt.Println(bm) //2022-02-15 15:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfDay">EndOfDay</span>
<p>返回指定时间的当天结束时间.</p>
<b>函数签名:</b>
<p>返回指定时间的当天结束时间。</p>
<b>Signature:</b>
```go
func EndOfDay(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -396,23 +471,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfDay(td)
fmt.Println(bm) //2022-02-15 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfWeek">EndOfWeek</span>
<p>返回指定时间的星期结束时间,默认结束时间星期六</p>
<b>函数签名:</b>
<p>返回指定时间的星期结束时间,默认结束时间星期六。</p>
<b>Signature:</b>
```go
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -424,23 +503,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfWeek(td)
fmt.Println(bm) //2022-02-19 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-14 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfMonth">EndOfMonth</span>
<p>返回指定时间的月份结束时间</p>
<b>函数签名:</b>
<p>返回指定时间的当月结束时间。</p>
<b>Signature:</b>
```go
func EndOfMonth(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -452,22 +535,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfMonth(td)
fmt.Println(bm) //2022-02-28 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-31 23:59:59.999999999 +0000 UTC
}
```
### <span id="EndOfYear">EndOfYear</span>
<p>返回指定时间的年份结束时间</p>
<b>函数签名:</b>
<p>返回指定时间的当年结束时间。</p>
<b>Signature:</b>
```go
func EndOfYear(t time.Time) time.Time
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -479,22 +567,27 @@ import (
)
func main() {
td := time.Date(2022, 2, 15, 15, 48, 40, 112, time.Local)
bm := datetime.EndOfYear(td)
fmt.Println(bm) //2022-12-31 23:59:59.999999999 +0800 CST
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := datetime.EndOfYear(input)
fmt.Println(result)
// Output:
// 2023-12-31 23:59:59.999999999 +0000 UTC
}
```
### <span id="GetNowDate">GetNowDate</span>
<p>获取当天日期,返回格式:yyyy-mm-dd</p>
<b>函数签名:</b>
<p>获取当天日期,返回格式:yyyy-mm-dd。</p>
<b>Signature:</b>
```go
func GetNowDate() string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -508,20 +601,25 @@ import (
func main() {
now := time.Now()
currentDate := datetime.GetNowDate()
fmt.Println(currentDate) // 2022-01-28
fmt.Println(currentDate)
// Output:
// 2022-01-28
}
```
### <span id="GetNowTime">GetNowTime</span>
<p>获取当时时间,返回格式:hh:mm:ss</p>
<b>函数签名:</b>
<b>Signature:</b>
```go
func GetNowTime() string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -535,20 +633,25 @@ import (
func main() {
now := time.Now()
currentTime := datetime.GetNowTime()
fmt.Println(currentDate) // 15:57:33
fmt.Println(currentTime) // 15:57:33
// Output:
// 15:57:33
}
```
### <span id="GetNowDateTime">GetNowDateTime</span>
<p>获取当时日期和时间,返回格式:yyyy-mm-dd hh:mm:ss.</p>
<b>函数签名:</b>
<p>获取当时日期和时间,返回格式:yyyy-mm-dd hh:mm:ss。</p>
<b>Signature:</b>
```go
func GetNowDateTime() string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -562,20 +665,25 @@ import (
func main() {
now := time.Now()
current := datetime.GetNowDateTime()
fmt.Println(current) // 2022-01-28 15:59:33
fmt.Println(current)
// Output:
// 2022-01-28 15:59:33
}
```
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>获取零时时间戳(timestamp of 00:00).</p>
<b>函数签名:</b>
<p>获取零点时间戳(timestamp of 00:00)</p>
<b>Signature:</b>
```go
func GetZeroHourTimestamp() int64
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -589,20 +697,25 @@ import (
func main() {
now := time.Now()
zeroTime := datetime.GetZeroHourTimestamp()
fmt.Println(zeroTime) // 1643299200
fmt.Println(zeroTime)
// Output:
// 1643299200
}
```
### <span id="GetNightTimestamp">GetNightTimestamp</span>
<p>获取午夜时间戳(timestamp of 23:59).</p>
<b>函数签名:</b>
<p>获取午夜时间戳(timestamp of 23:59)。</p>
<b>Signature:</b>
```go
func GetNightTimestamp() int64
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -616,19 +729,25 @@ import (
func main() {
now := time.Now()
nightTime := datetime.GetNightTimestamp()
fmt.Println(nightTime) // 1643385599
fmt.Println(nightTime)
// Output:
// 1643385599
}
```
### <span id="FormatTimeToStr">FormatTimeToStr</span>
<p>将日期格式化成字符串,`format` 参数格式参考注<sup>1</sup></p>
<b>函数签名:</b>
<p>将日期格式化成字符串,`format` 参数格式参考注1。</p>
<b>Signature:</b>
```go
func FormatTimeToStr(t time.Time, format string) string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -640,22 +759,34 @@ import (
)
func main() {
now := time.Now()
timeStr := datetime.FormatTimeToStr(now, "yyyy/mm/dd hh:mm:ss")
fmt.Println(timeStr) //2022/01/28 16:07:44
t, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
result1 := datetime.FormatTimeToStr(t, "yyyy-mm-dd hh:mm:ss")
result2 := datetime.FormatTimeToStr(t, "yyyy-mm-dd")
result3 := datetime.FormatTimeToStr(t, "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08
// 2021-01-02
// 02-01-21 16:04:08
}
```
### <span id="FormatStrToTime">FormatStrToTime</span>
<p>将字符串格式化成时间,`format` 参数格式参考注<sup>1</sup></p>
<b>函数签名:</b>
<p>将字符串格式化成时间,`format` 参数格式参考注1。</p>
<b>Signature:</b>
```go
func FormatStrToTime(str, format string) (time.Time, error)
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -666,16 +797,26 @@ import (
)
func main() {
time := datetime.FormatStrToTime("2006-01-02 15:04:05", "yyyy/mm/dd hh:mm:ss")
fmt.Println(time)
result1, _ := datetime.FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss")
result2, _ := datetime.FormatStrToTime("2021-01-02", "yyyy-mm-dd")
result3, _ := datetime.FormatStrToTime("02-01-21 16:04:08", "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08 +0000 UTC
// 2021-01-02 00:00:00 +0000 UTC
// 2021-01-02 16:04:08 +0000 UTC
}
```
### <span id="NewUnixNow">NewUnixNow</span>
<p>创建一个当前时间的unix时间戳</p>
<b>函数签名:</b>
<p>创建一个当前时间的unix时间戳。</p>
<b>Signature:</b>
```go
type theTime struct {
@@ -683,7 +824,8 @@ type theTime struct {
}
func NewUnixNow() *theTime
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -695,15 +837,18 @@ import (
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
fmt.Println(tm)
// Output:
// &{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>创建一个unix时间戳</p>
<b>函数签名:</b>
<p>创建一个unix时间戳。</p>
<b>Signature:</b>
```go
type theTime struct {
@@ -711,7 +856,8 @@ type theTime struct {
}
func NewUnix(unix int64) *theTime
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -723,16 +869,18 @@ import (
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
fmt.Println(tm)
// Output:
// &{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳。</p>
<b>Signature:</b>
```go
type theTime struct {
@@ -740,7 +888,8 @@ type theTime struct {
}
func NewFormat(t string) (*theTime, error)
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -752,17 +901,18 @@ import (
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
fmt.Println(tm)
// Output:
// &{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>创建一个iso8601格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
<p>创建一个iso8601格式时间字符串的unix时间戳。</p>
<b>Signature:</b>
```go
type theTime struct {
@@ -770,7 +920,8 @@ type theTime struct {
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -782,21 +933,24 @@ import (
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
fmt.Println(tm)
// Output:
// &{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>返回unix时间戳</p>
<b>函数签名:</b>
<p>返回unix时间戳。</p>
<b>Signature:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -808,21 +962,24 @@ import (
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
fmt.Println(tm.ToUnix())
// Output:
// 1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串</p>
<b>函数签名:</b>
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormat() string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -834,21 +991,24 @@ import (
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
fmt.Println(tm.ToFormat())
// Output:
// 2022-03-18 17:04:05
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>返回tpl格式指定的日期字符串</p>
<b>函数签名:</b>
<p>返回tpl格式指定的日期字符串。</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -861,20 +1021,24 @@ import (
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
fmt.Println(ts)
// Output:
// 2022/03/18 17:04:05
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>返回iso8601日期字符串</p>
<b>函数签名:</b>
<p>返回iso8601日期字符串。</p>
<b>Signature:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>例子:</b>
<b>Example:</b>
```go
package main
@@ -887,6 +1051,9 @@ import (
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
fmt.Println(ts)
// Output:
// 2006-01-02T23:04:05+08:00
}
```
+33 -33
View File
@@ -1,4 +1,5 @@
# Fileutil
Package fileutil implements some basic functions for file operations.
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ Package fileutil implements some basic functions for file operations.
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/fileutil"
@@ -19,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [ClearFile](#ClearFile)
- [CreateFile](#CreateFile)
- [CreateDir](#CreateDir)
@@ -40,9 +43,8 @@ import (
## Documentation
### <span id="ClearFile">ClearFile</span>
<p>Clear the file content, write empty string to the file.</p>
<b>Signature:</b>
@@ -50,6 +52,7 @@ import (
```go
func ClearFile(path string) error
```
<b>Example:</b>
```go
@@ -69,6 +72,7 @@ func main() {
```
### <span id="CreateFile">CreateFile</span>
<p>Create file in path. return true if create succeed.</p>
<b>Signature:</b>
@@ -76,6 +80,7 @@ func main() {
```go
func CreateFile(path string) bool
```
<b>Example:</b>
```go
@@ -92,9 +97,8 @@ func main() {
}
```
### <span id="CreateDir">CreateDir</span>
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
<b>Signature:</b>
@@ -102,6 +106,7 @@ func main() {
```go
func CreateDir(absPath string) error
```
<b>Example:</b>
```go
@@ -118,8 +123,8 @@ func main() {
}
```
### <span id="CopyFile">CopyFile</span>
<p>Copy src file to dest file. If dest file exist will overwrite it.</p>
<b>Signature:</b>
@@ -127,6 +132,7 @@ func main() {
```go
func CopyFile(srcFilePath string, dstFilePath string) error
```
<b>Example:</b>
```go
@@ -145,9 +151,8 @@ func main() {
}
```
### <span id="FileMode">FileMode</span>
<p>Return file mode infomation.</p>
<b>Signature:</b>
@@ -155,6 +160,7 @@ func main() {
```go
func FileMode(path string) (fs.FileMode, error)
```
<b>Example:</b>
```go
@@ -174,9 +180,8 @@ func main() {
}
```
### <span id="MiMeType">MiMeType</span>
<p>Get file mime type, 'file' param's type should be string or *os.File.</p>
<b>Signature:</b>
@@ -184,6 +189,7 @@ func main() {
```go
func MiMeType(file any) string
```
<b>Example:</b>
```go
@@ -205,10 +211,8 @@ func main() {
}
```
### <span id="IsExist">IsExist</span>
<p>Checks if a file or directory exists.</p>
<b>Signature:</b>
@@ -216,6 +220,7 @@ func main() {
```go
func IsExist(path string) bool
```
<b>Example:</b>
```go
@@ -233,9 +238,8 @@ func main() {
}
```
### <span id="IsLink">IsLink</span>
<p>Checks if a file is symbol link or not.</p>
<b>Signature:</b>
@@ -243,6 +247,7 @@ func main() {
```go
func IsLink(path string) bool
```
<b>Example:</b>
```go
@@ -259,9 +264,8 @@ func main() {
}
```
### <span id="IsDir">IsDir</span>
<p>Checks if the path is directy or not.</p>
<b>Signature:</b>
@@ -269,6 +273,7 @@ func main() {
```go
func IsDir(path string) bool
```
<b>Example:</b>
```go
@@ -288,9 +293,8 @@ func main() {
}
```
### <span id="ListFileNames">ListFileNames</span>
<p>List all file names in given path.</p>
<b>Signature:</b>
@@ -298,6 +302,7 @@ func main() {
```go
func ListFileNames(path string) ([]string, error)
```
<b>Example:</b>
```go
@@ -314,9 +319,8 @@ func main() {
}
```
### <span id="RemoveFile">RemoveFile</span>
<p>Remove the file of path.</p>
<b>Signature:</b>
@@ -324,6 +328,7 @@ func main() {
```go
func RemoveFile(path string) error
```
<b>Example:</b>
```go
@@ -342,8 +347,8 @@ func main() {
}
```
### <span id="ReadFileToString">ReadFileToString</span>
<p>Return string of file content.</p>
<b>Signature:</b>
@@ -351,6 +356,7 @@ func main() {
```go
func ReadFileToString(path string) (string, error)
```
<b>Example:</b>
```go
@@ -374,9 +380,8 @@ func main() {
}
```
### <span id="ReadFileByLine">ReadFileByLine</span>
<p>Read file line by line, and return slice of lines</p>
<b>Signature:</b>
@@ -384,6 +389,7 @@ func main() {
```go
func ReadFileByLine(path string)([]string, error)
```
<b>Example:</b>
```go
@@ -408,9 +414,8 @@ func main() {
}
```
### <span id="Zip">Zip</span>
<p>Create a zip file of fpath, fpath could be a file or a directory.</p>
<b>Signature:</b>
@@ -418,6 +423,7 @@ func main() {
```go
func Zip(fpath string, destPath string) error
```
<b>Example:</b>
```go
@@ -436,10 +442,8 @@ func main() {
}
```
### <span id="UnZip">UnZip</span>
<p>Unzip the file and save it to dest path.</p>
<b>Signature:</b>
@@ -447,6 +451,7 @@ func main() {
```go
func UnZip(zipFile string, destPath string) error
```
<b>Example:</b>
```go
@@ -464,8 +469,3 @@ func main() {
}
}
```
+49 -49
View File
@@ -1,4 +1,5 @@
# Fileutil
fileutil 包支持文件基本操作。
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ fileutil包支持文件基本操作。
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/fileutil"
@@ -19,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [ClearFile](#ClearFile)
- [CreateFile](#CreateFile)
- [CreateDir](#CreateDir)
@@ -39,9 +42,8 @@ import (
## 文档
### <span id="ClearFile">ClearFile</span>
<p>清空文件内容</p>
<b>函数签名:</b>
@@ -49,7 +51,8 @@ import (
```go
func ClearFile(path string) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -68,6 +71,7 @@ func main() {
```
### <span id="CreateFile">CreateFile</span>
<p>创建文件,创建成功返回true, 否则返回false</p>
<b>函数签名:</b>
@@ -75,7 +79,8 @@ func main() {
```go
func CreateFile(path string) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -91,8 +96,8 @@ func main() {
}
```
### <span id="CreateDir">CreateDir</span>
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
<b>函数签名:</b>
@@ -100,6 +105,7 @@ func main() {
```go
func CreateDir(absPath string) error
```
<b>Example:</b>
```go
@@ -116,17 +122,17 @@ func main() {
}
```
### <span id="CopyFile">CopyFile</span>
<p>拷贝文件,会覆盖原有的拷贝文件</p>
<p>拷贝文件,会覆盖原有的文件</p>
<b>函数签名:</b>
```go
func CopyFile(srcFilePath string, dstFilePath string) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -144,9 +150,8 @@ func main() {
}
```
### <span id="FileMode">FileMode</span>
<p>获取文件mode信息</p>
<b>函数签名:</b>
@@ -154,7 +159,8 @@ func main() {
```go
func FileMode(path string) (fs.FileMode, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -173,9 +179,8 @@ func main() {
}
```
### <span id="MiMeType">MiMeType</span>
<p>获取文件mime类型, 'file'参数的类型必须是string或者*os.File</p>
<b>函数签名:</b>
@@ -183,7 +188,8 @@ func main() {
```go
func MiMeType(file any) string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -204,10 +210,8 @@ func main() {
}
```
### <span id="IsExist">IsExist</span>
<p>判断文件或目录是否存在</p>
<b>函数签名:</b>
@@ -215,7 +219,8 @@ func main() {
```go
func IsExist(path string) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -232,9 +237,8 @@ func main() {
}
```
### <span id="IsLink">IsLink</span>
<p>判断文件是否是符号链接</p>
<b>函数签名:</b>
@@ -242,7 +246,8 @@ func main() {
```go
func IsLink(path string) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -258,17 +263,17 @@ func main() {
}
```
### <span id="IsDir">IsDir</span>
<p>判断目录是否存在</p>
<p>判断参数是否是目录</p>
<b>函数签名:</b>
```go
func IsDir(path string) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -287,9 +292,8 @@ func main() {
}
```
### <span id="ListFileNames">ListFileNames</span>
<p>返回目录下所有文件名</p>
<b>函数签名:</b>
@@ -297,7 +301,8 @@ func main() {
```go
func ListFileNames(path string) ([]string, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -313,9 +318,8 @@ func main() {
}
```
### <span id="RemoveFile">RemoveFile</span>
<p>删除文件</p>
<b>函数签名:</b>
@@ -323,7 +327,8 @@ func main() {
```go
func RemoveFile(path string) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -341,8 +346,8 @@ func main() {
}
```
### <span id="ReadFileToString">ReadFileToString</span>
<p>读取文件内容并返回字符串</p>
<b>函数签名:</b>
@@ -350,7 +355,8 @@ func main() {
```go
func ReadFileToString(path string) (string, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -373,9 +379,8 @@ func main() {
}
```
### <span id="ReadFileByLine">ReadFileByLine</span>
<p>按行读取文件内容,返回字符串切片包含每一行</p>
<b>函数签名:</b>
@@ -383,7 +388,8 @@ func main() {
```go
func ReadFileByLine(path string)([]string, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -407,9 +413,8 @@ func main() {
}
```
### <span id="Zip">Zip</span>
<p>zip压缩文件, fpath参数可以是文件或目录</p>
<b>函数签名:</b>
@@ -417,7 +422,8 @@ func main() {
```go
func Zip(fpath string, destPath string) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -435,10 +441,8 @@ func main() {
}
```
### <span id="UnZip">UnZip</span>
<p>zip解压缩文件并保存在目录中</p>
<b>Signature:</b>
@@ -446,7 +450,8 @@ func main() {
```go
func UnZip(zipFile string, destPath string) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -463,8 +468,3 @@ func main() {
}
}
```
+17 -4
View File
@@ -1,4 +1,5 @@
# Formatter
formatter contains some functions for data formatting.
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ formatter contains some functions for data formatting.
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/formatter"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [Comma](#Comma)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Comma">Comma</span>
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
<b>Signature:</b>
@@ -35,6 +37,7 @@ import (
```go
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
```
<b>Example:</b>
```go
@@ -46,7 +49,17 @@ import (
)
func main() {
fmt.Println(formatter.Comma("12345", "")) // "12,345"
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
result1 := formatter.Comma("123", "")
result2 := formatter.Comma("12345", "$")
result3 := formatter.Comma(1234567, "¥")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 123
// $12,345
// ¥1,234,567
}
```
+18 -5
View File
@@ -1,4 +1,5 @@
# Formatter
formatter 格式化器包含一些数据格式化处理方法。
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ formatter格式化器包含一些数据格式化处理方法。
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/formatter"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [Comma](#Comma)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Comma">Comma</span>
<p>用逗号每隔3位分割数字/字符串,支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
<b>函数签名:</b>
@@ -35,7 +37,8 @@ import (
```go
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -46,7 +49,17 @@ import (
)
func main() {
fmt.Println(formatter.Comma("12345", "")) // "12,345"
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
result1 := formatter.Comma("123", "")
result2 := formatter.Comma("12345", "$")
result3 := formatter.Comma(1234567, "¥")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 123
// $12,345
// ¥1,234,567
}
```
+98 -93
View File
@@ -1,4 +1,5 @@
# Function
Package function can control the flow of function execution and support part of functional programming.
<div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ Package function can control the flow of function execution and support part of
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/function"
@@ -20,9 +22,10 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [After](#After)
- [Before](#Before)
- [Curry](#Curry)
- [CurryFn](#CurryFn)
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
@@ -33,9 +36,8 @@ import (
## Documentation
### <span id="After">After</span>
<p>Creates a function that invokes given func once it's called n or more times.</p>
<b>Signature:</b>
@@ -43,6 +45,7 @@ import (
```go
func After(n int, fn any) func(args ...any) []reflect.Value
```
<b>Example:</b>
```go
@@ -54,33 +57,18 @@ import (
)
func main() {
arr := []string{"a", "b"}
f := function.After(len(arr), func(i int) int {
fmt.Println("last print")
return i
fn := function.After(2, func() {
fmt.Println("hello")
})
type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
}
fn()
fn()
fmt.Println("arr is", arr)
for i := 0; i < len(arr); i++ {
print(i, arr[i], f)
}
//output:
// arr is [a b]
// arr[0] is a
// arr[1] is b
// last print
// Output:
// hello
}
```
### <span id="Before">Before</span>
<p>creates a function that invokes func once it's called less than n times.</p>
@@ -90,6 +78,7 @@ func main() {
```go
func Before(n int, fn any) func(args ...any) []reflect.Value
```
<b>Example:</b>
```go
@@ -102,39 +91,32 @@ import (
)
func main() {
arr := []string{"a", "b", "c", "d", "e"}
f := function.Before(3, func(i int) int {
return i
fn := function.Before(2, func() {
fmt.Println("hello")
})
var res []int64
type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) {
v := fn(i)
res = append(res, v[0].Int())
}
fn()
fn()
fn()
fn()
for i := 0; i < len(arr); i++ {
appendStr(i, arr[i], f)
}
expected := []int64{0, 1, 2, 2, 2}
fmt.Println(res) // 0, 1, 2, 2, 2
// Output:
// hello
// hello
}
```
### <span id="CurryFn">CurryFn</span>
### <span id="Curry">Curry</span>
<p>Make a curry function.</p>
<p>Make curry function.</p>
<b>Signature:</b>
```go
type Fn func(...any) any
func (f Fn) Curry(i any) func(...any) any
type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T
```
<b>Example:</b>
```go
@@ -149,17 +131,21 @@ func main() {
add := func(a, b int) int {
return a + b
}
var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
var addCurry function.CurryFn[int] = func(values ...int) int {
return add(values[0], values[1])
}
add1 := addCurry.Curry(1)
add1 := addCurry.New(1)
result := add1(2)
fmt.Println(result) //3
fmt.Println(result)
// Output:
// 3
}
```
### <span id="Compose">Compose</span>
<p>Compose the function list from right to left, then return the composed function.</p>
@@ -167,8 +153,9 @@ func main() {
<b>Signature:</b>
```go
func Compose(fnList ...func(...any) any) func(...any) any
func Compose[T any](fnList ...func(...T) T) func(...T) T
```
<b>Example:</b>
```go
@@ -180,22 +167,23 @@ import (
)
func main() {
add1 := func(v ...any) any {
return v[0].(int) + 1
toUpper := func(strs ...string) string {
return strings.ToUpper(strs[0])
}
add2 := func(v ...any) any {
return v[0].(int) + 2
toLower := func(strs ...string) string {
return strings.ToLower(strs[0])
}
transform := function.Compose(toUpper, toLower)
add3 := function.Compose(add1, add2)
result := add3(1)
result := transform("aBCde")
fmt.Println(result) //4
fmt.Println(result)
// Output:
// ABCDE
}
```
### <span id="Debounced">Debounced</span>
<p>Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.</p>
@@ -205,6 +193,7 @@ func main() {
```go
func Debounced(fn func(), duration time.Duration) func()
```
<b>Example:</b>
```go
@@ -217,27 +206,34 @@ import (
func main() {
count := 0
add := func() {
count++
}
debouncedAdd := function.Debounced(add, 50*time.Microsecond)
function.debouncedAdd()
function.debouncedAdd()
function.debouncedAdd()
function.debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count) //1
function.debouncedAdd()
fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count) //2
fmt.Println(count)
// Output:
// 1
// 2
}
```
### <span id="Delay">Delay</span>
<p>Invoke function after delayed time.</p>
@@ -247,6 +243,7 @@ func main() {
```go
func Delay(delay time.Duration, fn any, args ...any)
```
<b>Example:</b>
```go
@@ -259,14 +256,16 @@ import (
func main() {
var print = func(s string) {
fmt.Println(count) //test delay
fmt.Println(s)
}
function.Delay(2*time.Second, print, "test delay")
function.Delay(2*time.Second, print, "hello")
// Output:
// hello
}
```
### <span id="Schedule">Schedule</span>
<p>Invoke function every duration time, until close the returned bool chan.</p>
@@ -276,6 +275,7 @@ func main() {
```go
func Schedule(d time.Duration, fn any, args ...any) chan bool
```
<b>Example:</b>
```go
@@ -287,20 +287,24 @@ import (
)
func main() {
var res []string
appendStr := func(s string) {
res = append(res, s)
count := 0
increase := func() {
count++
}
stop := function.Schedule(1*time.Second, appendStr, "*")
time.Sleep(5 * time.Second)
stop := function.Schedule(2*time.Second, increase)
time.Sleep(2 * time.Second)
close(stop)
fmt.Println(res) //[* * * * *]
fmt.Println(count)
// Output:
// 2
}
```
### <span id="Pipeline">Pipeline</span>
<p>Pipeline takes a list of functions and returns a function whose param will be passed into
@@ -311,6 +315,7 @@ the functions one by one.</p>
```go
func Pipeline[T any](funcs ...func(T) T) func(T) T
```
<b>Example:</b>
```go
@@ -332,13 +337,17 @@ func main() {
return x * x
}
f := Pipeline(addOne, double, square)
fn := function.Pipeline(addOne, double, square)
fmt.Println(f(2)) //36
result := fn(2)
fmt.Println(result)
// Output:
// 36
}
```
### <span id="Watcher">Watcher</span>
<p>Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.</p>
@@ -351,11 +360,13 @@ type Watcher struct {
stopTime int64
excuting bool
}
func NewWatcher() *Watcher
func (w *Watcher) Start() //start the watcher
func (w *Watcher) Stop() //stop the watcher
func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
```
<b>Example:</b>
```go
@@ -367,7 +378,8 @@ import (
)
func main() {
w := &function.Watcher{}
w := function.NewWatcher()
w.Start()
longRunningTask()
@@ -377,14 +389,10 @@ func main() {
w.Stop()
eapsedTime := w.GetElapsedTime().Milliseconds()
fmt.Println(eapsedTime)
w.Reset()
fmt.Println(w.excuting) //false
fmt.Println(w.startTime) //0
fmt.Println(w.stopTime) //0
}
func longRunningTask() {
@@ -395,6 +403,3 @@ func longRunningTask() {
}
```
+107 -102
View File
@@ -1,4 +1,5 @@
# Function
function 函数包控制函数执行流程,包含部分函数式编程。
<div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ function函数包控制函数执行流程,包含部分函数式编程。
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/function"
@@ -20,9 +22,10 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [After](#After)
- [Before](#Before)
- [Curry](#Curry)
- [CurryFn](#CurryFn)
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
@@ -33,9 +36,8 @@ import (
## 文档
### <span id="After">After</span>
<p>创建一个函数,当他被调用n或更多次之后将马上触发fn</p>
<b>函数签名:</b>
@@ -43,7 +45,8 @@ import (
```go
func After(n int, fn any) func(args ...any) []reflect.Value
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -54,33 +57,18 @@ import (
)
func main() {
arr := []string{"a", "b"}
f := function.After(len(arr), func(i int) int {
fmt.Println("last print")
return i
fn := function.After(2, func() {
fmt.Println("hello")
})
type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
}
fn()
fn()
fmt.Println("arr is", arr)
for i := 0; i < len(arr); i++ {
print(i, arr[i], f)
}
//output:
// arr is [a b]
// arr[0] is a
// arr[1] is b
// last print
// Output:
// hello
}
```
### <span id="Before">Before</span>
<p>创建一个函数,调用次数不超过n次,之后再调用这个函数,将返回一次最后调用fn的结果</p>
@@ -90,7 +78,8 @@ func main() {
```go
func Before(n int, fn any) func(args ...any) []reflect.Value
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -102,39 +91,33 @@ import (
)
func main() {
arr := []string{"a", "b", "c", "d", "e"}
f := function.Before(3, func(i int) int {
return i
fn := function.Before(2, func() {
fmt.Println("hello")
})
var res []int64
type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) {
v := fn(i)
res = append(res, v[0].Int())
}
fn()
fn()
fn()
fn()
for i := 0; i < len(arr); i++ {
appendStr(i, arr[i], f)
}
fmt.Println(res) // 0, 1, 2, 2, 2
// Output:
// hello
// hello
}
```
### <span id="CurryFn">CurryFn</span>
### <span id="Curry">Curry</span>
<p>创建一个柯里化的函数</p>
<p>创建柯里化函数</p>
<b>函数签名:</b>
```go
type Fn func(...any) any
func (f Fn) Curry(i any) func(...any) any
type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -148,17 +131,21 @@ func main() {
add := func(a, b int) int {
return a + b
}
var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
var addCurry function.CurryFn[int] = func(values ...int) int {
return add(values[0], values[1])
}
add1 := addCurry.Curry(1)
add1 := addCurry.New(1)
result := add1(2)
fmt.Println(result) //3
fmt.Println(result)
// Output:
// 3
}
```
### <span id="Compose">Compose</span>
<p>从右至左组合函数列表fnList,返回组合后的函数</p>
@@ -166,9 +153,10 @@ func main() {
<b>函数签名:</b>
```go
func Compose(fnList ...func(...any) any) func(...any) any
func Compose[T any](fnList ...func(...T) T) func(...T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -179,22 +167,23 @@ import (
)
func main() {
add1 := func(v ...any) any {
return v[0].(int) + 1
toUpper := func(strs ...string) string {
return strings.ToUpper(strs[0])
}
add2 := func(v ...any) any {
return v[0].(int) + 2
toLower := func(strs ...string) string {
return strings.ToLower(strs[0])
}
transform := function.Compose(toUpper, toLower)
add3 := function.Compose(add1, add2)
result := add3(1)
result := transform("aBCde")
fmt.Println(result) //4
fmt.Println(result)
// Output:
// ABCDE
}
```
### <span id="Debounced">Debounced</span>
<p>创建一个debounced函数,该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。</p>
@@ -204,7 +193,8 @@ func main() {
```go
func Debounced(fn func(), duration time.Duration) func()
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -216,27 +206,34 @@ import (
func main() {
count := 0
add := func() {
count++
}
debouncedAdd := function.Debounced(add, 50*time.Microsecond)
function.debouncedAdd()
function.debouncedAdd()
function.debouncedAdd()
function.debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count) //1
function.debouncedAdd()
fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count) //2
fmt.Println(count)
// Output:
// 1
// 2
}
```
### <span id="Delay">Delay</span>
<p>延迟delay时间后调用函数</p>
@@ -246,7 +243,8 @@ func main() {
```go
func Delay(delay time.Duration, fn any, args ...any)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -258,14 +256,16 @@ import (
func main() {
var print = func(s string) {
fmt.Println(count) //test delay
fmt.Println(s)
}
function.Delay(2*time.Second, print, "test delay")
function.Delay(2*time.Second, print, "hello")
// Output:
// hello
}
```
### <span id="Schedule">Schedule</span>
<p>每次持续时间调用函数,直到关闭返回的 bool chan</p>
@@ -275,7 +275,8 @@ func main() {
```go
func Schedule(d time.Duration, fn any, args ...any) chan bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -286,21 +287,24 @@ import (
)
func main() {
var res []string
appendStr := func(s string) {
res = append(res, s)
count := 0
increase := func() {
count++
}
stop := function.Schedule(1*time.Second, appendStr, "*")
time.Sleep(5 * time.Second)
stop := function.Schedule(2*time.Second, increase)
time.Sleep(2 * time.Second)
close(stop)
fmt.Println(res) //[* * * * *]
fmt.Println(count)
// Output:
// 2
}
```
### <span id="Pipeline">Pipeline</span>
<p>执行函数pipeline.</p>
@@ -310,7 +314,8 @@ func main() {
```go
func Pipeline[T any](funcs ...func(T) T) func(T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -331,14 +336,17 @@ func main() {
return x * x
}
f := Pipeline(addOne, double, square)
fn := function.Pipeline(addOne, double, square)
fmt.Println(f(2)) //36
result := fn(2)
fmt.Println(result)
// Output:
// 36
}
```
### <span id="Watcher">Watcher</span>
<p>Watcher用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。</p>
@@ -351,12 +359,14 @@ type Watcher struct {
stopTime int64
excuting bool
}
func NewWatcher() *Watcher
func (w *Watcher) Start() //start the watcher
func (w *Watcher) Stop() //stop the watcher
func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -367,7 +377,8 @@ import (
)
func main() {
w := &function.Watcher{}
w := function.NewWatcher()
w.Start()
longRunningTask()
@@ -377,14 +388,11 @@ func main() {
w.Stop()
eapsedTime := w.GetElapsedTime().Milliseconds()
fmt.Println(eapsedTime)
w.Reset()
fmt.Println(w.excuting) //false
fmt.Println(w.startTime) //0
fmt.Println(w.stopTime) //0
}
func longRunningTask() {
@@ -395,6 +403,3 @@ func longRunningTask() {
}
```
+79 -48
View File
@@ -1,4 +1,5 @@
# Maputil
Package maputil includes some functions to manipulate map.
<div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package maputil includes some functions to manipulate map.
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
<div STYLE="page-break-after: always;"></div>
## Example:
```go
import (
"github.com/duke-git/lancet/v2/maputil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [ForEach](#ForEach)
- [Filter](#Filter)
- [Intersect](#Intersect)
@@ -33,9 +35,8 @@ import (
## Documentation
### <span id="ForEach">ForEach</span>
<p>Executes iteratee funcation for every key and value pair in map.</p>
<b>Signature:</b>
@@ -43,6 +44,7 @@ import (
```go
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
```
<b>Example:</b>
```go
@@ -66,14 +68,16 @@ func main() {
maputil.ForEach(m, func(_ string, value int) {
sum += value
})
fmt.Println(sum) // 10
fmt.Println(sum)
// Output:
// 10
}
```
### <span id="Filter">Filter</span>
<p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p>
<b>Signature:</b>
@@ -81,6 +85,7 @@ func main() {
```go
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
```
<b>Example:</b>
```go
@@ -106,15 +111,18 @@ func main() {
maputil.Filter(m, func(_ string, value int) {
sum += value
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
result := maputil.Filter(m, isEven)
fmt.Println(result)
// Output:
// map[b:2 d:4]
}
```
### <span id="Intersect">Intersect</span>
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
<b>Signature:</b>
@@ -122,6 +130,7 @@ func main() {
```go
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>Example:</b>
```go
@@ -152,18 +161,23 @@ func main() {
"e": 9,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
result1 := maputil.Intersect(m1)
result2 := maputil.Intersect(m1, m2)
result3 := maputil.Intersect(m1, m2, m3)
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
// Output:
// map[a:1 b:2 c:3]
// map[a:1 b:2]
// map[a:1]
}
```
### <span id="Keys">Keys</span>
<p>Returns a slice of the map's keys.</p>
<b>Signature:</b>
@@ -171,6 +185,7 @@ func main() {
```go
func Keys[K comparable, V any](m map[K]V) []K
```
<b>Example:</b>
```go
@@ -192,14 +207,16 @@ func main() {
keys := maputil.Keys(m)
sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
fmt.Println(keys)
// Output:
// [1 2 3 4 5]
}
```
### <span id="Merge">Merge</span>
<p>Merge maps, next key will overwrite previous key.</p>
<b>Signature:</b>
@@ -207,6 +224,7 @@ func main() {
```go
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>Example:</b>
```go
@@ -226,14 +244,18 @@ func main() {
1: "1",
3: "2",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
result := maputil.Merge(m1, m2)
fmt.Println(result)
// Output:
// map[1:c 2:b 3:d]
}
```
### <span id="Minus">Minus</span>
<p>Creates an map of whose key in mapA but not in mapB.</p>
<b>Signature:</b>
@@ -241,6 +263,7 @@ func main() {
```go
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
```
<b>Example:</b>
```go
@@ -264,13 +287,17 @@ func main() {
"d": 33,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
result := maputil.Minus(m1, m2)
fmt.Println(result)
// Output:
// map[c:3]
}
```
### <span id="Values">Values</span>
<p>Returns a slice of the map's values.</p>
<b>Signature:</b>
@@ -278,6 +305,7 @@ func main() {
```go
func Values[K comparable, V any](m map[K]V) []V
```
<b>Example:</b>
```go
@@ -300,11 +328,15 @@ func main() {
values := maputil.Values(m)
sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
fmt.Println(values)
// Output:
// [a a b c d]
}
```
### <span id="IsDisjoint">IsDisjoint</span>
<p>Checks two maps are disjoint if they have no keys in common</p>
<b>Signature:</b>
@@ -312,6 +344,7 @@ func main() {
```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
```
<b>Example:</b>
```go
@@ -323,30 +356,28 @@ import (
)
func main() {
m1 := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
m2 := map[string]int{
"d": 22,
}
m3 := map[int]string{
6: "a",
m3 := map[string]int{
"a": 22,
}
ok := maputil.IsDisjoint(m2, m1)
fmt.Println(ok) // false
result1 := maputil.IsDisjoint(m1, m2)
result2 := maputil.IsDisjoint(m1, m3)
ok = maputil.IsDisjoint(m2, m3)
fmt.Println(ok) // true
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
+85 -56
View File
@@ -1,4 +1,5 @@
# Maputil
maputil 包包括一些操作 map 的函数。
<div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ maputil包包括一些操作map的函数。
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/maputil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录:
- [ForEach](#ForEach)
- [Filter](#Filter)
- [Intersect](#Intersect)
@@ -33,9 +35,8 @@ import (
## API 文档:
### <span id="ForEach">ForEach</span>
<p>对map中的每对key和value执行iteratee函数</p>
<b>函数签名:</b>
@@ -43,7 +44,8 @@ import (
```go
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -66,14 +68,16 @@ func main() {
maputil.ForEach(m, func(_ string, value int) {
sum += value
})
fmt.Println(sum) // 10
fmt.Println(sum)
// Output:
// 10
}
```
### <span id="Filter">Filter</span>
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
<b>函数签名:</b>
@@ -81,7 +85,8 @@ func main() {
```go
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
package main
@@ -106,15 +111,18 @@ func main() {
maputil.Filter(m, func(_ string, value int) {
sum += value
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
result := Filter(m, isEven)
fmt.Println(result)
// Output:
// map[b:2 d:4]
}
```
### <span id="Intersect">Intersect</span>
<p>多个map的交集操作</p>
<b>函数签名:</b>
@@ -122,7 +130,8 @@ func main() {
```go
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -152,18 +161,23 @@ func main() {
"e": 9,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
result1 := maputil.Intersect(m1)
result2 := maputil.Intersect(m1, m2)
result3 := maputil.Intersect(m1, m2, m3)
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
// Output:
// map[a:1 b:2 c:3]
// map[a:1 b:2]
// map[a:1]
}
```
### <span id="Keys">Keys</span>
<p>返回map中所有key的切片</p>
<b>函数签名:</b>
@@ -171,7 +185,8 @@ func main() {
```go
func Keys[K comparable, V any](m map[K]V) []K
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -192,14 +207,16 @@ func main() {
keys := maputil.Keys(m)
sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
fmt.Println(keys)
// Output:
// [1 2 3 4 5]
}
```
### <span id="Merge">Merge</span>
<p>合并多个maps, 相同的key会被后来的key覆盖</p>
<b>函数签名:</b>
@@ -207,7 +224,8 @@ func main() {
```go
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -226,13 +244,18 @@ func main() {
1: "1",
3: "2",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
result := maputil.Merge(m1, m2)
fmt.Println(result)
// Output:
// map[1:c 2:b 3:d]
}
```
### <span id="Minus">Minus</span>
<p>返回一个map,其中的key存在于mapA,不存在于mapB.</p>
<b>函数签名:</b>
@@ -240,7 +263,8 @@ func main() {
```go
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -263,13 +287,17 @@ func main() {
"d": 33,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
result := maputil.Minus(m1, m2)
fmt.Println(result)
// Output:
// map[c:3]
}
```
### <span id="Values">Values</span>
<p>返回map中所有value的切片</p>
<b>函数签名:</b>
@@ -277,7 +305,8 @@ func main() {
```go
func Values[K comparable, V any](m map[K]V) []V
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -299,12 +328,13 @@ func main() {
values := maputil.Values(m)
sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
// Output:
// [a a b c d]
}
```
### <span id="IsDisjoint">IsDisjoint</span>
<p>验证两个map是否具有不同的key</p>
<b>函数签名:</b>
@@ -312,7 +342,8 @@ func main() {
```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -323,30 +354,28 @@ import (
)
func main() {
m1 := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
m2 := map[string]int{
"d": 22,
}
m3 := map[int]string{
6: "a",
m3 := map[string]int{
"a": 22,
}
ok := maputil.IsDisjoint(m2, m1)
fmt.Println(ok) // false
result1 := maputil.IsDisjoint(m1, m2)
result2 := maputil.IsDisjoint(m1, m3)
ok = maputil.IsDisjoint(m2, m3)
fmt.Println(ok) // true
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
+162 -83
View File
@@ -1,4 +1,5 @@
# Mathutil
Package mathutil implements some functions for math calculation.
<div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package mathutil implements some functions for math calculation.
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
## Example:
```go
import (
"github.com/duke-git/lancet/v2/mathutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [Average](#Average)
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
@@ -37,9 +39,8 @@ import (
## Documentation
### <span id="Average">Average</span>
<p>Return average value of numbers. Maybe call RoundToFloat to round result.</p>
<b>Signature:</b>
@@ -47,6 +48,7 @@ import (
```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>Example:</b>
```go
@@ -58,16 +60,22 @@ import (
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
result1 := mathutil.Average(1, 2)
avg := mathutil.Average(1.2, 1.4)
result2 := mathutil.RoundToFloat(avg, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.3
}
```
### <span id="Exponent">Exponent</span>
<p>Calculate x to the nth power.</p>
<b>Signature:</b>
@@ -75,6 +83,7 @@ func main() {
```go
func Exponent(x, n int64) int64
```
<b>Example:</b>
```go
@@ -86,15 +95,23 @@ import (
)
func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1
fmt.Println(mathutil.Exponent(10, 1)) //10
fmt.Println(mathutil.Exponent(10, 2)) //100
result1 := mathutil.Exponent(10, 0)
result2 := mathutil.Exponent(10, 1)
result3 := mathutil.Exponent(10, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 10
// 100
}
```
### <span id="Fibonacci">Fibonacci</span>
<p>Calculate the nth number of fibonacci sequence.</p>
<b>Signature:</b>
@@ -102,6 +119,7 @@ func main() {
```go
func Fibonacci(first, second, n int) int
```
<b>Example:</b>
```go
@@ -113,17 +131,23 @@ import (
)
func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
result1 := mathutil.Fibonacci(1, 1, 1)
result2 := mathutil.Fibonacci(1, 1, 2)
result3 := mathutil.Fibonacci(1, 1, 5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 1
// 5
}
```
### <span id="Factorial">Factorial</span>
<p>Calculate the factorial of x.</p>
<b>Signature:</b>
@@ -131,6 +155,7 @@ func main() {
```go
func Factorial(x uint) uint
```
<b>Example:</b>
```go
@@ -142,16 +167,23 @@ import (
)
func main() {
fmt.Println(mathutil.Factorial(0)) //1
fmt.Println(mathutil.Factorial(1)) //1
fmt.Println(mathutil.Factorial(2)) //2
fmt.Println(mathutil.Factorial(3)) //6
result1 := mathutil.Factorial(1)
result2 := mathutil.Factorial(2)
result3 := mathutil.Factorial(3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 6
}
```
### <span id="Max">Max</span>
<p>Return max value of numbers.</p>
<b>Signature:</b>
@@ -159,6 +191,7 @@ func main() {
```go
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>Example:</b>
```go
@@ -170,16 +203,20 @@ import (
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
result1 := mathutil.Max(1, 2, 3)
result2 := mathutil.Max(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.4
}
```
### <span id="MaxBy">MaxBy</span>
<p>Return the maximum value of a slice using the given comparator function.</p>
<b>Signature:</b>
@@ -187,6 +224,7 @@ func main() {
```go
func MaxBy[T any](slice []T, comparator func(T, T) bool) T
```
<b>Example:</b>
```go
@@ -198,33 +236,39 @@ import (
)
func main() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
result1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
result2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
result3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abc
// abd
//
}
```
### <span id="Min">Min</span>
<p>Return min value of numbers.</p>
<p>Return the minimum value of numbers.</p>
<b>Signature:</b>
```go
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>Example:</b>
```go
@@ -236,15 +280,20 @@ import (
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
result1 := mathutil.Min(1, 2, 3)
result2 := mathutil.Min(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.1
}
```
### <span id="MinBy">MinBy</span>
<p>Return the minimum value of a slice using the given comparator function.</p>
<b>Signature:</b>
@@ -252,6 +301,7 @@ func main() {
```go
func MinBy[T any](slice []T, comparator func(T, T) bool) T
```
<b>Example:</b>
```go
@@ -263,27 +313,31 @@ import (
)
func main() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
result1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
result2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
result3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// a
// ab
//
}
```
### <span id="Percent">Percent</span>
<p>calculate the percentage of val to total, retain n decimal places.</p>
<b>Signature:</b>
@@ -291,6 +345,7 @@ func main() {
```go
func Percent(val, total float64, n int) float64
```
<b>Example:</b>
```go
@@ -302,14 +357,20 @@ import (
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
result1 := mathutil.Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0.5
// 0.33
}
```
### <span id="RoundToFloat">RoundToFloat</span>
<p>Round float up to n decimal places.</p>
<b>Signature:</b>
@@ -317,6 +378,7 @@ func main() {
```go
func RoundToFloat(x float64, n int) float64
```
<b>Example:</b>
```go
@@ -328,18 +390,23 @@ import (
)
func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
result1 := mathutil.RoundToFloat(0.124, 2)
result2 := mathutil.RoundToFloat(0.125, 2)
result3 := mathutil.RoundToFloat(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
```
### <span id="RoundToString">RoundToString</span>
<p>Round float up to n decimal places. will return string.</p>
<b>Signature:</b>
@@ -347,6 +414,7 @@ func main() {
```go
func RoundToString(x float64, n int) string
```
<b>Example:</b>
```go
@@ -358,17 +426,23 @@ import (
)
func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
result1 := mathutil.RoundToString(0.124, 2)
result2 := mathutil.RoundToString(0.125, 2)
result3 := mathutil.RoundToString(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
```
### <span id="TruncRound">TruncRound</span>
<p>Round float off n decimal places.</p>
<b>Signature:</b>
@@ -376,6 +450,7 @@ func main() {
```go
func TruncRound(x float64, n int) float64
```
<b>Example:</b>
```go
@@ -387,13 +462,17 @@ import (
)
func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0
fmt.Println(mathutil.TruncRound(0, 1)) //0
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
result1 := mathutil.TruncRound(0.124, 2)
result2 := mathutil.TruncRound(0.125, 2)
result3 := mathutil.TruncRound(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.12
// 0.125
}
```
+173 -91
View File
@@ -1,4 +1,5 @@
# Mathutil
mathutil 包实现了一些数学计算的函数.
<div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ mathutil包实现了一些数学计算的函数.
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/mathutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [Average](#Average)
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
@@ -37,8 +39,8 @@ import (
## Documentation
### <span id="Average">Average</span>
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
<b>函数签名:</b>
@@ -46,7 +48,8 @@ import (
```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -57,15 +60,22 @@ import (
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
result1 := mathutil.Average(1, 2)
avg := mathutil.Average(1.2, 1.4)
result2 := mathutil.RoundToFloat(avg, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.3
}
```
### <span id="Exponent">Exponent</span>
<p>指数计算(x的n次方)</p>
<b>函数签名:</b>
@@ -73,7 +83,8 @@ func main() {
```go
func Exponent(x, n int64) int64
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -84,15 +95,23 @@ import (
)
func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1
fmt.Println(mathutil.Exponent(10, 1)) //10
fmt.Println(mathutil.Exponent(10, 2)) //100
result1 := mathutil.Exponent(10, 0)
result2 := mathutil.Exponent(10, 1)
result3 := mathutil.Exponent(10, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 10
// 100
}
```
### <span id="Fibonacci">Fibonacci</span>
<p>计算斐波那契数列的第n个数</p>
<b>函数签名:</b>
@@ -100,7 +119,8 @@ func main() {
```go
func Fibonacci(first, second, n int) int
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -111,17 +131,23 @@ import (
)
func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
result1 := mathutil.Fibonacci(1, 1, 1)
result2 := mathutil.Fibonacci(1, 1, 2)
result3 := mathutil.Fibonacci(1, 1, 5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 1
// 5
}
```
### <span id="Factorial">Factorial</span>
<p>计算阶乘</p>
<b>函数签名:</b>
@@ -129,7 +155,8 @@ func main() {
```go
func Factorial(x uint) uint
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -140,15 +167,23 @@ import (
)
func main() {
fmt.Println(mathutil.Factorial(0)) //1
fmt.Println(mathutil.Factorial(1)) //1
fmt.Println(mathutil.Factorial(2)) //2
fmt.Println(mathutil.Factorial(3)) //6
result1 := mathutil.Factorial(1)
result2 := mathutil.Factorial(2)
result3 := mathutil.Factorial(3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 6
}
```
### <span id="Max">Max</span>
<p>返回参数中的最大数</p>
<b>函数签名:</b>
@@ -156,7 +191,8 @@ func main() {
```go
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -167,15 +203,20 @@ import (
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
result1 := mathutil.Max(1, 2, 3)
result2 := mathutil.Max(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.4
}
```
### <span id="MaxBy">MaxBy</span>
<p>使用给定的比较器函数返回切片的最大值</p>
<b>函数签名:</b>
@@ -183,7 +224,8 @@ func main() {
```go
func MaxBy[T any](slice []T, comparator func(T, T) bool) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -194,27 +236,31 @@ import (
)
func main() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
result1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
result2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
result3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abc
// abd
//
}
```
### <span id="Min">Min</span>
<p>返回参数中的最小数</p>
<b>函数签名:</b>
@@ -222,7 +268,8 @@ func main() {
```go
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -233,15 +280,20 @@ import (
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
result1 := mathutil.Min(1, 2, 3)
result2 := mathutil.Min(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.1
}
```
### <span id="MinBy">MinBy</span>
<p>使用给定的比较器函数返回切片的最小值</p>
<b>函数签名:</b>
@@ -249,7 +301,8 @@ func main() {
```go
func MinBy[T any](slice []T, comparator func(T, T) bool) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -260,27 +313,31 @@ import (
)
func main() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
result1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
result2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
result3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// a
// ab
//
}
```
### <span id="Percent">Percent</span>
<p>计算百分比,保留n位小数</p>
<b>函数签名:</b>
@@ -288,7 +345,8 @@ func main() {
```go
func Percent(val, total float64, n int) float64
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -299,14 +357,20 @@ import (
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
result1 := mathutil.Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0.5
// 0.33
}
```
### <span id="RoundToFloat">RoundToFloat</span>
<p>四舍五入,保留n位小数</p>
<b>函数签名:</b>
@@ -314,7 +378,8 @@ func main() {
```go
func RoundToFloat(x float64, n int) float64
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -325,18 +390,23 @@ import (
)
func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
result1 := mathutil.RoundToFloat(0.124, 2)
result2 := mathutil.RoundToFloat(0.125, 2)
result3 := mathutil.RoundToFloat(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
```
### <span id="RoundToString">RoundToString</span>
<p>四舍五入,保留n位小数,返回字符串</p>
<b>函数签名:</b>
@@ -344,7 +414,8 @@ func main() {
```go
func RoundToString(x float64, n int) string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -355,17 +426,23 @@ import (
)
func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
result1 := mathutil.RoundToString(0.124, 2)
result2 := mathutil.RoundToString(0.125, 2)
result3 := mathutil.RoundToString(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
```
### <span id="TruncRound">TruncRound</span>
<p>截短n位小数(不进行四舍五入)</p>
<b>函数签名:</b>
@@ -373,7 +450,8 @@ func main() {
```go
func TruncRound(x float64, n int) float64
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -384,13 +462,17 @@ import (
)
func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0
fmt.Println(mathutil.TruncRound(0, 1)) //0
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
result1 := mathutil.TruncRound(0.124, 2)
result2 := mathutil.TruncRound(0.125, 2)
result3 := mathutil.TruncRound(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.12
// 0.125
}
```
+118 -75
View File
@@ -1,4 +1,5 @@
# Netutil
Package netutil contains functions to get net information and send http request.
<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/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)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp)
@@ -48,8 +49,8 @@ import (
## Documentation
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>Convert map to url query string.</p>
<b>Signature:</b>
@@ -57,6 +58,7 @@ import (
```go
func ConvertMapToQueryString(param map[string]any) string
```
<b>Example:</b>
```go
@@ -75,13 +77,13 @@ func main() {
}
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>
<p>Encode url query string values.</p>
<b>Signature:</b>
@@ -89,6 +91,7 @@ func main() {
```go
func EncodeUrl(urlStr string) (string, error)
```
<b>Example:</b>
```go
@@ -102,16 +105,20 @@ import (
func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil {
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>
<p>Get internal ip information.</p>
<b>Signature:</b>
@@ -119,6 +126,7 @@ func main() {
```go
func GetInternalIp() string
```
<b>Example:</b>
```go
@@ -134,13 +142,15 @@ func main() {
internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9
fmt.Println(ip)
// Output:
// 192.168.1.9
}
```
### <span id="GetIps">GetIps</span>
<p>Get all ipv4 list.</p>
<b>Signature:</b>
@@ -148,6 +158,7 @@ func main() {
```go
func GetIps() []string
```
<b>Example:</b>
```go
@@ -161,13 +172,15 @@ import (
func main() {
ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9]
fmt.Println(ips)
// Output:
// [192.168.1.9]
}
```
### <span id="GetMacAddrs">GetMacAddrs</span>
<p>Get all mac addresses list.</p>
<b>Signature:</b>
@@ -175,6 +188,7 @@ func main() {
```go
func GetMacAddrs() []string {
```
<b>Example:</b>
```go
@@ -187,14 +201,16 @@ import (
)
func main() {
addrs := netutil.GetMacAddrs()
fmt.Println(addrs)
macAddrs := netutil.GetMacAddrs()
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>
<p>Get public ip information.</p>
<b>Signature:</b>
@@ -216,6 +232,7 @@ type PublicIpInfo struct {
Ip string `json:"query"`
}
```
<b>Example:</b>
```go
@@ -236,9 +253,8 @@ func main() {
}
```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>Get http request public ip.</p>
<b>Signature:</b>
@@ -246,6 +262,7 @@ func main() {
```go
func GetRequestPublicIp(req *http.Request) string
```
<b>Example:</b>
```go
@@ -259,29 +276,23 @@ import (
func main() {
ip := "36.112.24.10"
request1 := http.Request{
request := http.Request{
Method: "GET",
Header: http.Header{
"X-Forwarded-For": {ip},
},
}
publicIp1 := netutil.GetRequestPublicIp(&request1)
fmt.Println(publicIp1) //36.112.24.10
publicIp := netutil.GetRequestPublicIp(&request)
request2 := http.Request{
Method: "GET",
Header: http.Header{
"X-Real-Ip": {ip},
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
fmt.Println(publicIp)
// Output:
// 36.112.24.10
}
```
### <span id="IsPublicIP">IsPublicIP</span>
<p>Checks if an ip is public or not.</p>
<b>Signature:</b>
@@ -289,6 +300,7 @@ func main() {
```go
func IsPublicIP(IP net.IP) bool
```
<b>Example:</b>
```go
@@ -301,18 +313,23 @@ import (
)
func main() {
ip1 := net.ParseIP("192.168.0.1")
ip2 := net.ParseIP("36.112.24.10")
ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
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(netutil.IsPublicIP(ip2)) //true
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
}
```
### <span id="IsInternalIP">IsInternalIP</span>
<p>Checks if an ip is intranet or not.</p>
<b>Signature:</b>
@@ -320,6 +337,7 @@ func main() {
```go
func IsInternalIP(IP net.IP) bool
```
<b>Example:</b>
```go
@@ -332,16 +350,23 @@ import (
)
func main() {
ip1 := net.ParseIP("127.0.0.1")
ip2 := net.ParseIP("36.112.24.10")
ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
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(netutil.IsInternalIP(ip2)) //false
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
}
```
### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest is a struct used to abstract HTTP request entity.</p>
<b>Signature:</b>
@@ -356,6 +381,7 @@ type HttpRequest struct {
Body []byte
}
```
<b>Example:</b>
```go
@@ -384,8 +410,8 @@ func main() {
}
```
### <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>
<b>Signature:</b>
@@ -412,6 +438,7 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
```
<b>Example:</b>
```go
@@ -433,9 +460,8 @@ func main() {
}
```
### <span id="SendRequest">SendRequest</span>
<p>Use HttpClient to send HTTP request.</p>
<b>Signature:</b>
@@ -443,6 +469,7 @@ func main() {
```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -464,7 +491,7 @@ func main() {
httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
return
}
type Todo struct {
@@ -475,15 +502,20 @@ func main() {
}
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>
<p>Decode http response into target object.</p>
<b>Signature:</b>
@@ -491,6 +523,7 @@ func main() {
```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
```
<b>Example:</b>
```go
@@ -512,7 +545,7 @@ func main() {
httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
return
}
type Todo struct {
@@ -523,14 +556,20 @@ func main() {
}
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>
<p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p>
<b>Signature:</b>
@@ -538,6 +577,7 @@ func main() {
```go
func StructToUrlValues(targetStruct any) url.Values
```
<b>Example:</b>
```go
@@ -551,22 +591,25 @@ import (
func main() {
type TodoQuery struct {
Id int `json:"id"`
UserId int `json:"userId"`
Name string `json:"name"`
}
todoQuery := TodoQuery{
Id: 1,
UserId: 2,
Name: "Test",
}
todoValues := netutil.StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id")) //1
fmt.Println(todoValues.Get("userId")) //2
fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
}
```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>Send http get request.</p>
<b>Signature:</b>
@@ -578,6 +621,7 @@ func main() {
// params[3] is http client which type should be http.Client.
func HttpGet(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -606,9 +650,8 @@ func main() {
}
```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>Send http post request.</p>
<b>Signature:</b>
@@ -620,6 +663,7 @@ func main() {
// params[3] is http client which type should be http.Client.
func HttpPost(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -655,9 +699,8 @@ func main() {
}
```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>Send http put request.</p>
<b>Signature:</b>
@@ -669,6 +712,7 @@ func main() {
// params[3] is http client which type should be http.Client.
func HttpPut(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -705,9 +749,8 @@ func main() {
}
```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>Send http delete request.</p>
<b>Signature:</b>
@@ -719,6 +762,7 @@ func main() {
// params[3] is http client which type should be http.Client.
func HttpDelete(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -744,9 +788,8 @@ func main() {
}
```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>Send http patch request.</p>
<b>Signature:</b>
@@ -758,6 +801,7 @@ func main() {
// params[3] is http client which type should be http.Client.
func HttpPatch(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
```go
@@ -794,9 +838,8 @@ func main() {
}
```
### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>Decode http response to specified interface.</p>
<b>Signature:</b>
@@ -804,6 +847,7 @@ func main() {
```go
func ParseHttpResponse(resp *http.Response, obj any) error
```
<b>Example:</b>
```go
@@ -844,4 +888,3 @@ func main() {
fmt.Println(toDoResp)
}
```
+141 -96
View File
@@ -1,4 +1,5 @@
# Netutil
netutil 网络包支持获取 ip 地址,发送 http 请求。
<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/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)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp)
@@ -48,8 +49,8 @@ import (
## 文档
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>将map转换成http查询字符串.</p>
<b>函数签名:</b>
@@ -57,7 +58,8 @@ import (
```go
func ConvertMapToQueryString(param map[string]any) string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -75,13 +77,15 @@ func main() {
}
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>
<p>编码url query string的值</p>
<b>函数签名:</b>
@@ -89,7 +93,8 @@ func main() {
```go
func EncodeUrl(urlStr string) (string, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -102,17 +107,20 @@ import (
func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil {
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>
<p>获取内部ip</p>
<b>函数签名:</b>
@@ -120,7 +128,8 @@ func main() {
```go
func GetInternalIp() string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -135,12 +144,15 @@ func main() {
internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9
fmt.Println(ip)
// Output:
// 192.168.1.9
}
```
### <span id="GetIps">GetIps</span>
<p>获取ipv4地址列表</p>
<b>函数签名:</b>
@@ -148,7 +160,8 @@ func main() {
```go
func GetIps() []string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -161,13 +174,15 @@ import (
func main() {
ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9]
fmt.Println(ips)
// Output:
// [192.168.1.9]
}
```
### <span id="GetMacAddrs">GetMacAddrs</span>
<p>获取mac地址列</p>
<b>函数签名:</b>
@@ -175,7 +190,8 @@ func main() {
```go
func GetMacAddrs() []string {
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -187,14 +203,16 @@ import (
)
func main() {
addrs := netutil.GetMacAddrs()
fmt.Println(addrs)
macAddrs := netutil.GetMacAddrs()
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>
<p>获取公网ip信息</p>
<b>函数签名:</b>
@@ -216,7 +234,8 @@ type PublicIpInfo struct {
Ip string `json:"query"`
}
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -236,9 +255,8 @@ func main() {
}
```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>获取http请求ip</p>
<b>函数签名:</b>
@@ -246,7 +264,8 @@ func main() {
```go
func GetRequestPublicIp(req *http.Request) string
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -259,30 +278,23 @@ import (
func main() {
ip := "36.112.24.10"
request1 := http.Request{
request := http.Request{
Method: "GET",
Header: http.Header{
"X-Forwarded-For": {ip},
},
}
publicIp1 := netutil.GetRequestPublicIp(&request1)
fmt.Println(publicIp1) //36.112.24.10
publicIp := netutil.GetRequestPublicIp(&request)
request2 := http.Request{
Method: "GET",
Header: http.Header{
"X-Real-Ip": {ip},
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
fmt.Println(publicIp)
// Output:
// 36.112.24.10
}
```
### <span id="IsPublicIP">IsPublicIP</span>
<p>判断ip是否是公共ip</p>
<b>函数签名:</b>
@@ -290,7 +302,8 @@ func main() {
```go
func IsPublicIP(IP net.IP) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -302,17 +315,23 @@ import (
)
func main() {
ip1 := net.ParseIP("192.168.0.1")
ip2 := net.ParseIP("36.112.24.10")
ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
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(netutil.IsPublicIP(ip2)) //true
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
}
```
### <span id="IsInternalIP">IsInternalIP</span>
<p>判断ip是否是局域网ip.</p>
<b>函数签名:</b>
@@ -320,7 +339,8 @@ func main() {
```go
func IsInternalIP(IP net.IP) bool
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -332,16 +352,23 @@ import (
)
func main() {
ip1 := net.ParseIP("127.0.0.1")
ip2 := net.ParseIP("36.112.24.10")
ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
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(netutil.IsInternalIP(ip2)) //false
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
}
```
### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest用于抽象HTTP请求实体的结构</p>
<b>函数签名:</b>
@@ -356,7 +383,8 @@ type HttpRequest struct {
Body []byte
}
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -384,8 +412,8 @@ func main() {
}
```
### <span id="HttpClient">HttpClient</span>
<p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p>
<b>函数签名:</b>
@@ -412,7 +440,8 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -433,9 +462,8 @@ func main() {
}
```
### <span id="SendRequest">SendRequest</span>
<p>HttpClient发送http请求</p>
<b>函数签名:</b>
@@ -443,7 +471,8 @@ func main() {
```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -464,7 +493,7 @@ func main() {
httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
return
}
type Todo struct {
@@ -475,15 +504,20 @@ func main() {
}
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>
<p>解析http响应体到目标结构体</p>
<b>函数签名:</b>
@@ -491,7 +525,8 @@ func main() {
```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -512,7 +547,7 @@ func main() {
httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
log.Fatal(err)
return
}
type Todo struct {
@@ -523,22 +558,29 @@ func main() {
}
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>
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag.</p>
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p>
<b>函数签名:</b>
```go
func StructToUrlValues(targetStruct any) url.Values
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -551,22 +593,25 @@ import (
func main() {
type TodoQuery struct {
Id int `json:"id"`
UserId int `json:"userId"`
Name string `json:"name"`
}
todoQuery := TodoQuery{
Id: 1,
UserId: 2,
Name: "Test",
}
todoValues := netutil.StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id")) //1
fmt.Println(todoValues.Get("userId")) //2
fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
}
```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>发送http get请求</p>
<b>函数签名:</b>
@@ -578,7 +623,8 @@ func main() {
// params[3] http client,类型必须是http.Client
func HttpGet(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -606,9 +652,8 @@ func main() {
}
```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>发送http post请求</p>
<b>函数签名:</b>
@@ -620,7 +665,8 @@ func main() {
// params[3] http client,类型必须是http.Client
func HttpPost(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -655,9 +701,8 @@ func main() {
}
```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>发送http put请求</p>
<b>函数签名:</b>
@@ -669,7 +714,8 @@ func main() {
// params[3] http client,类型必须是http.Client
func HttpPut(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -705,9 +751,8 @@ func main() {
}
```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>发送http delete请求</p>
<b>函数签名:</b>
@@ -719,7 +764,8 @@ func main() {
// params[3] http client,类型必须是http.Client
func HttpDelete(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -744,9 +790,8 @@ func main() {
}
```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>发送http patch请求</p>
<b>函数签名:</b>
@@ -758,7 +803,8 @@ func main() {
// params[3] http client,类型必须是http.Client
func HttpPatch(url string, params ...any) (*http.Response, error)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -794,9 +840,8 @@ func main() {
}
```
### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>将http请求响应解码成特定struct值</p>
<b>函数签名:</b>
@@ -804,7 +849,8 @@ func main() {
```go
func ParseHttpResponse(resp *http.Response, obj any) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -844,4 +890,3 @@ func main() {
fmt.Println(toDoResp)
}
```
+8 -8
View File
@@ -45,7 +45,7 @@ import (
func RandBytes(length int) []byte
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -71,7 +71,7 @@ func main() {
func RandInt(min, max int) int
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -97,7 +97,7 @@ func main() {
func RandString(length int) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -123,7 +123,7 @@ func main() {
func RandUpper(length int) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -149,7 +149,7 @@ func main() {
func RandLower(length int) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -175,7 +175,7 @@ func main() {
func RandNumeral(length int) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -201,7 +201,7 @@ func main() {
func RandNumeralOrLetter(length int) string
```
<b>例:</b>
<b>例:</b>
```go
package main
@@ -227,7 +227,7 @@ func main() {
func UUIdV4() (string, error)
```
<b>例:</b>
<b>例:</b>
```go
package main
+56 -32
View File
@@ -1,4 +1,5 @@
# Retry
Package retry is for executing a function repeatedly until it was successful or canceled by the context.
<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)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/retry"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [Context](#Context)
- [Retry](#Retry)
- [RetryFunc](#RetryFunc)
@@ -30,8 +32,8 @@ import (
## Documentation
### <span id="Context">Context</span>
<p>Set retry context config, can cancel the retry with context.</p>
<b>Signature:</b>
@@ -39,6 +41,7 @@ import (
```go
func Context(ctx context.Context)
```
<b>Example:</b>
```go
@@ -52,7 +55,8 @@ import (
func main() {
ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error {
number++
if number > 3 {
@@ -61,21 +65,22 @@ func main() {
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber,
retry.RetryDuration(time.Microsecond*50),
duration := retry.RetryDuration(time.Microsecond*50)
retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
if err != nil {
fmt.Println(err) //retry is cancelled
}
fmt.Println(number)
// Output:
// 4
}
```
### <span id="RetryFunc">RetryFunc</span>
<p>Function that retry executes.</p>
<b>Signature:</b>
@@ -83,6 +88,7 @@ func main() {
```go
type RetryFunc func() error
```
<b>Example:</b>
```go
@@ -96,9 +102,8 @@ import (
)
func main() {
var number int
increaseNumber := func() error {
number := 0
var increaseNumber retry.RetryFunc = func() error {
number++
if number == 3 {
return nil
@@ -106,18 +111,22 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryTimes">RetryTimes</span>
<p>Set times of retry. Default times is 5.</p>
<b>Signature:</b>
@@ -125,6 +134,7 @@ func main() {
```go
func RetryTimes(n uint)
```
<b>Example:</b>
```go
@@ -138,7 +148,7 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
@@ -150,14 +160,16 @@ func main() {
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
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>
<p>Set duration of retries. Default duration is 3 second.</p>
<b>Signature:</b>
@@ -165,6 +177,7 @@ func main() {
```go
func RetryDuration(d time.Duration)
```
<b>Example:</b>
```go
@@ -178,7 +191,7 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
if number == 3 {
@@ -187,17 +200,22 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
### <span id="Retry">Retry</span>
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
<b>Signature:</b>
@@ -205,6 +223,7 @@ func main() {
```go
func Retry(retryFunc RetryFunc, opts ...Option) error
```
<b>Example:</b>
```go
@@ -218,7 +237,7 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
if number == 3 {
@@ -227,11 +246,16 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
+62 -38
View File
@@ -1,4 +1,5 @@
# Retry
retry 重试执行函数直到函数运行成功或被 context cancel。
<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)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/retry"
@@ -20,20 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [Context](#Context)
- [Retry](#Retry)
- [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
<div STYLE="page-break-after: always;"></div>
## Document 文档
### <span id="Context">Context</span>
<p>设置重试context参数</p>
<b>函数签名:</b>
@@ -41,7 +41,8 @@ import (
```go
func Context(ctx context.Context)
```
<b>例子:</b>
<b>示例:</b>
```go
import (
@@ -54,7 +55,8 @@ import (
func main() {
ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error {
number++
if number > 3 {
@@ -63,21 +65,22 @@ func main() {
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber,
retry.RetryDuration(time.Microsecond*50),
duration := retry.RetryDuration(time.Microsecond*50)
retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
if err != nil {
fmt.Println(err) //retry is cancelled
}
fmt.Println(number)
// Output:
// 4
}
```
### <span id="RetryFunc">RetryFunc</span>
<p>被重试执行的函数</p>
<b>函数签名:</b>
@@ -85,7 +88,8 @@ func main() {
```go
type RetryFunc func() error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -98,8 +102,8 @@ import (
)
func main() {
var number int
increaseNumber := func() error {
number := 0
var increaseNumber retry.RetryFunc = func() error {
number++
if number == 3 {
return nil
@@ -107,18 +111,22 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryTimes">RetryTimes</span>
<p>设置重试次数,默认5</p>
<b>函数签名:</b>
@@ -126,7 +134,8 @@ func main() {
```go
func RetryTimes(n uint)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -139,7 +148,8 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
if number == 3 {
@@ -150,14 +160,16 @@ func main() {
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
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>
<p>设置重试间隔时间,默认3秒</p>
<b>函数签名:</b>
@@ -165,7 +177,8 @@ func main() {
```go
func RetryDuration(d time.Duration)
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -178,7 +191,7 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
if number == 3 {
@@ -187,17 +200,22 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
### <span id="Retry">Retry</span>
<p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p>
<b>函数签名:</b>
@@ -205,7 +223,8 @@ func main() {
```go
func Retry(retryFunc RetryFunc, opts ...Option) error
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -218,7 +237,7 @@ import (
)
func main() {
var number int
number := 0
increaseNumber := func() error {
number++
if number == 3 {
@@ -227,11 +246,16 @@ func main() {
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 {
log.Fatal(err)
return
}
fmt.Println(number) //3
fmt.Println(number)
// Output:
// 3
}
```
+481 -204
View File
File diff suppressed because it is too large Load Diff
+540 -261
View File
File diff suppressed because it is too large Load Diff
+346 -255
View File
@@ -1,4 +1,5 @@
# Strutil
Package strutil contains some functions to manipulate string.
<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)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/strutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [After](#After)
- [AfterLast](#AfterLast)
- [Before](#Before)
@@ -37,23 +39,24 @@ import (
- [SnakeCase](#SnakeCase)
- [UpperSnakeCase](#UpperSnakeCase)
- [SplitEx](#SplitEx)
- [Substring](#Substring)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="After">After</span>
<p>Creates substring in source string after position when char first appear.</p>
<p>Returns the substring after the first occurrence of a specified string in the source string.</p>
<b>Signature:</b>
```go
func After(s, char string) string
```
<b>Example:</b>
```go
@@ -63,27 +66,37 @@ import (
)
func main() {
s1 := strutil.After("lancet", "")
fmt.Println(s1) //lancet
result1 := strutil.After("foo", "")
result2 := strutil.After("foo", "foo")
result3 := strutil.After("foo/bar", "foo")
result4 := strutil.After("foo/bar", "/")
result5 := strutil.After("foo/bar/baz", "/")
s2 := strutil.After("github.com/test/lancet", "/")
fmt.Println(s2) //test/lancet
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
s3 := strutil.After("github.com/test/lancet", "test")
fmt.Println(s3) // /lancet
// Output:
// foo
//
// /bar
// bar
// bar/baz
}
```
### <span id="AfterLast">AfterLast</span>
<p>Creates substring in source string after position when char last appear.</p>
<p>Returns the substring after the last occurrence of a specified string in the source string.</p>
<b>Signature:</b>
```go
func AfterLast(s, char string) string
```
<b>Example:</b>
```go
@@ -93,28 +106,37 @@ import (
)
func main() {
s1 := strutil.AfterLast("lancet", "")
fmt.Println(s1) //lancet
result1 := strutil.AfterLast("foo", "")
result2 := strutil.AfterLast("foo", "foo")
result3 := strutil.AfterLast("foo/bar", "/")
result4 := strutil.AfterLast("foo/bar/baz", "/")
result5 := strutil.AfterLast("foo/bar/foo/baz", "foo")
s2 := strutil.AfterLast("github.com/test/lancet", "/")
fmt.Println(s2) //lancet
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
s3 := strutil.AfterLast("github.com/test/test/lancet", "test")
fmt.Println(s3) // /test/lancet
// Output:
// foo
//
// bar
// baz
// /baz
}
```
### <span id="Before">Before</span>
<p>Creates substring in source string before position when char first appear.</p>
<p>Returns the substring of the source string up to the first occurrence of the specified string.</p>
<b>Signature:</b>
```go
func Before(s, char string) string
```
<b>Example:</b>
```go
@@ -124,28 +146,34 @@ import (
)
func main() {
s1 := strutil.Before("lancet", "")
fmt.Println(s1) //lancet
result1 := strutil.Before("foo", "")
result2 := strutil.Before("foo", "foo")
result3 := strutil.Before("foo/bar", "/")
result4 := strutil.Before("foo/bar/baz", "/")
s2 := strutil.Before("github.com/test/lancet", "/")
fmt.Println(s2) //github.com
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
s3 := strutil.Before("github.com/test/lancet", "test")
fmt.Println(s3) // github.com/
// Output:
// foo
//
// foo
// foo
}
```
### <span id="BeforeLast">BeforeLast</span>
<p>Creates substring in source string before position when char first appear.</p>
<p>Returns the substring of the source string up to the last occurrence of the specified string.</p>
<b>Signature:</b>
```go
func BeforeLast(s, char string) string
```
<b>Example:</b>
```go
@@ -155,19 +183,26 @@ import (
)
func main() {
s1 := strutil.BeforeLast("lancet", "")
fmt.Println(s1) //lancet
result1 := strutil.BeforeLast("foo", "")
result2 := strutil.BeforeLast("foo", "foo")
result3 := strutil.BeforeLast("foo/bar", "/")
result4 := strutil.BeforeLast("foo/bar/baz", "/")
s2 := strutil.BeforeLast("github.com/test/lancet", "/")
fmt.Println(s2) //github.com/test
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
s3 := strutil.BeforeLast("github.com/test/test/lancet", "test")
fmt.Println(s3) //github.com/test/
// Output:
// foo
//
// foo
// foo/bar
}
```
### <span id="CamelCase">CamelCase</span>
<p>Coverts string to camelCase string, non letters and numbers will be ignored.</p>
<b>Signature:</b>
@@ -175,6 +210,7 @@ func main() {
```go
func CamelCase(s string) string
```
<b>Example:</b>
```go
@@ -184,26 +220,24 @@ import (
)
func main() {
s1 := strutil.CamelCase("foo_bar")
fmt.Println(s1) //fooBar
strings := []string{"", "foobar", "&FOO:BAR$BAZ", "$foo%", "Foo-#1😄$_%^&*(1bar"}
s2 := strutil.CamelCase("Foo-Bar")
fmt.Println(s2) //fooBar
s3 := strutil.CamelCase("Foo&bar")
fmt.Println(s3) //fooBar
s4 := strutil.CamelCase("foo bar")
fmt.Println(s4) //fooBar
s4 := strutil.CamelCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s4) //foo11Bar
for _, v := range strings {
s := strutil.CamelCase(v)
fmt.Println(s)
}
// Output:
//
// foobar
// fooBarBaz
// foo
// foo11Bar
}
```
### <span id="KebabCase">KebabCase</span>
<p>KebabCase covert string to kebab-case, non letters and numbers will be ignored.</p>
<b>Signature:</b>
@@ -211,6 +245,7 @@ func main() {
```go
func KebabCase(s string) string
```
<b>Example:</b>
```go
@@ -220,30 +255,32 @@ import (
)
func main() {
s1 := strutil.KebabCase("Foo Bar-")
fmt.Println(s1) //foo-bar
strings := []string{"", "foo-bar", "Foo Bar-", "FOOBAR", "Foo-#1😄$_%^&*(1bar"}
s2 := strutil.KebabCase("foo_Bar")
fmt.Println(s2) //foo-bar
for _, v := range strings {
s := strutil.KebabCase(v)
fmt.Println(s)
}
s3 := strutil.KebabCase("fooBar")
fmt.Println(s3) //foo-bar
s4 := strutil.KebabCase("__FOO_BAR__")
fmt.Println(s4) //foo-bar
// Output:
//
// foo-bar
// foo-bar
// foobar
// foo-1-1-bar
}
```
### <span id="UpperKebabCase">UpperKebabCase</span>
<p>UpperKebabCase covert string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b>
```go
func KebabCase(s string) string
func UpperKebabCase(s string) string
```
<b>Example:</b>
```go
@@ -253,24 +290,24 @@ import (
)
func main() {
s1 := strutil.UpperKebabCase("Foo Bar-")
fmt.Println(s1) //FOO-BAR
strings := []string{"", "foo-bar", "Foo Bar-", "FooBAR", "Foo-#1😄$_%^&*(1bar"}
s2 := strutil.UpperKebabCase("foo_Bar")
fmt.Println(s2) //FOO-BAR
for _, v := range strings {
s := strutil.UpperKebabCase(v)
fmt.Println(s)
}
s3 := strutil.UpperKebabCase("fooBar")
fmt.Println(s3) //FOO-BAR
s4 := strutil.UpperKebabCase("__FOO_BAR__")
fmt.Println(s4) //FOO-BAR
// Output:
//
// FOO-BAR
// FOO-BAR
// FOO-BAR
// FOO-1-1-BAR
}
```
### <span id="Capitalize">Capitalize</span>
<p>Convert the first character of a string to upper case.</p>
<b>Signature:</b>
@@ -278,6 +315,7 @@ func main() {
```go
func Capitalize(s string) string
```
<b>Example:</b>
```go
@@ -287,20 +325,24 @@ import (
)
func main() {
s1 := strutil.Capitalize("foo")
fmt.Println(s1) //foo
strings := []string{"", "Foo", "_foo", "fooBar", "foo-bar"}
s2 := strutil.Capitalize("Foo")
fmt.Println(s2) //foo
for _, v := range strings {
s := strutil.Capitalize(v)
fmt.Println(s)
}
s3 := strutil.Capitalize("FOo"
fmt.Println(s3) //fOo
// Output:
//
// Foo
// _foo
// Foobar
// Foo-bar
}
```
### <span id="IsString">IsString</span>
<p>Check if the value's data type is string.</p>
<b>Signature:</b>
@@ -308,6 +350,7 @@ func main() {
```go
func IsString(v any) bool
```
<b>Example:</b>
```go
@@ -317,52 +360,29 @@ import (
)
func main() {
fmt.Println(strutil.IsString("lancet")) //true
fmt.Println(strutil.IsString("")) //true
result1 := strutil.IsString("")
result2 := strutil.IsString("a")
result3 := strutil.IsString(1)
result4 := strutil.IsString(true)
result5 := strutil.IsString([]string{"a"})
fmt.Println(strutil.IsString(1)) //false
fmt.Println(strutil.IsString("")) //false
fmt.Println(strutil.IsString([]string{})) //false
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// true
// true
// false
// false
// false
}
```
### <span id="KebabCase">KebabCase</span>
<p>Covert string to kebab-case.</p>
<b>Signature:</b>
```go
func KebabCase(s string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.KebabCase("Foo Bar-")
fmt.Println(s1) //foo-bar
s2 := strutil.KebabCase("foo_Bar")
fmt.Println(s2) //foo-bar
s3 := strutil.KebabCase("fooBar")
fmt.Println(s3) //foo-bar
s4 := strutil.KebabCase("__FOO_BAR__")
fmt.Println(s4) //f-o-o-b-a-r
}
```
### <span id="LowerFirst">LowerFirst</span>
<p>Convert the first character of string to lower case.</p>
<b>Signature:</b>
@@ -370,6 +390,7 @@ func main() {
```go
func LowerFirst(s string) string
```
<b>Example:</b>
```go
@@ -379,24 +400,23 @@ import (
)
func main() {
s1 := strutil.LowerFirst("foo")
fmt.Println(s1) //foo
strings := []string{"", "bar", "BAr", "Bar大"}
s2 := strutil.LowerFirst("BAR")
fmt.Println(s2) //bAR
for _, v := range strings {
s := strutil.LowerFirst(v)
fmt.Println(s)
}
s3 := strutil.LowerFirst("FOo")
fmt.Println(s3) //fOo
s4 := strutil.LowerFirst("fOo大")
fmt.Println(s4) //fOo
// Output:
//
// bar
// bAr
// bar
}
```
### <span id="UpperFirst">UpperFirst</span>
<p>Convert the first character of string to upper case.</p>
<b>Signature:</b>
@@ -404,6 +424,7 @@ func main() {
```go
func UpperFirst(s string) string
```
<b>Example:</b>
```go
@@ -413,24 +434,23 @@ import (
)
func main() {
s1 := strutil.UpperFirst("foo")
fmt.Println(s1) //Foo
strings := []string{"", "bar", "BAr", "bar大"}
s2 := strutil.UpperFirst("bAR")
fmt.Println(s2) //BAR
for _, v := range strings {
s := strutil.UpperFirst(v)
fmt.Println(s)
}
s3 := strutil.UpperFirst("FOo")
fmt.Println(s3) //FOo
s4 := strutil.UpperFirst("fOo大")
fmt.Println(s4) //FOo
// Output:
//
// Bar
// BAr
// Bar
}
```
### <span id="PadEnd">PadEnd</span>
<p>Pads string on the right side if it's shorter than size.</p>
<b>Signature:</b>
@@ -438,6 +458,7 @@ func main() {
```go
func PadEnd(source string, size int, padStr string) string
```
<b>Example:</b>
```go
@@ -447,24 +468,35 @@ import (
)
func main() {
s1 := strutil.PadEnd("a", 1, "b")
fmt.Println(s1) //a
result1 := strutil.PadEnd("foo", 1, "bar")
result2 := strutil.PadEnd("foo", 2, "bar")
result3 := strutil.PadEnd("foo", 3, "bar")
result4 := strutil.PadEnd("foo", 4, "bar")
result5 := strutil.PadEnd("foo", 5, "bar")
result6 := strutil.PadEnd("foo", 6, "bar")
result7 := strutil.PadEnd("foo", 7, "bar")
s2 := strutil.PadEnd("a", 2, "b")
fmt.Println(s2) //ab
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
s3 := strutil.PadEnd("abcd", 6, "mno")
fmt.Println(s3) //abcdmn
s4 := strutil.PadEnd("abc", 6, "ab")
fmt.Println(s4) //abcaba
// Output:
// foo
// foo
// foo
// foob
// fooba
// foobar
// foobarb
}
```
### <span id="PadStart">PadStart</span>
<p>Pads string on the left side if it's shorter than size.</p>
<b>Signature:</b>
@@ -472,6 +504,7 @@ func main() {
```go
func PadStart(source string, size int, padStr string) string
```
<b>Example:</b>
```go
@@ -481,24 +514,35 @@ import (
)
func main() {
s1 := strutil.PadStart("a", 1, "b")
fmt.Println(s1) //a
result1 := strutil.PadStart("foo", 1, "bar")
result2 := strutil.PadStart("foo", 2, "bar")
result3 := strutil.PadStart("foo", 3, "bar")
result4 := strutil.PadStart("foo", 4, "bar")
result5 := strutil.PadStart("foo", 5, "bar")
result6 := strutil.PadStart("foo", 6, "bar")
result7 := strutil.PadStart("foo", 7, "bar")
s2 := strutil.PadStart("a", 2, "b")
fmt.Println(s2) //ba
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
s3 := strutil.PadStart("abcd", 6, "mno")
fmt.Println(s3) //mnabcd
s4 := strutil.PadStart("abc", 6, "ab")
fmt.Println(s4) //abaabc
// Output:
// foo
// foo
// foo
// bfoo
// bafoo
// barfoo
// barbfoo
}
```
### <span id="Reverse">Reverse</span>
<p>Return string whose char order is reversed to the given string.</p>
<b>Signature:</b>
@@ -506,6 +550,7 @@ func main() {
```go
func Reverse(s string) string
```
<b>Example:</b>
```go
@@ -515,17 +560,20 @@ import (
)
func main() {
s1 := strutil.ReverseStr("abc")
fmt.Println(s1) //cba
s := "foo"
rs := strutil.Reverse(s)
s2 := strutil.ReverseStr("12345")
fmt.Println(s2) //54321
fmt.Println(s)
fmt.Println(rs)
// Output:
// foo
// oof
}
```
### <span id="SnakeCase">SnakeCase</span>
<p>Coverts string to snake_case, non letters and numbers will be ignored.</p>
<b>Signature:</b>
@@ -533,6 +581,7 @@ func main() {
```go
func SnakeCase(s string) string
```
<b>Example:</b>
```go
@@ -542,25 +591,24 @@ import (
)
func main() {
s1 := strutil.SnakeCase("Foo Bar-")
fmt.Println(s1) //foo_bar
strings := []string{"", "foo-bar", "Foo Bar-", "FOOBAR", "Foo-#1😄$_%^&*(1bar"}
s2 := strutil.SnakeCase("foo_Bar")
fmt.Println(s2) //foo_bar
for _, v := range strings {
s := strutil.SnakeCase(v)
fmt.Println(s)
}
s3 := strutil.SnakeCase("fooBar")
fmt.Println(s3) //foo_bar
s4 := strutil.SnakeCase("__FOO_BAR__")
fmt.Println(s4) //foo_bar
s5 := strutil.SnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //foo_1_1_bar
// Output:
//
// foo_bar
// foo_bar
// foobar
// foo_1_1_bar
}
```
### <span id="UpperSnakeCase">UpperSnakeCase</span>
<p>Coverts string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b>
@@ -568,6 +616,7 @@ func main() {
```go
func SnakeCase(s string) string
```
<b>Example:</b>
```go
@@ -577,25 +626,24 @@ import (
)
func main() {
s1 := strutil.UpperSnakeCase("Foo Bar-")
fmt.Println(s1) //FOO_BAR
strings := []string{"", "foo-bar", "Foo Bar-", "FooBAR", "Foo-#1😄$_%^&*(1bar"}
s2 := strutil.UpperSnakeCase("foo_Bar")
fmt.Println(s2) //FOO_BAR
for _, v := range strings {
s := strutil.UpperSnakeCase(v)
fmt.Println(s)
}
s3 := strutil.UpperSnakeCase("fooBar")
fmt.Println(s3) //FOO_BAR
s4 := strutil.UpperSnakeCase("__FOO_BAR__")
fmt.Println(s4) //FOO_BAR
s5 := strutil.UpperSnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //FOO_1_1_BAR
// Output:
//
// FOO_BAR
// FOO_BAR
// FOO_BAR
// FOO_1_1_BAR
}
```
### <span id="SplitEx">SplitEx</span>
<p>Split a given string whether the result contains empty string.</p>
<b>Signature:</b>
@@ -603,6 +651,7 @@ func main() {
```go
func SplitEx(s, sep string, removeEmptyString bool) []string
```
<b>Example:</b>
```go
@@ -612,34 +661,81 @@ import (
)
func main() {
arr1 := strutil.SplitEx(" a b c ", "", true)
fmt.Println(arr1) //[]string{}
result1 := strutil.SplitEx(" a b c ", "", true)
arr2 := strutil.SplitEx(" a b c ", " ", false)
fmt.Println(arr2) //[]string{"", "a", "b", "c", ""}
result2 := strutil.SplitEx(" a b c ", " ", false)
result3 := strutil.SplitEx(" a b c ", " ", true)
arr3 := strutil.SplitEx(" a b c ", " ", true)
fmt.Println(arr3) //[]string{"a", "b", "c"}
result4 := strutil.SplitEx("a = b = c = ", " = ", false)
result5 := strutil.SplitEx("a = b = c = ", " = ", true)
arr4 := strutil.SplitEx(" a = b = c = ", " = ", false)
fmt.Println(arr4) //[]string{" a", "b", "c", ""}
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
arr5 := strutil.SplitEx(" a = b = c = ", " = ", true)
fmt.Println(arr5) //[]string{" a", "b", "c"}
// Output:
// []
// [ a b c ]
// [a b c]
// [a b c ]
}
```
### <span id="Substring">Substring</span>
<p>Returns a substring of the specified length starting at the specified offset position.</p>
<b>Signature:</b>
```go
func Substring(s string, offset int, length uint) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.Substring("abcde", 1, 3)
result2 := strutil.Substring("abcde", 1, 5)
result3 := strutil.Substring("abcde", -1, 3)
result4 := strutil.Substring("abcde", -2, 2)
result5 := strutil.Substring("abcde", -2, 3)
result6 := strutil.Substring("你好,欢迎你", 0, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// bcd
// bcde
// e
// de
// de
// 你好
}
```
### <span id="Wrap">Wrap</span>
<p>Wrap a string with another string.</p>
<p>Wrap a string with given string.</p>
<b>Signature:</b>
```go
func Wrap(str string, wrapWith string) string
```
<b>Example:</b>
```go
@@ -649,34 +745,34 @@ import (
)
func main() {
s1 := strutil.Wrap("ab", "")
fmt.Println(s1) //ab
result1 := strutil.Wrap("foo", "")
result2 := strutil.Wrap("foo", "*")
result3 := strutil.Wrap("'foo'", "'")
result4 := strutil.Wrap("", "*")
s2 := strutil.Wrap("", "*")
fmt.Println(s2) //""
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
s3 := strutil.Wrap("ab", "*")
fmt.Println(s3) //*ab*
s4 := strutil.Wrap("ab", "\"")
fmt.Println(s4) //\"ab\"
s5 := strutil.Wrap("ab", "'")
fmt.Println(s5) //'ab'
// Output:
// foo
// *foo*
// ''foo''
//
}
```
### <span id="Wrap">Wrap</span>
<p>Unwrap a given string from anther string. will change str value.</p>
<p>Unwrap a given string from anther string. will change source string.</p>
<b>Signature:</b>
```go
func Unwrap(str string, wrapToken string) string
```
<b>Example:</b>
```go
@@ -686,28 +782,23 @@ import (
)
func main() {
s1 := strutil.Unwrap("ab", "")
fmt.Println(s1) //ab
result1 := strutil.Unwrap("foo", "")
result2 := strutil.Unwrap("*foo*", "*")
result3 := strutil.Unwrap("*foo", "*")
result4 := strutil.Unwrap("foo*", "*")
result5 := strutil.Unwrap("**foo**", "*")
s2 := strutil.Unwrap("ab", "*")
fmt.Println(s2) //ab
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
s3 := strutil.Unwrap("**ab**", "*")
fmt.Println(s3) //*ab*
s4 := strutil.Unwrap("*ab", "*")
fmt.Println(s4) //*ab
s5 := strutil.Unwrap("***", "**")
fmt.Println(s5) //***
// Output:
// foo
// foo
// *foo
// foo*
// *foo*
}
```
+415 -294
View File
File diff suppressed because it is too large Load Diff
+65 -38
View File
@@ -1,4 +1,5 @@
# System
Package system contains some functions about os, runtime, shell command.
<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)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/system"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux)
- [IsMac](#IsMac)
@@ -30,13 +32,12 @@ import (
- [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="IsWindows">IsWindows</span>
<p>Check if current os is windows.</p>
<b>Signature:</b>
@@ -44,6 +45,7 @@ import (
```go
func IsWindows() bool
```
<b>Example:</b>
```go
@@ -58,10 +60,8 @@ func main() {
}
```
### <span id="IsLinux">IsLinux</span>
<p>Check if current os is linux.</p>
<b>Signature:</b>
@@ -69,6 +69,7 @@ func main() {
```go
func IsLinux() bool
```
<b>Example:</b>
```go
@@ -83,9 +84,8 @@ func main() {
}
```
### <span id="IsMac">IsMac</span>
<p>Check if current os is macos.</p>
<b>Signature:</b>
@@ -93,6 +93,7 @@ func main() {
```go
func IsMac() bool
```
<b>Example:</b>
```go
@@ -102,14 +103,13 @@ import (
)
func main() {
isOsMac := system.IsMac
isOsMac := system.IsMac()
fmt.Println(isOsMac)
}
```
### <span id="GetOsEnv">GetOsEnv</span>
<p>Gets the value of the environment variable named by the key.</p>
<b>Signature:</b>
@@ -117,6 +117,7 @@ func main() {
```go
func GetOsEnv(key string) string
```
<b>Example:</b>
```go
@@ -126,14 +127,19 @@ import (
)
func main() {
fooEnv := system.GetOsEnv("foo")
fmt.Println(fooEnv)
err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
}
```
### <span id="SetOsEnv">SetOsEnv</span>
<p>Sets the value of the environment variable named by the key.</p>
<b>Signature:</b>
@@ -141,6 +147,7 @@ func main() {
```go
func SetOsEnv(key, value string) error
```
<b>Example:</b>
```go
@@ -150,15 +157,19 @@ import (
)
func main() {
err := system.SetOsEnv("foo", "foo_value")
err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
}
```
### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>Remove a single environment variable.</p>
<b>Signature:</b>
@@ -166,6 +177,7 @@ func main() {
```go
func RemoveOsEnv(key string) error
```
<b>Example:</b>
```go
@@ -175,16 +187,27 @@ import (
)
func main() {
err := system.RemoveOsEnv("foo")
if err != nil {
fmt.Println(err)
}
err1 := system.SetOsEnv("foo", "abc")
result1 := GetOsEnv("foo")
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>
<p>Get env named by the key and compare it with comparedEnv.</p>
<b>Signature:</b>
@@ -192,6 +215,7 @@ func main() {
```go
func CompareOsEnv(key, comparedEnv string) bool
```
<b>Example:</b>
```go
@@ -201,16 +225,22 @@ import (
)
func main() {
system.SetOsEnv("foo", "foo_value")
res := system.CompareOsEnv("foo", "foo_value")
fmt.Println(res) //true
err := system.SetOsEnv("foo", "abc")
if err != nil {
return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
}
```
### <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>
<b>Signature:</b>
@@ -218,6 +248,7 @@ func main() {
```go
func ExecCommand(command string) (stdout, stderr string, err error)
```
<b>Example:</b>
```go
@@ -248,10 +279,8 @@ func main() {
}
```
### <span id="GetOsBits">GetOsBits</span>
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
<b>Signature:</b>
@@ -259,6 +288,7 @@ func main() {
```go
func GetOsBits() int
```
<b>Example:</b>
```go
@@ -269,9 +299,6 @@ import (
func main() {
osBit := system.GetOsBits()
fmt.Println(osBit)
fmt.Println(osBit) // 32 or 64
}
```
+66 -44
View File
@@ -1,4 +1,5 @@
# System
system 包含 os, runtime, shell command 相关函数。
<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)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/system"
@@ -20,24 +21,23 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [IsWindows](#IsWindows)
- [IsLinux](#IsLinux)
- [IsMac](#IsMac)
- [GetOsEnv](#GetOsEnv)
- [SetOsEnv](#SetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv)
- [CompareOsEnv](#CompareOsEnv)
- [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div>
## Documentation 文档
### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p>
<b>Signature:</b>
@@ -45,6 +45,7 @@ import (
```go
func IsWindows() bool
```
<b>Example:</b>
```go
@@ -59,10 +60,8 @@ func main() {
}
```
### <span id="IsLinux">IsLinux</span>
<p>检查当前操作系统是否是linux</p>
<b>Signature:</b>
@@ -70,6 +69,7 @@ func main() {
```go
func IsLinux() bool
```
<b>Example:</b>
```go
@@ -84,9 +84,8 @@ func main() {
}
```
### <span id="IsMac">IsMac</span>
<p>检查当前操作系统是否是macos</p>
<b>Signature:</b>
@@ -94,6 +93,7 @@ func main() {
```go
func IsMac() bool
```
<b>Example:</b>
```go
@@ -103,14 +103,13 @@ import (
)
func main() {
isOsMac := system.IsMac
isOsMac := system.IsMac()
fmt.Println(isOsMac)
}
```
### <span id="GetOsEnv">GetOsEnv</span>
<p>获取key命名的环境变量的值</p>
<b>Signature:</b>
@@ -118,6 +117,7 @@ func main() {
```go
func GetOsEnv(key string) string
```
<b>Example:</b>
```go
@@ -127,14 +127,19 @@ import (
)
func main() {
fooEnv := system.GetOsEnv("foo")
fmt.Println(fooEnv)
err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
}
```
### <span id="SetOsEnv">SetOsEnv</span>
<p>设置由key命名的环境变量的值</p>
<b>Signature:</b>
@@ -142,6 +147,7 @@ func main() {
```go
func SetOsEnv(key, value string) error
```
<b>Example:</b>
```go
@@ -151,15 +157,19 @@ import (
)
func main() {
err := system.SetOsEnv("foo", "foo_value")
err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
}
```
### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>删除单个环境变量</p>
<b>Signature:</b>
@@ -167,6 +177,7 @@ func main() {
```go
func RemoveOsEnv(key string) error
```
<b>Example:</b>
```go
@@ -176,16 +187,27 @@ import (
)
func main() {
err := system.RemoveOsEnv("foo")
if err != nil {
fmt.Println(err)
}
err1 := system.SetOsEnv("foo", "abc")
result1 := GetOsEnv("foo")
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>
<p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b>
@@ -193,6 +215,7 @@ func main() {
```go
func CompareOsEnv(key, comparedEnv string) bool
```
<b>Example:</b>
```go
@@ -202,16 +225,22 @@ import (
)
func main() {
system.SetOsEnv("foo", "foo_value")
res := system.CompareOsEnv("foo", "foo_value")
fmt.Println(res) //true
err := system.SetOsEnv("foo", "abc")
if err != nil {
return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
}
```
### <span id="ExecCommand">ExecCommand</span>
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-alinux),dirwindows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
<b>Signature:</b>
@@ -219,6 +248,7 @@ func main() {
```go
func ExecCommand(command string) (stdout, stderr string, err error)
```
<b>Example:</b>
```go
@@ -249,10 +279,8 @@ func main() {
}
```
### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数,返回32或64</p>
<b>函数签名:</b>
@@ -260,7 +288,8 @@ func main() {
```go
func GetOsBits() int
```
<b>例子:</b>
<b>示例:</b>
```go
import (
@@ -270,13 +299,6 @@ import (
func main() {
osBit := system.GetOsBits()
fmt.Println(osBit)
fmt.Println(osBit) // 32 or 64
}
```
+355 -220
View File
File diff suppressed because it is too large Load Diff
+383 -242
View File
File diff suppressed because it is too large Load Diff
+14 -3
View File
@@ -1,4 +1,5 @@
# Xerror
Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
@@ -19,15 +21,15 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <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>
<b>Signature:</b>
@@ -35,6 +37,7 @@ import (
```go
func Unwrap[T any](val T, err error) T
```
<b>Example:</b>
```go
@@ -46,12 +49,20 @@ import (
)
func main() {
result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1)
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2)
}()
xerror.Unwrap(strconv.Atoi("4o2"))
// Output:
// 42
// true
}
```
+16 -5
View File
@@ -1,4 +1,5 @@
# Xerror
xerror 错误处理逻辑封装
<div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ xerror错误处理逻辑封装
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
@@ -19,23 +21,24 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Unwrap">Unwrap</span>
<p>如果err为nil则展开,则它返回一个有效值。 如果err不是nil则Unwrap使用err发生恐慌。</p>
<p>检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。</p>
<b>函数签名:</b>
```go
func Unwrap[T any](val T, err error) T
```
<b>例子:</b>
<b>示例:</b>
```go
package main
@@ -46,12 +49,20 @@ import (
)
func main() {
result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1)
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2)
}()
xerror.Unwrap(strconv.Atoi("4o2"))
// Output:
// 42
// true
}
```
+30 -15
View File
@@ -18,7 +18,8 @@ import (
"strings"
)
// IsExist checks if a file or directory exists
// IsExist checks if a file or directory exists.
// Play: https://go.dev/play/p/nKKXt8ZQbmh
func IsExist(path string) bool {
_, err := os.Stat(path)
if err == nil {
@@ -30,7 +31,8 @@ func IsExist(path string) bool {
return false
}
// CreateFile create a file in path
// CreateFile create a file in path.
// Play: https://go.dev/play/p/lDt8PEsTNKI
func CreateFile(path string) bool {
file, err := os.Create(path)
if err != nil {
@@ -41,12 +43,14 @@ func CreateFile(path string) bool {
return true
}
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/.
// Play: https://go.dev/play/p/qUuCe1OGQnM
func CreateDir(absPath string) error {
return os.MkdirAll(path.Dir(absPath), os.ModePerm)
}
// IsDir checks if the path is directory or not
// IsDir checks if the path is directory or not.
// Play: https://go.dev/play/p/WkVwEKqtOWk
func IsDir(path string) bool {
file, err := os.Stat(path)
if err != nil {
@@ -55,12 +59,14 @@ func IsDir(path string) bool {
return file.IsDir()
}
// RemoveFile remove the path file
// RemoveFile remove the path file.
// Play: https://go.dev/play/p/P2y0XW8a1SH
func RemoveFile(path string) error {
return os.Remove(path)
}
// CopyFile copy src file to dest file
// CopyFile copy src file to dest file.
// Play: https://go.dev/play/p/Jg9AMJMLrJi
func CopyFile(srcFilePath string, dstFilePath string) error {
srcFile, err := os.Open(srcFilePath)
if err != nil {
@@ -90,7 +96,8 @@ func CopyFile(srcFilePath string, dstFilePath string) error {
}
}
//ClearFile write empty string to path file
// ClearFile write empty string to path file.
// Play: https://go.dev/play/p/NRZ0ZT-G94H
func ClearFile(path string) error {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
if err != nil {
@@ -102,7 +109,8 @@ func ClearFile(path string) error {
return err
}
//ReadFileToString return string of file content
// ReadFileToString return string of file content.
// Play: https://go.dev/play/p/cmfwp_5SQTp
func ReadFileToString(path string) (string, error) {
bytes, err := os.ReadFile(path)
if err != nil {
@@ -111,7 +119,8 @@ func ReadFileToString(path string) (string, error) {
return string(bytes), nil
}
// ReadFileByLine read file line by line
// ReadFileByLine read file line by line.
// Play: https://go.dev/play/p/svJP_7ZrBrD
func ReadFileByLine(path string) ([]string, error) {
f, err := os.Open(path)
if err != nil {
@@ -137,7 +146,8 @@ func ReadFileByLine(path string) ([]string, error) {
return result, nil
}
// ListFileNames return all file names in the path
// ListFileNames return all file names in the path.
// Play: https://go.dev/play/p/Tjd7Y07rejl
func ListFileNames(path string) ([]string, error) {
if !IsExist(path) {
return []string{}, nil
@@ -163,7 +173,8 @@ func ListFileNames(path string) ([]string, error) {
return result, nil
}
// Zip create zip file, fpath could be a single file or a directory
// Zip create zip file, fpath could be a single file or a directory.
// Play: https://go.dev/play/p/j-3sWBp8ik_P
func Zip(fpath string, destPath string) error {
zipFile, err := os.Create(destPath)
if err != nil {
@@ -218,7 +229,8 @@ func Zip(fpath string, destPath string) error {
return nil
}
// UnZip unzip the file and save it to destPath
// UnZip unzip the file and save it to destPath.
// Play: https://go.dev/play/p/g0w34kS7B8m
func UnZip(zipFile string, destPath string) error {
zipReader, err := zip.OpenReader(zipFile)
@@ -277,7 +289,8 @@ func safeFilepathJoin(path1, path2 string) (string, error) {
return filepath.Join(path1, filepath.Join("/", relPath)), nil
}
// IsLink checks if a file is symbol link or not
// IsLink checks if a file is symbol link or not.
// Play: https://go.dev/play/p/TL-b-Kzvf44
func IsLink(path string) bool {
fi, err := os.Lstat(path)
if err != nil {
@@ -286,7 +299,8 @@ func IsLink(path string) bool {
return fi.Mode()&os.ModeSymlink != 0
}
// FileMode return file's mode and permission
// FileMode return file's mode and permission.
// Play: https://go.dev/play/p/2l2hI42fA3p
func FileMode(path string) (fs.FileMode, error) {
fi, err := os.Lstat(path)
if err != nil {
@@ -296,7 +310,8 @@ func FileMode(path string) (fs.FileMode, error) {
}
// MiMeType return file mime type
// param `file` should be string(file path) or *os.File
// param `file` should be string(file path) or *os.File.
// Play: https://go.dev/play/p/bd5sevSUZNu
func MiMeType(file any) string {
var mediatype string
+225
View File
@@ -0,0 +1,225 @@
package fileutil
import (
"fmt"
"os"
)
func ExampleIsExist() {
result1 := IsExist("./")
result2 := IsExist("./xxx.go")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleCreateFile() {
fname := "./a.txt"
result1 := IsExist(fname)
CreateFile(fname)
result2 := IsExist(fname)
os.Remove(fname)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// false
// true
}
func ExampleCreateDir() {
pwd, _ := os.Getwd()
dirPath := pwd + "/test_xxx/"
result1 := IsExist(dirPath)
err := CreateDir(dirPath)
if err != nil {
return
}
result2 := IsExist(dirPath)
os.Remove(dirPath)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// false
// true
}
func ExampleIsDir() {
result1 := IsDir("./")
result2 := IsDir("./xxx.go")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleRemoveFile() {
srcFile := "./text.txt"
CreateFile(srcFile)
copyFile := "./text_copy.txt"
err := CopyFile(srcFile, copyFile)
if err != nil {
return
}
file, err := os.Open(copyFile)
if err != nil {
return
}
result1 := IsExist(copyFile)
result2 := file.Name()
os.Remove(srcFile)
os.Remove(copyFile)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// ./text_copy.txt
}
func ExampleReadFileToString() {
fname := "./test.txt"
CreateFile(fname)
f, _ := os.OpenFile(fname, os.O_WRONLY|os.O_TRUNC, 0777)
defer f.Close()
_, err := f.WriteString("hello world")
if err != nil {
return
}
content, _ := ReadFileToString(fname)
os.Remove(fname)
fmt.Println(content)
// Output:
// hello world
}
func ExampleClearFile() {
fname := "./test.txt"
CreateFile(fname)
f, _ := os.OpenFile(fname, os.O_WRONLY|os.O_TRUNC, 0777)
defer f.Close()
_, err := f.WriteString("hello world")
if err != nil {
return
}
content1, _ := ReadFileToString(fname)
err = ClearFile(fname)
if err != nil {
return
}
content2, _ := ReadFileToString(fname)
os.Remove(fname)
fmt.Println(content1)
fmt.Println(content2)
// Output:
// hello world
//
}
func ExampleReadFileByLine() {
fname := "./test.txt"
CreateFile(fname)
f, _ := os.OpenFile(fname, os.O_WRONLY|os.O_TRUNC, 0777)
defer f.Close()
_, err := f.WriteString("hello\nworld")
if err != nil {
return
}
content, _ := ReadFileByLine(fname)
os.Remove(fname)
fmt.Println(content)
// Output:
// [hello world]
}
func ExampleListFileNames() {
fileList, _ := ListFileNames("../formatter/")
fmt.Println(fileList)
// Output:
// [formatter.go formatter_example_test.go formatter_test.go]
}
func ExampleZip() {
srcFile := "./test.txt"
CreateFile(srcFile)
zipFile := "./test.zip"
err := Zip(srcFile, zipFile)
if err != nil {
return
}
result := IsExist(zipFile)
os.Remove(srcFile)
os.Remove(zipFile)
fmt.Println(result)
// Output:
// true
}
func ExampleUnZip() {
fname := "./test.txt"
file, _ := os.Create(fname)
_, err := file.WriteString("hello\nworld")
if err != nil {
return
}
f, _ := os.Open(fname)
defer f.Close()
mimeType := MiMeType(f)
fmt.Println(mimeType)
os.Remove(fname)
// Output:
// application/octet-stream
}
+10 -10
View File
@@ -96,16 +96,6 @@ func TestCopyFile(t *testing.T) {
os.Remove(destFile)
}
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("./")
assert.IsNil(err)
expected := []string{"file.go", "file_test.go"}
assert.Equal(expected, filesInPath)
}
func TestReadFileToString(t *testing.T) {
assert := internal.NewAssert(t, "TestReadFileToString")
@@ -241,3 +231,13 @@ func TestMiMeType(t *testing.T) {
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
}
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("../formatter/")
assert.IsNil(err)
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"}
assert.Equal(expected, filesInPath)
}
+43
View File
@@ -5,6 +5,9 @@
package formatter
import (
"fmt"
"reflect"
"strconv"
"strings"
"golang.org/x/exp/constraints"
@@ -13,6 +16,7 @@ import (
// Comma add comma to a number value by every 3 numbers from right. ahead by symbol char.
// if value is invalid number string eg "aa", return empty string
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
// Play: https://go.dev/play/p/eRD5k2vzUVX
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
s, err := numberToString(value)
if err != nil {
@@ -26,3 +30,42 @@ func Comma[T constraints.Float | constraints.Integer | string](value T, symbol s
return symbol + commaString(s)
}
func commaString(s string) string {
if len(s) <= 3 {
return s
}
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
}
func numberToString(value any) (string, error) {
switch reflect.TypeOf(value).Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return fmt.Sprintf("%v", value), nil
// todo: need to handle 12345678.9 => 1.23456789e+07
case reflect.Float32, reflect.Float64:
return fmt.Sprintf("%v", value), nil
case reflect.String:
{
sv := fmt.Sprintf("%v", value)
if strings.Contains(sv, ".") {
_, err := strconv.ParseFloat(sv, 64)
if err != nil {
return "", err
}
return sv, nil
} else {
_, err := strconv.ParseInt(sv, 10, 64)
if err != nil {
return "", nil
}
return sv, nil
}
}
default:
return "", nil
}
}
+18
View File
@@ -0,0 +1,18 @@
package formatter
import "fmt"
func ExampleComma() {
result1 := Comma("123", "")
result2 := Comma("12345", "$")
result3 := Comma(1234567, "¥")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 123
// $12,345
// ¥1,234,567
}
-47
View File
@@ -1,47 +0,0 @@
package formatter
import (
"fmt"
"reflect"
"strconv"
"strings"
)
func commaString(s string) string {
if len(s) <= 3 {
return s
}
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
}
func numberToString(value any) (string, error) {
switch reflect.TypeOf(value).Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return fmt.Sprintf("%v", value), nil
// todo: need to handle 12345678.9 => 1.23456789e+07
case reflect.Float32, reflect.Float64:
return fmt.Sprintf("%v", value), nil
case reflect.String:
{
sv := fmt.Sprintf("%v", value)
if strings.Contains(sv, ".") {
_, err := strconv.ParseFloat(sv, 64)
if err != nil {
return "", err
}
return sv, nil
} else {
_, err := strconv.ParseInt(sv, 10, 64)
if err != nil {
return "", nil
}
return sv, nil
}
}
default:
return "", nil
}
}
+47 -19
View File
@@ -5,11 +5,13 @@
package function
import (
"fmt"
"reflect"
"time"
)
// After creates a function that invokes func once it's called n or more times
// After creates a function that invokes func once it's called n or more times.
// Play: https://go.dev/play/p/8mQhkFmsgqs
func After(n int, fn any) func(args ...any) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
@@ -23,7 +25,8 @@ func After(n int, fn any) func(args ...any) []reflect.Value {
}
}
// Before creates a function that invokes func once it's called less than n times
// Before creates a function that invokes func once it's called less than n times.
// Play: https://go.dev/play/p/0HqUDIFZ3IL
func Before(n int, fn any) func(args ...any) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
@@ -40,41 +43,48 @@ func Before(n int, fn any) func(args ...any) []reflect.Value {
}
}
// Fn is for curry function which is func(...any) any
type Fn func(...any) any
// CurryFn is for make curry function
type CurryFn[T any] func(...T) T
// Curry make a curry function
func (f Fn) Curry(i any) func(...any) any {
return func(values ...any) any {
v := append([]any{i}, values...)
return f(v...)
// New make a curry function for specific value.
// Play: https://go.dev/play/p/5HopfDwANKX
func (cf CurryFn[T]) New(val T) func(...T) T {
return func(vals ...T) T {
args := append([]T{val}, vals...)
return cf(args...)
}
}
// Compose compose the functions from right to left
func Compose(fnList ...func(...any) any) func(...any) any {
return func(s ...any) any {
f := fnList[0]
restFn := fnList[1:]
// Compose compose the functions from right to left.
// Play: https://go.dev/play/p/KKfugD4PKYF
func Compose[T any](fnList ...func(...T) T) func(...T) T {
return func(args ...T) T {
firstFn := fnList[0]
restFns := fnList[1:]
if len(fnList) == 1 {
return f(s...)
return firstFn(args...)
}
return f(Compose(restFn...)(s...))
fn := Compose(restFns...)
arg := fn(args...)
return firstFn(arg)
}
}
// Delay make the function execution after delayed time
// Delay make the function execution after delayed time.
// Play: https://go.dev/play/p/Ivtc2ZE-Tye
func Delay(delay time.Duration, fn any, args ...any) {
// Catch programming error while constructing the closure
mustBeFunction(fn)
time.Sleep(delay)
invokeFunc(fn, args...)
unsafeInvokeFunc(fn, args...)
}
// Debounced creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
// Play: https://go.dev/play/p/absuEGB_GN7
func Debounced(fn func(), duration time.Duration) func() {
// Catch programming error while constructing the closure
mustBeFunction(fn)
@@ -92,7 +102,8 @@ func Debounced(fn func(), duration time.Duration) func() {
return func() { timer.Reset(duration) }
}
// Schedule invoke function every duration time, util close the returned bool chan
// Schedule invoke function every duration time, util close the returned bool channel.
// Play: https://go.dev/play/p/hbON-Xeyn5N
func Schedule(d time.Duration, fn any, args ...any) chan bool {
// Catch programming error while constructing the closure
mustBeFunction(fn)
@@ -114,6 +125,7 @@ func Schedule(d time.Duration, fn any, args ...any) chan bool {
// Pipeline takes a list of functions and returns a function whose param will be passed into
// the functions one by one.
// Play: https://go.dev/play/p/mPdUVvj6HD6
func Pipeline[T any](funcs ...func(T) T) func(T) T {
return func(arg T) (result T) {
result = arg
@@ -123,3 +135,19 @@ func Pipeline[T any](funcs ...func(T) T) func(T) T {
return
}
}
func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
params[i] = reflect.ValueOf(item)
}
return fv.Call(params)
}
func mustBeFunction(function any) {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
}
}
+147
View File
@@ -0,0 +1,147 @@
package function
import (
"fmt"
"strings"
"time"
)
func ExampleAfter() {
fn := After(2, func() {
fmt.Println("test")
})
fn()
fn()
// Output:
// test
}
func ExampleBefore() {
fn := Before(2, func() {
fmt.Println("test")
})
fn()
fn()
fn()
fn()
// Output:
// test
// test
}
func ExampleCurryFn_New() {
add := func(a, b int) int {
return a + b
}
var addCurry CurryFn[int] = func(values ...int) int {
return add(values[0], values[1])
}
add1 := addCurry.New(1)
result := add1(2)
fmt.Println(result)
// Output:
// 3
}
func ExampleCompose() {
toUpper := func(strs ...string) string {
return strings.ToUpper(strs[0])
}
toLower := func(strs ...string) string {
return strings.ToLower(strs[0])
}
transform := Compose(toUpper, toLower)
result := transform("aBCde")
fmt.Println(result)
// Output:
// ABCDE
}
func ExampleDelay() {
var print = func(s string) {
fmt.Println(s)
}
Delay(2*time.Second, print, "hello")
// Output:
// hello
}
func ExampleDebounced() {
count := 0
add := func() {
count++
}
debouncedAdd := Debounced(add, 50*time.Microsecond)
debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count)
// Output:
// 1
// 2
}
func ExampleSchedule() {
count := 0
increase := func() {
count++
}
stop := Schedule(2*time.Second, increase)
time.Sleep(2 * time.Second)
close(stop)
fmt.Println(count)
// Output:
// 2
}
func ExamplePipeline() {
addOne := func(x int) int {
return x + 1
}
double := func(x int) int {
return 2 * x
}
square := func(x int) int {
return x * x
}
fn := Pipeline(addOne, double, square)
result := fn(2)
fmt.Println(result)
// Output:
// 36
}
-39
View File
@@ -1,39 +0,0 @@
package function
import (
"fmt"
"reflect"
)
func invokeFunc(fn any, args ...any) []reflect.Value {
fv := functionValue(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
params[i] = reflect.ValueOf(item)
}
return fv.Call(params)
}
func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args))
for i, item := range args {
params[i] = reflect.ValueOf(item)
}
return fv.Call(params)
}
func functionValue(function any) reflect.Value {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
}
return v
}
func mustBeFunction(function any) {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
}
}
+9 -7
View File
@@ -62,24 +62,26 @@ func TestCurry(t *testing.T) {
add := func(a, b int) int {
return a + b
}
var addCurry Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int))
var addCurry CurryFn[int] = func(values ...int) int {
return add(values[0], values[1])
}
add1 := addCurry.Curry(1)
add1 := addCurry.New(1)
assert.Equal(3, add1(2))
}
func TestCompose(t *testing.T) {
assert := internal.NewAssert(t, "TestCompose")
toUpper := func(a ...any) any {
return strings.ToUpper(a[0].(string))
toUpper := func(strs ...string) string {
return strings.ToUpper(strs[0])
}
toLower := func(a ...any) any {
return strings.ToLower(a[0].(string))
toLower := func(strs ...string) string {
return strings.ToLower(strs[0])
}
expected := toUpper(toLower("aBCde"))
cf := Compose(toUpper, toLower)
res := cf("aBCde")
+6
View File
@@ -3,12 +3,18 @@ package function
import "time"
// Watcher is used for record code excution time
// Play: https://go.dev/play/p/l2yrOpCLd1I
type Watcher struct {
startTime int64
stopTime int64
excuting bool
}
// Start the watch timer.
func NewWatcher() *Watcher {
return &Watcher{}
}
// Start the watch timer.
func (w *Watcher) Start() {
w.startTime = time.Now().UnixNano()
+22
View File
@@ -0,0 +1,22 @@
package function
import "fmt"
func ExampleWatcher() {
w := NewWatcher()
w.Start()
longRunningTask()
w.Stop()
// eapsedTime := w.GetElapsedTime().Milliseconds()
fmt.Println("foo")
w.Reset()
// Output:
// foo
}
+1 -1
View File
@@ -9,7 +9,7 @@ import (
func TestWatcher(t *testing.T) {
assert := internal.NewAssert(t, "TestWatcher")
w := &Watcher{}
w := NewWatcher()
w.Start()
longRunningTask()
+43 -9
View File
@@ -11,6 +11,8 @@
package iterator
import (
"context"
"golang.org/x/exp/constraints"
)
@@ -102,21 +104,15 @@ func (iter *sliceIterator[T]) HasNext() bool {
func (iter *sliceIterator[T]) Next() (T, bool) {
iter.index++
ok := iter.index >= 0 && iter.index < len(iter.slice)
var item T
if ok {
item = iter.slice[iter.index]
}
return item, ok
// if len(iter.slice) == 0 {
// var zero T
// return zero, false
// }
// iter.index++
// item := iter.slice[0]
// iter.slice = iter.slice[1:]
// return item, true
return item, ok
}
// Prev implements PrevIterator.
@@ -171,3 +167,41 @@ func (iter *rangeIterator[T]) Next() (T, bool) {
iter.start += iter.step
return num, true
}
// FromRange creates a iterator which returns the numeric range between start inclusive and end
// exclusive by the step size. start should be less than end, step shoud be positive.
func FromChannel[T any](channel <-chan T) Iterator[T] {
return &channelIterator[T]{channel: channel}
}
type channelIterator[T any] struct {
channel <-chan T
}
func (iter *channelIterator[T]) Next() (T, bool) {
item, ok := <-iter.channel
return item, ok
}
func (iter *channelIterator[T]) HasNext() bool {
return len(iter.channel) == 0
}
// ToChannel create a new goroutine to pull items from the channel iterator to the returned channel.
func ToChannel[T any](ctx context.Context, iter Iterator[T], buffer int) <-chan T {
result := make(chan T, buffer)
go func() {
defer close(result)
for item, ok := iter.Next(); ok; item, ok = iter.Next() {
select {
case result <- item:
case <-ctx.Done():
return
}
}
}()
return result
}
+53
View File
@@ -5,6 +5,7 @@
package iterator
import (
"context"
"testing"
"github.com/duke-git/lancet/v2/internal"
@@ -47,4 +48,56 @@ func TestSliceIterator(t *testing.T) {
assert.Equal(false, ok)
})
t.Run("slice iterator ToSlice: ", func(t *testing.T) {
iter := FromSlice([]int{1, 2, 3, 4})
item, _ := iter.Next()
assert.Equal(1, item)
data := ToSlice(iter)
assert.Equal([]int{2, 3, 4}, data)
})
}
func TestRangeIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestRangeIterator")
t.Run("range iterator: ", func(t *testing.T) {
iter := FromRange(1, 4, 1)
item, ok := iter.Next()
assert.Equal(1, item)
assert.Equal(true, ok)
item, ok = iter.Next()
assert.Equal(2, item)
assert.Equal(true, ok)
item, ok = iter.Next()
assert.Equal(3, item)
assert.Equal(true, ok)
_, ok = iter.Next()
assert.Equal(false, ok)
assert.Equal(false, iter.HasNext())
})
}
func TestChannelIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestRangeIterator")
iter := FromSlice([]int{1, 2, 3, 4})
ctx, cancel := context.WithCancel(context.Background())
iter = FromChannel(ToChannel(ctx, iter, 0))
item, ok := iter.Next()
assert.Equal(1, item)
assert.Equal(true, ok)
assert.Equal(true, iter.HasNext())
cancel()
_, ok = iter.Next()
assert.Equal(false, ok)
}
+78
View File
@@ -59,3 +59,81 @@ func (fr *filterIterator[T]) Next() (T, bool) {
func (fr *filterIterator[T]) HasNext() bool {
return fr.iter.HasNext()
}
// Join creates an iterator that join all elements of iters[0], then all elements of iters[1] and so on.
func Join[T any](iters ...Iterator[T]) Iterator[T] {
return &joinIterator[T]{
iters: iters,
}
}
type joinIterator[T any] struct {
iters []Iterator[T]
}
func (iter *joinIterator[T]) Next() (T, bool) {
for len(iter.iters) > 0 {
item, ok := iter.iters[0].Next()
if ok {
return item, true
}
iter.iters = iter.iters[1:]
}
var zero T
return zero, false
}
func (iter *joinIterator[T]) HasNext() bool {
if len(iter.iters) == 0 {
return false
}
if len(iter.iters) == 1 {
return iter.iters[0].HasNext()
}
result := iter.iters[0].HasNext()
for i := 1; i < len(iter.iters); i++ {
it := iter.iters[i]
hasNext := it.HasNext()
result = result || hasNext
}
return result
}
// Reduce reduces iter to a single value using the reduction function reducer
func Reduce[T any, U any](iter Iterator[T], initial U, reducer func(U, T) U) U {
acc := initial
for item, ok := iter.Next(); ok; item, ok = iter.Next() {
acc = reducer(acc, item)
}
return acc
}
func Take[T any](it Iterator[T], num int) Iterator[T] {
return &takeIterator[T]{it: it, num: num}
}
type takeIterator[T any] struct {
it Iterator[T]
num int
}
func (iter *takeIterator[T]) Next() (T, bool) {
if iter.num <= 0 {
var zero T
return zero, false
}
item, ok := iter.it.Next()
if ok {
iter.num--
}
return item, ok
}
func (iter *takeIterator[T]) HasNext() bool {
return iter.num > 0
}
+73
View File
@@ -0,0 +1,73 @@
// Copyright 2022 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package iterator provides a way to iterate over values stored in containers.
// note:
// 1. Full feature iterator is complicated, this package is just a experiment to explore how iterators could work in Go.
// 2. The functionality of this package is very simple and limited, may not meet the actual dev needs.
// 3. It is currently under development, unstable, and will not be completed for some time in the future.
// So, based on above factors, you may not use it in production. but, anyone is welcome to improve it.
// Hope that Go can support iterator in future. see https://github.com/golang/go/discussions/54245 and https://github.com/golang/go/discussions/56413
package iterator
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestMapIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestMapIterator")
iter := FromSlice([]int{1, 2, 3, 4})
iter = Map(iter, func(n int) int { return n / 2 })
result := ToSlice(iter)
assert.Equal([]int{0, 1, 1, 2}, result)
}
func TestFilterIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestFilterIterator")
iter := FromSlice([]int{1, 2, 3, 4})
iter = Filter(iter, func(n int) bool { return n < 3 })
result := ToSlice(iter)
assert.Equal([]int{1, 2}, result)
}
func TestJoinIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestJoinIterator")
iter1 := FromSlice([]int{1, 2})
iter2 := FromSlice([]int{3, 4})
iter := Join(iter1, iter2)
item, ok := iter.Next()
assert.Equal(1, item)
assert.Equal(true, ok)
assert.Equal([]int{2, 3, 4}, ToSlice(iter))
}
func TestReduce(t *testing.T) {
assert := internal.NewAssert(t, "TestReduce")
iter := FromSlice([]int{1, 2, 3, 4})
sum := Reduce(iter, 0, func(a, b int) int { return a + b })
assert.Equal(10, sum)
}
func TestTakeIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestTakeIterator")
iter := FromSlice([]int{1, 2, 3, 4, 5})
iter = Take(iter, 3)
result := ToSlice(iter)
assert.Equal([]int{1, 2, 3}, result)
}
+16 -8
View File
@@ -6,7 +6,8 @@ package maputil
import "reflect"
// Keys returns a slice of the map's keys
// Keys returns a slice of the map's keys.
// Play: https://go.dev/play/p/xNB5bTb97Wd
func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, len(m))
@@ -19,7 +20,8 @@ func Keys[K comparable, V any](m map[K]V) []K {
return keys
}
// Values returns a slice of the map's values
// Values returns a slice of the map's values.
// Play: https://go.dev/play/p/CBKdUc5FTW6
func Values[K comparable, V any](m map[K]V) []V {
values := make([]V, len(m))
@@ -32,7 +34,8 @@ func Values[K comparable, V any](m map[K]V) []V {
return values
}
// Merge maps, next key will overwrite previous key
// Merge maps, next key will overwrite previous key.
// Play: https://go.dev/play/p/H95LENF1uB-
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
result := make(map[K]V, 0)
@@ -45,14 +48,16 @@ func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
return result
}
// ForEach executes iteratee funcation for every key and value pair in map
// ForEach executes iteratee funcation for every key and value pair in map.
// Play: https://go.dev/play/p/OaThj6iNVXK
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
for k, v := range m {
iteratee(k, v)
}
}
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function.
// Play: https://go.dev/play/p/fSvF3wxuNG7
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
result := make(map[K]V)
@@ -64,7 +69,8 @@ func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool)
return result
}
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
// Intersect iterates over maps, return a new map of key and value pairs in all given maps.
// Play: https://go.dev/play/p/Zld0oj3sjcC
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
if len(maps) == 0 {
return map[K]V{}
@@ -97,7 +103,8 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
return result
}
// Minus creates an map of whose key in mapA but not in mapB
// Minus creates a map of whose key in mapA but not in mapB.
// Play: https://go.dev/play/p/3u5U9K7YZ9m
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
result := make(map[K]V)
@@ -109,7 +116,8 @@ func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
return result
}
// IsDisjoint two map are disjoint if they have no keys in common
// IsDisjoint two map are disjoint if they have no keys in common.
// Play: https://go.dev/play/p/N9qgYg_Ho6f
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool {
for k := range mapA {
if _, ok := mapB[k]; ok {

Some files were not shown because too many files have changed in this diff Show More