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

Compare commits

..

42 Commits

Author SHA1 Message Date
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
62 changed files with 5610 additions and 925 deletions

792
README.md
View File

@@ -32,13 +32,13 @@ English | [简体中文](./README_zh-CN.md)
### Note:
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause v2.x.x rewrite all functions with generics of go1.18.</b>
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause in v2.x.x all functions was rewriten with generics of go1.18.</b>
```go
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.3.5. </b>
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.5. </b>
```go
go get github.com/duke-git/lancet@v1.3.5 // below go1.18, install latest version of v1.x.x
@@ -71,9 +71,7 @@ func main() {
}
```
## API Documentation
## [lancet API doc](https://uvdream.github.io/lancet-docs/) Thanks [@UvDream](https://github.com/UvDream) for contributing.
## Documentation
### 1. Algorithm package implements some basic algorithm. eg. sort, search.
@@ -83,18 +81,41 @@ import "github.com/duke-git/lancet/v2/algorithm"
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)
- **<big>BubbleSort</big>** : sorts slice with bubble sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)]
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
- **<big>CountSort</big>** : sorts slice with bubble sort algorithm, don't change original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)]
[[play](https://go.dev/play/p/tB-Umgm0DrP)]
- **<big>HeapSort</big>** : sorts slice with heap sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)]
[[play](https://go.dev/play/p/u6Iwa1VZS_f)]
- **<big>InsertionSort</big>** : sorts slice with insertion sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)]
[[play](https://go.dev/play/p/G5LJiWgJJW6)]
- **<big>MergeSort</big>** : sorts slice with merge sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)]
[[play](https://go.dev/play/p/ydinn9YzUJn)]
- **<big>QuickSort</big>** : sorts slice with quick sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)]
[[play](https://go.dev/play/p/7Y7c1Elk3ax)]
- **<big>SelectionSort</big>** : sorts slice with selection sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)]
[[play](https://go.dev/play/p/oXovbkekayS)]
- **<big>ShellSort</big>** : sorts slice with shell sort algorithm, will change the original slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)]
[[play](https://go.dev/play/p/3ibkszpJEu3)]
- **<big>BinarySearch</big>** : returns the index of target within a sorted slice, use binary search (recursive call itself).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)]
[[play](https://go.dev/play/p/t6MeGiUSN47)]
- **<big>BinaryIterativeSearch</big>** : returns the index of target within a sorted slice, use binary search (no recursive).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)]
[[play](https://go.dev/play/p/Anozfr8ZLH3)]
- **<big>LinearSearch</big>** : returns the index of target in slice base on equal function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)]
- **<big>LRUCache</big>** : implements memory cache with lru algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
@@ -104,16 +125,26 @@ import "github.com/duke-git/lancet/v2/concurrency"
#### Function list:
- [NewChannel](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#NewChannel)
- [Bridge](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Bridge)
- [FanIn](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#FanIn)
- [Generate](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Generate)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Or)
- [OrDone](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#OrDone)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Repeat)
- [RepeatFn](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#RepeatFn)
- [Take](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Take)
- [Tee](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)
- **<big>NewChannel</big>** : create a Channel pointer instance.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#NewChannel)]
- **<big>Bridge</big>** : link multiply channels into one channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/Bridge.md#NewChannel)]
- **<big>FanIn</big>** : merge multiple channels into one channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#FanIn)]
- **<big>Generate</big>** : creates a channel, then put values into the channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Generate)]
- **<big>Or</big>** : read one or more channels into one channel, will close when any readin channel is closed.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Or)]
- **<big>OrDone</big>** : read a channel into another channel, will close until cancel context.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#OrDone)]
- **<big>Repeat</big>** : create channel, put values into the channel repeatly until cancel the context.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Repeat)]
- **<big>RepeatFn</big>** : create a channel, excutes fn repeatly, and put the result into the channel, until close context.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#RepeatFn)]
- **<big>Take</big>** : create a channel whose values are taken from another channel with limit number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Take)]
- **<big>Tee</big>** : split one chanel into two channels, until cancel the context.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)]
### 3. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...
@@ -123,13 +154,30 @@ import "github.com/duke-git/lancet/v2/condition"
#### Function list:
- [Bool](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Bool)
- [And](https://github.com/duke-git/lancet/blob/main/docs/condition.md#And)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)
- [Xor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)
- [Nor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)
- [Nand](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nand)
- [TernaryOperator](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)
- **<big>Bool</big>** : returns the truthy value of anything.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Bool)]
[[play](https://go.dev/play/p/ETzeDJRSvhm)]
- **<big>And</big>** : returns true if both a and b are truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#And)]
[[play](https://go.dev/play/p/W1SSUmt6pvr)]
- **<big>Or</big>** : returns false if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)]
[[play](https://go.dev/play/p/UlQTxHaeEkq)]
- **<big>Xor</big>** : returns true if a or b but not both is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)]
[[play](https://go.dev/play/p/gObZrW7ZbG8)]
- **<big>Nor</big>** : returns true if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)]
[[play](https://go.dev/play/p/g2j08F_zZky)
- **<big>Xnor</big>** : returns true if both a and b or neither a nor b are truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)]
- **<big>Nand</big>** : returns false if both a and b are truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nand)]
[[play](https://go.dev/play/p/vSRMLxLIbq8)]
- **<big>TernaryOperator</big>** : ternary operator.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
### 4. Convertor package contains some functions for data convertion.
@@ -139,22 +187,54 @@ import "github.com/duke-git/lancet/v2/convertor"
#### Function list:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)
- [EncodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#EncodeByte)
- [DecodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)
- **<big>ColorHexToRGB</big>** : convert color hex to color rgb.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)]
[[play](https://go.dev/play/p/o7_ft-JCJBV)]
- **<big>ColorRGBToHex</big>** : convert rgb color to hex color.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)]
[[play](https://go.dev/play/p/nzKS2Ro87J1)]
- **<big>ToBool</big>** : convert string to bool.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)]
[[play](https://go.dev/play/p/ARht2WnGdIN)]
- **<big>ToBytes</big>** : convert value to byte slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)]
[[play](https://go.dev/play/p/fAMXYFDvOvr)]
- **<big>ToChar</big>** : convert string to char slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)]
[[play](https://go.dev/play/p/JJ1SvbFkVdM)]
- **<big>ToChannel</big>** : convert a collection of elements to a read-only channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)]
[[play](https://go.dev/play/p/hOx_oYZbAnL)]
- **<big>ToFloat</big>** : convert value to float64, if param is a invalid floatable, will return 0.0 and error.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)]
[[play](https://go.dev/play/p/4YTmPCibqHJ)]
- **<big>ToInt</big>** : convert value to int64 value, if input is not numerical, return 0 and error.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)]
[[play](https://go.dev/play/p/9_h9vIt-QZ_b)]
- **<big>ToJson</big>** : convert value to a json string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)]
[[play](https://go.dev/play/p/2rLIkMmXWvR)]
- **<big>ToMap</big>** : convert a slice of structs to a map based on iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)]
[[play](https://go.dev/play/p/tVFy7E-t24l)]
- **<big>ToPointer</big>** : return a pointer of passed value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)]
[[play](https://go.dev/play/p/ASf_etHNlw1)]
- **<big>ToString</big>** : convert value to string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)]
[[play](https://go.dev/play/p/nF1zOOslpQq)]
- **<big>StructToMap</big>** : convert struct to map, only convert exported struct field.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)]
[[play](https://go.dev/play/p/KYGYJqNUBOI)]
- **<big>MapToSlice</big>** : convert map to slice based on iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)]
[[play](https://go.dev/play/p/dmX4Ix5V6Wl)]
- **<big>EncodeByte</big>** : encode data to byte slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#EncodeByte)]
[[play](https://go.dev/play/p/DVmM1G5JfuP)]
- **<big>DecodeByte</big>** : decode byte slice data to target object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)]
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
### 5. Cryptor package is for data encryption and decryption.
@@ -268,21 +348,51 @@ import "github.com/duke-git/lancet/v2/fileutil"
#### Function list
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateDir)
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsExist)
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsLink)
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsDir)
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ListFileNames)
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#RemoveFile)
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileToString)
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
- **<big>ClearFile</big>** : write empty string to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)]
[[play](https://go.dev/play/p/NRZ0ZT-G94H)]
- **<big>CreateFile</big>** : create file in path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)]
[[play](https://go.dev/play/p/lDt8PEsTNKI)]
- **<big>CreateDir</big>** : create directory in absolute path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateDir)]
[[play](https://go.dev/play/p/qUuCe1OGQnM)]
- **<big>CopyFile</big>** :copy src file to dest file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)]
[[play](https://go.dev/play/p/Jg9AMJMLrJi)]
- **<big>FileMode</big>** : return file's mode and permission.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)]
[[play](https://go.dev/play/p/2l2hI42fA3p)]
- **<big>MiMeType</big>** : return file mime type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)]
[[play](https://go.dev/play/p/bd5sevSUZNu)]
- **<big>IsExist</big>** : checks if a file or directory exists.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsExist)]
[[play](https://go.dev/play/p/nKKXt8ZQbmh)]
- **<big>IsLink</big>** : checks if a file is symbol link or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsLink)]
[[play](https://go.dev/play/p/TL-b-Kzvf44)]
- **<big>IsDir</big>** : checks if the path is directory or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsDir)]
[[play](https://go.dev/play/p/WkVwEKqtOWk)]
- **<big>ListFileNames</big>** : return all file names in the path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ListFileNames)]
[[play](https://go.dev/play/p/Tjd7Y07rejl)]
- **<big>RemoveFile</big>** : remove file, param should be file path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#RemoveFile)]
[[play](https://go.dev/play/p/P2y0XW8a1SH)]
- **<big>ReadFileToString</big>** : return string of file content.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileToString)]
[[play](https://go.dev/play/p/cmfwp_5SQTp)]
- **<big>ReadFileByLine</big>** : read file line by line, return string slice of file content.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)]
[[play](https://go.dev/play/p/svJP_7ZrBrD)]
- **<big>Zip</big>** : create zip file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>UnZip</big>** : unzip the zip file and save it to dest path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)]
### 9. Formatter contains some functions for data formatting.
@@ -292,7 +402,9 @@ import "github.com/duke-git/lancet/v2/formatter"
#### Function list:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)]
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
### 10. Function package can control the flow of function execution and support part of functional programming
@@ -319,14 +431,30 @@ import "github.com/duke-git/lancet/v2/maputil"
#### Function list:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)
- **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)]
[[play](https://go.dev/play/p/OaThj6iNVXK)]
- **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)]
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
- **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)]
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
- **<big>Keys</big>** : returns a slice of the map's keys.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)]
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
- **<big>Merge</big>** : merge maps, next key will overwrite previous key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)]
[[play](https://go.dev/play/p/H95LENF1uB-)]
- **<big>Minus</big>** : creates a map of whose key in mapA but not in mapB.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)]
[[play](https://go.dev/play/p/3u5U9K7YZ9m)]
- **<big>Values</big>** : returns a slice of the map's values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)]
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
- **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 12. Mathutil package implements some functions for math calculation.
@@ -336,18 +464,41 @@ import "github.com/duke-git/lancet/v2/mathutil"
#### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MaxBy)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MinBy)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
- **<big>Average</big>** :return average value of numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)]
[[play](https://go.dev/play/p/Vv7LBwER-pz)]
- **<big>Exponent</big>** : calculate x^n for int64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)]
[[play](https://go.dev/play/p/uF3HGNPk8wr)]
- **<big>Fibonacci</big>** :calculate fibonacci number before n for int.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)]
[[play](https://go.dev/play/p/IscseUNMuUc)]
- **<big>Factorial</big>** : calculate x! for uint.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)]
[[play](https://go.dev/play/p/tt6LdOK67Nx)]
- **<big>Max</big>** : return maximum value of numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)]
[[play](https://go.dev/play/p/cN8DHI0rTkH)]
- **<big>MaxBy</big>** : return the maximum value of a slice using the given comparator function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MaxBy)]
[[play](https://go.dev/play/p/pbe2MT-7DV2)]
- **<big>Min</big>** : return minimum value of numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)]
[[play](https://go.dev/play/p/21BER_mlGUj)]
- **<big>MinBy</big>** : return the minimum value of a slice using the given comparator function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MinBy)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : calculate the percentage of value to total.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)]
- **<big>RoundToFloat</big>** : round up to n decimal places for float64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)]
- **<big>RoundToString</big>** : round up to n decimal places for float64, return string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)]
[[play](https://go.dev/play/p/kZwpBRAcllO)]
- **<big>TruncRound</big>** : round off n decimal places for int64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)]
[[play](https://go.dev/play/p/aumarSHIGzP)]
### 13. Netutil package contains functions to get net information and send http request.
@@ -386,14 +537,30 @@ import "github.com/duke-git/lancet/v2/random"
#### Function list:
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
- [RandUpper](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUpper)
- [RandLower](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandLower)
- [RandNumeral](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeral)
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeralOrLetter)
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
- **<big>RandBytes</big>** : generate random byte slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)]
[[play](https://go.dev/play/p/EkiLESeXf8d)]
- **<big>RandInt</big>** : generate random int number between min and max.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)]
[[play](https://go.dev/play/p/pXyyAAI5YxD)]
- **<big>RandString</big>** : generate random string of specified length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)]
[[play](https://go.dev/play/p/W2xvRUXA7Mi)]
- **<big>RandUpper</big>** : generate a random upper case string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUpper)]
[[play](https://go.dev/play/p/29QfOh0DVuh)]
- **<big>RandLower</big>** : generate a random lower case string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandLower)]
[[play](https://go.dev/play/p/XJtZ471cmtI)]
- **<big>RandNumeral</big>** : generate a random numeral string of specified length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeral)]
[[play](https://go.dev/play/p/g4JWVpHsJcf)]
- **<big>RandNumeralOrLetter</big>** : generate a random numeral or letter string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeralOrLetter)]
[[play](https://go.dev/play/p/19CEQvpx2jD)]
- **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
### 15. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
@@ -417,59 +584,165 @@ import "github.com/duke-git/lancet/v2/slice"
#### Function list:
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
- [CountBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#CountBy)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
- [IntSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
- [InterfaceSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Merge)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
- [Replace](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)
- [ReplaceAll](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReplaceAll)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Repeat)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
- [Sort](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)
- [SortBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortBy)
- [SortByField<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
- [StringSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SymmetricDifference)
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlicePointer)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UniqueBy)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
- [UnionBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UnionBy)
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
- [KeyBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)
- **<big>AppendIfAbsent</big>** : if the item is absent,append it to the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#AppendIfAbsent)]
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
- **<big>Contain</big>** : check if the value is in the slice or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)]
[[play](https://go.dev/play/p/_454yEHcNjf)]
- **<big>ContainSubSlice</big>** : check if the slice contain a given subslice or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)]
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
- **<big>Chunk</big>** : creates a slice of elements split into groups the length of size.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)]
[[play](https://go.dev/play/p/b4Pou5j2L_C)]
- **<big>Compact</big>** : creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)]
[[play](https://go.dev/play/p/pO5AnxEr3TK)]
- **<big>Concat</big>** : creates a new slice concatenating slice with any additional slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)]
[[play](https://go.dev/play/p/gPt-q7zr5mk)]
- **<big>Count</big>** : returns the number of occurrences of the given item in the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)]
[[play](https://go.dev/play/p/Mj4oiEnQvRJ)]
- **<big>CountBy</big>** : iterates over elements of slice with predicate function, returns the number of all matched elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#CountBy)]
[[play](https://go.dev/play/p/tHOccTMDZCC)]
- **<big>Difference</big>** : creates an slice of whose element in slice but not in compared slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)]
[[play](https://go.dev/play/p/VXvadzLzhDa)]
- **<big>DifferenceBy</big>** : accepts iteratee which is invoked for each element of slice and values to generate the criterion by which they're compared.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)]
[[play](https://go.dev/play/p/DiivgwM5OnC)]
- **<big>DifferenceWith</big>** : accepts comparator which is invoked to compare elements of slice to values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)]
[[play](https://go.dev/play/p/v2U2deugKuV)]
- **<big>DeleteAt</big>** : delete the element of slice from specific start index to end index - 1.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Drop</big>** : creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)]
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
- **<big>EqualWith</big>** : checks if two slices are equal with comparator func.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)]
[[play](https://go.dev/play/p/b9iygtgsHI1)]
- **<big>Every</big>** : return true if all of the values in the slice pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)]
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
- **<big>Filter</big>** : iterates over elements of slice, returning an slice of all elements pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)]
[[play](https://go.dev/play/p/SdPna-7qK4T)]
- **<big>Find</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)]
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
- **<big>FindLast</big>** : return the last item that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)]
[[play](https://go.dev/play/p/FFDPV_j7URd)]
- **<big>Flatten</big>** : flattens slice one level.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)]
[[play](https://go.dev/play/p/hYa3cBEevtm)]
- **<big>FlattenDeep</big>** : flattens slice recursive to one level.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)]
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
- **<big>ForEach</big>** : iterates over elements of slice and invokes function for each element.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)]
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
- **<big>GroupBy</big>** : iterate over elements of the slice, each element will be group by criteria, returns two slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)]
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
- **<big>GroupWith</big>** : return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)]
[[play](https://go.dev/play/p/ApCvMNTLO8a)]
- **<big>IntSlice<sup>deprecated</sup></big>** : convert param to int slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)]
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
- **<big>InterfaceSlice<sup>deprecated</sup></big>** : convert param to interface slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)]
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
- **<big>Intersection</big>** : creates a slice of unique elements that included by all slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)]
[[play](https://go.dev/play/p/anJXfB5wq_t)]
- **<big>InsertAt</big>** : insert the value or other slice into slice at index.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)]
[[play](https://go.dev/play/p/hMLNxPEGJVE)]
- **<big>IndexOf</big>** : returns the index at which the first occurrence of an item is found in a slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)]
[[play](https://go.dev/play/p/MRN1f0FpABb)]
- **<big>LastIndexOf</big>** : returns the index at which the last occurrence of the item is found in a slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)]
[[play](https://go.dev/play/p/DokM4cf1IKH)]
- **<big>Map</big>** : creates an slice of values by running each element of slice thru iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)]
[[play](https://go.dev/play/p/biaTefqPquw)]
- **<big>Merge</big>** : merge all given slices into one slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Merge)]
[[play](https://go.dev/play/p/lbjFp784r9N)]
- **<big>Reverse</big>** : return slice of element order is reversed to the given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)]
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
- **<big>Reduce</big>** : creates an slice of values by running each element of slice thru iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)]
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
- **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
- **<big>ReplaceAll</big>** : returns a copy of the slice with all non-overlapping instances of old replaced by new.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReplaceAll)]
[[play](https://go.dev/play/p/CzqXMsuYUrx)]
- **<big>Repeat</big>** : creates a slice with length n whose elements are passed item.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Repeat)]
[[play](https://go.dev/play/p/1CbOmtgILUU)]
- **<big>Shuffle</big>** : shuffle the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)]
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
- **<big>Sort</big>** : sorts a slice of any ordered type(number or string).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)]
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
- **<big>SortBy</big>** : sorts the slice in ascending order as determined by the less function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortBy)]
[[play](https://go.dev/play/p/DAhLQSZEumm)]
- **<big>SortByField<sup>deprecated</sup></big>** : return sorted slice by specific field.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)]
[[play](https://go.dev/play/p/fU1prOBP9p1)]
- **<big>Some</big>** : return true if any of the values in the list pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)]
[[play](https://go.dev/play/p/4pO9Xf9NDGS)]
- **<big>StringSlice<sup>deprecated</sup></big>** : convert param to slice of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)]
[[play](https://go.dev/play/p/W0TZDWCPFcI)]
- **<big>SymmetricDifference</big>** : the symmetric difference of two slice, also known as the disjunctive union.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#h42nJX5xMln)]
[[play](https://go.dev/play/p/1CbOmtgILUU)]
- **<big>ToSlice</big>** : returns a slices of a variable parameter transformation.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)]
[[play](https://go.dev/play/p/YzbzVq5kscN)]
- **<big>ToSlicePointer</big>** : returns a pointer to the slices of a variable parameter transformation.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlicePointer)]
[[play](https://go.dev/play/p/gx4tr6_VXSF)]
- **<big>Unique</big>** : remove duplicate elements in slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)]
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
- **<big>UniqueBy</big>** : call iteratee func with every item of slice, then remove duplicated.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UniqueBy)]
[[play](https://go.dev/play/p/UR323iZLDpv)]
- **<big>Union</big>** : creates a slice of unique elements, in order, from all given slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)]
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
- **<big>UnionBy</big>** : accepts iteratee which is invoked for each element of each slice, then union slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UnionBy)]
[[play](https://go.dev/play/p/HGKHfxKQsFi)]
- **<big>UpdateAt</big>** : update the slice element at index.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)]
[[play](https://go.dev/play/p/f3mh2KloWVm)]
- **<big>Without</big>** : creates a slice excluding all given items.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)]
[[play](https://go.dev/play/p/bwhEXEypThg)]
- **<big>KeyBy</big>** : converts a slice to a map based on a callback function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
### 17. Strutil package contains some functions to manipulate string.
@@ -479,25 +752,64 @@ import "github.com/duke-git/lancet/v2/strutil"
#### Function list:
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#CamelCase)
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperKebabCase)
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Reverse)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
- [UpperSnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperSnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
- **<big>After</big>** : returns the substring after the first occurrence of a specified string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)]
[[play](https://go.dev/play/p/RbCOQqCDA7m)]
- **<big>AfterLast</big>** : returns the substring after the last occurrence of a specified string in the source string. [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)]
[[play](https://go.dev/play/p/1TegARrb8Yn)]
- **<big>Before</big>** : returns the substring before the first occurrence of a specified string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)]
[[play](https://go.dev/play/p/JAWTZDS4F5w)]
- **<big>BeforeLast</big>** : returns the substring before the last occurrence of a specified string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)]
[[play](https://go.dev/play/p/pJfXXAoG_Te)]
- **<big>CamelCase</big>** : coverts source string to its camelCase string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#CamelCase)]
[[play](https://go.dev/play/p/9eXP3tn2tUy)]
- **<big>Capitalize</big>** : converts the first character of source string to upper case and the remaining to lower case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>IsString</big>** : checks if the parameter value data type is string or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
- **<big>KebabCase</big>** : coverts string to kebab-case string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)]
[[play](https://go.dev/play/p/dcZM9Oahw-Y)]
- **<big>UpperKebabCase</big>** : coverts string to upper KEBAB-CASE string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperKebabCase)]
[[play](https://go.dev/play/p/zDyKNneyQXk)]
- **<big>LowerFirst</big>** : converts the first character of string to lower case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)]
[[play](https://go.dev/play/p/CbzAyZmtJwL)]
- **<big>UpperFirst</big>** : converts the first character of string to upper case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)]
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
- **<big>PadEnd</big>** : pads string with given characters on the right side if it's shorter than limit size. Padding characters are truncated if they exceed size.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)]
[[play](https://go.dev/play/p/9xP8rN0vz--)]
- **<big>PadStart</big>** : pads string with given characters on the left side if it's shorter than limit size. Padding characters are truncated if they exceed size.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)]
[[play](https://go.dev/play/p/xpTfzArDfvT)]
- **<big>Reverse</big>** : returns string whose char order is reversed to the given string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Reverse)]
[[play](https://go.dev/play/p/adfwalJiecD)]
- **<big>SnakeCase</big>** : coverts string to snake_case string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)]
[[play](https://go.dev/play/p/tgzQG11qBuN)]
- **<big>UpperSnakeCase</big>** : coverts string to upper SNAKE_CASE string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperSnakeCase)]
[[play](https://go.dev/play/p/4COPHpnLx38)]
- **<big>SplitEx</big>** : split a given string which can control the result slice contains empty string or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)]
[[play](https://go.dev/play/p/Us-ySSbWh-3)]
- **<big>Substring</big>** : returns a substring of the specified length starting at the specified offset position.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Substring)]
- **<big>Wrap</big>** : wrap a string with given string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)]
[[play](https://go.dev/play/p/KoZOlZDDt9y)]
- **<big>Unwrap</big>** : unwrap a given string from anther string. will change source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)]
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
### 19. System package contain some functions about os, runtime, shell command.
@@ -507,15 +819,33 @@ import "github.com/duke-git/lancet/v2/system"
#### Function list:
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
- **<big>IsWindows</big>** : check if current os is windows.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)]
[[play](https://go.dev/play/p/XzJULbzmf9m)]
- **<big>IsLinux</big>** : check if current os is linux.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)]
[[play](https://go.dev/play/p/zIflQgZNuxD)]
- **<big>IsMac</big>** : check if current os is macos.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)]
[[play](https://go.dev/play/p/Mg4Hjtyq7Zc)]
- **<big>GetOsEnv</big>** : get the value of the environment variable named by the key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)]
[[play](https://go.dev/play/p/D88OYVCyjO-)]
- **<big>SetOsEnv</big>** : set the value of the environment variable named by the key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)]
[[play](https://go.dev/play/p/D88OYVCyjO-)]
- **<big>RemoveOsEnv</big>** : remove a single environment variable.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)]
[[play](https://go.dev/play/p/fqyq4b3xUFQ)]
- **<big>CompareOsEnv</big>** : get env named by the key and compare it with passed env.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)]
[[play](https://go.dev/play/p/BciHrKYOHbp)]
- **<big>ExecCommand</big>** : execute command, return the stdout and stderr string of command, and error if error occurs.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)]
[[play](https://go.dev/play/p/n-2fLyZef-4)]
- **<big>GetOsBits</big>** : return current os bits (32 or 64).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 19. Validator package contains some functions for data validation.
@@ -525,34 +855,90 @@ import "github.com/duke-git/lancet/v2/validator"
#### Function list:
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLetter)
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLower)
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainUpper)
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAlpha)
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllUpper)
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllLower)
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsBase64)
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseMobile)
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseIdNum)
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChinesePhone)
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsCreditCard)
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsDns)
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmail)
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIp)
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV4)
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue)
- [IsGBK](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsGBK)
- **<big>ContainChinese</big>** : check if the string contain mandarin chinese.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)]
[[play](https://go.dev/play/p/7DpU0uElYeM)]
- **<big>ContainLetter</big>** : check if the string contain at least one letter.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLetter)]
[[play](https://go.dev/play/p/lqFD04Yyewp)]
- **<big>ContainLower</big>** : check if the string contain at least one lower case letter a-z.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLower)]
[[play](https://go.dev/play/p/Srqi1ItvnAA)]
- **<big>ContainUpper</big>** : check if the string contain at least one upper case letter A-Z.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainUpper)]
[[play](https://go.dev/play/p/CmWeBEk27-z)]
- **<big>IsAlpha</big>** : checks if the string contains only letters (a-zA-Z).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAlpha)]
[[play](https://go.dev/play/p/7Q5sGOz2izQ)]
- **<big>IsAllUpper</big>** : check if the string is all upper case letters A-Z.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllUpper)]
[[play](https://go.dev/play/p/ZHctgeK1n4Z)]
- **<big>IsAllLower</big>** : check if the string is all lower case letters a-z.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllLower)]
[[play](https://go.dev/play/p/GjqCnOfV6cM)]
- **<big>IsBase64</big>** : check if the string is base64 string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsBase64)]
[[play](https://go.dev/play/p/sWHEySAt6hl)]
- **<big>IsChineseMobile</big>** : check if the string is chinese mobile number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseMobile)]
[[play](https://go.dev/play/p/GPYUlGTOqe3)]
- **<big>IsChineseIdNum</big>** : check if the string is chinese id card.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseIdNum)]
[[play](https://go.dev/play/p/d8EWhl2UGDF)]
- **<big>IsChinesePhone</big>** : check if the string is chinese phone number.(xxx-xxxxxxxx or xxxx-xxxxxxx.)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChinesePhone)]
[[play](https://go.dev/play/p/RUD_-7YZJ3I)]
- **<big>IsCreditCard</big>** : check if the string is credit card.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsCreditCard)]
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
- **<big>IsDns</big>** : check if the string is dns.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsDns)]
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
- **<big>IsEmail</big>** : check if the string is a email address.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmail)]
[[play](https://go.dev/play/p/Os9VaFlT33G)]
- **<big>IsEmptyString</big>** : check if the string is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)]
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
- **<big>IsFloatStr</big>** : check if the string can convert to a float.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#LOYwS_Oyl7U)]
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
- **<big>IsNumberStr</big>** : check if the string can convert to a number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsJSON</big>** : check if the string is valid JSON.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)]
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
- **<big>IsRegexMatch</big>** : check if the string match the regexp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)]
[[play](https://go.dev/play/p/z_XeZo_litG)]
- **<big>IsIntStr</big>** : check if the string can convert to a integer.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)]
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
- **<big>IsIp</big>** : check if the string is ip.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIp)]
[[play](https://go.dev/play/p/FgcplDvmxoD)]
- **<big>IsIpV4</big>** : check if the string is ipv4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV4)]
[[play](https://go.dev/play/p/zBGT99EjaIu)]
- **<big>IsIpV6</big>** : check if the string is ipv6.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)]
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
- **<big>IsStrongPassword</big>** : check if the string is strong password.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)]
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
- **<big>IsUrl</big>** : check if the string is url.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)]
[[play](https://go.dev/play/p/pbJGa7F98Ka)]
- **<big>IsWeakPassword</big>** : check if the string is weak password.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)]
[[play](https://go.dev/play/p/wqakscZH5gH)]
- **<big>IsZeroValue</big>** : check if value is a zero value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue)]
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
- **<big>IsGBK</big>** : check if data encoding is gbk.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsGBK)]
[[play](https://go.dev/play/p/E2nt3unlmzP)]
### 20. xerror package implements helpers for errors.

View File

@@ -31,7 +31,7 @@
### Note:
1. <b>对于使用 go1.18 及以上的用户,建议安装 v2.x.x。 因为 v2.x.x 用 go1.18 的泛型重写了大部分函数。</b>
1. <b>使用 go1.18 及以上版本的用户,建议安装 v2.x.x。 因为 v2.x.x 用 go1.18 的泛型重写了大部分函数。</b>
```go
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
@@ -70,11 +70,9 @@ func main() {
}
```
## API 文档
## 文档
## [lancet API doc](https://uvdream.github.io/lancet-docs/) 感谢[@UvDream](https://github.com/UvDream)整理
### 1. algorithm 算法包实现一些基本算法。eg. sort, search.
### 1. algorithm 包实现一些基本查找和排序算法。
```go
import "github.com/duke-git/lancet/v2/algorithm"
@@ -82,20 +80,43 @@ import "github.com/duke-git/lancet/v2/algorithm"
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)
- **<big>BubbleSort</big>** : 使用冒泡排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)]
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
- **<big>CountSort</big>** : 使用计数排序算法对切片进行排序。不改变原数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)]
[[play](https://go.dev/play/p/tB-Umgm0DrP)]
- **<big>HeapSort</big>** : 使用堆排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)]
[[play](https://go.dev/play/p/u6Iwa1VZS_f)]
- **<big>InsertionSort</big>** : 使用插入排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)]
[[play](https://go.dev/play/p/G5LJiWgJJW6)]
- **<big>MergeSort</big>** : 使用合并排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)]
[[play](https://go.dev/play/p/ydinn9YzUJn)]
- **<big>QuickSort</big>** : 使用快速排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)]
[[play](https://go.dev/play/p/7Y7c1Elk3ax)]
- **<big>SelectionSort</big>** : 使用选择排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)]
[[play](https://go.dev/play/p/oXovbkekayS)]
- **<big>ShellSort</big>** : 使用希尔排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)]
[[play](https://go.dev/play/p/3ibkszpJEu3)]
- **<big>BinarySearch</big>** : 返回排序切片中目标值的索引,使用二分搜索(递归调用)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)]
[[play](https://go.dev/play/p/t6MeGiUSN47)]
- **<big>BinaryIterativeSearch</big>** :返回排序切片中目标值的索引,使用二分搜索(非递归)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)]
[[play](https://go.dev/play/p/Anozfr8ZLH3)]
- **<big>LinearSearch</big>** : 基于传入的相等函数返回切片中目标值的索引。(线性查找)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)]
- **<big>LRUCache</big>** : 应用 lru 算法实现内存缓存.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. concurrency 并发包包含一些支持并发编程的功能。例如goroutine, channel, async 等。
### 2. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。
```go
import "github.com/duke-git/lancet/v2/concurrency"
@@ -103,18 +124,28 @@ import "github.com/duke-git/lancet/v2/concurrency"
#### Function list:
- [NewChannel](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#NewChannel)
- [Bridge](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Bridge)
- [FanIn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#FanIn)
- [Generate](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Generate)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Or)
- [OrDone](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#OrDone)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Repeat)
- [RepeatFn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#RepeatFn)
- [Take](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Take)
- [Tee](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)
- **<big>NewChannel</big>** : 返回一个 Channel 指针实例。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#NewChannel)]
- **<big>Bridge</big>** : 将多个 channel 链接到一个 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/Bridge.md#NewChannel)]
- **<big>FanIn</big>** : 将多个 channel 合并为一个 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#FanIn)]
- **<big>Generate</big>** : 根据传入的值,生成 channel。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Generate)]
- **<big>Or</big>** : 将一个或多个 channel 读取到一个 channel 中,当任何读取 channel 关闭时将结束读取。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Or)]
- **<big>OrDone</big>** : 将一个 channel 读入另一个 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#OrDone)]
- **<big>Repeat</big>** : 返回一个 channel将参数`values`重复放入 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Repeat)]
- **<big>RepeatFn</big>** : 返回一个 channel重复执行函数 fn并将结果放入返回的 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#RepeatFn)]
- **<big>Take</big>** : 返回一个 channel其值从另一个 channel 获取,直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Take)]
- **<big>Tee</big>** : 将一个 channel 分成两个 channel直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)]
### 3. condition 条件包含一些用于条件判断的函数。eg. And, Or, TernaryOperator...
### 3. condition 包含一些用于条件判断的函数。
```go
import "github.com/duke-git/lancet/v2/condition"
@@ -122,13 +153,30 @@ import "github.com/duke-git/lancet/v2/condition"
#### Function list:
- [Bool](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Bool)
- [And](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#And)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Or)
- [Xor](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xor)
- [Nor](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nor)
- [Nand](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)
- [TernaryOperator](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)
- **<big>Bool</big>** : 返回传入参数的 bool 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Bool)]
[[play](https://go.dev/play/p/ETzeDJRSvhm)]
- **<big>And</big>** : 逻辑且操作,当切仅当 a 和 b 都为 true 时返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#And)]
[[play](https://go.dev/play/p/W1SSUmt6pvr)]
- **<big>Or</big>** : 逻辑或操作,当切仅当 a 和 b 都为 false 时返回 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Or)]
[[play](https://go.dev/play/p/UlQTxHaeEkq)]
- **<big>Xor</big>** : 逻辑异或操作a 和 b 相同返回 falsea 和 b 不相同返回 true
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xor)]
[[play](https://go.dev/play/p/gObZrW7ZbG8)]
- **<big>Nor</big>** : 异或的取反操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nor)]
[[play](https://go.dev/play/p/g2j08F_zZky)
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)]
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
[[play](https://go.dev/play/p/vSRMLxLIbq8)]
- **<big>TernaryOperator</big>** : 三元运算符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
### 4. convertor 转换器包支持一些常见的数据类型转换。
@@ -138,22 +186,54 @@ import "github.com/duke-git/lancet/v2/convertor"
#### 函数列表:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB)
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorRGBToHex)
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBool)
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBytes)
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChar)
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChannel)
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToFloat)
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInt)
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToJson)
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToMap)
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToPointer)
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#MapToSlice)
- [EncodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#EncodeByte)
- [DecodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DecodeByte)
- **<big>ColorHexToRGB</big>** : 颜色值十六进制转 rgb。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB)]
[[play](https://go.dev/play/p/o7_ft-JCJBV)]
- **<big>ColorRGBToHex</big>** : 颜色值 rgb 转十六进制。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorRGBToHex)]
[[play](https://go.dev/play/p/nzKS2Ro87J1)]
- **<big>ToBool</big>** : 字符串转布尔类型,使用 strconv.ParseBool。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBool)]
[[play](https://go.dev/play/p/ARht2WnGdIN)]
- **<big>ToBytes</big>** : interface 转字节切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBytes)]
[[play](https://go.dev/play/p/fAMXYFDvOvr)]
- **<big>ToChar</big>** : 字符串转字符切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChar)]
[[play](https://go.dev/play/p/JJ1SvbFkVdM)]
- **<big>ToChannel</big>** : 将切片转为只读 channel。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChannel)]
[[play](https://go.dev/play/p/hOx_oYZbAnL)]
- **<big>ToFloat</big>** : 将 interface 转成 float64 类型,如果参数无法转换,会返回 0.0 和 error。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToFloat)]
[[play](https://go.dev/play/p/4YTmPCibqHJ)]
- **<big>ToInt</big>** : 将 interface 转成 int64 类型,如果参数无法转换,会返回 0 和 error。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInt)]
[[play](https://go.dev/play/p/9_h9vIt-QZ_b)]
- **<big>ToJson</big>** : 将 interface 转成 json 字符串,如果参数无法转换,会返回""和 error。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToJson)]
[[play](https://go.dev/play/p/2rLIkMmXWvR)]
- **<big>ToMap</big>** : 将切片转为 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToMap)]
[[play](https://go.dev/play/p/tVFy7E-t24l)]
- **<big>ToPointer</big>** : 返回传入值的指针。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToPointer)]
[[play](https://go.dev/play/p/ASf_etHNlw1)]
- **<big>ToString</big>** : 将值转换为字符串,对于数字、字符串、[]byte将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)]
[[play](https://go.dev/play/p/nF1zOOslpQq)]
- **<big>StructToMap</big>** : 将 struct 转成 map只会转换 struct 中可导出的字段。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)]
[[play](https://go.dev/play/p/KYGYJqNUBOI)]
- **<big>MapToSlice</big>** : map 中 key 和 value 执行函数 iteratee 后,转为切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#MapToSlice)]
[[play](https://go.dev/play/p/dmX4Ix5V6Wl)]
- **<big>EncodeByte</big>** : 将传入的 data 编码成字节切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#EncodeByte)]
[[play](https://go.dev/play/p/DVmM1G5JfuP)]
- **<big>DecodeByte</big>** : 解码字节切片到目标对象,目标对象需要传入一个指针实例。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DecodeByte)]
[[play](https://go.dev/play/p/zI6xsmuQRbn)]
### 5. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。
@@ -259,7 +339,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md)
- [HashMap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)
### 8. fileutil 包支持文件基本操作。
### 8. fileutil 包文件基本操作。
```go
import "github.com/duke-git/lancet/v2/fileutil"
@@ -267,21 +347,51 @@ import "github.com/duke-git/lancet/v2/fileutil"
#### 函数列表:
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateDir)
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsExist)
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsLink)
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsDir)
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ListFileNames)
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#RemoveFile)
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileToString)
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileByLine)
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
- **<big>ClearFile</big>** : 清空文件内容。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)]
[[play](https://go.dev/play/p/NRZ0ZT-G94H)]
- **<big>CreateFile</big>** : 创建文件,创建成功返回 true, 否则返回 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)]
[[play](https://go.dev/play/p/lDt8PEsTNKI)]
- **<big>CreateDir</big>** : 创建嵌套目录,例如/a/, /a/b/。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateDir)]
[[play](https://go.dev/play/p/qUuCe1OGQnM)]
- **<big>CopyFile</big>** :拷贝文件,会覆盖原有的文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)]
[[play](https://go.dev/play/p/Jg9AMJMLrJi)]
- **<big>FileMode</big>** : 获取文件 mode 信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)]
[[play](https://go.dev/play/p/2l2hI42fA3p)]
- **<big>MiMeType</big>** : 获取文件 mime 类型, 参数的类型必须是 string 或者\*os.File。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)]
[[play](https://go.dev/play/p/bd5sevSUZNu)]
- **<big>IsExist</big>** : 判断文件或目录是否存在。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsExist)]
[[play](https://go.dev/play/p/nKKXt8ZQbmh)]
- **<big>IsLink</big>** : 判断文件是否是符号链接。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsLink)]
[[play](https://go.dev/play/p/TL-b-Kzvf44)]
- **<big>IsDir</big>** : 判断参数是否是目录。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsDir)]
[[play](https://go.dev/play/p/WkVwEKqtOWk)]
- **<big>ListFileNames</big>** : 返回目录下所有文件名。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ListFileNames)]
[[play](https://go.dev/play/p/Tjd7Y07rejl)]
- **<big>RemoveFile</big>** : 删除文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#RemoveFile)]
[[play](https://go.dev/play/p/P2y0XW8a1SH)]
- **<big>ReadFileToString</big>** : 读取文件内容并返回字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileToString)]
[[play](https://go.dev/play/p/cmfwp_5SQTp)]
- **<big>ReadFileByLine</big>** : 按行读取文件内容,返回字符串切片包含每一行。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileByLine)]
[[play](https://go.dev/play/p/svJP_7ZrBrD)]
- **<big>Zip</big>** : zip 压缩文件, 参数可以是文件或目录。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)]
### 9. formatter 格式化器包含一些数据格式化处理方法。
@@ -291,7 +401,9 @@ import "github.com/duke-git/lancet/v2/formatter"
#### 函数列表:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)]
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
### 10. function 函数包控制函数执行流程,包含部分函数式编程。
@@ -310,7 +422,7 @@ import "github.com/duke-git/lancet/v2/function"
- [Pipeline](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Pipeline)
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
### 11. maputil 包括一些操作 map 的函数.
### 11. maputil 包括一些操作 map 的函数.
```go
import "github.com/duke-git/lancet/v2/maputil"
@@ -318,14 +430,30 @@ import "github.com/duke-git/lancet/v2/maputil"
#### 函数列表:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Minus)
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)
- **<big>ForEach</big>** : 对 map 中的每对 key 和 value 执行 iteratee 函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)]
[[play](https://go.dev/play/p/OaThj6iNVXK)]
- **<big>Filter</big>** : 迭代 map 中的每对 key 和 value返回 map其中的 key 和 value 符合 predicate 函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)]
[[play](https://go.dev/play/p/fSvF3wxuNG7)]
- **<big>Intersect</big>** : 多个 map 的交集操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)]
[[play](https://go.dev/play/p/Zld0oj3sjcC)]
- **<big>Keys</big>** : 返回 map 中所有 key 组成的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)]
[[play](https://go.dev/play/p/xNB5bTb97Wd)]
- **<big>Merge</big>** : 合并多个 map, 相同的 key 会被之后的 key 覆盖。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)]
[[play](https://go.dev/play/p/H95LENF1uB-)]
- **<big>Minus</big>** : 返回一个 map其中的 key 存在于 mapA不存在于 mapB。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Minus)]
[[play](https://go.dev/play/p/3u5U9K7YZ9m)]
- **<big>Values</big>** : 返回 map 中所有 values 组成的切片
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)]
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
- **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 12. mathutil 包实现了一些数学计算的函数。
@@ -335,18 +463,41 @@ import "github.com/duke-git/lancet/v2/mathutil"
#### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MaxBy)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MinBy)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
- **<big>Average</big>** :计算平均数,可能需要对结果调用 RoundToFloat 方法四舍五入。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)]
[[play](https://go.dev/play/p/Vv7LBwER-pz)]
- **<big>Exponent</big>** : 指数计算x 的 n 次方)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)]
[[play](https://go.dev/play/p/uF3HGNPk8wr)]
- **<big>Fibonacci</big>** :计算斐波那契数列的第 n 个数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)]
[[play](https://go.dev/play/p/IscseUNMuUc)]
- **<big>Factorial</big>** : 计算阶乘。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)]
[[play](https://go.dev/play/p/tt6LdOK67Nx)]
- **<big>Max</big>** : 返回参数中的最大数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)]
[[play](https://go.dev/play/p/cN8DHI0rTkH)]
- **<big>MaxBy</big>** : 使用给定的比较器函数返回切片的最大值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MaxBy)]
[[play](https://go.dev/play/p/pbe2MT-7DV2)]
- **<big>Min</big>** : 返回参数中的最小数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)]
[[play](https://go.dev/play/p/21BER_mlGUj)]
- **<big>MinBy</big>** : 使用给定的比较器函数返回切片的最小值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MinBy)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : 计算百分比,可以指定保留 n 位小数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)]
- **<big>RoundToFloat</big>** : 四舍五入,保留 n 位小数,返回 float64。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)]
- **<big>RoundToString</big>** : 四舍五入,保留 n 位小数,返回 string。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)]
[[play](https://go.dev/play/p/kZwpBRAcllO)]
- **<big>TruncRound</big>** : 截短 n 位小数(不进行四舍五入)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)]
[[play](https://go.dev/play/p/aumarSHIGzP)]
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
@@ -385,14 +536,32 @@ import "github.com/duke-git/lancet/v2/random"
#### 函数列表:
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
- [RandUpper](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUpper)
- [RandLower](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandLower)
- [RandNumeral](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeral)
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeralOrLetter)
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
- **<big>RandBytes</big>** : 生成随机字节切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)]
[[play](https://go.dev/play/p/EkiLESeXf8d)]
- **<big>RandInt</big>** : 生成随机int, 范围[min, max)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)]
[[play](https://go.dev/play/p/pXyyAAI5YxD)]
- **<big>RandString</big>** : 生成给定长度的随机字符串,只包含字母(a-zA-Z)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)]
[[play](https://go.dev/play/p/W2xvRUXA7Mi)]
- **<big>RandUpper</big>** : 生成给定长度的随机大写字母字符串(A-Z)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUpper)]
[[play](https://go.dev/play/p/29QfOh0DVuh)]
- **<big>RandLower</big>** : 生成给定长度的随机小写字母字符串(a-z)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandLower)]
[[play](https://go.dev/play/p/XJtZ471cmtI)]
- **<big>RandNumeral</big>** : 生成给定长度的随机数字字符串(0-9)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeral)]
[[play](https://go.dev/play/p/g4JWVpHsJcf)]
- **<big>RandNumeralOrLetter</big>** : 生成给定长度的随机字符串(数字+字母)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeralOrLetter)]
[[play](https://go.dev/play/p/19CEQvpx2jD)]
- **<big>UUIdV4</big>** : 生成UUID v4字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
@@ -408,67 +577,175 @@ import "github.com/duke-git/lancet/v2/retry"
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration)
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)
### 16. slice 包含操作切片的方法集合。
### 16. slice 包含操作切片的方法集合。
```go
import "github.com/duke-git/lancet/v2/slice"
```
#### 函数列表:
- **<big>AppendIfAbsent</big>** : 当前切片中不包含值时,将该值追加到切片中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)]
[[play](https://go.dev/play/p/GNdv7Jg2Taj)]
- **<big>Contain</big>** : 判断slice是否包含value。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)]
[[play](https://go.dev/play/p/_454yEHcNjf)]
- **<big>ContainSubSlice</big>** : 判断slice是否包含subslice。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)]
[[play](https://go.dev/play/p/bcuQ3UT6Sev)]
- **<big>Chunk</big>** : 按照size参数均分slice。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)]
[[play](https://go.dev/play/p/b4Pou5j2L_C)]
- **<big>Compact</big>** : 去除slice中的假值false values are false, nil, 0, "")。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)]
[[play](https://go.dev/play/p/pO5AnxEr3TK)]
- **<big>Concat</big>** : 合并多个slices到一个slice中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)]
[[play](https://go.dev/play/p/gPt-q7zr5mk)]
- **<big>Count</big>** : 返回切片中指定元素的个数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)]
[[play](https://go.dev/play/p/Mj4oiEnQvRJ)]
- **<big>CountBy</big>** : 遍历切片对每个元素执行函数predicate. 返回符合函数返回值为true的元素的个数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#CountBy)]
[[play](https://go.dev/play/p/tHOccTMDZCC)]
- **<big>Difference</big>** : 创建一个切片,其元素不包含在另一个给定切片中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)]
[[play](https://go.dev/play/p/VXvadzLzhDa)]
- **<big>DifferenceBy</big>** : 将两个slice中的每个元素调用iteratee函数并比较它们的返回值如果不相等返回在slice中对应的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)]
[[play](https://go.dev/play/p/DiivgwM5OnC)]
- **<big>DifferenceWith</big>** : 接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceWith)]
[[play](https://go.dev/play/p/v2U2deugKuV)]
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Drop</big>** : 创建一个切片当n > 0时从开头删除n个元素或者当n < 0时从结尾删除n个元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)]
[[play](https://go.dev/play/p/WcRQJ37ifPa)]
- **<big>EqualWith</big>** : 检查两个切片是否相等相等条件对两个切片的元素调用比较函数comparator返回true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#EqualWith)]
[[play](https://go.dev/play/p/b9iygtgsHI1)]
- **<big>Every</big>** : 如果切片中的所有值都通过谓词函数则返回true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)]
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
- **<big>Filter</big>** : 返回切片中通过predicate函数真值测试的所有元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)]
[[play](https://go.dev/play/p/SdPna-7qK4T)]
- **<big>Find</big>** : 遍历切片的元素返回第一个通过predicate函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)]
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
- **<big>FindLast</big>** : 从头到尾遍历slice的元素返回最后一个通过predicate函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)]
[[play](https://go.dev/play/p/FFDPV_j7URd)]
- **<big>Flatten</big>** : 将多维切片展平一层。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)]
[[play](https://go.dev/play/p/hYa3cBEevtm)]
- **<big>FlattenDeep</big>** : 将多维切片递归展平到一层。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)]
[[play](https://go.dev/play/p/yjYNHPyCFaF)]
- **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用iteratee函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)]
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
- **<big>GroupBy</big>** : 迭代切片的元素,每个元素将按条件分组,返回两个切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)]
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
- **<big>GroupWith</big>** : 创建一个mapkey是iteratee遍历slice中的每个元素返回的结果。值是切片元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)]
[[play](https://go.dev/play/p/ApCvMNTLO8a)]
- **<big>IntSlice<sup>deprecated</sup></big>** : 将接口切片转换为int切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)]
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
- **<big>InterfaceSlice<sup>deprecated</sup></big>** : 将值转换为interface切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)]
[[play](https://go.dev/play/p/FdQXF0Vvqs-)]
- **<big>Intersection</big>** : 返回多个切片的交集。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)]
[[play](https://go.dev/play/p/anJXfB5wq_t)]
- **<big>InsertAt</big>** : 将元素插入到索引处的切片中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)]
[[play](https://go.dev/play/p/hMLNxPEGJVE)]
- **<big>IndexOf</big>** : 返回在切片中找到值的第一个匹配项的索引,如果找不到值,则返回-1。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IndexOf)]
[[play](https://go.dev/play/p/MRN1f0FpABb)]
- **<big>LastIndexOf</big>** : 返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)]
[[play](https://go.dev/play/p/DokM4cf1IKH)]
- **<big>Map</big>** : 对slice中的每个元素执行map函数以创建一个新切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)]
[[play](https://go.dev/play/p/biaTefqPquw)]
- **<big>Merge</big>** : 合并多个切片(不会消除重复元素)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Merge)]
[[play](https://go.dev/play/p/lbjFp784r9N)]
- **<big>Reverse</big>** : 反转切片中的元素顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
- **<big>Reduce</big>** : 将切片中的元素依次运行iteratee函数返回运行结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
- **<big>Replace</big>** : 返回切片的副本其中前n个不重叠的old替换为new。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
- **<big>ReplaceAll</big>** : 返回切片的副本将其中old全部替换为new。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReplaceAll)]
[[play](https://go.dev/play/p/CzqXMsuYUrx)]
- **<big>Repeat</big>** : 创建一个切片包含n个传入的item。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Repeat)]
[[play](https://go.dev/play/p/1CbOmtgILUU)]
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)]
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
- **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)]
[[play](https://go.dev/play/p/V9AVjzf_4Fk)]
- **<big>SortBy</big>** : 按照less函数确定的升序规则对切片进行排序。排序不保证稳定性。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortBy)]
[[play](https://go.dev/play/p/DAhLQSZEumm)]
- **<big>SortByField<sup>deprecated</sup></big>** : 按字段对结构切片进行排序。slice元素应为struct字段类型应为int、uint、string或bool。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)]
[[play](https://go.dev/play/p/fU1prOBP9p1)]
- **<big>Some</big>** : 如果列表中的任何值通过谓词函数则返回true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)]
[[play](https://go.dev/play/p/4pO9Xf9NDGS)]
- **<big>StringSlice<sup>deprecated</sup></big>** : 将接口切片转换为字符串切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)]
[[play](https://go.dev/play/p/W0TZDWCPFcI)]
- **<big>SymmetricDifference</big>** : 返回一个切片,其中的元素存在于参数切片中,但不同时存储在于参数切片中(交集取反)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#h42nJX5xMln)]
[[play](https://go.dev/play/p/1CbOmtgILUU)]
- **<big>ToSlice</big>** : 将可变参数转为切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)]
[[play](https://go.dev/play/p/YzbzVq5kscN)]
- **<big>ToSlicePointer</big>** : 将可变参数转为指针切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlicePointer)]
[[play](https://go.dev/play/p/gx4tr6_VXSF)]
- **<big>Unique</big>** : 删除切片中的重复元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)]
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
- **<big>UniqueBy</big>** : 对切片的每个元素调用iteratee函数然后删除重复元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)]
[[play](https://go.dev/play/p/UR323iZLDpv)]
- **<big>Union</big>** : 合并多个切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)]
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
- **<big>UnionBy</big>** : 对切片的每个元素调用函数后,合并多个切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UnionBy)]
[[play](https://go.dev/play/p/HGKHfxKQsFi)]
- **<big>UpdateAt</big>** : 更新索引处的切片元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)]
[[play](https://go.dev/play/p/f3mh2KloWVm)]
- **<big>Without</big>** : 创建一个不包括所有给定值的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)]
[[play](https://go.dev/play/p/bwhEXEypThg)]
- **<big>KeyBy</big>** :将切片每个元素调用函数后转为map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
- [CountBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#CountBy)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)
- [IntSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
- [InterfaceSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Merge)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)
- [Replace](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)
- [ReplaceAll](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReplaceAll)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Repeat)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
- [Sort](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)
- [SortBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortBy)
- [SortByField<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
- [StringSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SymmetricDifference)
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlicePointer)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
- [KeyBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)
### 17. strutil 包含处理字符串的相关函数。
### 17. strutil 包含字符串处理的相关函数。
```go
import "github.com/duke-git/lancet/v2/strutil"
@@ -476,27 +753,67 @@ import "github.com/duke-git/lancet/v2/strutil"
#### 函数列表:
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#AfterLast)
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Before)
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BeforeLast)
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#CamelCase)
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperKebabCase)
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Reverse)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
- [UpperSnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperSnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
- **<big>After</big>** : 返回源字符串中指定字符串首次出现时的位置之后的子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)]
[[play](https://go.dev/play/p/RbCOQqCDA7m)]
- **<big>AfterLast</big>** : 返回源字符串中指定字符串最后一次出现时的位置之后的子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#AfterLast)]
[[play](https://go.dev/play/p/1TegARrb8Yn)]
- **<big>Before</big>** : 返回源字符串中指定字符串第一次出现时的位置之前的子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Before)]
[[play](https://go.dev/play/p/JAWTZDS4F5w)]
- **<big>BeforeLast</big>** : 返回源字符串中指定字符串最后一次出现时的位置之前的子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BeforeLast)]
[[play](https://go.dev/play/p/pJfXXAoG_Te)]
- **<big>CamelCase</big>** : 将字符串转换为 CamelCase 驼峰式字符串, 非字母和数字会被忽略。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#CamelCase)]
[[play](https://go.dev/play/p/9eXP3tn2tUy)]
- **<big>Capitalize</big>** : 将字符串的第一个字符转换为大写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>IsString</big>** : 判断传入参数的数据类型是否为字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
- **<big>KebabCase</big>** : 将字符串转换为 kebab-case 形式字符串, 非字母和数字会被忽略。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)]
[[play](https://go.dev/play/p/dcZM9Oahw-Y)]
- **<big>UpperKebabCase</big>** : 将字符串转换为大写 KEBAB-CASE 形式字符串, 非字母和数字会被忽略。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperKebabCase)]
[[play](https://go.dev/play/p/zDyKNneyQXk)]
- **<big>LowerFirst</big>** : 将字符串的第一个字符转换为小写形式。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)]
[[play](https://go.dev/play/p/CbzAyZmtJwL)]
- **<big>UpperFirst</big>** : 将字符串的第一个字符转换为大写形式。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)]
[[play](https://go.dev/play/p/sBbBxRbs8MM)]
- **<big>PadEnd</big>** : 如果字符串短于限制大小,则在右侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)]
[[play](https://go.dev/play/p/9xP8rN0vz--)]
- **<big>PadStart</big>** : 如果字符串短于限制大小,则在左侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)]
[[play](https://go.dev/play/p/xpTfzArDfvT)]
- **<big>Reverse</big>** : 返回字符顺序与给定字符串相反的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Reverse)]
[[play](https://go.dev/play/p/adfwalJiecD)]
- **<big>SnakeCase</big>** : 将字符串转换为 snake_case 形式, 非字母和数字会被忽略。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)]
[[play](https://go.dev/play/p/tgzQG11qBuN)]
- **<big>UpperSnakeCase</big>** : 将字符串转换为大写 SNAKE_CASE 形式, 非字母和数字会被忽略。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperSnakeCase)]
[[play](https://go.dev/play/p/4COPHpnLx38)]
- **<big>SplitEx</big>** : 拆分给定的字符串可以控制结果切片是否包含空字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)]
[[play](https://go.dev/play/p/Us-ySSbWh-3)]
- **<big>Substring</big>** : 根据指定的位置和长度截取子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Substring)]
- **<big>Wrap</big>** : 用给定字符包裹传入的字符串
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)]
[[play](https://go.dev/play/p/KoZOlZDDt9y)]
- **<big>Unwrap</big>** : 从另一个字符串中解开一个给定的字符串。 将更改源字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/Ec2q4BzCpG-)]
### 18. system 包含 os, runtime, shell command 相关函数。
### 18. system 包含 os, runtime, shell command 相关函数。
```go
import "github.com/duke-git/lancet/v2/system"
@@ -504,15 +821,33 @@ import "github.com/duke-git/lancet/v2/system"
#### 函数列表:
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsWindows)
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsLinux)
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#IsMac)
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsEnv)
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#SetOsEnv)
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#RemoveOsEnv)
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsBits)
- **<big>IsWindows</big>** : 检查当前操作系统是否是 windows
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#IsWindows)]
[[play](https://go.dev/play/p/XzJULbzmf9m)]
- **<big>IsLinux</big>** : 检查当前操作系统是否是 linux。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#IsLinux)]
[[play](https://go.dev/play/p/zIflQgZNuxD)]
- **<big>IsMac</big>** : 检查当前操作系统是否是 macos。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#IsMac)]
[[play](https://go.dev/play/p/Mg4Hjtyq7Zc)]
- **<big>GetOsEnv</big>** : 根据 key 获取对应的环境变量值
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsEnv)]
[[play](https://go.dev/play/p/D88OYVCyjO-)]
- **<big>SetOsEnv</big>** : 设置环境变量。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#SetOsEnv)]
[[play](https://go.dev/play/p/D88OYVCyjO-)]
- **<big>RemoveOsEnv</big>** : 删除环境变量。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#RemoveOsEnv)]
[[play](https://go.dev/play/p/fqyq4b3xUFQ)]
- **<big>CompareOsEnv</big>** : 换取环境变量并与传入值进行比较。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#CompareOsEnv)]
[[play](https://go.dev/play/p/BciHrKYOHbp)]
- **<big>ExecCommand</big>** : 执行 shell 命令。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#ExecCommand)]
[[play](https://go.dev/play/p/n-2fLyZef-4)]
- **<big>GetOsBits</big>** : 获取当前操作系统位数(32/64)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 19. validator 验证器包,包含常用字符串格式验证函数。
@@ -522,34 +857,91 @@ import "github.com/duke-git/lancet/v2/validator"
#### 函数列表:
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLetter)
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLower)
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainUpper)
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAlpha)
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllUpper)
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseMobile)
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseIdNum)
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChinesePhone)
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmail)
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)
- [IsGBK](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)
- **<big>ContainChinese</big>** : 验证字符串是否包含中文字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)]
[[play](https://go.dev/play/p/7DpU0uElYeM)]
- **<big>ContainLetter</big>** : 验证字符串是否包含至少一个英文字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLetter)]
[[play](https://go.dev/play/p/lqFD04Yyewp)]
- **<big>ContainLower</big>** : 验证字符串是否包含至少一个英文小写字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLower)]
[[play](https://go.dev/play/p/Srqi1ItvnAA)]
- **<big>ContainUpper</big>** : 验证字符串是否包含至少一个英文大写字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainUpper)]
[[play](https://go.dev/play/p/CmWeBEk27-z)]
- **<big>IsAlpha</big>** : 验证字符串是否只包含英文字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAlpha)]
[[play](https://go.dev/play/p/7Q5sGOz2izQ)]
- **<big>IsAllUpper</big>** : 验证字符串是否全是大写英文字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllUpper)]
[[play](https://go.dev/play/p/ZHctgeK1n4Z)]
- **<big>IsAllLower</big>** : 验证字符串是否全是小写英文字母。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)]
[[play](https://go.dev/play/p/GjqCnOfV6cM)]
- **<big>IsBase64</big>** : 验证字符串是否是base64编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)]
[[play](https://go.dev/play/p/sWHEySAt6hl)]
- **<big>IsChineseMobile</big>** : 验证字符串是否是中国手机号码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseMobile)]
[[play](https://go.dev/play/p/GPYUlGTOqe3)]
- **<big>IsChineseIdNum</big>** : 验证字符串是否是中国身份证号码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseIdNum)]
[[play](https://go.dev/play/p/d8EWhl2UGDF)]
- **<big>IsChinesePhone</big>** : 验证字符串是否是中国电话座机号码(xxx-xxxxxxxx or xxxx-xxxxxxx.)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChinesePhone)]
[[play](https://go.dev/play/p/RUD_-7YZJ3I)]
- **<big>IsCreditCard</big>** : 验证字符串是否是信用卡号码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)]
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
- **<big>IsDns</big>** : 验证字符串是否是有效dns。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)]
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
- **<big>IsEmail</big>** : 验证字符串是否是有效电子邮件地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmail)]
[[play](https://go.dev/play/p/Os9VaFlT33G)]
- **<big>IsEmptyString</big>** : 验证字符串是否是空字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)]
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
- **<big>IsFloatStr</big>** : 验证字符串是否是可以转换为浮点数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#LOYwS_Oyl7U)]
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsJSON</big>** : 验证字符串是否是有效json。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)]
[[play](https://go.dev/play/p/z_XeZo_litG)]
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
- **<big>IsIp</big>** : 验证字符串是否是ip地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)]
[[play](https://go.dev/play/p/FgcplDvmxoD)]
- **<big>IsIpV4</big>** : 验证字符串是否是ipv4地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)]
[[play](https://go.dev/play/p/zBGT99EjaIu)]
- **<big>IsIpV6</big>** : 验证字符串是否是ipv6地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)]
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
- **<big>IsStrongPassword</big>** : 验证字符串是否是强密码:(字母+数字+特殊字符)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)]
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
- **<big>IsUrl</big>** : 验证字符串是否是url。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)]
[[play](https://go.dev/play/p/pbJGa7F98Ka)]
- **<big>IsWeakPassword</big>** : 验证字符串是否是弱密码(只包含字母+数字)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)]
[[play](https://go.dev/play/p/wqakscZH5gH)]
- **<big>IsZeroValue</big>** : 判断传入的参数值是否为零值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)]
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
- **<big>IsGBK</big>** : 检查数据编码是否为gbk汉字内部代码扩展规范
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)]
[[play](https://go.dev/play/p/E2nt3unlmzP)]
### 20. xerror 包实现一些错误处理函数

View File

@@ -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

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
}

View File

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

View File

@@ -1,26 +1,27 @@
// 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
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 +40,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

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
}

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

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)

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]
}

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)

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:
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:
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:
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:
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:
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:
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:
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:
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:
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T {
valStream := make(chan T)
go func() {
defer close(valStream)

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
}

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

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

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
}

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)

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
}

View File

@@ -570,6 +570,8 @@ 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>
@@ -586,10 +588,14 @@ func main() {
cache.Put(1, 1)
cache.Put(2, 2)
cache.Put(3, 3)
_, ok := cache.Get(0) // ok -> false
fmt.Println(cache.Len()) // 3
v, ok := cache.Get(1) // v->1, ok->true
v, ok := cache.Get(1)
fmt.Println(v, ok) // 1 true
ok = cache.Delete(1)
fmt.Println(ok) // true
}
```

View File

@@ -570,6 +570,8 @@ 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>
@@ -586,10 +588,14 @@ func main() {
cache.Put(1, 1)
cache.Put(2, 2)
cache.Put(3, 3)
_, ok := cache.Get(0) // ok -> false
fmt.Println(cache.Len()) // 3
v, ok := cache.Get(1) // v->1, ok->true
v, ok := cache.Get(1)
fmt.Println(v, ok) // 1 true
ok = cache.Delete(1)
fmt.Println(ok) // true
}
```

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,7 +57,7 @@ import (
)
func main() {
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
}
```
@@ -70,7 +70,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,25 +87,30 @@ 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
}
```
@@ -114,12 +119,12 @@ func main() {
### <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,17 +141,17 @@ 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
}
}
```
@@ -154,12 +159,12 @@ func main() {
### <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 +181,30 @@ 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>
### <span id="RepeatFn">RepeatFn</span>
<p>Return a chan, excutes fn repeatly, and put the result into retruned chan until cancel context.</p>
<p>Creates a channel, then put values into the channel.</p>
<b>Signature:</b>
```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>Example:</b>
@@ -212,16 +221,58 @@ func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
}
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
c := concurrency.NewChannel[int]()
intStream := c.Generate(ctx, 1, 2, 3)
for v := range dataStream {
fmt.Println(v) //a, a, a
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
```
### <span id="RepeatFn">RepeatFn</span>
<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[T]) RepeatFn(ctx context.Context, fn func() 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()
fn := func() string {
return "hello"
}
c := concurrency.NewChannel[string]()
intStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range intStream {
fmt.Println(v)
}
// Output:
// hello
// hello
// hello
}
```
@@ -234,7 +285,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 +300,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,13 +310,11 @@ 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
@@ -282,7 +331,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,12 +348,16 @@ 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
}
```
@@ -313,12 +366,12 @@ func main() {
### <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 +388,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,12 +396,16 @@ 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
}
```
@@ -356,12 +413,12 @@ func main() {
### <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 +435,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
}
```

View File

@@ -38,13 +38,13 @@ import (
### Channel
### <span id="NewChannel">NewChannel</span>
<p>返回一个 Channel 指针实例</p>
<p>返回一个Channel指针实例</p>
<b>函数签名:</b>
```go
type Channel struct {}
func NewChannel() *Channel
type Channel[T any] struct
func NewChannel[T any]() *Channel[T]
```
<b>例子:</b>
@@ -57,7 +57,7 @@ import (
)
func main() {
c := concurrency.NewChannel()
c := concurrency.NewChannel[int]()
}
```
@@ -65,12 +65,12 @@ func main() {
### <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>
@@ -84,28 +84,33 @@ import (
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
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
}
```
@@ -114,12 +119,12 @@ func main() {
### <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>
@@ -133,33 +138,33 @@ import (
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
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>
### <span id="Generate">Generate</span>
<p>返回一个chan将参数`values`重复放入chan直到取消上下文。</p>
<p>根据传入的值生成channel.</p>
<b>函数签名:</b>
```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>例子:</b>
@@ -173,15 +178,58 @@ import (
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
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.Generate(ctx, 1, 2, 3)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
fmt.Println(<-intStream)
// Output:
// 1
// 2
// 3
}
```
### <span id="Repeat">Repeat</span>
<p>返回一个channel将参数`values`重复放入channel直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel[T]) Repeat(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.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
}
```
@@ -190,12 +238,12 @@ func main() {
### <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>
@@ -209,19 +257,23 @@ import (
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
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
}
```
@@ -229,12 +281,12 @@ func main() {
### <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>
@@ -249,7 +301,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,13 +311,11 @@ 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
@@ -277,12 +327,12 @@ func main() {
### <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>
@@ -299,12 +349,16 @@ 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
}
```
@@ -313,12 +367,12 @@ func main() {
### <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>
@@ -335,7 +389,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,12 +397,16 @@ 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
}
```
@@ -356,12 +414,12 @@ func main() {
### <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>
@@ -378,13 +436,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
}
```

View File

@@ -25,6 +25,7 @@ import (
- [Or](#Or)
- [Xor](#Generate)
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [TernaryOperator](#TernaryOperator)
@@ -120,7 +121,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 +149,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 +177,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 +198,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>

View File

@@ -25,6 +25,7 @@ import (
- [Or](#Or)
- [Xor](#Generate)
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [TernaryOperator](#TernaryOperator)
@@ -196,12 +197,38 @@ 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>

View File

@@ -102,7 +102,7 @@ func main() {
### <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>
@@ -138,7 +138,7 @@ func main() {
### <span id="ToBytes">ToBytes</span>
<p>Convert interface to byte slice.</p>
<p>Convert value to byte slice.</p>
<b>Signature:</b>
@@ -200,7 +200,7 @@ func main() {
### <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>
@@ -238,7 +238,7 @@ func main() {
### <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>
@@ -271,7 +271,7 @@ func main() {
### <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>
@@ -332,7 +332,7 @@ func main() {
### <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>

View File

@@ -522,7 +522,7 @@ func main() {
### <span id="DecodeByte">DecodeByte</span>
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p>
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p>
<b>函数签名:</b>

View File

@@ -119,7 +119,7 @@ func main() {
### <span id="CopyFile">CopyFile</span>
<p>拷贝文件,会覆盖原有的拷贝文件</p>
<p>拷贝文件,会覆盖原有的文件</p>
<b>函数签名:</b>
@@ -261,7 +261,7 @@ func main() {
### <span id="IsDir">IsDir</span>
<p>判断目录是否存在</p>
<p>判断参数是否是目录</p>
<b>函数签名:</b>

View File

@@ -218,7 +218,7 @@ func main() {
### <span id="Min">Min</span>
<p>Return min value of numbers.</p>
<p>Return the minimum value of numbers.</p>
<b>Signature:</b>
@@ -302,8 +302,8 @@ import (
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
fmt.Println(mathutil.Percent(1, 2, 2)) //0.5
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //0.33
}
```

View File

@@ -299,8 +299,8 @@ import (
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
fmt.Println(mathutil.Percent(1, 2, 2)) //0.5
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //0.33
}
```

View File

@@ -319,7 +319,7 @@ func main() {
### <span id="DifferenceBy">DifferenceBy</span>
<p>在slice和comparedSlice中的每个元素调用iteratee函数并比较它们的返回值如果不等返回在slice中对应的值</p>
<p>将两个slice中的每个元素调用iteratee函数并比较它们的返回值如果不等返回在slice中对应的值</p>
<b>函数签名:</b>
@@ -349,7 +349,7 @@ func main() {
### <span id="DifferenceWith">DifferenceWith</span>
<p>DifferenceWith 接受比较器,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定</p>
<p>接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定</p>
<b>函数签名:</b>
@@ -379,7 +379,7 @@ func main() {
### <span id="DeleteAt">DeleteAt</span>
<p>删除切片中开始索引到结束索引-1的元素</p>
<p>删除切片中指定开始索引到结束索引的元素</p>
<b>函数签名:</b>
@@ -407,7 +407,7 @@ func main() {
### <span id="Drop">Drop</span>
<p>创建一个切片,当 n > 0 时从开头删除 n 个元素,或者当 n < 0 时从结尾删除 n 个元素</p>
<p>创建一个切片当n > 0时从开头删除n个元素或者当n < 0时从结尾删除n个元素</p>
<b>函数签名:</b>
@@ -1442,7 +1442,7 @@ func main() {
### <span id="Union">Union</span>
<p>合并多个切片.</p>
<p>合并多个切片</p>
<b>函数签名:</b>

View File

@@ -37,6 +37,7 @@ import (
- [SnakeCase](#SnakeCase)
- [UpperSnakeCase](#UpperSnakeCase)
- [SplitEx](#SplitEx)
- [Substring](#Substring)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap)
@@ -47,7 +48,7 @@ import (
### <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>
@@ -77,7 +78,7 @@ func main() {
### <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>
@@ -108,7 +109,7 @@ func main() {
### <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>
@@ -139,7 +140,7 @@ func main() {
### <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>
@@ -631,9 +632,45 @@ func main() {
### <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)
fmt.Println(result1) //bcd
result2 := strutil.Substring("abcde", 1, 5)
fmt.Println(result2) //bcde
result3 := strutil.Substring("abcde", -1, 3)
fmt.Println(result3) //e
result4 := strutil.Substring("abcde", -2, 2)
fmt.Println(result4) //de
result5 := strutil.Substring("abcde", -2, 3)
fmt.Println(result5) //de
result6 := strutil.Substring("你好,欢迎你", 0, 2)
fmt.Println(result6) //你好
}
```
### <span id="Wrap">Wrap</span>
<p>Wrap a string with another string.</p>
<p>Wrap a string with given string.</p>
<b>Signature:</b>
@@ -670,7 +707,7 @@ func main() {
### <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>

View File

@@ -37,6 +37,7 @@ import (
- [SnakeCase](#SnakeCase)
- [UpperSnakeCase](#UpperSnakeCase)
- [SplitEx](#SplitEx)
- [Substring](#Substring)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap)
@@ -48,7 +49,7 @@ import (
### <span id="After">After</span>
<p>截取源字符串中char首次出现时的位置之后的子字符串</p>
<p>返回源字符串中特定字符串首次出现时的位置之后的子字符串</p>
<b>函数签名:</b>
@@ -78,7 +79,7 @@ func main() {
### <span id="AfterLast">AfterLast</span>
<p>截取源字符串中char最后一次出现时的位置之后的子字符串</p>
<p>返回源字符串中指定字符串最后一次出现时的位置之后的子字符串</p>
<b>函数签名:</b>
@@ -109,7 +110,7 @@ func main() {
### <span id="Before">Before</span>
<p>截取源字符串中char首次出现时的位置之前的子字符串</p>
<p>返回源字符串中指定字符串第一次出现时的位置之前的子字符串</p>
<b>函数签名:</b>
@@ -140,7 +141,7 @@ func main() {
### <span id="BeforeLast">BeforeLast</span>
<p>截取源字符串中char最后一次出现时的位置之前的子字符串</p>
<p>返回源字符串中指定字符串最后一次出现时的位置之前的子字符串</p>
<b>函数签名:</b>
@@ -238,7 +239,7 @@ func main() {
### <span id="IsString">IsString</span>
<p>检查值的数据类型是否为字符串</p>
<p>判断传入参数的数据类型是否为字符串</p>
<b>函数签名:</b>
@@ -367,7 +368,7 @@ func main() {
### <span id="UpperFirst">UpperFirst</span>
<p>将字符串的第一个字符转换为大写</p>
<p>将字符串的第一个字符转换为大写形式</p>
<b>函数签名:</b>
@@ -600,6 +601,42 @@ func main() {
}
```
### <span id="Substring">Substring</span>
<p>根据指定的位置和长度截取子字符串</p>
<b>函数签名:</b>
```go
func Substring(s string, offset int, length uint) string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.Substring("abcde", 1, 3)
fmt.Println(result1) //bcd
result2 := strutil.Substring("abcde", 1, 5)
fmt.Println(result2) //bcde
result3 := strutil.Substring("abcde", -1, 3)
fmt.Println(result3) //e
result4 := strutil.Substring("abcde", -2, 2)
fmt.Println(result4) //de
result5 := strutil.Substring("abcde", -2, 3)
fmt.Println(result5) //de
result6 := strutil.Substring("你好,欢迎你", 0, 2)
fmt.Println(result6) //你好
}
```
### <span id="Wrap">Wrap</span>

View File

@@ -102,7 +102,7 @@ import (
)
func main() {
isOsMac := system.IsMac
isOsMac := system.IsMac()
fmt.Println(isOsMac)
}
```

View File

@@ -26,7 +26,6 @@ import (
- [GetOsEnv](#GetOsEnv)
- [SetOsEnv](#SetOsEnv)
- [RemoveOsEnv](#RemoveOsEnv)
- [CompareOsEnv](#CompareOsEnv)
- [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
@@ -103,7 +102,7 @@ import (
)
func main() {
isOsMac := system.IsMac
isOsMac := system.IsMac()
fmt.Println(isOsMac)
}
```

View File

@@ -459,8 +459,6 @@ func main() {
### <span id="IsEmptyString">IsEmptyString</span>
<p>验证字符串是否是空字符串</p>
@@ -488,7 +486,6 @@ func main() {
### <span id="IsFloatStr">IsFloatStr</span>
<p>验证字符串是否是可以转换为浮点数</p>
@@ -574,8 +571,6 @@ func main() {
```
### <span id="IsRegexMatch">IsRegexMatch</span>
<p>验证字符串是否可以匹配正则表达式</p>
@@ -601,7 +596,6 @@ func main() {
### <span id="IsIntStr">IsIntStr</span>
<p>验证字符串是否是可以转换为整数</p>

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

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 := "./test.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("./")
fmt.Println(fileList)
// Output:
// [file.go file_example_test.go file_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
}

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

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
}

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

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
}

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

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
}

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

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 {

181
maputil/map_example_test.go Normal file
View File

@@ -0,0 +1,181 @@
package maputil
import (
"fmt"
"sort"
)
func ExampleKeys() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
keys := Keys(m)
sort.Ints(keys)
fmt.Println(keys)
// Output:
// [1 2 3 4 5]
}
func ExampleValues() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
values := Values(m)
sort.Strings(values)
fmt.Println(values)
// Output:
// [a a b c d]
}
func ExampleMerge() {
m1 := map[int]string{
1: "a",
2: "b",
}
m2 := map[int]string{
1: "c",
3: "d",
}
result := Merge(m1, m2)
fmt.Println(result)
// Output:
// map[1:c 2:b 3:d]
}
func ExampleForEach() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
var sum int
ForEach(m, func(_ string, value int) {
sum += value
})
fmt.Println(sum)
// Output:
// 10
}
func ExampleFilter() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
result := Filter(m, isEven)
fmt.Println(result)
// Output:
// map[b:2 d:4]
}
func ExampleIntersect() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 6,
"d": 7,
}
m3 := map[string]int{
"a": 1,
"b": 9,
"e": 9,
}
result1 := Intersect(m1)
result2 := Intersect(m1, m2)
result3 := Intersect(m1, m2, m3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// map[a:1 b:2 c:3]
// map[a:1 b:2]
// map[a:1]
}
func ExampleMinus() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 11,
"b": 22,
"d": 33,
}
result := Minus(m1, m2)
fmt.Println(result)
// Output:
// map[c:3]
}
func ExampleIsDisjoint() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"d": 22,
}
m3 := map[string]int{
"a": 22,
}
result1 := IsDisjoint(m1, m2)
result2 := IsDisjoint(m1, m3)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}

View File

@@ -13,7 +13,8 @@ import (
"golang.org/x/exp/constraints"
)
// Exponent calculate x^n
// Exponent calculate x^n.
// Play: https://go.dev/play/p/uF3HGNPk8wr
func Exponent(x, n int64) int64 {
if n == 0 {
return 1
@@ -28,7 +29,8 @@ func Exponent(x, n int64) int64 {
return t * t
}
// Fibonacci calculate fibonacci number before n
// Fibonacci calculate fibonacci number before n.
// Play: https://go.dev/play/p/IscseUNMuUc
func Fibonacci(first, second, n int) int {
if n <= 0 {
return 0
@@ -42,7 +44,8 @@ func Fibonacci(first, second, n int) int {
}
}
// Factorial calculate x!
// Factorial calculate x!.
// Play: https://go.dev/play/p/tt6LdOK67Nx
func Factorial(x uint) uint {
var f uint = 1
for ; x > 1; x-- {
@@ -51,18 +54,19 @@ func Factorial(x uint) uint {
return f
}
// Percent calculate the percentage of val to total
// Percent calculate the percentage of value to total.
func Percent(val, total float64, n int) float64 {
if total == 0 {
return float64(0)
}
tmp := val / total * 100
tmp := val / total
result := RoundToFloat(tmp, n)
return result
}
// RoundToString round up to n decimal places
// RoundToString round up to n decimal places.
// Play: https://go.dev/play/p/kZwpBRAcllO
func RoundToString(x float64, n int) string {
tmp := math.Pow(10.0, float64(n))
x *= tmp
@@ -71,7 +75,8 @@ func RoundToString(x float64, n int) string {
return result
}
// RoundToFloat round up to n decimal places
// RoundToFloat round up to n decimal places.
// Play: https://go.dev/play/p/ghyb528JRJL
func RoundToFloat(x float64, n int) float64 {
tmp := math.Pow(10.0, float64(n))
x *= tmp
@@ -79,7 +84,8 @@ func RoundToFloat(x float64, n int) float64 {
return x / tmp
}
// TruncRound round off n decimal places
// TruncRound round off n decimal places.
// Play: https://go.dev/play/p/aumarSHIGzP
func TruncRound(x float64, n int) float64 {
floatStr := fmt.Sprintf("%."+strconv.Itoa(n+1)+"f", x)
temp := strings.Split(floatStr, ".")
@@ -93,7 +99,8 @@ func TruncRound(x float64, n int) float64 {
return result
}
// Max return max value of params
// Max return max value of numbers.
// Play: https://go.dev/play/p/cN8DHI0rTkH
func Max[T constraints.Integer | constraints.Float](numbers ...T) T {
max := numbers[0]
@@ -106,7 +113,8 @@ func Max[T constraints.Integer | constraints.Float](numbers ...T) T {
return max
}
// MaxBy search the maximum value of a slice using the given comparator function.
// MaxBy return the maximum value of a slice using the given comparator function.
// Play: https://go.dev/play/p/pbe2MT-7DV2
func MaxBy[T any](slice []T, comparator func(T, T) bool) T {
var max T
@@ -127,7 +135,8 @@ func MaxBy[T any](slice []T, comparator func(T, T) bool) T {
return max
}
// Min return min value of params
// Min return min value of numbers.
// Play: https://go.dev/play/p/21BER_mlGUj
func Min[T constraints.Integer | constraints.Float](numbers ...T) T {
min := numbers[0]
@@ -140,7 +149,8 @@ func Min[T constraints.Integer | constraints.Float](numbers ...T) T {
return min
}
// MinBy search the minimum value of a slice using the given comparator function.
// MinBy return the minimum value of a slice using the given comparator function.
// Play: https://go.dev/play/p/XuJDKrDdglW
func MinBy[T any](slice []T, comparator func(T, T) bool) T {
var min T
@@ -161,7 +171,8 @@ func MinBy[T any](slice []T, comparator func(T, T) bool) T {
return min
}
// Average return average value of numbers
// Average return average value of numbers.
// Play: https://go.dev/play/p/Vv7LBwER-pz
func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
var sum T
n := T(len(numbers))

View File

@@ -0,0 +1,187 @@
package mathutil
import "fmt"
func ExampleExponent() {
result1 := Exponent(10, 0)
result2 := Exponent(10, 1)
result3 := Exponent(10, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 10
// 100
}
func ExampleFibonacci() {
result1 := Fibonacci(1, 1, 1)
result2 := Fibonacci(1, 1, 2)
result3 := Fibonacci(1, 1, 5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 1
// 5
}
func ExampleFactorial() {
result1 := Factorial(1)
result2 := Factorial(2)
result3 := Factorial(3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 6
}
func ExamplePercent() {
result1 := Percent(1, 2, 2)
result2 := Percent(0.1, 0.3, 2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0.5
// 0.33
}
func ExampleRoundToFloat() {
result1 := RoundToFloat(0.124, 2)
result2 := RoundToFloat(0.125, 2)
result3 := RoundToFloat(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
func ExampleRoundToString() {
result1 := RoundToString(0.124, 2)
result2 := RoundToString(0.125, 2)
result3 := RoundToString(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
}
func ExampleTruncRound() {
result1 := TruncRound(0.124, 2)
result2 := TruncRound(0.125, 2)
result3 := TruncRound(0.125, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.12
// 0.125
}
func ExampleAverage() {
result1 := Average(1, 2)
result2 := RoundToFloat(Average(1.2, 1.4), 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.3
}
func ExampleMax() {
result1 := Max(1, 2, 3)
result2 := Max(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.4
}
func ExampleMaxBy() {
result1 := MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
result2 := MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
result3 := MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abc
// abd
//
}
func ExampleMin() {
result1 := Min(1, 2, 3)
result2 := Min(1.2, 1.4, 1.1, 1.4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.1
}
func ExampleMinBy() {
result1 := MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
result2 := MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
result3 := MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// a
// ab
//
}

View File

@@ -35,8 +35,8 @@ func TestFactorial(t *testing.T) {
func TestPercent(t *testing.T) {
assert := internal.NewAssert(t, "TestPercent")
assert.Equal(float64(50), Percent(1, 2, 2))
assert.Equal(float64(33.33), Percent(0.1, 0.3, 2))
assert.Equal(0.5, Percent(1, 2, 2))
assert.Equal(0.33, Percent(0.1, 0.3, 2))
}
func TestRoundToFloat(t *testing.T) {

View File

@@ -19,7 +19,8 @@ const (
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
)
// RandInt generate random int between min and max, maybe min, not be max
// RandInt generate random int between min and max, maybe min, not be max.
// Play: https://go.dev/play/p/pXyyAAI5YxD
func RandInt(min, max int) int {
if min == max {
return min
@@ -28,10 +29,12 @@ func RandInt(min, max int) int {
min, max = max, min
}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
return r.Intn(max-min) + min
}
// RandBytes generate random byte slice
// RandBytes generate random byte slice.
// Play: https://go.dev/play/p/EkiLESeXf8d
func RandBytes(length int) []byte {
if length < 1 {
return []byte{}
@@ -41,45 +44,54 @@ func RandBytes(length int) []byte {
if _, err := io.ReadFull(crand.Reader, b); err != nil {
return nil
}
return b
}
// RandString generate random string
// RandString generate random string of specified length.
// Play: https://go.dev/play/p/W2xvRUXA7Mi
func RandString(length int) string {
return random(LETTERS, length)
}
// RandUpper generate a random upper case string
// RandUpper generate a random upper case string.
// Play: https://go.dev/play/p/29QfOh0DVuh
func RandUpper(length int) string {
return random(UPPER_LETTERS, length)
}
// RandLower generate a random lower case string
// RandLower generate a random lower case string.
// Play: https://go.dev/play/p/XJtZ471cmtI
func RandLower(length int) string {
return random(LOWER_LETTERS, length)
}
// RandNumeral generate a random numeral string
// RandNumeral generate a random numeral string of specified length.
// Play: https://go.dev/play/p/g4JWVpHsJcf
func RandNumeral(length int) string {
return random(NUMERAL, length)
}
// RandNumeralOrLetter generate a random numeral or letter string
// RandNumeralOrLetter generate a random numeral or letter string.
// Play: https://go.dev/play/p/19CEQvpx2jD
func RandNumeralOrLetter(length int) string {
return random(NUMERAL+LETTERS, length)
}
// random generate a random string based on given string range
// random generate a random string based on given string range.
func random(s string, length int) string {
b := make([]byte, length)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := range b {
b[i] = s[r.Int63()%int64(len(s))]
}
return string(b)
}
// UUIdV4 generate a random UUID of version 4 according to RFC 4122
// UUIdV4 generate a random UUID of version 4 according to RFC 4122.
// Play: https://go.dev/play/p/_Z9SFmr28ft
func UUIdV4() (string, error) {
uuid := make([]byte, 16)

View File

@@ -0,0 +1,126 @@
package random
import (
"fmt"
"regexp"
)
func ExampleRandInt() {
result := RandInt(1, 10)
if result >= 1 && result < 10 {
fmt.Println("ok")
}
// Output:
// ok
}
func ExampleRandBytes() {
bytes := RandBytes(4)
fmt.Println(len(bytes))
// Output:
// 4
}
func ExampleRandString() {
pattern := `^[a-zA-Z]+$`
reg := regexp.MustCompile(pattern)
s := RandString(6)
result1 := reg.MatchString(s)
result2 := len(s)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// 6
}
func ExampleRandUpper() {
pattern := `^[A-Z]+$`
reg := regexp.MustCompile(pattern)
s := RandUpper(6)
result1 := reg.MatchString(s)
result2 := len(s)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// 6
}
func ExampleRandLower() {
pattern := `^[a-z]+$`
reg := regexp.MustCompile(pattern)
s := RandLower(6)
result1 := reg.MatchString(s)
result2 := len(s)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// 6
}
func ExampleRandNumeral() {
pattern := `^[0-9]+$`
reg := regexp.MustCompile(pattern)
s := RandNumeral(6)
result1 := reg.MatchString(s)
result2 := len(s)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// 6
}
func ExampleRandNumeralOrLetter() {
pattern := `^[0-9a-zA-Z]+$`
reg := regexp.MustCompile(pattern)
s := RandNumeralOrLetter(6)
result1 := reg.MatchString(s)
result2 := len(s)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// 6
}
func ExampleUUIdV4() {
pattern := `^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`
reg := regexp.MustCompile(pattern)
s, _ := UUIdV4()
result := reg.MatchString(s)
fmt.Println(result)
// Output:
// true
}

View File

@@ -68,6 +68,7 @@ func TestRandInt(t *testing.T) {
assert := internal.NewAssert(t, "TestRandInt")
r1 := RandInt(1, 10)
t.Log(r1)
assert.GreaterOrEqual(r1, 1)
assert.Less(r1, 10)

View File

@@ -10,6 +10,7 @@ import (
"math/rand"
"reflect"
"sort"
"time"
"golang.org/x/exp/constraints"
)
@@ -21,7 +22,8 @@ var (
memoryHashCounter = make(map[string]int)
)
// Contain check if the target value is in the slice or not
// Contain check if the target value is in the slice or not.
// Play: https://go.dev/play/p/_454yEHcNjf
func Contain[T comparable](slice []T, target T) bool {
for _, item := range slice {
if item == target {
@@ -32,7 +34,8 @@ func Contain[T comparable](slice []T, target T) bool {
return false
}
// ContainSubSlice check if the slice contain a given subslice or not
// ContainSubSlice check if the slice contain a given subslice or not.
// Play: https://go.dev/play/p/bcuQ3UT6Sev
func ContainSubSlice[T comparable](slice, subSlice []T) bool {
for _, v := range subSlice {
if !Contain(slice, v) {
@@ -43,7 +46,8 @@ func ContainSubSlice[T comparable](slice, subSlice []T) bool {
return true
}
// Chunk creates a slice of elements split into groups the length of size
// Chunk creates a slice of elements split into groups the length of size.
// Play: https://go.dev/play/p/b4Pou5j2L_C
func Chunk[T any](slice []T, size int) [][]T {
result := [][]T{}
@@ -62,14 +66,15 @@ func Chunk[T any](slice []T, size int) [][]T {
}
return result
}
// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey
// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey.
// Play: https://go.dev/play/p/pO5AnxEr3TK
func Compact[T comparable](slice []T) []T {
var zero T
result := []T{}
for _, v := range slice {
if v != zero {
result = append(result, v)
@@ -80,6 +85,7 @@ func Compact[T comparable](slice []T) []T {
}
// Concat creates a new slice concatenating slice with any additional slices.
// Play: https://go.dev/play/p/gPt-q7zr5mk
func Concat[T any](slice []T, slices ...[]T) []T {
result := append([]T{}, slice...)
@@ -90,7 +96,8 @@ func Concat[T any](slice []T, slices ...[]T) []T {
return result
}
// Difference creates an slice of whose element in slice but not in comparedSlice
// Difference creates an slice of whose element in slice but not in comparedSlice.
// Play: https://go.dev/play/p/VXvadzLzhDa
func Difference[T comparable](slice, comparedSlice []T) []T {
result := []T{}
@@ -105,7 +112,8 @@ func Difference[T comparable](slice, comparedSlice []T) []T {
// DifferenceBy it accepts iteratee which is invoked for each element of slice
// and values to generate the criterion by which they're compared.
// like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy,
// like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy.
// Play: https://go.dev/play/p/DiivgwM5OnC
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T {
orginSliceAfterMap := Map(slice, iteratee)
comparedSliceAfterMap := Map(comparedSlice, iteratee)
@@ -120,7 +128,10 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
return result
}
// DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice. The comparator is invoked with two arguments: (arrVal, othVal).
// DifferenceWith accepts comparator which is invoked to compare elements of slice to values.
// The order and references of result values are determined by the first slice.
// The comparator is invoked with two arguments: (arrVal, othVal).
// Play: https://go.dev/play/p/v2U2deugKuV
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1, item2 T) bool) []T {
result := make([]T, 0)
@@ -145,7 +156,8 @@ func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1,
return result
}
// Equal checks if two slices are equal: the same length and all elements' order and value are equal
// Equal checks if two slices are equal: the same length and all elements' order and value are equal.
// Play: https://go.dev/play/p/WcRQJ37ifPa
func Equal[T comparable](slice1, slice2 []T) bool {
if len(slice1) != len(slice2) {
return false
@@ -160,7 +172,8 @@ func Equal[T comparable](slice1, slice2 []T) bool {
return true
}
// EqualWith checks if two slices are equal with comparator func
// EqualWith checks if two slices are equal with comparator func.
// Play: https://go.dev/play/p/b9iygtgsHI1
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool {
if len(slice1) != len(slice2) {
return false
@@ -176,6 +189,7 @@ func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) boo
}
// Every return true if all of the values in the slice pass the predicate function.
// Play: https://go.dev/play/p/R8U6Sl-j8cD
func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
for i, v := range slice {
if !predicate(i, v) {
@@ -186,7 +200,8 @@ func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
return true
}
// None return true if all the values in the slice mismatch the criteria
// None return true if all the values in the slice mismatch the criteria.
// Play: https://go.dev/play/p/KimdalUlC-T
func None[T any](slice []T, predicate func(index int, item T) bool) bool {
l := 0
for i, v := range slice {
@@ -199,6 +214,7 @@ func None[T any](slice []T, predicate func(index int, item T) bool) bool {
}
// Some return true if any of the values in the list pass the predicate function.
// Play: https://go.dev/play/p/4pO9Xf9NDGS
func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
for i, v := range slice {
if predicate(i, v) {
@@ -209,7 +225,8 @@ func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
return false
}
// Filter iterates over elements of slice, returning an slice of all elements pass the predicate function
// Filter iterates over elements of slice, returning an slice of all elements pass the predicate function.
// Play: https://go.dev/play/p/SdPna-7qK4T
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
result := make([]T, 0)
@@ -222,7 +239,8 @@ func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
return result
}
// Count returns the number of occurrences of the given item in the slice
// Count returns the number of occurrences of the given item in the slice.
// Play: https://go.dev/play/p/Mj4oiEnQvRJ
func Count[T comparable](slice []T, item T) int {
count := 0
@@ -235,7 +253,8 @@ func Count[T comparable](slice []T, item T) int {
return count
}
// CountBy iterates over elements of slice with predicate function, returns the number of all matched elements
// CountBy iterates over elements of slice with predicate function, returns the number of all matched elements.
// Play: https://go.dev/play/p/tHOccTMDZCC
func CountBy[T any](slice []T, predicate func(index int, item T) bool) int {
count := 0
@@ -248,7 +267,8 @@ func CountBy[T any](slice []T, predicate func(index int, item T) bool) int {
return count
}
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices.
// Play: https://go.dev/play/p/QVkPxzPR0iA
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) {
if len(slice) == 0 {
return make([]T, 0), make([]T, 0)
@@ -270,6 +290,7 @@ func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
}
// GroupWith return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
// Play: https://go.dev/play/p/ApCvMNTLO8a
func GroupWith[T any, U comparable](slice []T, iteratee func(item T) U) map[U][]T {
result := make(map[U][]T)
@@ -285,7 +306,8 @@ func GroupWith[T any, U comparable](slice []T, iteratee func(item T) U) map[U][]
}
// Find iterates over elements of slice, returning the first one that passes a truth test on predicate function.
// If return T is nil then no items matched the predicate func
// If return T is nil then no items matched the predicate func.
// Play: https://go.dev/play/p/CBKeBoHVLgq
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
index := -1
@@ -303,8 +325,10 @@ func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
return &slice[index], true
}
// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on predicate function.
// If return T is nil then no items matched the predicate func
// FindLast iterates over elements of slice from end to begin,
// return the first one that passes a truth test on predicate function.
// If return T is nil then no items matched the predicate func.
// Play: https://go.dev/play/p/FFDPV_j7URd
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
index := -1
@@ -322,7 +346,8 @@ func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, boo
return &slice[index], true
}
// Flatten flattens slice with one level
// Flatten flattens slice with one level.
// Play: https://go.dev/play/p/hYa3cBEevtm
func Flatten(slice any) any {
sv := sliceValue(slice)
@@ -349,7 +374,8 @@ func Flatten(slice any) any {
return result.Interface()
}
// FlattenDeep flattens slice recursive
// FlattenDeep flattens slice recursive.
// Play: https://go.dev/play/p/yjYNHPyCFaF
func FlattenDeep(slice any) any {
sv := sliceValue(slice)
st := sliceElemType(sv.Type())
@@ -376,7 +402,8 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
return result
}
// ForEach iterates over elements of slice and invokes function for each element
// ForEach iterates over elements of slice and invokes function for each element.
// Play: https://go.dev/play/p/DrPaa4YsHRF
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
for i, v := range slice {
iteratee(i, v)
@@ -384,6 +411,7 @@ func ForEach[T any](slice []T, iteratee func(index int, item T)) {
}
// Map creates an slice of values by running each element of slice thru iteratee function.
// Play: https://go.dev/play/p/biaTefqPquw
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
result := make([]U, len(slice), cap(slice))
@@ -395,6 +423,7 @@ func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
}
// Reduce creates an slice of values by running each element of slice thru iteratee function.
// Play: https://go.dev/play/p/_RfXJJWIsIm
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
if len(slice) == 0 {
return initial
@@ -412,7 +441,8 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
return result
}
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
// Play: https://go.dev/play/p/P5mZp7IhOFo
func Replace[T comparable](slice []T, old T, new T, n int) []T {
result := make([]T, len(slice))
copy(result, slice)
@@ -428,11 +458,13 @@ func Replace[T comparable](slice []T, old T, new T, n int) []T {
}
// ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new.
// Play: https://go.dev/play/p/CzqXMsuYUrx
func ReplaceAll[T comparable](slice []T, old T, new T) []T {
return Replace(slice, old, new, -1)
}
// Repeat creates a slice with length n whose elements are param `item`.
// Play: https://go.dev/play/p/1CbOmtgILUU
func Repeat[T any](item T, n int) []T {
result := make([]T, n)
@@ -444,7 +476,8 @@ func Repeat[T any](item T, n int) []T {
}
// InterfaceSlice convert param to slice of interface.
// This function is deprecated, use generics feature of go1.18+ for replacement
// This function is deprecated, use generics feature of go1.18+ for replacement.
// Play: https://go.dev/play/p/FdQXF0Vvqs-
func InterfaceSlice(slice any) []any {
sv := sliceValue(slice)
if sv.IsNil() {
@@ -460,7 +493,8 @@ func InterfaceSlice(slice any) []any {
}
// StringSlice convert param to slice of string.
// This function is deprecated, use generics feature of go1.18+ for replacement
// This function is deprecated, use generics feature of go1.18+ for replacement.
// Play: https://go.dev/play/p/W0TZDWCPFcI
func StringSlice(slice any) []string {
v := sliceValue(slice)
@@ -477,7 +511,8 @@ func StringSlice(slice any) []string {
}
// IntSlice convert param to slice of int.
// This function is deprecated, use generics feature of go1.18+ for replacement
// This function is deprecated, use generics feature of go1.18+ for replacement.
// Play: https://go.dev/play/p/UQDj-on9TGN
func IntSlice(slice any) []int {
sv := sliceValue(slice)
@@ -494,6 +529,7 @@ func IntSlice(slice any) []int {
}
// DeleteAt delete the element of slice from start index to end index - 1.
// Play: https://go.dev/play/p/pJ-d6MUWcvK
func DeleteAt[T any](slice []T, start int, end ...int) []T {
size := len(slice)
@@ -523,7 +559,8 @@ func DeleteAt[T any](slice []T, start int, end ...int) []T {
return slice
}
// Drop creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0
// Drop creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0.
// Play: https://go.dev/play/p/pJ-d6MUWcvK
func Drop[T any](slice []T, n int) []T {
size := len(slice)
@@ -543,6 +580,7 @@ func Drop[T any](slice []T, n int) []T {
}
// InsertAt insert the value or other slice into slice at index.
// Play: https://go.dev/play/p/hMLNxPEGJVE
func InsertAt[T any](slice []T, index int, value any) []T {
size := len(slice)
@@ -564,6 +602,7 @@ func InsertAt[T any](slice []T, index int, value any) []T {
}
// UpdateAt update the slice element at index.
// Play: https://go.dev/play/p/f3mh2KloWVm
func UpdateAt[T any](slice []T, index int, value T) []T {
size := len(slice)
@@ -576,6 +615,7 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
}
// Unique remove duplicate elements in slice.
// Play: https://go.dev/play/p/AXw0R3ZTE6a
func Unique[T comparable](slice []T) []T {
result := []T{}
@@ -597,6 +637,7 @@ func Unique[T comparable](slice []T) []T {
}
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
// Play: https://go.dev/play/p/UR323iZLDpv
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
result := []T{}
@@ -609,6 +650,7 @@ func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
}
// Union creates a slice of unique elements, in order, from all given slices.
// Play: https://go.dev/play/p/hfXV1iRIZOf
func Union[T comparable](slices ...[]T) []T {
result := []T{}
contain := map[T]struct{}{}
@@ -625,7 +667,8 @@ func Union[T comparable](slices ...[]T) []T {
return result
}
// UnionBy is like Union, what's more it accepts iteratee which is invoked for each element of each slice
// UnionBy is like Union, what's more it accepts iteratee which is invoked for each element of each slice.
// Play: https://go.dev/play/p/HGKHfxKQsFi
func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T {
result := []T{}
contain := map[V]struct{}{}
@@ -643,7 +686,8 @@ func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T {
return result
}
// Merge all given slices into one slice
// Merge all given slices into one slice.
// Play: https://go.dev/play/p/lbjFp784r9N
func Merge[T any](slices ...[]T) []T {
result := make([]T, 0)
@@ -655,6 +699,7 @@ func Merge[T any](slices ...[]T) []T {
}
// Intersection creates a slice of unique elements that included by all slices.
// Play: https://go.dev/play/p/anJXfB5wq_t
func Intersection[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return []T{}
@@ -691,7 +736,8 @@ func Intersection[T comparable](slices ...[]T) []T {
return result
}
// SymmetricDifference oppoiste operation of intersection function
// SymmetricDifference oppoiste operation of intersection function.
// Play: https://go.dev/play/p/h42nJX5xMln
func SymmetricDifference[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return []T{}
@@ -717,25 +763,29 @@ func SymmetricDifference[T comparable](slices ...[]T) []T {
return Unique(result)
}
// Reverse return slice of element order is reversed to the given slice
// Reverse return slice of element order is reversed to the given slice.
// Play: https://go.dev/play/p/8uI8f1lwNrQ
func Reverse[T any](slice []T) {
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
slice[i], slice[j] = slice[j], slice[i]
}
}
// Shuffle creates an slice of shuffled values
// Shuffle the slice.
// Play: https://go.dev/play/p/YHvhnWGU3Ge
func Shuffle[T any](slice []T) []T {
result := make([]T, len(slice))
for i, v := range rand.Perm(len(slice)) {
result[i] = slice[v]
}
rand.Seed(time.Now().UnixNano())
return result
rand.Shuffle(len(slice), func(i, j int) {
slice[i], slice[j] = slice[j], slice[i]
})
return slice
}
// Sort sorts a slice of any ordered type(number or string), use quick sort algrithm.
// default sort order is ascending (asc), if want descending order, set param `sortOrder` to `desc`
// default sort order is ascending (asc), if want descending order, set param `sortOrder` to `desc`.
// Play: https://go.dev/play/p/V9AVjzf_4Fk
func Sort[T constraints.Ordered](slice []T, sortOrder ...string) {
if len(sortOrder) > 0 && sortOrder[0] == "desc" {
quickSort(slice, 0, len(slice)-1, "desc")
@@ -745,7 +795,8 @@ func Sort[T constraints.Ordered](slice []T, sortOrder ...string) {
}
// SortBy sorts the slice in ascending order as determined by the less function.
// This sort is not guaranteed to be stable
// This sort is not guaranteed to be stable.
// Play: https://go.dev/play/p/DAhLQSZEumm
func SortBy[T any](slice []T, less func(a, b T) bool) {
quickSortBy(slice, 0, len(slice)-1, less)
}
@@ -753,7 +804,8 @@ func SortBy[T any](slice []T, less func(a, b T) bool) {
// SortByField return sorted slice by field
// slice element should be struct, field type should be int, uint, string, or bool
// default sortType is ascending (asc), if descending order, set sortType to desc
// This function is deprecated, use Sort and SortBy for replacement
// This function is deprecated, use Sort and SortBy for replacement.
// Play: https://go.dev/play/p/fU1prOBP9p1
func SortByField(slice any, field string, sortType ...string) error {
sv := sliceValue(slice)
t := sv.Type().Elem()
@@ -823,7 +875,8 @@ func SortByField(slice any, field string, sortType ...string) error {
return nil
}
// Without creates a slice excluding all given items
// Without creates a slice excluding all given items.
// Play: https://go.dev/play/p/bwhEXEypThg
func Without[T comparable](slice []T, items ...T) []T {
if len(items) == 0 || len(slice) == 0 {
return slice
@@ -840,6 +893,7 @@ func Without[T comparable](slice []T, items ...T) []T {
}
// IndexOf returns the index at which the first occurrence of an item is found in a slice or return -1 if the item cannot be found.
// Play: https://go.dev/play/p/MRN1f0FpABb
func IndexOf[T comparable](arr []T, val T) int {
limit := 10
// gets the hash value of the array as the key of the hash table.
@@ -881,6 +935,7 @@ func IndexOf[T comparable](arr []T, val T) int {
}
// LastIndexOf returns the index at which the last occurrence of the item is found in a slice or return -1 if the then cannot be found.
// Play: https://go.dev/play/p/DokM4cf1IKH
func LastIndexOf[T comparable](slice []T, item T) int {
for i := len(slice) - 1; i > 0; i-- {
if item == slice[i] {
@@ -891,7 +946,8 @@ func LastIndexOf[T comparable](slice []T, item T) int {
return -1
}
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation.
// Play: https://go.dev/play/p/gx4tr6_VXSF
func ToSlicePointer[T any](items ...T) []*T {
result := make([]*T, len(items))
for i := range items {
@@ -901,7 +957,8 @@ func ToSlicePointer[T any](items ...T) []*T {
return result
}
// ToSlice returns a slices of a variable parameter transformation
// ToSlice returns a slices of a variable parameter transformation.
// Play: https://go.dev/play/p/YzbzVq5kscN
func ToSlice[T any](items ...T) []T {
result := make([]T, len(items))
copy(result, items)
@@ -909,7 +966,8 @@ func ToSlice[T any](items ...T) []T {
return result
}
// AppendIfAbsent only absent append the item
// AppendIfAbsent only absent append the item.
// Play: https://go.dev/play/p/KcC1QXQ-RkL
func AppendIfAbsent[T comparable](slice []T, item T) []T {
if !Contain(slice, item) {
slice = append(slice, item)
@@ -917,7 +975,8 @@ func AppendIfAbsent[T comparable](slice []T, item T) []T {
return slice
}
// KeyBy converts a slice to a map based on a callback function
// KeyBy converts a slice to a map based on a callback function.
// Play: https://go.dev/play/p/uXod2LWD1Kg
func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T {
result := make(map[U]T, len(slice))

761
slice/slice_example_test.go Normal file
View File

@@ -0,0 +1,761 @@
package slice
import (
"fmt"
"math"
"reflect"
)
func ExampleContain() {
result1 := Contain([]string{"a", "b", "c"}, "a")
result2 := Contain([]int{1, 2, 3}, 4)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleContainSubSlice() {
result1 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "b"})
result2 := ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "d"})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleChunk() {
arr := []string{"a", "b", "c", "d", "e"}
result1 := Chunk(arr, 1)
result2 := Chunk(arr, 2)
result3 := Chunk(arr, 3)
result4 := Chunk(arr, 4)
result5 := Chunk(arr, 5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// [[a] [b] [c] [d] [e]]
// [[a b] [c d] [e]]
// [[a b c] [d e]]
// [[a b c d] [e]]
// [[a b c d e]]
}
func ExampleCompact() {
result1 := Compact([]int{0})
result2 := Compact([]int{0, 1, 2, 3})
result3 := Compact([]string{"", "a", "b", "0"})
result4 := Compact([]bool{false, true, true})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// []
// [1 2 3]
// [a b 0]
// [true true]
}
func ExampleConcat() {
result1 := Concat([]int{1, 2}, []int{3, 4})
result2 := Concat([]string{"a", "b"}, []string{"c"}, []string{"d"})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [1 2 3 4]
// [a b c d]
}
func ExampleDifference() {
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{4, 5, 6}
result := Difference(slice1, slice2)
fmt.Println(result)
// Output:
// [1 2 3]
}
func ExampleDifferenceBy() {
slice1 := []int{1, 2, 3, 4, 5} //after add one: 2 3 4 5 6
slice2 := []int{3, 4, 5} //after add one: 4 5 6
addOne := func(i int, v int) int {
return v + 1
}
result := DifferenceBy(slice1, slice2, addOne)
fmt.Println(result)
// Output:
// [1 2]
}
func ExampleDifferenceWith() {
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
result := DifferenceWith(slice1, slice2, isDouble)
fmt.Println(result)
// Output:
// [1 5]
}
func ExampleEqual() {
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
slice3 := []int{1, 3, 2}
result1 := Equal(slice1, slice2)
result2 := Equal(slice1, slice3)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleEqualWith() {
slice1 := []int{1, 2, 3}
slice2 := []int{2, 4, 6}
isDouble := func(a, b int) bool {
return b == a*2
}
result := EqualWith(slice1, slice2, isDouble)
fmt.Println(result)
// Output:
// true
}
func ExampleEvery() {
nums := []int{1, 2, 3, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result := Every(nums, isEven)
fmt.Println(result)
// Output:
// false
}
func ExampleNone() {
nums := []int{1, 3, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result := None(nums, isEven)
fmt.Println(result)
// Output:
// true
}
func ExampleSome() {
nums := []int{1, 2, 3, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result := Some(nums, isEven)
fmt.Println(result)
// Output:
// true
}
func ExampleFilter() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result := Filter(nums, isEven)
fmt.Println(result)
// Output:
// [2 4]
}
func ExampleCount() {
nums := []int{1, 2, 3, 3, 4}
result1 := Count(nums, 1)
result2 := Count(nums, 3)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 2
}
func ExampleCountBy() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result := CountBy(nums, isEven)
fmt.Println(result)
// Output:
// 2
}
func ExampleGroupBy() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
even, odd := GroupBy(nums, isEven)
fmt.Println(even)
fmt.Println(odd)
// Output:
// [2 4]
// [1 3 5]
}
func ExampleGroupWith() {
nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
result := GroupWith(nums, floor) //map[float64][]float64
fmt.Println(result)
// Output:
// map[4:[4.2] 6:[6.1 6.3]]
}
func ExampleFind() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := Find(nums, isEven)
fmt.Println(*result)
fmt.Println(ok)
// Output:
// 2
// true
}
func ExampleFindLast() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := FindLast(nums, isEven)
fmt.Println(*result)
fmt.Println(ok)
// Output:
// 4
// true
}
func ExampleFlatten() {
arrs := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
result := Flatten(arrs)
fmt.Println(result)
// Output:
// [[a b] [c d]]
}
func ExampleFlattenDeep() {
arrs := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
result := FlattenDeep(arrs)
fmt.Println(result)
// Output:
// [a b c d]
}
func ExampleForEach() {
nums := []int{1, 2, 3}
var result []int
addOne := func(_ int, v int) {
result = append(result, v+1)
}
ForEach(nums, addOne)
fmt.Println(result)
// Output:
// [2 3 4]
}
func ExampleMap() {
nums := []int{1, 2, 3}
addOne := func(_ int, v int) int {
return v + 1
}
result := Map(nums, addOne)
fmt.Println(result)
// Output:
// [2 3 4]
}
func ExampleReduce() {
nums := []int{1, 2, 3}
sum := func(_ int, v1, v2 int) int {
return v1 + v2
}
result := Reduce(nums, sum, 0)
fmt.Println(result)
// Output:
// 6
}
func ExampleReplace() {
strs := []string{"a", "b", "c", "a"}
result1 := Replace(strs, "a", "x", 0)
result2 := Replace(strs, "a", "x", 1)
result3 := Replace(strs, "a", "x", 2)
result4 := Replace(strs, "a", "x", 3)
result5 := Replace(strs, "a", "x", -1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// [a b c a]
// [x b c a]
// [x b c x]
// [x b c x]
// [x b c x]
}
func ExampleReplaceAll() {
result := ReplaceAll([]string{"a", "b", "c", "a"}, "a", "x")
fmt.Println(result)
// Output:
// [x b c x]
}
func ExampleRepeat() {
result := Repeat("a", 3)
fmt.Println(result)
// Output:
// [a a a]
}
func ExampleInterfaceSlice() {
strs := []string{"a", "b", "c"}
result := InterfaceSlice(strs) //[]interface{}{"a", "b", "c"}
fmt.Println(result)
// Output:
// [a b c]
}
func ExampleStringSlice() {
strs := []interface{}{"a", "b", "c"}
result := StringSlice(strs) //[]string{"a", "b", "c"}
fmt.Println(result)
// Output:
// [a b c]
}
func ExampleIntSlice() {
nums := []interface{}{1, 2, 3}
result := IntSlice(nums) //[]int{1, 2, 3}
fmt.Println(result)
// Output:
// [1 2 3]
}
func ExampleDeleteAt() {
result1 := DeleteAt([]string{"a", "b", "c"}, -1)
result2 := DeleteAt([]string{"a", "b", "c"}, 0)
result3 := DeleteAt([]string{"a", "b", "c"}, 0, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// [a b c]
// [b c]
// [c]
}
func ExampleDrop() {
result1 := Drop([]string{"a", "b", "c"}, 0)
result2 := Drop([]string{"a", "b", "c"}, 1)
result3 := Drop([]string{"a", "b", "c"}, -1)
result4 := Drop([]string{"a", "b", "c"}, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// [a b c]
// [b c]
// [a b]
// []
}
func ExampleInsertAt() {
result1 := InsertAt([]string{"a", "b", "c"}, 0, "1")
result2 := InsertAt([]string{"a", "b", "c"}, 1, "1")
result3 := InsertAt([]string{"a", "b", "c"}, 2, "1")
result4 := InsertAt([]string{"a", "b", "c"}, 3, "1")
result5 := InsertAt([]string{"a", "b", "c"}, 0, []string{"1", "2", "3"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// [1 a b c]
// [a 1 b c]
// [a b 1 c]
// [a b c 1]
// [1 2 3 a b c]
}
func ExampleUpdateAt() {
result1 := UpdateAt([]string{"a", "b", "c"}, -1, "1")
result2 := UpdateAt([]string{"a", "b", "c"}, 0, "1")
result3 := UpdateAt([]string{"a", "b", "c"}, 1, "1")
result4 := UpdateAt([]string{"a", "b", "c"}, 2, "1")
result5 := UpdateAt([]string{"a", "b", "c"}, 3, "1")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// [a b c]
// [1 b c]
// [a 1 c]
// [a b 1]
// [a b c]
}
func ExampleUnique() {
result := Unique([]string{"a", "a", "b"})
fmt.Println(result)
// Output:
// [a b]
}
func ExampleUniqueBy() {
nums := []int{1, 2, 3, 4, 5, 6}
result := UniqueBy(nums, func(val int) int {
return val % 3
})
fmt.Println(result)
// Output:
// [1 2 0]
}
func ExampleUnion() {
nums1 := []int{1, 3, 4, 6}
nums2 := []int{1, 2, 5, 6}
result := Union(nums1, nums2)
fmt.Println(result)
// Output:
// [1 3 4 6 2 5]
}
func ExampleUnionBy() {
nums := []int{1, 2, 3, 4}
divideTwo := func(n int) int {
return n / 2
}
result := UnionBy(divideTwo, nums)
fmt.Println(result)
// Output:
// [1 2 4]
}
func ExampleMerge() {
nums1 := []int{1, 2, 3}
nums2 := []int{3, 4}
result := Merge(nums1, nums2)
fmt.Println(result)
// Output:
// [1 2 3 3 4]
}
func ExampleIntersection() {
nums1 := []int{1, 2, 3}
nums2 := []int{2, 3, 4}
result := Intersection(nums1, nums2)
fmt.Println(result)
// Output:
// [2 3]
}
func ExampleSymmetricDifference() {
nums1 := []int{1, 2, 3}
nums2 := []int{1, 2, 4}
result := SymmetricDifference(nums1, nums2)
fmt.Println(result)
// Output:
// [3 4]
}
func ExampleReverse() {
strs := []string{"a", "b", "c", "d"}
Reverse(strs)
fmt.Println(strs)
// Output:
// [d c b a]
}
func ExampleSort() {
nums := []int{1, 4, 3, 2, 5}
Sort(nums)
fmt.Println(nums)
// Output:
// [1 2 3 4 5]
}
func ExampleSortBy() {
type User struct {
Name string
Age uint
}
users := []User{
{Name: "a", Age: 21},
{Name: "b", Age: 15},
{Name: "c", Age: 100}}
SortBy(users, func(a, b User) bool {
return a.Age < b.Age
})
fmt.Println(users)
// Output:
// [{b 15} {a 21} {c 100}]
}
func ExampleSortByField() {
type User struct {
Name string
Age uint
}
users := []User{
{Name: "a", Age: 21},
{Name: "b", Age: 15},
{Name: "c", Age: 100}}
err := SortByField(users, "Age", "desc")
if err != nil {
return
}
fmt.Println(users)
// Output:
// [{c 100} {a 21} {b 15}]
}
func ExampleWithout() {
result := Without([]int{1, 2, 3, 4}, 1, 2)
fmt.Println(result)
// Output:
// [3 4]
}
func ExampleIndexOf() {
strs := []string{"a", "a", "b", "c"}
result1 := IndexOf(strs, "a")
result2 := IndexOf(strs, "d")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// -1
}
func ExampleLastIndexOf() {
strs := []string{"a", "a", "b", "c"}
result1 := LastIndexOf(strs, "a")
result2 := LastIndexOf(strs, "d")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// -1
}
func ExampleToSlice() {
result := ToSlice("a", "b", "c")
fmt.Println(result)
// Output:
// [a b c]
}
func ExampleToSlicePointer() {
str1 := "a"
str2 := "b"
result := ToSlicePointer(str1, str2)
expect := []*string{&str1, &str2}
isEqual := reflect.DeepEqual(result, expect)
fmt.Println(isEqual)
// Output:
// true
}
func ExampleAppendIfAbsent() {
result1 := AppendIfAbsent([]string{"a", "b"}, "b")
result2 := AppendIfAbsent([]string{"a", "b"}, "c")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b]
// [a b c]
}
func ExampleKeyBy() {
result := KeyBy([]string{"a", "ab", "abc"}, func(str string) int {
return len(str)
})
fmt.Println(result)
// Output:
// map[1:a 2:ab 3:abc]
}

View File

@@ -257,7 +257,7 @@ func TestFlatten(t *testing.T) {
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
expected := [][]string{{"a", "b"}, {"c", "d"}}
assert := internal.NewAssert(t, "TestFlattenDeep")
assert := internal.NewAssert(t, "TestFlatten")
assert.Equal(expected, Flatten(input))
}

View File

@@ -9,9 +9,8 @@ import (
"unicode/utf8"
)
// CamelCase covert string to camelCase string.
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo11Bar"
// CamelCase coverts string to camelCase string. Non letters and numbers will be ignored.
// Play: https://go.dev/play/p/9eXP3tn2tUy
func CamelCase(s string) string {
var builder strings.Builder
@@ -28,6 +27,7 @@ func CamelCase(s string) string {
}
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
// Play: https://go.dev/play/p/2OAjgbmAqHZ
func Capitalize(s string) string {
result := make([]rune, len(s))
for i, v := range s {
@@ -42,6 +42,7 @@ func Capitalize(s string) string {
}
// UpperFirst converts the first character of string to upper case.
// Play: https://go.dev/play/p/sBbBxRbs8MM
func UpperFirst(s string) string {
if len(s) == 0 {
return ""
@@ -54,6 +55,7 @@ func UpperFirst(s string) string {
}
// LowerFirst converts the first character of string to lower case.
// Play: https://go.dev/play/p/CbzAyZmtJwL
func LowerFirst(s string) string {
if len(s) == 0 {
return ""
@@ -67,6 +69,7 @@ func LowerFirst(s string) string {
// PadEnd pads string on the right side if it's shorter than size.
// Padding characters are truncated if they exceed size.
// Play: https://go.dev/play/p/9xP8rN0vz--
func PadEnd(source string, size int, padStr string) string {
len1 := len(source)
len2 := len(padStr)
@@ -86,6 +89,7 @@ func PadEnd(source string, size int, padStr string) string {
// PadStart pads string on the left side if it's shorter than size.
// Padding characters are truncated if they exceed size.
// Play: https://go.dev/play/p/xpTfzArDfvT
func PadStart(source string, size int, padStr string) string {
len1 := len(source)
len2 := len(padStr)
@@ -103,39 +107,36 @@ func PadStart(source string, size int, padStr string) string {
return fill[0:size-len1] + source
}
// KebabCase covert string to kebab-case
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo-1-1-bar"
// KebabCase coverts string to kebab-case, non letters and numbers will be ignored.
// Play: https://go.dev/play/p/dcZM9Oahw-Y
func KebabCase(s string) string {
result := splitIntoStrings(s, false)
return strings.Join(result, "-")
}
// UpperKebabCase covert string to upper KEBAB-CASE
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "FOO-1-1-BAR"
// UpperKebabCase coverts string to upper KEBAB-CASE, non letters and numbers will be ignored
// Play: https://go.dev/play/p/zDyKNneyQXk
func UpperKebabCase(s string) string {
result := splitIntoStrings(s, true)
return strings.Join(result, "-")
}
// SnakeCase covert string to snake_case
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo_1_1_bar"
// SnakeCase coverts string to snake_case, non letters and numbers will be ignored
// Play: https://go.dev/play/p/tgzQG11qBuN
func SnakeCase(s string) string {
result := splitIntoStrings(s, false)
return strings.Join(result, "_")
}
// UpperSnakeCase covert string to upper SNAKE_CASE
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "FOO_1_1_BAR"
// UpperSnakeCase coverts string to upper SNAKE_CASE, non letters and numbers will be ignored
// Play: https://go.dev/play/p/4COPHpnLx38
func UpperSnakeCase(s string) string {
result := splitIntoStrings(s, true)
return strings.Join(result, "_")
}
// Before create substring in source string before position when char first appear
// Before returns the substring of the source string up to the first occurrence of the specified string.
// Play: https://go.dev/play/p/JAWTZDS4F5w
func Before(s, char string) string {
if s == "" || char == "" {
return s
@@ -144,7 +145,8 @@ func Before(s, char string) string {
return s[0:i]
}
// BeforeLast create substring in source string before position when char last appear
// BeforeLast returns the substring of the source string up to the last occurrence of the specified string.
// Play: https://go.dev/play/p/pJfXXAoG_Te
func BeforeLast(s, char string) string {
if s == "" || char == "" {
return s
@@ -153,7 +155,8 @@ func BeforeLast(s, char string) string {
return s[0:i]
}
// After create substring in source string after position when char first appear
// After returns the substring after the first occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/RbCOQqCDA7m
func After(s, char string) string {
if s == "" || char == "" {
return s
@@ -162,7 +165,8 @@ func After(s, char string) string {
return s[i+len(char):]
}
// AfterLast create substring in source string after position when char last appear
// AfterLast returns the substring after the last occurrence of a specified string in the source string.
// Play: https://go.dev/play/p/1TegARrb8Yn
func AfterLast(s, char string) string {
if s == "" || char == "" {
return s
@@ -172,6 +176,7 @@ func AfterLast(s, char string) string {
}
// IsString check if the value data type is string or not.
// Play: https://go.dev/play/p/IOgq7oF9ERm
func IsString(v any) bool {
if v == nil {
return false
@@ -184,7 +189,8 @@ func IsString(v any) bool {
}
}
// Reverse return string whose char order is reversed to the given string
// Reverse returns string whose char order is reversed to the given string.
// Play: https://go.dev/play/p/adfwalJiecD
func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
@@ -193,7 +199,8 @@ func Reverse(s string) string {
return string(r)
}
// Wrap a string with another string.
// Wrap a string with given string.
// Play: https://go.dev/play/p/KoZOlZDDt9y
func Wrap(str string, wrapWith string) string {
if str == "" || wrapWith == "" {
return str
@@ -206,7 +213,8 @@ func Wrap(str string, wrapWith string) string {
return sb.String()
}
// Unwrap a given string from anther string. will change str value
// Unwrap a given string from anther string. will change source string.
// Play: https://go.dev/play/p/Ec2q4BzCpG-
func Unwrap(str string, wrapToken string) string {
if str == "" || wrapToken == "" {
return str
@@ -224,7 +232,8 @@ func Unwrap(str string, wrapToken string) string {
return str
}
// SplitEx split a given string whether the result contains empty string
// SplitEx split a given string which can control the result slice contains empty string or not.
// Play: https://go.dev/play/p/Us-ySSbWh-3
func SplitEx(s, sep string, removeEmptyString bool) []string {
if sep == "" {
return []string{}
@@ -272,3 +281,27 @@ func SplitEx(s, sep string, removeEmptyString bool) []string {
return ret
}
// Substring returns a substring of the specified length starting at the specified offset position.
func Substring(s string, offset int, length uint) string {
rs := []rune(s)
size := len(rs)
if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
}
if offset > size {
return ""
}
if length > uint(size)-uint(offset) {
length = uint(size - offset)
}
str := string(rs[offset : offset+int(length)])
return strings.Replace(str, "\x00", "", -1)
}

View File

@@ -0,0 +1,363 @@
package strutil
import (
"fmt"
)
func ExampleAfter() {
result1 := After("foo", "")
result2 := After("foo", "foo")
result3 := After("foo/bar", "foo")
result4 := After("foo/bar", "/")
result5 := After("foo/bar/baz", "/")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// foo
//
// /bar
// bar
// bar/baz
}
func ExampleAfterLast() {
result1 := AfterLast("foo", "")
result2 := AfterLast("foo", "foo")
result3 := AfterLast("foo/bar", "/")
result4 := AfterLast("foo/bar/baz", "/")
result5 := AfterLast("foo/bar/foo/baz", "foo")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// foo
//
// bar
// baz
// /baz
}
func ExampleBefore() {
result1 := Before("foo", "")
result2 := Before("foo", "foo")
result3 := Before("foo/bar", "/")
result4 := Before("foo/bar/baz", "/")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// foo
//
// foo
// foo
}
func ExampleBeforeLast() {
result1 := BeforeLast("foo", "")
result2 := BeforeLast("foo", "foo")
result3 := BeforeLast("foo/bar", "/")
result4 := BeforeLast("foo/bar/baz", "/")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// foo
//
// foo
// foo/bar
}
func ExampleCamelCase() {
strings := []string{"", "foobar", "&FOO:BAR$BAZ", "$foo%", "Foo-#1😄$_%^&*(1bar"}
for _, v := range strings {
s := CamelCase(v)
fmt.Println(s)
}
// Output:
//
// foobar
// fooBarBaz
// foo
// foo11Bar
}
func ExampleCapitalize() {
strings := []string{"", "Foo", "_foo", "fooBar", "foo-bar"}
for _, v := range strings {
s := Capitalize(v)
fmt.Println(s)
}
// Output:
//
// Foo
// _foo
// Foobar
// Foo-bar
}
func ExampleIsString() {
result1 := IsString("")
result2 := IsString("a")
result3 := IsString(1)
result4 := IsString(true)
result5 := IsString([]string{"a"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// true
// true
// false
// false
// false
}
func ExampleKebabCase() {
strings := []string{"", "foo-bar", "Foo Bar-", "FOOBAR", "Foo-#1😄$_%^&*(1bar"}
for _, v := range strings {
s := KebabCase(v)
fmt.Println(s)
}
// Output:
//
// foo-bar
// foo-bar
// foobar
// foo-1-1-bar
}
func ExampleUpperKebabCase() {
strings := []string{"", "foo-bar", "Foo Bar-", "FooBAR", "Foo-#1😄$_%^&*(1bar"}
for _, v := range strings {
s := UpperKebabCase(v)
fmt.Println(s)
}
// Output:
//
// FOO-BAR
// FOO-BAR
// FOO-BAR
// FOO-1-1-BAR
}
func ExampleLowerFirst() {
strings := []string{"", "bar", "BAr", "Bar大"}
for _, v := range strings {
s := LowerFirst(v)
fmt.Println(s)
}
// Output:
//
// bar
// bAr
// bar大
}
func ExampleUpperFirst() {
strings := []string{"", "bar", "BAr", "bar大"}
for _, v := range strings {
s := UpperFirst(v)
fmt.Println(s)
}
// Output:
//
// Bar
// BAr
// Bar大
}
func ExamplePadEnd() {
result1 := PadEnd("foo", 1, "bar")
result2 := PadEnd("foo", 2, "bar")
result3 := PadEnd("foo", 3, "bar")
result4 := PadEnd("foo", 4, "bar")
result5 := PadEnd("foo", 5, "bar")
result6 := PadEnd("foo", 6, "bar")
result7 := PadEnd("foo", 7, "bar")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// foo
// foo
// foo
// foob
// fooba
// foobar
// foobarb
}
func ExamplePadStart() {
result1 := PadStart("foo", 1, "bar")
result2 := PadStart("foo", 2, "bar")
result3 := PadStart("foo", 3, "bar")
result4 := PadStart("foo", 4, "bar")
result5 := PadStart("foo", 5, "bar")
result6 := PadStart("foo", 6, "bar")
result7 := PadStart("foo", 7, "bar")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// foo
// foo
// foo
// bfoo
// bafoo
// barfoo
// barbfoo
}
func ExampleReverse() {
s := "foo"
rs := Reverse(s)
fmt.Println(s)
fmt.Println(rs)
// Output:
// foo
// oof
}
func ExampleSnakeCase() {
strings := []string{"", "foo-bar", "Foo Bar-", "FOOBAR", "Foo-#1😄$_%^&*(1bar"}
for _, v := range strings {
s := SnakeCase(v)
fmt.Println(s)
}
// Output:
//
// foo_bar
// foo_bar
// foobar
// foo_1_1_bar
}
func ExampleUpperSnakeCase() {
strings := []string{"", "foo-bar", "Foo Bar-", "FooBAR", "Foo-#1😄$_%^&*(1bar"}
for _, v := range strings {
s := UpperSnakeCase(v)
fmt.Println(s)
}
// Output:
//
// FOO_BAR
// FOO_BAR
// FOO_BAR
// FOO_1_1_BAR
}
func ExampleSplitEx() {
result1 := SplitEx(" a b c ", "", true)
result2 := SplitEx(" a b c ", " ", false)
result3 := SplitEx(" a b c ", " ", true)
result4 := SplitEx("a = b = c = ", " = ", false)
result5 := SplitEx("a = b = c = ", " = ", true)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// []
// [ a b c ]
// [a b c]
// [a b c ]
// [a b c]
}
func ExampleWrap() {
result1 := Wrap("foo", "")
result2 := Wrap("foo", "*")
result3 := Wrap("'foo'", "'")
result4 := Wrap("", "*")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// foo
// *foo*
// ''foo''
//
}
func ExampleUnwrap() {
result1 := Unwrap("foo", "")
result2 := Unwrap("*foo*", "*")
result3 := Unwrap("*foo", "*")
result4 := Unwrap("foo*", "*")
result5 := Unwrap("**foo**", "*")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// foo
// foo
// *foo
// foo*
// *foo*
}
func ExampleSubstring() {
result1 := Substring("abcde", 1, 3)
result2 := Substring("abcde", 1, 5)
result3 := Substring("abcde", -1, 3)
result4 := Substring("abcde", -2, 2)
result5 := Substring("abcde", -2, 3)
result6 := 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
// 你好
}

View File

@@ -196,6 +196,7 @@ func TestBefore(t *testing.T) {
assert := internal.NewAssert(t, "TestBefore")
assert.Equal("lancet", Before("lancet", ""))
assert.Equal("", Before("lancet", "lancet"))
assert.Equal("github.com", Before("github.com/test/lancet", "/"))
assert.Equal("github.com/", Before("github.com/test/lancet", "test"))
}
@@ -214,6 +215,7 @@ func TestAfter(t *testing.T) {
assert := internal.NewAssert(t, "TestAfter")
assert.Equal("lancet", After("lancet", ""))
assert.Equal("", After("lancet", "lancet"))
assert.Equal("test/lancet", After("github.com/test/lancet", "/"))
assert.Equal("/lancet", After("github.com/test/lancet", "test"))
}
@@ -282,6 +284,17 @@ func TestSplitEx(t *testing.T) {
assert.Equal([]string{"", "a", "b", "c", ""}, SplitEx(" a b c ", " ", false))
assert.Equal([]string{"a", "b", "c"}, SplitEx(" a b c ", " ", true))
assert.Equal([]string{" a", "b", "c", ""}, SplitEx(" a = b = c = ", " = ", false))
assert.Equal([]string{" a", "b", "c"}, SplitEx(" a = b = c = ", " = ", true))
assert.Equal([]string{"a", "b", "c", ""}, SplitEx("a = b = c = ", " = ", false))
assert.Equal([]string{"a", "b", "c"}, SplitEx("a = b = c = ", " = ", true))
}
func TestSubstring(t *testing.T) {
assert := internal.NewAssert(t, "TestSubstring")
assert.Equal("bcd", Substring("abcde", 1, 3))
assert.Equal("bcde", Substring("abcde", 1, 5))
assert.Equal("e", Substring("abcde", -1, 3))
assert.Equal("de", Substring("abcde", -2, 2))
assert.Equal("de", Substring("abcde", -2, 3))
assert.Equal("你好", Substring("你好,欢迎你", 0, 2))
}

View File

@@ -15,37 +15,44 @@ import (
"golang.org/x/text/encoding/simplifiedchinese"
)
// IsWindows check if current os is windows
// IsWindows check if current os is windows.
// Play: https://go.dev/play/p/XzJULbzmf9m
func IsWindows() bool {
return runtime.GOOS == "windows"
}
// IsLinux check if current os is linux
// IsLinux check if current os is linux.
// Play: https://go.dev/play/p/zIflQgZNuxD
func IsLinux() bool {
return runtime.GOOS == "linux"
}
// IsMac check if current os is macos
// IsMac check if current os is macos.
// Play: https://go.dev/play/p/Mg4Hjtyq7Zc
func IsMac() bool {
return runtime.GOOS == "darwin"
}
// GetOsEnv gets the value of the environment variable named by the key.
// Play: https://go.dev/play/p/D88OYVCyjO-
func GetOsEnv(key string) string {
return os.Getenv(key)
}
// SetOsEnv sets the value of the environment variable named by the key.
// Play: https://go.dev/play/p/D88OYVCyjO-
func SetOsEnv(key, value string) error {
return os.Setenv(key, value)
}
// RemoveOsEnv remove a single environment variable.
// Play: https://go.dev/play/p/fqyq4b3xUFQ
func RemoveOsEnv(key string) error {
return os.Unsetenv(key)
}
// CompareOsEnv gets env named by the key and compare it with comparedEnv
// CompareOsEnv gets env named by the key and compare it with comparedEnv.
// Play: https://go.dev/play/p/BciHrKYOHbp
func CompareOsEnv(key, comparedEnv string) bool {
env := GetOsEnv(key)
if env == "" {
@@ -58,6 +65,7 @@ func CompareOsEnv(key, comparedEnv string) bool {
// 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
// Play: https://go.dev/play/p/n-2fLyZef-4
func ExecCommand(command string) (stdout, stderr string, err error) {
var out bytes.Buffer
var errOut bytes.Buffer
@@ -109,8 +117,8 @@ func byteToString(data []byte, charset string) string {
return result
}
// GetOsBits get this system bits 32bit or 64bit
// return bit int (32/64)
// GetOsBits return current os bits (32 or 64).
// Play: https://go.dev/play/p/ml-_XH3gJbW
func GetOsBits() int {
return 32 << (^uint(0) >> 63)
}

76
system/os_example_test.go Normal file
View File

@@ -0,0 +1,76 @@
package system
import "fmt"
func ExampleSetOsEnv() {
ok := SetOsEnv("foo", "abc")
result := GetOsEnv("foo")
fmt.Println(ok)
fmt.Println(result)
// Output:
// <nil>
// abc
}
func ExampleGetOsEnv() {
ok := SetOsEnv("foo", "abc")
result := GetOsEnv("foo")
fmt.Println(ok)
fmt.Println(result)
// Output:
// <nil>
// abc
}
func ExampleRemoveOsEnv() {
ok1 := SetOsEnv("foo", "abc")
result1 := GetOsEnv("foo")
ok2 := RemoveOsEnv("foo")
result2 := GetOsEnv("foo")
fmt.Println(ok1)
fmt.Println(ok2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// <nil>
// <nil>
// abc
//
}
func ExampleCompareOsEnv() {
err := SetOsEnv("foo", "abc")
if err != nil {
return
}
result1 := CompareOsEnv("foo", "abc")
fmt.Println(result1)
// Output:
// true
}
func ExampleExecCommand() {
_, stderr, err := ExecCommand("ls")
// fmt.Println(stdout)
fmt.Println(stderr)
fmt.Println(err)
// Output:
//
// <nil>
}
func ExampleGetOsBits() {
osBits := GetOsBits()
fmt.Println(osBits)
// Output:
// 64
}

View File

@@ -30,12 +30,14 @@ var (
base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
)
// IsAlpha checks if the string contains only letters (a-zA-Z)
// IsAlpha checks if the string contains only letters (a-zA-Z).
// Play: https://go.dev/play/p/7Q5sGOz2izQ
func IsAlpha(str string) bool {
return alphaMatcher.MatchString(str)
}
// IsAllUpper check if the string is all upper case letters A-Z
// IsAllUpper check if the string is all upper case letters A-Z.
// Play: https://go.dev/play/p/ZHctgeK1n4Z
func IsAllUpper(str string) bool {
for _, r := range str {
if !unicode.IsUpper(r) {
@@ -45,7 +47,8 @@ func IsAllUpper(str string) bool {
return str != ""
}
// IsAllLower check if the string is all lower case letters a-z
// IsAllLower check if the string is all lower case letters a-z.
// Play: https://go.dev/play/p/GjqCnOfV6cM
func IsAllLower(str string) bool {
for _, r := range str {
if !unicode.IsLower(r) {
@@ -55,7 +58,8 @@ func IsAllLower(str string) bool {
return str != ""
}
// ContainUpper check if the string contain at least one upper case letter A-Z
// ContainUpper check if the string contain at least one upper case letter A-Z.
// Play: https://go.dev/play/p/CmWeBEk27-z
func ContainUpper(str string) bool {
for _, r := range str {
if unicode.IsUpper(r) && unicode.IsLetter(r) {
@@ -65,7 +69,8 @@ func ContainUpper(str string) bool {
return false
}
// ContainLower check if the string contain at least one lower case letter A-Z
// ContainLower check if the string contain at least one lower case letter a-z.
// Play: https://go.dev/play/p/Srqi1ItvnAA
func ContainLower(str string) bool {
for _, r := range str {
if unicode.IsLower(r) && unicode.IsLetter(r) {
@@ -75,40 +80,47 @@ func ContainLower(str string) bool {
return false
}
// ContainLetter check if the string contain at least one letter
// ContainLetter check if the string contain at least one letter.
// Play: https://go.dev/play/p/lqFD04Yyewp
func ContainLetter(str string) bool {
return letterRegexMatcher.MatchString(str)
}
// IsJSON checks if the string is valid JSON
// IsJSON checks if the string is valid JSON.
// Play: https://go.dev/play/p/sRS6c4K8jGk
func IsJSON(str string) bool {
var js json.RawMessage
return json.Unmarshal([]byte(str), &js) == nil
}
// IsNumberStr check if the string can convert to a number.
// Play: https://go.dev/play/p/LzaKocSV79u
func IsNumberStr(s string) bool {
return IsIntStr(s) || IsFloatStr(s)
}
// IsFloatStr check if the string can convert to a float.
// Play: https://go.dev/play/p/LOYwS_Oyl7U
func IsFloatStr(str string) bool {
_, e := strconv.ParseFloat(str, 64)
return e == nil
}
// IsIntStr check if the string can convert to a integer.
// Play: https://go.dev/play/p/jQRtFv-a0Rk
func IsIntStr(str string) bool {
return intStrMatcher.MatchString(str)
}
// IsIp check if the string is a ip address.
// Play: https://go.dev/play/p/FgcplDvmxoD
func IsIp(ipstr string) bool {
ip := net.ParseIP(ipstr)
return ip != nil
}
// IsIpV4 check if the string is a ipv4 address.
// Play: https://go.dev/play/p/zBGT99EjaIu
func IsIpV4(ipstr string) bool {
ip := net.ParseIP(ipstr)
if ip == nil {
@@ -118,6 +130,7 @@ func IsIpV4(ipstr string) bool {
}
// IsIpV6 check if the string is a ipv6 address.
// Play: https://go.dev/play/p/AHA0r0AzIdC
func IsIpV6(ipstr string) bool {
ip := net.ParseIP(ipstr)
if ip == nil {
@@ -127,6 +140,7 @@ func IsIpV6(ipstr string) bool {
}
// IsPort check if the string is a valid net port.
// Play:
func IsPort(str string) bool {
if i, err := strconv.ParseInt(str, 10, 64); err == nil && i > 0 && i < 65536 {
return true
@@ -135,6 +149,7 @@ func IsPort(str string) bool {
}
// IsUrl check if the string is url.
// Play: https://go.dev/play/p/pbJGa7F98Ka
func IsUrl(str string) bool {
if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
return false
@@ -154,59 +169,70 @@ func IsUrl(str string) bool {
}
// IsDns check if the string is dns.
// Play: https://go.dev/play/p/jlYApVLLGTZ
func IsDns(dns string) bool {
return dnsMatcher.MatchString(dns)
}
// IsEmail check if the string is a email address.
// Play: https://go.dev/play/p/Os9VaFlT33G
func IsEmail(email string) bool {
return emailMatcher.MatchString(email)
}
// IsChineseMobile check if the string is chinese mobile number.
// Play: https://go.dev/play/p/GPYUlGTOqe3
func IsChineseMobile(mobileNum string) bool {
return chineseMobileMatcher.MatchString(mobileNum)
}
// IsChineseIdNum check if the string is chinese id number.
// IsChineseIdNum check if the string is chinese id card.
// Play: https://go.dev/play/p/d8EWhl2UGDF
func IsChineseIdNum(id string) bool {
return chineseIdMatcher.MatchString(id)
}
// ContainChinese check if the string contain mandarin chinese.
// Play: https://go.dev/play/p/7DpU0uElYeM
func ContainChinese(s string) bool {
return chineseMatcher.MatchString(s)
}
// IsChinesePhone check if the string is chinese phone number.
// Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx
// Valid chinese phone is xxx-xxxxxxxx or xxxx-xxxxxxx.
// Play: https://go.dev/play/p/RUD_-7YZJ3I
func IsChinesePhone(phone string) bool {
return chinesePhoneMatcher.MatchString(phone)
}
// IsCreditCard check if the string is credit card.
// Play: https://go.dev/play/p/sNwwL6B0-v4
func IsCreditCard(creditCart string) bool {
return creditCardMatcher.MatchString(creditCart)
}
// IsBase64 check if the string is base64 string.
// Play: https://go.dev/play/p/sWHEySAt6hl
func IsBase64(base64 string) bool {
return base64Matcher.MatchString(base64)
}
// IsEmptyString check if the string is empty.
// Play: https://go.dev/play/p/dpzgUjFnBCX
func IsEmptyString(str string) bool {
return len(str) == 0
}
// IsRegexMatch check if the string match the regexp
// IsRegexMatch check if the string match the regexp.
// Play: https://go.dev/play/p/z_XeZo_litG
func IsRegexMatch(str, regex string) bool {
reg := regexp.MustCompile(regex)
return reg.MatchString(str)
}
// IsStrongPassword check if the string is strong password, if len(password) is less than the length param, return false
// Strong password: alpha(lower+upper) + number + special chars(!@#$%^&*()?><)
// Strong password: alpha(lower+upper) + number + special chars(!@#$%^&*()?><).
// Play: https://go.dev/play/p/QHdVcSQ3uDg
func IsStrongPassword(password string, length int) bool {
if len(password) < length {
return false
@@ -229,7 +255,8 @@ func IsStrongPassword(password string, length int) bool {
}
// IsWeakPassword check if the string is weak password
// Weak password: only letter or only number or letter + number
// Weak password: only letter or only number or letter + number.
// Play: https://go.dev/play/p/wqakscZH5gH
func IsWeakPassword(password string) bool {
var num, letter, special bool
for _, r := range password {
@@ -246,7 +273,8 @@ func IsWeakPassword(password string) bool {
return (num || letter) && !special
}
// IsZeroValue checks if value is a zero value
// IsZeroValue checks if value is a zero value.
// Play: https://go.dev/play/p/UMrwaDCi_t4
func IsZeroValue(value any) bool {
if value == nil {
return true
@@ -289,6 +317,7 @@ func IsZeroValue(value any) bool {
}
fmt.Println("data encoding is unknown")
**/
// Play: https://go.dev/play/p/E2nt3unlmzP
func IsGBK(data []byte) bool {
i := 0
for i < len(data) {

View File

@@ -0,0 +1,409 @@
package validator
import (
"fmt"
"golang.org/x/text/encoding/simplifiedchinese"
)
func ExampleContainChinese() {
result1 := ContainChinese("你好")
result2 := ContainChinese("你好hello")
result3 := ContainChinese("hello")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
func ExampleContainLetter() {
result1 := ContainLetter("你好")
result2 := ContainLetter("&@#$%^&*")
result3 := ContainLetter("ab1")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// false
// false
// true
}
func ExampleContainLower() {
result1 := ContainLower("abc")
result2 := ContainLower("aBC")
result3 := ContainLower("ABC")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
func ExampleContainUpper() {
result1 := ContainUpper("ABC")
result2 := ContainUpper("abC")
result3 := ContainUpper("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
func ExampleIsAlpha() {
result1 := IsAlpha("abc")
result2 := IsAlpha("ab1")
result3 := IsAlpha("")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// false
// false
}
func ExampleIsAllUpper() {
result1 := IsAllUpper("ABC")
result2 := IsAllUpper("ABc")
result3 := IsAllUpper("AB1")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// false
// false
}
func ExampleIsAllLower() {
result1 := IsAllLower("abc")
result2 := IsAllLower("abC")
result3 := IsAllLower("ab1")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// false
// false
}
func ExampleIsBase64() {
result1 := IsBase64("aGVsbG8=")
result2 := IsBase64("123456")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsChineseMobile() {
result1 := IsChineseMobile("13263527980")
result2 := IsChineseMobile("434324324")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsChineseIdNum() {
result1 := IsChineseIdNum("210911192105130715")
result2 := IsChineseIdNum("123456")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsChinesePhone() {
result1 := IsChinesePhone("010-32116675")
result2 := IsChinesePhone("123-87562")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsCreditCard() {
result1 := IsCreditCard("4111111111111111")
result2 := IsCreditCard("123456")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsDns() {
result1 := IsDns("abc.com")
result2 := IsDns("a.b.com")
result3 := IsDns("http://abc.com")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// false
// false
}
func ExampleIsUrl() {
result1 := IsUrl("abc.com")
result2 := IsUrl("http://abc.com")
result3 := IsUrl("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
func ExampleIsEmail() {
result1 := IsEmail("abc@xyz.com")
result2 := IsEmail("a.b@@com")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsEmptyString() {
result1 := IsEmptyString("")
result2 := IsEmptyString(" ")
result3 := IsEmptyString("\t")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// false
// false
}
func ExampleIsFloatStr() {
result1 := IsFloatStr("3.")
result2 := IsFloatStr("+3.")
result3 := IsFloatStr("12")
result4 := IsFloatStr("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
func ExampleIsNumberStr() {
result1 := IsNumberStr("3.")
result2 := IsNumberStr("+3.")
result3 := IsNumberStr("+3e2")
result4 := IsNumberStr("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
func ExampleIsIntStr() {
result1 := IsIntStr("+3")
result2 := IsIntStr("-3")
result3 := IsIntStr("3.")
result4 := IsIntStr("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// false
// false
}
func ExampleIsJSON() {
result1 := IsJSON("{}")
result2 := IsJSON("{\"name\": \"test\"}")
result3 := IsIntStr("")
result4 := IsIntStr("abc")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// false
// false
}
func ExampleIsRegexMatch() {
result1 := IsRegexMatch("abc", `^[a-zA-Z]+$`)
result2 := IsRegexMatch("ab1", `^[a-zA-Z]+$`)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsIp() {
result1 := IsIp("127.0.0.1")
result2 := IsIp("::0:0:0:0:0:0:1")
result3 := IsIp("127.0.0")
result4 := IsIp("::0:0:0:0:")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// false
// false
}
func ExampleIsIpV4() {
result1 := IsIpV4("127.0.0.1")
result2 := IsIpV4("::0:0:0:0:0:0:1")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsIpV6() {
result1 := IsIpV6("127.0.0.1")
result2 := IsIpV6("::0:0:0:0:0:0:1")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// false
// true
}
func ExampleIsStrongPassword() {
result1 := IsStrongPassword("abcABC", 6)
result2 := IsStrongPassword("abcABC123@#$", 10)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// false
// true
}
func ExampleIsWeakPassword() {
result1 := IsWeakPassword("abcABC")
result2 := IsWeakPassword("abc123@#$")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleIsZeroValue() {
result1 := IsZeroValue("")
result2 := IsZeroValue(0)
result3 := IsZeroValue("abc")
result4 := IsZeroValue(1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// false
// false
}
func ExampleIsGBK() {
str := "你好"
gbkData, _ := simplifiedchinese.GBK.NewEncoder().Bytes([]byte(str))
result := IsGBK(gbkData)
fmt.Println(result)
// Output:
// true
}