mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-17 03:02:28 +08:00
Compare commits
80 Commits
v2.1.7
...
76bdec2b54
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76bdec2b54 | ||
|
|
fa20aba3a7 | ||
|
|
7a4a429e23 | ||
|
|
a70ec6ad1e | ||
|
|
e435fa271b | ||
|
|
1533d00891 | ||
|
|
8b99641de0 | ||
|
|
251f899f18 | ||
|
|
00407e5182 | ||
|
|
4e457ad672 | ||
|
|
7d8d9c3543 | ||
|
|
1197e8d1b6 | ||
|
|
13bbe19ab2 | ||
|
|
2725575d2f | ||
|
|
037d2729ce | ||
|
|
09d98745b0 | ||
|
|
af5cfe6da1 | ||
|
|
d59259bbe0 | ||
|
|
3189628d54 | ||
|
|
62c5e251a5 | ||
|
|
6e6444c8c0 | ||
|
|
dd613e98b2 | ||
|
|
2d905ab03e | ||
|
|
205fedb197 | ||
|
|
4c864da62d | ||
|
|
263ab7e316 | ||
|
|
809b7a53df | ||
|
|
61c43daabb | ||
|
|
18914ee2cd | ||
|
|
0a8058956f | ||
|
|
a044da7d2f | ||
|
|
f8b785c4cb | ||
|
|
82c8a04c35 | ||
|
|
280ecb5cef | ||
|
|
ec27ad4c40 | ||
|
|
d66f92cd68 | ||
|
|
d8ed692651 | ||
|
|
a16de97d1d | ||
|
|
6f458e4367 | ||
|
|
37c7508ad0 | ||
|
|
acb5844b15 | ||
|
|
76f4eeea16 | ||
|
|
5466a23019 | ||
|
|
5692982dd1 | ||
|
|
c39c8914fb | ||
|
|
29bdca1bd2 | ||
|
|
eb66d038ac | ||
|
|
a99ada5ee1 | ||
|
|
a87faf5453 | ||
|
|
ab6fec2f69 | ||
|
|
7b290989f5 | ||
|
|
5722c724e6 | ||
|
|
f84584ca04 | ||
|
|
80cbbdc787 | ||
|
|
be148e07ba | ||
|
|
d36ab5cc3a | ||
|
|
2b17329094 | ||
|
|
f869a0a670 | ||
|
|
be000a4bd6 | ||
|
|
81efa800ea | ||
|
|
a783de57a8 | ||
|
|
a622959a78 | ||
|
|
f709dd53ce | ||
|
|
ee9e9625e2 | ||
|
|
84da7d4f27 | ||
|
|
089fd4e13c | ||
|
|
6c40e02324 | ||
|
|
a270b1b634 | ||
|
|
260fb795d3 | ||
|
|
8c036f830c | ||
|
|
bf332b9f1c | ||
|
|
6b6cd66f9f | ||
|
|
5399c2290e | ||
|
|
6248293c49 | ||
|
|
eced25b76d | ||
|
|
96a4327aa7 | ||
|
|
fcfbdea597 | ||
|
|
87896f917a | ||
|
|
b8563ed646 | ||
|
|
1ccf0af2b3 |
634
README.md
634
README.md
@@ -4,12 +4,13 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
[](https://codecov.io/gh/duke-git/lancet)
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -22,22 +23,25 @@ English | [简体中文](./README_zh-CN.md)
|
|||||||
|
|
||||||
## Feature
|
## Feature
|
||||||
|
|
||||||
- 👏 Comprehensive, efficient and reusable.
|
- 👏 Comprehensive, efficient and reusable.
|
||||||
- 💪 300+ go util functions, support string, slice, datetime, net, crypt...
|
- 💪 300+ go util functions, support string, slice, datetime, net, crypt...
|
||||||
- 💅 Only depend on the go standard library.
|
- 💅 Only depend on the go standard library.
|
||||||
- 🌍 Unit test for every exported function.
|
- 🌍 Unit test for every exported function.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Note:
|
### 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 v2.x.x rewrite all functions with generics of go1.18.</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
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.2. </b>
|
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.3.4. </b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.2 // below go1.18, install latest version of v1.x.x
|
go get github.com/duke-git/lancet@v1.3.3 // below go1.18, install latest version of v1.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -68,82 +72,89 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## API Documentation
|
## API Documentation
|
||||||
|
|
||||||
## [lancet API doc](https://uvdream.github.io/lancet-docs/) Thanks [@UvDream](https://github.com/UvDream) for contributing.
|
## [lancet API doc](https://uvdream.github.io/lancet-docs/) Thanks [@UvDream](https://github.com/UvDream) for contributing.
|
||||||
|
|
||||||
### 1. Algorithm package implements some basic algorithm. eg. sort, search.
|
### 1. Algorithm package implements some basic algorithm. eg. sort, search.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/algorithm"
|
import "github.com/duke-git/lancet/v2/algorithm"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
### 2. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
|
### 2. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/concurrency"
|
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)
|
|
||||||
|
|
||||||
|
#### 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)
|
||||||
|
|
||||||
### 3. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...
|
### 3. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/condition"
|
import "github.com/duke-git/lancet/v2/condition"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
- [Bool](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Bool)
|
||||||
- [Or](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)
|
- [And](https://github.com/duke-git/lancet/blob/main/docs/condition.md#And)
|
||||||
- [Xor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)
|
- [Or](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)
|
||||||
- [Nor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)
|
- [Xor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)
|
||||||
- [Nand](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nand)
|
- [Nor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)
|
||||||
- [TernaryOperator](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)
|
- [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)
|
||||||
|
|
||||||
### 4. Convertor package contains some functions for data convertion.
|
### 4. Convertor package contains some functions for data convertion.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/convertor"
|
import "github.com/duke-git/lancet/v2/convertor"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
|
||||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)
|
||||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
||||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
||||||
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
|
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
||||||
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)
|
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
|
||||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)
|
||||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
||||||
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)
|
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
||||||
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)
|
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)
|
||||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)
|
||||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
||||||
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)
|
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
||||||
- [EncodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#EncodeByte)
|
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)
|
||||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)
|
- [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)
|
||||||
|
|
||||||
### 5. Cryptor package is for data encryption and decryption.
|
### 5. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
@@ -152,82 +163,81 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbEncrypt)
|
|
||||||
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbDecrypt)
|
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbEncrypt)
|
||||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)
|
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbDecrypt)
|
||||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)
|
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)
|
||||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)
|
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)
|
||||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)
|
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)
|
||||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)
|
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)
|
||||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)
|
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)
|
||||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)
|
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)
|
||||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)
|
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)
|
||||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)
|
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)
|
||||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)
|
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)
|
||||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)
|
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)
|
||||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)
|
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)
|
||||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)
|
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)
|
||||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)
|
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)
|
||||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)
|
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)
|
||||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)
|
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)
|
||||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)
|
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)
|
||||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)
|
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)
|
||||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)
|
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)
|
||||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)
|
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)
|
||||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)
|
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)
|
||||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)
|
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)
|
||||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)
|
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)
|
||||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)
|
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)
|
||||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)
|
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)
|
||||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)
|
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)
|
||||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)
|
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)
|
||||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)
|
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)
|
||||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)
|
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)
|
||||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)
|
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)
|
||||||
|
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)
|
||||||
|
|
||||||
### 6. Datetime package supports date and time format and compare.
|
### 6. Datetime package supports date and time format and compare.
|
||||||
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/datetime"
|
import "github.com/duke-git/lancet/v2/datetime"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)
|
|
||||||
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddHour)
|
|
||||||
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)
|
|
||||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
|
||||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
|
||||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
|
||||||
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
|
||||||
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
|
||||||
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
|
||||||
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
|
||||||
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
|
||||||
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
|
||||||
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
|
||||||
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
|
||||||
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
|
||||||
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate)
|
|
||||||
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime)
|
|
||||||
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)
|
|
||||||
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp)
|
|
||||||
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
|
|
||||||
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
|
|
||||||
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
|
|
||||||
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
|
|
||||||
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
|
|
||||||
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
|
|
||||||
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
|
|
||||||
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
|
|
||||||
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
|
|
||||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
|
|
||||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
|
|
||||||
|
|
||||||
|
|
||||||
|
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)
|
||||||
|
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddHour)
|
||||||
|
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)
|
||||||
|
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
||||||
|
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
||||||
|
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
||||||
|
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
||||||
|
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
||||||
|
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
||||||
|
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
||||||
|
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
||||||
|
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
||||||
|
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
||||||
|
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
||||||
|
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
||||||
|
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate)
|
||||||
|
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime)
|
||||||
|
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)
|
||||||
|
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp)
|
||||||
|
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
|
||||||
|
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
|
||||||
|
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
|
||||||
|
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
|
||||||
|
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
|
||||||
|
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
|
||||||
|
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
|
||||||
|
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
|
||||||
|
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
|
||||||
|
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
|
||||||
|
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
|
||||||
|
|
||||||
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
||||||
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||||
import link "github.com/duke-git/lancet/v2/datastructure/link"
|
import link "github.com/duke-git/lancet/v2/datastructure/link"
|
||||||
@@ -238,16 +248,17 @@ import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
|||||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||||
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||||
```
|
```
|
||||||
#### Function list:
|
|
||||||
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md)
|
|
||||||
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist.md)
|
|
||||||
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack.md)
|
|
||||||
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue.md)
|
|
||||||
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set.md)
|
|
||||||
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree.md)
|
|
||||||
- [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)
|
|
||||||
|
|
||||||
|
#### Function list:
|
||||||
|
|
||||||
|
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md)
|
||||||
|
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist.md)
|
||||||
|
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack.md)
|
||||||
|
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue.md)
|
||||||
|
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set.md)
|
||||||
|
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree.md)
|
||||||
|
- [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 package implements some basic functions for file operations.
|
### 8. Fileutil package implements some basic functions for file operations.
|
||||||
|
|
||||||
@@ -257,29 +268,31 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
|||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
|
||||||
|
|
||||||
### 9. Formatter contains some functions for data formatting.
|
### 9. Formatter contains some functions for data formatting.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/formatter"
|
import "github.com/duke-git/lancet/v2/formatter"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
|
|
||||||
|
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
|
||||||
|
|
||||||
### 10. Function package can control the flow of function execution and support part of functional programming
|
### 10. Function package can control the flow of function execution and support part of functional programming
|
||||||
|
|
||||||
@@ -288,14 +301,15 @@ import "github.com/duke-git/lancet/v2/function"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/function.md#After)
|
|
||||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function.md#Before)
|
|
||||||
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function.md#Curry)
|
|
||||||
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function.md#Compose)
|
|
||||||
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function.md#Debounced)
|
|
||||||
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function.md#Delay)
|
|
||||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
|
|
||||||
|
|
||||||
|
- [After](https://github.com/duke-git/lancet/blob/main/docs/function.md#After)
|
||||||
|
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function.md#Before)
|
||||||
|
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function.md#Curry)
|
||||||
|
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function.md#Compose)
|
||||||
|
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function.md#Debounced)
|
||||||
|
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function.md#Delay)
|
||||||
|
- [Pipeline](https://github.com/duke-git/lancet/blob/main/docs/function.md#Pipeline)
|
||||||
|
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
|
||||||
|
|
||||||
### 11. Maputil package includes some functions to manipulate map.
|
### 11. Maputil package includes some functions to manipulate map.
|
||||||
|
|
||||||
@@ -304,15 +318,15 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
### 12. Mathutil package implements some functions for math calculation.
|
### 12. Mathutil package implements some functions for math calculation.
|
||||||
|
|
||||||
@@ -321,19 +335,19 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
### 13. Netutil package contains functions to get net information and send http request.
|
### 13. Netutil package contains functions to get net information and send http request.
|
||||||
|
|
||||||
@@ -342,27 +356,28 @@ import "github.com/duke-git/lancet/v2/netutil"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
|
|
||||||
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#EncodeUrl)
|
|
||||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)
|
|
||||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
|
||||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
|
||||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)
|
|
||||||
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp)
|
|
||||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
|
|
||||||
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsInternalIP)
|
|
||||||
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpRequest)
|
|
||||||
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpClient)
|
|
||||||
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest)
|
|
||||||
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse)
|
|
||||||
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)
|
|
||||||
|
|
||||||
- [HttpGet<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
|
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
|
||||||
- [HttpDelete<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
|
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#EncodeUrl)
|
||||||
- [HttpPost<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
|
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)
|
||||||
- [HttpPut<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)
|
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||||
- [HttpPatch<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
|
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
|
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)
|
||||||
|
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp)
|
||||||
|
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
|
||||||
|
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsInternalIP)
|
||||||
|
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpRequest)
|
||||||
|
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpClient)
|
||||||
|
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest)
|
||||||
|
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse)
|
||||||
|
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)
|
||||||
|
|
||||||
|
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
|
||||||
|
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
|
||||||
|
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
|
||||||
|
- [HttpPut<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)
|
||||||
|
- [HttpPatch<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
|
||||||
|
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
|
||||||
|
|
||||||
### 14. Random package implements some basic functions to generate random int and string.
|
### 14. Random package implements some basic functions to generate random int and string.
|
||||||
|
|
||||||
@@ -371,10 +386,15 @@ import "github.com/duke-git/lancet/v2/random"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
|
||||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
|
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
|
||||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
- [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)
|
||||||
|
|
||||||
### 15. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
### 15. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||||
|
|
||||||
@@ -383,11 +403,12 @@ import "github.com/duke-git/lancet/v2/retry"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Context)
|
|
||||||
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Retry)
|
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Context)
|
||||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)
|
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Retry)
|
||||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
|
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)
|
||||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
|
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
|
||||||
|
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
|
||||||
|
|
||||||
### 16. Slice contains some functions to manipulate slice.
|
### 16. Slice contains some functions to manipulate slice.
|
||||||
|
|
||||||
@@ -396,91 +417,104 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice.md#AppendIfAbsent)
|
||||||
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
|
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
|
||||||
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
|
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
|
||||||
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
|
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
|
||||||
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
|
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
|
||||||
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
|
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
|
||||||
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
|
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
|
||||||
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
|
- [CountBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#CountBy)
|
||||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
|
||||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
|
||||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||||
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
|
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
||||||
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
|
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
||||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
|
||||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
|
||||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
||||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
||||||
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)
|
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
||||||
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
|
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
||||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)
|
||||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
|
||||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
||||||
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
|
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
||||||
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
|
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
||||||
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
|
- [IntSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
|
||||||
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
|
- [InterfaceSlice<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
|
||||||
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
|
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
|
||||||
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
|
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
|
||||||
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
|
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
|
||||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
|
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
|
||||||
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
|
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
|
||||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
|
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Merge)
|
||||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
|
||||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
|
||||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
|
- [Replace](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)
|
||||||
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SymmetricDifference)
|
- [ReplaceAll](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReplaceAll)
|
||||||
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)
|
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Repeat)
|
||||||
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlicePointer)
|
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
|
||||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
|
- [Sort](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)
|
||||||
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UniqueBy)
|
- [SortBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortBy)
|
||||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
|
- [SortByField<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
||||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
|
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||||
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
|
- [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)
|
||||||
|
|
||||||
### 17. Strutil package contains some functions to manipulate string.
|
### 17. Strutil package contains some functions to manipulate string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/strutil"
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
|
||||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
|
||||||
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
|
- [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)
|
- [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)
|
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
|
||||||
|
|
||||||
### 19. System package contain some functions about os, runtime, shell command.
|
### 19. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/system"
|
import "github.com/duke-git/lancet/v2/system"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
|
||||||
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
|
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
|
||||||
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
|
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
|
||||||
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
|
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
|
||||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
|
||||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
||||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
|
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
||||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
|
- [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)
|
||||||
|
|
||||||
### 19. Validator package contains some functions for data validation.
|
### 19. Validator package contains some functions for data validation.
|
||||||
|
|
||||||
@@ -490,41 +524,43 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue)
|
||||||
|
|
||||||
### 20. xerror package implements helpers for errors.
|
### 20. xerror package implements helpers for errors.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/xerror"
|
import "github.com/duke-git/lancet/v2/xerror"
|
||||||
```
|
```
|
||||||
#### Function list:
|
|
||||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
|
|
||||||
|
|
||||||
|
#### Function list:
|
||||||
|
|
||||||
|
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
|
|||||||
681
README_zh-CN.md
681
README_zh-CN.md
@@ -4,12 +4,13 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
[](https://codecov.io/gh/duke-git/lancet)
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -19,30 +20,32 @@
|
|||||||
|
|
||||||
简体中文 | [English](./README.md)
|
简体中文 | [English](./README.md)
|
||||||
|
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 👏 全面、高效、可复用
|
- 👏 全面、高效、可复用
|
||||||
- 💪 300+常用go工具函数,支持string、slice、datetime、net、crypt...
|
- 💪 300+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||||
- 💅 只依赖go标准库
|
- 💅 只依赖 go 标准库
|
||||||
- 🌍 所有导出函数单元测试覆盖率100%
|
- 🌍 所有导出函数单元测试覆盖率 100%
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
### Note:
|
### 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
|
||||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
2. <b>使用go1.18以下版本的用户,必须安装v1.x.x。目前最新的v1版本是v1.3.2。</b>
|
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.4。</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.2 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
go get github.com/duke-git/lancet@v1.3.3 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||||
```
|
```
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
|
|
||||||
lancet是以包的结构组织代码的,使用时需要导入相应的包名。例如:如果使用字符串相关函数,需要导入strutil包:
|
lancet 是以包的结构组织代码的,使用时需要导入相应的包名。例如:如果使用字符串相关函数,需要导入 strutil 包:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/strutil"
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
@@ -50,7 +53,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
|
|
||||||
## 例子
|
## 例子
|
||||||
|
|
||||||
此处以字符串工具函数Reverse(逆序字符串)为例,需要导入strutil包:
|
此处以字符串工具函数 Reverse(逆序字符串)为例,需要导入 strutil 包:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -67,164 +70,172 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## API文档
|
## API 文档
|
||||||
|
|
||||||
## [lancet API doc](https://uvdream.github.io/lancet-docs/) 感谢[@UvDream](https://github.com/UvDream)整理
|
## [lancet API doc](https://uvdream.github.io/lancet-docs/) 感谢[@UvDream](https://github.com/UvDream)整理
|
||||||
### 1. algorithm算法包实现一些基本算法。eg. sort, search.
|
|
||||||
|
### 1. algorithm 算法包实现一些基本算法。eg. sort, search.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/algorithm"
|
import "github.com/duke-git/lancet/v2/algorithm"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
### 2. concurrency并发包包含一些支持并发编程的功能。例如:goroutine, channel, async等。
|
### 2. concurrency 并发包包含一些支持并发编程的功能。例如:goroutine, channel, async 等。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/concurrency"
|
import "github.com/duke-git/lancet/v2/concurrency"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
### 3. condition条件包含一些用于条件判断的函数。eg. And, Or, TernaryOperator...
|
### 3. condition 条件包含一些用于条件判断的函数。eg. And, Or, TernaryOperator...
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/condition"
|
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)
|
|
||||||
|
|
||||||
### 4. convertor转换器包支持一些常见的数据类型转换。
|
#### 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)
|
||||||
|
|
||||||
|
### 4. convertor 转换器包支持一些常见的数据类型转换。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/convertor"
|
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)
|
|
||||||
|
|
||||||
### 5. cryptor加密包支持数据加密和解密,获取md5,hash值。支持base64, md5, hmac, aes, des, rsa。
|
#### 函数列表:
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
|
### 5. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/cryptor"
|
import "github.com/duke-git/lancet/v2/cryptor"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)
|
|
||||||
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)
|
|
||||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)
|
|
||||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)
|
|
||||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)
|
|
||||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)
|
|
||||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)
|
|
||||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)
|
|
||||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)
|
|
||||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)
|
|
||||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)
|
|
||||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)
|
|
||||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)
|
|
||||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)
|
|
||||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)
|
|
||||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)
|
|
||||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)
|
|
||||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)
|
|
||||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)
|
|
||||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)
|
|
||||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)
|
|
||||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)
|
|
||||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)
|
|
||||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)
|
|
||||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)
|
|
||||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)
|
|
||||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)
|
|
||||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)
|
|
||||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)
|
|
||||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)
|
|
||||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)
|
|
||||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)
|
|
||||||
|
|
||||||
### 6. datetime日期时间处理包,格式化日期,比较日期。
|
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)
|
||||||
|
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)
|
||||||
|
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)
|
||||||
|
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)
|
||||||
|
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)
|
||||||
|
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)
|
||||||
|
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)
|
||||||
|
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)
|
||||||
|
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)
|
||||||
|
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)
|
||||||
|
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)
|
||||||
|
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)
|
||||||
|
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)
|
||||||
|
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)
|
||||||
|
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)
|
||||||
|
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)
|
||||||
|
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)
|
||||||
|
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)
|
||||||
|
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)
|
||||||
|
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)
|
||||||
|
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)
|
||||||
|
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)
|
||||||
|
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)
|
||||||
|
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)
|
||||||
|
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)
|
||||||
|
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)
|
||||||
|
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)
|
||||||
|
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)
|
||||||
|
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)
|
||||||
|
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)
|
||||||
|
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)
|
||||||
|
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)
|
||||||
|
|
||||||
|
### 6. datetime 日期时间处理包,格式化日期,比较日期。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/datetime"
|
import "github.com/duke-git/lancet/v2/datetime"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)
|
|
||||||
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddHour)
|
|
||||||
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)
|
|
||||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
|
||||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
|
||||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
|
||||||
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
|
||||||
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
|
||||||
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
|
||||||
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
|
||||||
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
|
||||||
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
|
||||||
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
|
||||||
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
|
||||||
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
|
||||||
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate)
|
|
||||||
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime)
|
|
||||||
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)
|
|
||||||
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp)
|
|
||||||
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
|
|
||||||
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
|
|
||||||
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
|
|
||||||
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
|
|
||||||
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
|
|
||||||
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
|
|
||||||
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
|
|
||||||
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
|
|
||||||
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
|
|
||||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
|
|
||||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
|
|
||||||
|
|
||||||
|
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)
|
||||||
|
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddHour)
|
||||||
|
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)
|
||||||
|
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)
|
||||||
|
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)
|
||||||
|
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)
|
||||||
|
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
|
||||||
|
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
|
||||||
|
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
|
||||||
|
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
|
||||||
|
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
|
||||||
|
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
|
||||||
|
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
|
||||||
|
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
|
||||||
|
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
|
||||||
|
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate)
|
||||||
|
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime)
|
||||||
|
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)
|
||||||
|
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp)
|
||||||
|
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
|
||||||
|
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
|
||||||
|
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
|
||||||
|
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
|
||||||
|
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
|
||||||
|
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
|
||||||
|
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
|
||||||
|
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
|
||||||
|
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
|
||||||
|
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
|
||||||
|
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
|
||||||
|
|
||||||
### 7. datastructure包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
### 7. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||||
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||||
@@ -236,18 +247,19 @@ import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
|||||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||||
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)
|
|
||||||
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist_zh-CN.md)
|
|
||||||
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack_zh-CN.md)
|
|
||||||
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue_zh-CN.md)
|
|
||||||
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)
|
|
||||||
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)
|
|
||||||
- [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)
|
|
||||||
|
|
||||||
|
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)
|
||||||
|
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist_zh-CN.md)
|
||||||
|
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack_zh-CN.md)
|
||||||
|
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue_zh-CN.md)
|
||||||
|
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)
|
||||||
|
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)
|
||||||
|
- [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
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/fileutil"
|
import "github.com/duke-git/lancet/v2/fileutil"
|
||||||
@@ -255,189 +267,209 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
|
||||||
|
|
||||||
### 9. formatter格式化器包含一些数据格式化处理方法。
|
### 9. formatter 格式化器包含一些数据格式化处理方法。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/formatter"
|
import "github.com/duke-git/lancet/v2/formatter"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
|
|
||||||
|
|
||||||
|
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
|
||||||
|
|
||||||
### 10. function函数包控制函数执行流程,包含部分函数式编程。
|
### 10. function 函数包控制函数执行流程,包含部分函数式编程。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/function"
|
import "github.com/duke-git/lancet/v2/function"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#After)
|
|
||||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Before)
|
|
||||||
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Curry)
|
|
||||||
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)
|
|
||||||
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)
|
|
||||||
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
|
|
||||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
|
|
||||||
|
|
||||||
|
- [After](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#After)
|
||||||
|
- [Before](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Before)
|
||||||
|
- [Curry](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Curry)
|
||||||
|
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)
|
||||||
|
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)
|
||||||
|
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
|
||||||
|
- [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
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/maputil"
|
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)
|
|
||||||
|
|
||||||
### 12. mathutil包实现了一些数学计算的函数。
|
- [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)
|
||||||
|
|
||||||
|
### 12. mathutil 包实现了一些数学计算的函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/mathutil"
|
import "github.com/duke-git/lancet/v2/mathutil"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Function list:
|
#### 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)
|
|
||||||
|
|
||||||
### 13. netutil网络包支持获取ip地址,发送http请求。
|
- [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)
|
||||||
|
|
||||||
|
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/netutil"
|
import "github.com/duke-git/lancet/v2/netutil"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)
|
|
||||||
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)
|
|
||||||
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)
|
|
||||||
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
|
||||||
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
|
||||||
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)
|
|
||||||
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)
|
|
||||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
|
|
||||||
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)
|
|
||||||
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest)
|
|
||||||
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient)
|
|
||||||
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)
|
|
||||||
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)
|
|
||||||
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)
|
|
||||||
|
|
||||||
- [HttpGet<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
|
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)
|
||||||
- [HttpDelete<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
|
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)
|
||||||
- [HttpPost<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
|
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)
|
||||||
- [HttpPut<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)
|
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
|
||||||
- [HttpPatch<sup>Deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
|
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
|
||||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
|
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)
|
||||||
|
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)
|
||||||
|
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
|
||||||
|
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)
|
||||||
|
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest)
|
||||||
|
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient)
|
||||||
|
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)
|
||||||
|
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)
|
||||||
|
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)
|
||||||
|
|
||||||
### 14. random随机数生成器包,可以生成随机[]bytes, int, string。
|
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
|
||||||
|
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
|
||||||
|
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
|
||||||
|
- [HttpPut<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)
|
||||||
|
- [HttpPatch<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
|
||||||
|
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
|
||||||
|
|
||||||
|
### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/random"
|
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)
|
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
|
||||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
|
||||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
||||||
### 15. retry重试执行函数直到函数运行成功或被context cancel。
|
- [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)
|
||||||
|
|
||||||
|
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/retry"
|
import "github.com/duke-git/lancet/v2/retry"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)
|
|
||||||
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)
|
|
||||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)
|
|
||||||
- [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)
|
|
||||||
|
|
||||||
|
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)
|
||||||
|
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)
|
||||||
|
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)
|
||||||
|
- [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
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/slice"
|
import "github.com/duke-git/lancet/v2/slice"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [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)
|
|
||||||
- [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](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
|
|
||||||
- [InterfaceSlice](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)
|
|
||||||
- [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)
|
|
||||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
|
|
||||||
- [SortByField](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](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)
|
|
||||||
- [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)
|
|
||||||
|
|
||||||
|
- [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
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/strutil"
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
@@ -445,91 +477,94 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
|
||||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
|
||||||
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
|
- [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)
|
- [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)
|
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
|
||||||
|
|
||||||
|
### 18. system 包含 os, runtime, shell command 相关函数。
|
||||||
### 18. system包含os, runtime, shell command相关函数。
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/system"
|
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)
|
|
||||||
|
|
||||||
### 19. validator验证器包,包含常用字符串格式验证函数。
|
- [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)
|
||||||
|
|
||||||
|
### 19. validator 验证器包,包含常用字符串格式验证函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/validator"
|
import "github.com/duke-git/lancet/v2/validator"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)
|
||||||
|
|
||||||
### 20. xerror包实现一些错误处理函数
|
### 20. xerror 包实现一些错误处理函数
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/xerror"
|
import "github.com/duke-git/lancet/v2/xerror"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
|
|
||||||
|
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
|
||||||
|
|
||||||
## 如何贡献代码
|
## 如何贡献代码
|
||||||
|
|
||||||
非常感激任何的代码提交以使lancet的功能越来越强大。创建pull request时请遵守以下规则。
|
非常感激任何的代码提交以使 lancet 的功能越来越强大。创建 pull request 时请遵守以下规则。
|
||||||
|
|
||||||
1. Fork lancet仓库。
|
1. Fork lancet 仓库。
|
||||||
2. 创建自己的特性分支。
|
2. 创建自己的特性分支。
|
||||||
3. 提交变更。
|
3. 提交变更。
|
||||||
4. Push分支。
|
4. Push 分支。
|
||||||
5. 创建新的pull request。
|
5. 创建新的 pull request。
|
||||||
|
|||||||
15
SECURITY.md
Normal file
15
SECURITY.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
Here is the lancet version and compatibility with go language version.
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------|
|
||||||
|
| 2.x.x | +go v1.18 |
|
||||||
|
| 1.x.x | +go v1.12 |
|
||||||
|
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
For now, there is no public website to report a vulnerability, If you find security issue in lancet, you can send it to me via my email `lanliddd.2007@163.com`.
|
||||||
|
we can discuss it. I am appreciate if someone can create a public page for reporting vulnerability.
|
||||||
@@ -158,7 +158,7 @@ func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-ch
|
|||||||
var stream <-chan any
|
var stream <-chan any
|
||||||
select {
|
select {
|
||||||
case maybeStream, ok := <-chanStream:
|
case maybeStream, ok := <-chanStream:
|
||||||
if ok == false {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stream = maybeStream
|
stream = maybeStream
|
||||||
|
|||||||
@@ -90,34 +90,53 @@ func ToChannel[T any](array []T) <-chan T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToString convert value to string
|
// ToString convert value to string
|
||||||
|
// for number, string, []byte, will convert to string
|
||||||
|
// for other type (slice, map, array, struct) will call json.Marshal
|
||||||
func ToString(value any) string {
|
func ToString(value any) string {
|
||||||
result := ""
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return result
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(value)
|
switch val := value.(type) {
|
||||||
|
case float32:
|
||||||
switch value.(type) {
|
return strconv.FormatFloat(float64(val), 'f', -1, 32)
|
||||||
case float32, float64:
|
case float64:
|
||||||
result = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
return strconv.FormatFloat(val, 'f', -1, 64)
|
||||||
return result
|
case int:
|
||||||
case int, int8, int16, int32, int64:
|
return strconv.FormatInt(int64(val), 10)
|
||||||
result = strconv.FormatInt(v.Int(), 10)
|
case int8:
|
||||||
return result
|
return strconv.FormatInt(int64(val), 10)
|
||||||
case uint, uint8, uint16, uint32, uint64:
|
case int16:
|
||||||
result = strconv.FormatUint(v.Uint(), 10)
|
return strconv.FormatInt(int64(val), 10)
|
||||||
return result
|
case int32:
|
||||||
|
return strconv.FormatInt(int64(val), 10)
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(val, 10)
|
||||||
|
case uint:
|
||||||
|
return strconv.FormatUint(uint64(val), 10)
|
||||||
|
case uint8:
|
||||||
|
return strconv.FormatUint(uint64(val), 10)
|
||||||
|
case uint16:
|
||||||
|
return strconv.FormatUint(uint64(val), 10)
|
||||||
|
case uint32:
|
||||||
|
return strconv.FormatUint(uint64(val), 10)
|
||||||
|
case uint64:
|
||||||
|
return strconv.FormatUint(val, 10)
|
||||||
case string:
|
case string:
|
||||||
result = v.String()
|
return val
|
||||||
return result
|
|
||||||
case []byte:
|
case []byte:
|
||||||
result = string(v.Bytes())
|
return string(val)
|
||||||
return result
|
|
||||||
default:
|
default:
|
||||||
newValue, _ := json.Marshal(value)
|
b, err := json.Marshal(val)
|
||||||
result = string(newValue)
|
if err != nil {
|
||||||
return result
|
return ""
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
|
||||||
|
// todo: maybe we should't supprt other type conversion
|
||||||
|
// v := reflect.ValueOf(value)
|
||||||
|
// log.Panicf("Unsupported data type: %s ", v.String())
|
||||||
|
// return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,9 @@ func TestToChannel(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestToChannel")
|
assert := internal.NewAssert(t, "TestToChannel")
|
||||||
|
|
||||||
ch := ToChannel([]int{1, 2, 3})
|
ch := ToChannel([]int{1, 2, 3})
|
||||||
val1, _ := <-ch
|
assert.Equal(1, <-ch)
|
||||||
assert.Equal(1, val1)
|
assert.Equal(2, <-ch)
|
||||||
|
assert.Equal(3, <-ch)
|
||||||
val2, _ := <-ch
|
|
||||||
assert.Equal(2, val2)
|
|
||||||
|
|
||||||
val3, _ := <-ch
|
|
||||||
assert.Equal(3, val3)
|
|
||||||
|
|
||||||
_, ok := <-ch
|
_, ok := <-ch
|
||||||
assert.Equal(false, ok)
|
assert.Equal(false, ok)
|
||||||
@@ -137,9 +132,10 @@ func TestToString(t *testing.T) {
|
|||||||
"", "",
|
"", "",
|
||||||
"0", "1", "-1",
|
"0", "1", "-1",
|
||||||
"123", "123", "123", "123", "123", "123", "123",
|
"123", "123", "123", "123", "123", "123", "123",
|
||||||
"12.3", "12.300000190734863",
|
"12.3", "12.3",
|
||||||
"true", "false",
|
"true", "false",
|
||||||
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
|
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello",
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
actual := ToString(cases[i])
|
actual := ToString(cases[i])
|
||||||
@@ -253,6 +249,7 @@ func TestDecodeByte(t *testing.T) {
|
|||||||
|
|
||||||
var obj string
|
var obj string
|
||||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||||
DecodeByte(byteData, &obj)
|
err := DecodeByte(byteData, &obj)
|
||||||
|
assert.IsNil(err)
|
||||||
assert.Equal("abc", obj)
|
assert.Equal("abc", obj)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,19 @@ import (
|
|||||||
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||||||
// len(key) should be 16, 24 or 32
|
// len(key) should be 16, 24 or 32
|
||||||
func AesEcbEncrypt(data, key []byte) []byte {
|
func AesEcbEncrypt(data, key []byte) []byte {
|
||||||
cipher, _ := aes.NewCipher(generateAesKey(key))
|
|
||||||
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||||||
plain := make([]byte, length*aes.BlockSize)
|
plain := make([]byte, length*aes.BlockSize)
|
||||||
|
|
||||||
copy(plain, data)
|
copy(plain, data)
|
||||||
|
|
||||||
pad := byte(len(plain) - len(data))
|
pad := byte(len(plain) - len(data))
|
||||||
for i := len(data); i < len(plain); i++ {
|
for i := len(data); i < len(plain); i++ {
|
||||||
plain[i] = pad
|
plain[i] = pad
|
||||||
}
|
}
|
||||||
|
|
||||||
encrypted := make([]byte, len(plain))
|
encrypted := make([]byte, len(plain))
|
||||||
|
cipher, _ := aes.NewCipher(generateAesKey(key))
|
||||||
|
|
||||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||||
}
|
}
|
||||||
@@ -108,27 +112,32 @@ func AesCfbEncrypt(data, key []byte) []byte {
|
|||||||
|
|
||||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||||
iv := encrypted[:aes.BlockSize]
|
iv := encrypted[:aes.BlockSize]
|
||||||
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stream := cipher.NewCFBEncrypter(block, iv)
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||||
|
|
||||||
return encrypted
|
return encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
|
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
|
||||||
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
|
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
|
||||||
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||||
block, _ := aes.NewCipher(key)
|
|
||||||
if len(encrypted) < aes.BlockSize {
|
if len(encrypted) < aes.BlockSize {
|
||||||
panic("encrypted data is too short")
|
panic("encrypted data is too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block, _ := aes.NewCipher(key)
|
||||||
iv := encrypted[:aes.BlockSize]
|
iv := encrypted[:aes.BlockSize]
|
||||||
encrypted = encrypted[aes.BlockSize:]
|
encrypted = encrypted[aes.BlockSize:]
|
||||||
|
|
||||||
stream := cipher.NewCFBDecrypter(block, iv)
|
stream := cipher.NewCFBDecrypter(block, iv)
|
||||||
|
|
||||||
stream.XORKeyStream(encrypted, encrypted)
|
stream.XORKeyStream(encrypted, encrypted)
|
||||||
|
|
||||||
return encrypted
|
return encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +148,7 @@ func AesOfbEncrypt(data, key []byte) []byte {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
data = pkcs7Padding(data, aes.BlockSize)
|
data = pkcs7Padding(data, aes.BlockSize)
|
||||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||||
iv := encrypted[:aes.BlockSize]
|
iv := encrypted[:aes.BlockSize]
|
||||||
@@ -148,6 +158,7 @@ func AesOfbEncrypt(data, key []byte) []byte {
|
|||||||
|
|
||||||
stream := cipher.NewOFB(block, iv)
|
stream := cipher.NewOFB(block, iv)
|
||||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||||
|
|
||||||
return encrypted
|
return encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,5 +181,6 @@ func AesOfbDecrypt(data, key []byte) []byte {
|
|||||||
mode.XORKeyStream(decrypted, data)
|
mode.XORKeyStream(decrypted, data)
|
||||||
|
|
||||||
decrypted = pkcs7UnPadding(decrypted)
|
decrypted = pkcs7UnPadding(decrypted)
|
||||||
|
|
||||||
return decrypted
|
return decrypted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
||||||
// len(key) should be 8
|
// len(key) should be 8
|
||||||
func DesEcbEncrypt(data, key []byte) []byte {
|
func DesEcbEncrypt(data, key []byte) []byte {
|
||||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
|
||||||
length := (len(data) + des.BlockSize) / des.BlockSize
|
length := (len(data) + des.BlockSize) / des.BlockSize
|
||||||
plain := make([]byte, length*des.BlockSize)
|
plain := make([]byte, length*des.BlockSize)
|
||||||
copy(plain, data)
|
copy(plain, data)
|
||||||
@@ -26,6 +25,8 @@ func DesEcbEncrypt(data, key []byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encrypted := make([]byte, len(plain))
|
encrypted := make([]byte, len(plain))
|
||||||
|
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||||
|
|
||||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||||
}
|
}
|
||||||
@@ -59,6 +60,7 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
|||||||
|
|
||||||
encrypted := make([]byte, des.BlockSize+len(data))
|
encrypted := make([]byte, des.BlockSize+len(data))
|
||||||
iv := encrypted[:des.BlockSize]
|
iv := encrypted[:des.BlockSize]
|
||||||
|
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
pem.Encode(file, &block)
|
err = pem.Encode(file, &block)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
// public key
|
// public key
|
||||||
@@ -49,12 +53,16 @@ func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
|||||||
Bytes: derpText,
|
Bytes: derpText,
|
||||||
}
|
}
|
||||||
|
|
||||||
//file,err = os.Create("rsa_public.pem")
|
|
||||||
file, err = os.Create(pubKeyFile)
|
file, err = os.Create(pubKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pem.Encode(file, &block)
|
|
||||||
|
err = pem.Encode(file, &block)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -72,7 +80,11 @@ func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
buf := make([]byte, fileInfo.Size())
|
buf := make([]byte, fileInfo.Size())
|
||||||
file.Read(buf)
|
|
||||||
|
_, err = file.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
block, _ := pem.Decode(buf)
|
block, _ := pem.Decode(buf)
|
||||||
|
|
||||||
@@ -101,7 +113,11 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
|||||||
}
|
}
|
||||||
buf := make([]byte, fileInfo.Size())
|
buf := make([]byte, fileInfo.Size())
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
file.Read(buf)
|
|
||||||
|
_, err = file.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
block, _ := pem.Decode(buf)
|
block, _ := pem.Decode(buf)
|
||||||
|
|
||||||
|
|||||||
@@ -146,9 +146,9 @@ func (h *MaxHeap[T]) PrintStructure() {
|
|||||||
lastNum := powerTwo(level - 1)
|
lastNum := powerTwo(level - 1)
|
||||||
lastLen := lastNum + (lastNum - 1)
|
lastLen := lastNum + (lastNum - 1)
|
||||||
|
|
||||||
heapTree := make([][]string, level, level)
|
heapTree := make([][]string, level)
|
||||||
for i := 0; i < level; i++ {
|
for i := 0; i < level; i++ {
|
||||||
heapTree[i] = make([]string, lastLen, lastLen)
|
heapTree[i] = make([]string, lastLen)
|
||||||
for j := 0; j < lastLen; j++ {
|
for j := 0; j < lastLen; j++ {
|
||||||
heapTree[i][j] = ""
|
heapTree[i][j] = ""
|
||||||
}
|
}
|
||||||
@@ -169,9 +169,9 @@ func (h *MaxHeap[T]) PrintStructure() {
|
|||||||
for n := 0; n < lastLen; n++ {
|
for n := 0; n < lastLen; n++ {
|
||||||
val := heapTree[m][n]
|
val := heapTree[m][n]
|
||||||
if val == "" {
|
if val == "" {
|
||||||
fmt.Printf(" ")
|
fmt.Print(" ")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf(val)
|
fmt.Print(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
|||||||
assert.Equal(expected, heap.data)
|
assert.Equal(expected, heap.data)
|
||||||
|
|
||||||
assert.Equal(12, heap.Size())
|
assert.Equal(12, heap.Size())
|
||||||
|
|
||||||
heap.PrintStructure()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxHeap_Push(t *testing.T) {
|
func TestMaxHeap_Push(t *testing.T) {
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package datastructure
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/datastructure"
|
"github.com/duke-git/lancet/v2/datastructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the link, Next pointer points to a next node of the link.
|
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the dl, Next pointer points to a next node of the dl.
|
||||||
type DoublyLink[T any] struct {
|
type DoublyLink[T any] struct {
|
||||||
Head *datastructure.LinkNode[T]
|
Head *datastructure.LinkNode[T]
|
||||||
length int
|
length int
|
||||||
@@ -19,30 +18,30 @@ func NewDoublyLink[T any]() *DoublyLink[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertAtHead insert value into doubly linklist at head index
|
// InsertAtHead insert value into doubly linklist at head index
|
||||||
func (link *DoublyLink[T]) InsertAtHead(value T) {
|
func (dl *DoublyLink[T]) InsertAtHead(value T) {
|
||||||
newNode := datastructure.NewLinkNode(value)
|
newNode := datastructure.NewLinkNode(value)
|
||||||
size := link.Size()
|
size := dl.Size()
|
||||||
|
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
link.Head = newNode
|
dl.Head = newNode
|
||||||
link.length++
|
dl.length++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newNode.Next = link.Head
|
newNode.Next = dl.Head
|
||||||
newNode.Pre = nil
|
newNode.Pre = nil
|
||||||
|
|
||||||
link.Head.Pre = newNode
|
dl.Head.Pre = newNode
|
||||||
link.Head = newNode
|
dl.Head = newNode
|
||||||
|
|
||||||
link.length++
|
dl.length++
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertAtTail insert value into doubly linklist at tail index
|
// InsertAtTail insert value into doubly linklist at tail index
|
||||||
func (link *DoublyLink[T]) InsertAtTail(value T) {
|
func (dl *DoublyLink[T]) InsertAtTail(value T) {
|
||||||
current := link.Head
|
current := dl.Head
|
||||||
if current == nil {
|
if current == nil {
|
||||||
link.InsertAtHead(value)
|
dl.InsertAtHead(value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,28 +54,29 @@ func (link *DoublyLink[T]) InsertAtTail(value T) {
|
|||||||
newNode.Pre = current
|
newNode.Pre = current
|
||||||
current.Next = newNode
|
current.Next = newNode
|
||||||
|
|
||||||
link.length++
|
dl.length++
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertAt insert value into doubly linklist at index
|
// InsertAt insert value into doubly linklist at index
|
||||||
func (link *DoublyLink[T]) InsertAt(index int, value T) error {
|
// param `index` should between [0, length], if index do not meet the conditions, do nothing
|
||||||
size := link.length
|
func (dl *DoublyLink[T]) InsertAt(index int, value T) {
|
||||||
|
size := dl.length
|
||||||
if index < 0 || index > size {
|
if index < 0 || index > size {
|
||||||
return errors.New("param index should between 0 and the length of doubly link.")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
link.InsertAtHead(value)
|
dl.InsertAtHead(value)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == size {
|
if index == size {
|
||||||
link.InsertAtTail(value)
|
dl.InsertAtTail(value)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
current := link.Head
|
current := dl.Head
|
||||||
|
|
||||||
for current != nil {
|
for current != nil {
|
||||||
if i == index-1 {
|
if i == index-1 {
|
||||||
@@ -85,38 +85,36 @@ func (link *DoublyLink[T]) InsertAt(index int, value T) error {
|
|||||||
newNode.Pre = current
|
newNode.Pre = current
|
||||||
|
|
||||||
current.Next = newNode
|
current.Next = newNode
|
||||||
link.length++
|
dl.length++
|
||||||
|
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
current = current.Next
|
current = current.Next
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New("doubly link list no exist")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAtHead delete value in doubly linklist at head index
|
// DeleteAtHead delete value in doubly linklist at head index
|
||||||
func (link *DoublyLink[T]) DeleteAtHead() error {
|
func (dl *DoublyLink[T]) DeleteAtHead() {
|
||||||
if link.Head == nil {
|
if dl.Head == nil {
|
||||||
return errors.New("doubly link list no exist")
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
|
||||||
link.Head = current.Next
|
|
||||||
link.Head.Pre = nil
|
|
||||||
link.length--
|
|
||||||
|
|
||||||
return nil
|
current := dl.Head
|
||||||
|
dl.Head = current.Next
|
||||||
|
dl.Head.Pre = nil
|
||||||
|
dl.length--
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAtTail delete value in doubly linklist at tail index
|
// DeleteAtTail delete value in doubly linklist at tail
|
||||||
func (link *DoublyLink[T]) DeleteAtTail() error {
|
func (dl *DoublyLink[T]) DeleteAtTail() {
|
||||||
if link.Head == nil {
|
if dl.Head == nil {
|
||||||
return errors.New("doubly link list no exist")
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
|
||||||
|
current := dl.Head
|
||||||
if current.Next == nil {
|
if current.Next == nil {
|
||||||
return link.DeleteAtHead()
|
dl.DeleteAtHead()
|
||||||
}
|
}
|
||||||
|
|
||||||
for current.Next.Next != nil {
|
for current.Next.Next != nil {
|
||||||
@@ -124,45 +122,44 @@ func (link *DoublyLink[T]) DeleteAtTail() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
current.Next = nil
|
current.Next = nil
|
||||||
link.length--
|
dl.length--
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAt delete value in doubly linklist at index
|
// DeleteAt delete value in doubly linklist at index
|
||||||
func (link *DoublyLink[T]) DeleteAt(index int) error {
|
// param `index` should be [0, len(DoublyLink)-1]
|
||||||
if link.Head == nil {
|
func (dl *DoublyLink[T]) DeleteAt(index int) {
|
||||||
return errors.New("doubly link list no exist")
|
if dl.Head == nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
|
||||||
|
current := dl.Head
|
||||||
if current.Next == nil || index == 0 {
|
if current.Next == nil || index == 0 {
|
||||||
return link.DeleteAtHead()
|
dl.DeleteAtHead()
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == link.length-1 {
|
if index == dl.length-1 {
|
||||||
return link.DeleteAtTail()
|
dl.DeleteAtTail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < 0 || index > link.length-1 {
|
if index < 0 || index > dl.length-1 {
|
||||||
return errors.New("param index should between 0 and link size -1.")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for current != nil {
|
for current != nil {
|
||||||
if i == index-1 {
|
if i == index-1 {
|
||||||
current.Next = current.Next.Next
|
current.Next = current.Next.Next
|
||||||
link.length--
|
dl.length--
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
current = current.Next
|
current = current.Next
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New("delete error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse the linked list
|
// Reverse the linked list
|
||||||
func (link *DoublyLink[T]) Reverse() {
|
func (dl *DoublyLink[T]) Reverse() {
|
||||||
current := link.Head
|
current := dl.Head
|
||||||
var temp *datastructure.LinkNode[T]
|
var temp *datastructure.LinkNode[T]
|
||||||
|
|
||||||
for current != nil {
|
for current != nil {
|
||||||
@@ -173,20 +170,20 @@ func (link *DoublyLink[T]) Reverse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if temp != nil {
|
if temp != nil {
|
||||||
link.Head = temp.Pre
|
dl.Head = temp.Pre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMiddleNode return node at middle index of linked list
|
// GetMiddleNode return node at middle index of linked list
|
||||||
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
func (dl *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
||||||
if link.Head == nil {
|
if dl.Head == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if link.Head.Next == nil {
|
if dl.Head.Next == nil {
|
||||||
return link.Head
|
return dl.Head
|
||||||
}
|
}
|
||||||
fast := link.Head
|
fast := dl.Head
|
||||||
slow := link.Head
|
slow := dl.Head
|
||||||
|
|
||||||
for fast != nil {
|
for fast != nil {
|
||||||
fast = fast.Next
|
fast = fast.Next
|
||||||
@@ -202,14 +199,14 @@ func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size return the count of doubly linked list
|
// Size return the count of doubly linked list
|
||||||
func (link *DoublyLink[T]) Size() int {
|
func (dl *DoublyLink[T]) Size() int {
|
||||||
return link.length
|
return dl.length
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values return slice of all doubly linklist node value
|
// Values return slice of all doubly linklist node value
|
||||||
func (link *DoublyLink[T]) Values() []T {
|
func (dl *DoublyLink[T]) Values() []T {
|
||||||
result := []T{}
|
result := []T{}
|
||||||
current := link.Head
|
current := dl.Head
|
||||||
for current != nil {
|
for current != nil {
|
||||||
result = append(result, current.Value)
|
result = append(result, current.Value)
|
||||||
current = current.Next
|
current = current.Next
|
||||||
@@ -218,8 +215,8 @@ func (link *DoublyLink[T]) Values() []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print all nodes info of a linked list
|
// Print all nodes info of a linked list
|
||||||
func (link *DoublyLink[T]) Print() {
|
func (dl *DoublyLink[T]) Print() {
|
||||||
current := link.Head
|
current := dl.Head
|
||||||
info := "[ "
|
info := "[ "
|
||||||
for current != nil {
|
for current != nil {
|
||||||
info += fmt.Sprintf("%+v, ", current)
|
info += fmt.Sprintf("%+v, ", current)
|
||||||
@@ -229,13 +226,13 @@ func (link *DoublyLink[T]) Print() {
|
|||||||
fmt.Println(info)
|
fmt.Println(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty checks if link is empty or not
|
// IsEmpty checks if dl is empty or not
|
||||||
func (link *DoublyLink[T]) IsEmpty() bool {
|
func (dl *DoublyLink[T]) IsEmpty() bool {
|
||||||
return link.length == 0
|
return dl.length == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all nodes in doubly linklist
|
// Clear all nodes in doubly linklist
|
||||||
func (link *DoublyLink[T]) Clear() {
|
func (dl *DoublyLink[T]) Clear() {
|
||||||
link.Head = nil
|
dl.Head = nil
|
||||||
link.length = 0
|
dl.length = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,29 +41,24 @@ func TestDoublyLink_InsertAt(t *testing.T) {
|
|||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
|
|
||||||
err := link.InsertAt(1, 1)
|
link.InsertAt(1, 1) //do nothing
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAt(0, 1)
|
link.InsertAt(0, 1)
|
||||||
link.InsertAt(1, 2)
|
link.InsertAt(1, 2)
|
||||||
link.InsertAt(2, 4)
|
link.InsertAt(2, 4)
|
||||||
link.InsertAt(2, 3)
|
link.InsertAt(2, 3)
|
||||||
|
|
||||||
link.Print()
|
|
||||||
|
|
||||||
expected := []int{1, 2, 3, 4}
|
expected := []int{1, 2, 3, 4}
|
||||||
values := link.Values()
|
values := link.Values()
|
||||||
|
|
||||||
assert.Equal(expected, values)
|
assert.Equal(expected, values)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
err := link.DeleteAtHead()
|
link.DeleteAtHead()
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -71,7 +66,6 @@ func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
|
|
||||||
link.DeleteAtHead()
|
link.DeleteAtHead()
|
||||||
link.Print()
|
|
||||||
|
|
||||||
expected := []int{2, 3, 4}
|
expected := []int{2, 3, 4}
|
||||||
values := link.Values()
|
values := link.Values()
|
||||||
@@ -83,8 +77,7 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
err := link.DeleteAtTail()
|
link.DeleteAtTail()
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -92,7 +85,6 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
|
|
||||||
link.DeleteAtTail()
|
link.DeleteAtTail()
|
||||||
link.Print()
|
|
||||||
|
|
||||||
expected := []int{1, 2, 3}
|
expected := []int{1, 2, 3}
|
||||||
values := link.Values()
|
values := link.Values()
|
||||||
@@ -104,8 +96,7 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
err := link.DeleteAt(0)
|
link.DeleteAt(0)
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -113,11 +104,7 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
link.InsertAtTail(5)
|
link.InsertAtTail(5)
|
||||||
|
|
||||||
err = link.DeleteAt(5)
|
link.DeleteAt(0)
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
err = link.DeleteAt(0)
|
|
||||||
assert.IsNil(err)
|
|
||||||
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
||||||
|
|
||||||
link.DeleteAt(3)
|
link.DeleteAt(3)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package datastructure
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/datastructure"
|
"github.com/duke-git/lancet/v2/datastructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SinglyLink is a linked list. Whose node has a Value generics and Next pointer points to a next node of the link.
|
// SinglyLink is a linked list. Whose node has a Value generics and Next pointer points to a next node of the sl.
|
||||||
type SinglyLink[T any] struct {
|
type SinglyLink[T any] struct {
|
||||||
Head *datastructure.LinkNode[T]
|
Head *datastructure.LinkNode[T]
|
||||||
length int
|
length int
|
||||||
@@ -20,18 +19,18 @@ func NewSinglyLink[T any]() *SinglyLink[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertAtHead insert value into singly linklist at head index
|
// InsertAtHead insert value into singly linklist at head index
|
||||||
func (link *SinglyLink[T]) InsertAtHead(value T) {
|
func (sl *SinglyLink[T]) InsertAtHead(value T) {
|
||||||
newNode := datastructure.NewLinkNode(value)
|
newNode := datastructure.NewLinkNode(value)
|
||||||
newNode.Next = link.Head
|
newNode.Next = sl.Head
|
||||||
link.Head = newNode
|
sl.Head = newNode
|
||||||
link.length++
|
sl.length++
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertAtTail insert value into singly linklist at tail index
|
// InsertAtTail insert value into singly linklist at tail index
|
||||||
func (link *SinglyLink[T]) InsertAtTail(value T) {
|
func (sl *SinglyLink[T]) InsertAtTail(value T) {
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
if current == nil {
|
if current == nil {
|
||||||
link.InsertAtHead(value)
|
sl.InsertAtHead(value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,65 +42,63 @@ func (link *SinglyLink[T]) InsertAtTail(value T) {
|
|||||||
newNode.Next = nil
|
newNode.Next = nil
|
||||||
current.Next = newNode
|
current.Next = newNode
|
||||||
|
|
||||||
link.length++
|
sl.length++
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertAt insert value into singly linklist at index
|
// InsertAt insert value into singly linklist at index
|
||||||
func (link *SinglyLink[T]) InsertAt(index int, value T) error {
|
// param `index` should between [0, len(SinglyLink)], if index do not meet the conditions, do nothing
|
||||||
size := link.length
|
func (sl *SinglyLink[T]) InsertAt(index int, value T) {
|
||||||
|
size := sl.length
|
||||||
if index < 0 || index > size {
|
if index < 0 || index > size {
|
||||||
return errors.New("param index should between 0 and the length of singly link.")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
link.InsertAtHead(value)
|
sl.InsertAtHead(value)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == size {
|
if index == size {
|
||||||
link.InsertAtTail(value)
|
sl.InsertAtTail(value)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
|
|
||||||
for current != nil {
|
for current != nil {
|
||||||
if i == index-1 {
|
if i == index-1 {
|
||||||
newNode := datastructure.NewLinkNode(value)
|
newNode := datastructure.NewLinkNode(value)
|
||||||
newNode.Next = current.Next
|
newNode.Next = current.Next
|
||||||
current.Next = newNode
|
current.Next = newNode
|
||||||
link.length++
|
sl.length++
|
||||||
|
return
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
current = current.Next
|
current = current.Next
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New("singly link list no exist")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAtHead delete value in singly linklist at head index
|
// DeleteAtHead delete value in singly linklist at head index
|
||||||
func (link *SinglyLink[T]) DeleteAtHead() error {
|
func (sl *SinglyLink[T]) DeleteAtHead() {
|
||||||
if link.Head == nil {
|
if sl.Head == nil {
|
||||||
return errors.New("singly link list no exist")
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
|
||||||
link.Head = current.Next
|
|
||||||
link.length--
|
|
||||||
|
|
||||||
return nil
|
current := sl.Head
|
||||||
|
sl.Head = current.Next
|
||||||
|
sl.length--
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAtTail delete value in singly linklist at tail index
|
// DeleteAtTail delete value in singly linklist at tail
|
||||||
func (link *SinglyLink[T]) DeleteAtTail() error {
|
func (sl *SinglyLink[T]) DeleteAtTail() {
|
||||||
if link.Head == nil {
|
if sl.Head == nil {
|
||||||
return errors.New("singly link list no exist")
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
|
||||||
|
current := sl.Head
|
||||||
if current.Next == nil {
|
if current.Next == nil {
|
||||||
return link.DeleteAtHead()
|
sl.DeleteAtHead()
|
||||||
}
|
}
|
||||||
|
|
||||||
for current.Next.Next != nil {
|
for current.Next.Next != nil {
|
||||||
@@ -109,68 +106,66 @@ func (link *SinglyLink[T]) DeleteAtTail() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
current.Next = nil
|
current.Next = nil
|
||||||
link.length--
|
sl.length--
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAt delete value in singly linklist at index
|
// DeleteAt delete value in singly linklist at index
|
||||||
func (link *SinglyLink[T]) DeleteAt(index int) error {
|
// param `index` should be [0, len(SinglyLink)-1]
|
||||||
if link.Head == nil {
|
func (sl *SinglyLink[T]) DeleteAt(index int) {
|
||||||
return errors.New("singly link list no exist")
|
if sl.Head == nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
if current.Next == nil || index == 0 {
|
if current.Next == nil || index == 0 {
|
||||||
return link.DeleteAtHead()
|
sl.DeleteAtHead()
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == link.length-1 {
|
if index == sl.length-1 {
|
||||||
return link.DeleteAtTail()
|
sl.DeleteAtTail()
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < 0 || index > link.length-1 {
|
if index < 0 || index > sl.length-1 {
|
||||||
return errors.New("param index should between 0 and link size -1.")
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for current != nil {
|
for current != nil {
|
||||||
if i == index-1 {
|
if i == index-1 {
|
||||||
current.Next = current.Next.Next
|
current.Next = current.Next.Next
|
||||||
link.length--
|
sl.length--
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
current = current.Next
|
current = current.Next
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.New("delete error")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteValue delete value in singly linklist
|
// DeleteValue delete value in singly linklist
|
||||||
func (link *SinglyLink[T]) DeleteValue(value T) {
|
func (sl *SinglyLink[T]) DeleteValue(value T) {
|
||||||
if link.Head == nil {
|
if sl.Head == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dummyHead := datastructure.NewLinkNode(value)
|
dummyHead := datastructure.NewLinkNode(value)
|
||||||
dummyHead.Next = link.Head
|
dummyHead.Next = sl.Head
|
||||||
current := dummyHead
|
current := dummyHead
|
||||||
|
|
||||||
for current.Next != nil {
|
for current.Next != nil {
|
||||||
if reflect.DeepEqual(current.Next.Value, value) {
|
if reflect.DeepEqual(current.Next.Value, value) {
|
||||||
current.Next = current.Next.Next
|
current.Next = current.Next.Next
|
||||||
link.length--
|
sl.length--
|
||||||
} else {
|
} else {
|
||||||
current = current.Next
|
current = current.Next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
link.Head = dummyHead.Next
|
sl.Head = dummyHead.Next
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse the linked list
|
// Reverse the linked list
|
||||||
func (link *SinglyLink[T]) Reverse() {
|
func (sl *SinglyLink[T]) Reverse() {
|
||||||
var pre, next *datastructure.LinkNode[T]
|
var pre, next *datastructure.LinkNode[T]
|
||||||
|
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
|
|
||||||
for current != nil {
|
for current != nil {
|
||||||
next = current.Next
|
next = current.Next
|
||||||
@@ -179,19 +174,19 @@ func (link *SinglyLink[T]) Reverse() {
|
|||||||
current = next
|
current = next
|
||||||
}
|
}
|
||||||
|
|
||||||
link.Head = pre
|
sl.Head = pre
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMiddleNode return node at middle index of linked list
|
// GetMiddleNode return node at middle index of linked list
|
||||||
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
func (sl *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
||||||
if link.Head == nil {
|
if sl.Head == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if link.Head.Next == nil {
|
if sl.Head.Next == nil {
|
||||||
return link.Head
|
return sl.Head
|
||||||
}
|
}
|
||||||
fast := link.Head
|
fast := sl.Head
|
||||||
slow := link.Head
|
slow := sl.Head
|
||||||
|
|
||||||
for fast != nil {
|
for fast != nil {
|
||||||
fast = fast.Next
|
fast = fast.Next
|
||||||
@@ -207,14 +202,14 @@ func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size return the count of singly linked list
|
// Size return the count of singly linked list
|
||||||
func (link *SinglyLink[T]) Size() int {
|
func (sl *SinglyLink[T]) Size() int {
|
||||||
return link.length
|
return sl.length
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values return slice of all singly linklist node value
|
// Values return slice of all singly linklist node value
|
||||||
func (link *SinglyLink[T]) Values() []T {
|
func (sl *SinglyLink[T]) Values() []T {
|
||||||
result := []T{}
|
result := []T{}
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
for current != nil {
|
for current != nil {
|
||||||
result = append(result, current.Value)
|
result = append(result, current.Value)
|
||||||
current = current.Next
|
current = current.Next
|
||||||
@@ -222,20 +217,20 @@ func (link *SinglyLink[T]) Values() []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty checks if link is empty or not
|
// IsEmpty checks if sl is empty or not
|
||||||
func (link *SinglyLink[T]) IsEmpty() bool {
|
func (sl *SinglyLink[T]) IsEmpty() bool {
|
||||||
return link.length == 0
|
return sl.length == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all the node in singly linklist
|
// Clear all the node in singly linklist
|
||||||
func (link *SinglyLink[T]) Clear() {
|
func (sl *SinglyLink[T]) Clear() {
|
||||||
link.Head = nil
|
sl.Head = nil
|
||||||
link.length = 0
|
sl.length = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print all nodes info of a linked list
|
// Print all nodes info of a linked list
|
||||||
func (link *SinglyLink[T]) Print() {
|
func (sl *SinglyLink[T]) Print() {
|
||||||
current := link.Head
|
current := sl.Head
|
||||||
info := "[ "
|
info := "[ "
|
||||||
for current != nil {
|
for current != nil {
|
||||||
info += fmt.Sprintf("%+v, ", current)
|
info += fmt.Sprintf("%+v, ", current)
|
||||||
|
|||||||
@@ -41,25 +41,12 @@ func TestSinglyLink_InsertAt(t *testing.T) {
|
|||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
|
|
||||||
err := link.InsertAt(1, 1)
|
link.InsertAt(1, 1) //do nothing
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
err = link.InsertAt(0, 1)
|
link.InsertAt(0, 1)
|
||||||
if err != nil {
|
link.InsertAt(1, 2)
|
||||||
t.FailNow()
|
link.InsertAt(2, 4)
|
||||||
}
|
link.InsertAt(2, 3)
|
||||||
err = link.InsertAt(1, 2)
|
|
||||||
if err != nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
err = link.InsertAt(2, 4)
|
|
||||||
if err != nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
err = link.InsertAt(2, 3)
|
|
||||||
if err != nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
link.Print()
|
link.Print()
|
||||||
|
|
||||||
@@ -73,8 +60,8 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
err := link.DeleteAtHead()
|
|
||||||
assert.IsNotNil(err)
|
link.DeleteAtHead()
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -94,8 +81,6 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
err := link.DeleteAtTail()
|
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -103,7 +88,6 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
|
|
||||||
link.DeleteAtTail()
|
link.DeleteAtTail()
|
||||||
link.Print()
|
|
||||||
|
|
||||||
expected := []int{1, 2, 3}
|
expected := []int{1, 2, 3}
|
||||||
values := link.Values()
|
values := link.Values()
|
||||||
@@ -133,8 +117,6 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
err := link.DeleteAt(0)
|
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -142,11 +124,7 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
link.InsertAtTail(5)
|
link.InsertAtTail(5)
|
||||||
|
|
||||||
err = link.DeleteAt(5)
|
link.DeleteAt(0)
|
||||||
assert.IsNotNil(err)
|
|
||||||
|
|
||||||
err = link.DeleteAt(0)
|
|
||||||
assert.IsNil(err)
|
|
||||||
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
assert.Equal([]int{2, 3, 4, 5}, link.Values())
|
||||||
|
|
||||||
link.DeleteAt(3)
|
link.DeleteAt(3)
|
||||||
@@ -167,7 +145,6 @@ func TestSinglyLink_Reverse(t *testing.T) {
|
|||||||
link.InsertAtTail(4)
|
link.InsertAtTail(4)
|
||||||
|
|
||||||
link.Reverse()
|
link.Reverse()
|
||||||
link.Print()
|
|
||||||
assert.Equal([]int{4, 3, 2, 1}, link.Values())
|
assert.Equal([]int{4, 3, 2, 1}, link.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ func (l *List[T]) DeleteAt(index int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if index == size-1 {
|
if index == size-1 {
|
||||||
data = append(data[:index])
|
data = data[:index]
|
||||||
} else {
|
} else {
|
||||||
data = append(data[:index], data[index+1:]...)
|
data = append(data[:index], data[index+1:]...)
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ func (l *List[T]) DeleteIf(f func(T) bool) int {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if index == size-1 {
|
if index == size-1 {
|
||||||
data = append(data[:index])
|
data = data[:index]
|
||||||
} else {
|
} else {
|
||||||
data = append(data[:index], data[index+1:]...)
|
data = append(data[:index], data[index+1:]...)
|
||||||
index--
|
index--
|
||||||
@@ -221,7 +221,7 @@ func (l *List[T]) IsEmpty() bool {
|
|||||||
|
|
||||||
// Clear the data of list
|
// Clear the data of list
|
||||||
func (l *List[T]) Clear() {
|
func (l *List[T]) Clear() {
|
||||||
l.data = make([]T, 0, 0)
|
l.data = make([]T, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone return a copy of list
|
// Clone return a copy of list
|
||||||
@@ -235,7 +235,7 @@ func (l *List[T]) Clone() *List[T] {
|
|||||||
// Merge two list, return new list, don't change original list
|
// Merge two list, return new list, don't change original list
|
||||||
func (l *List[T]) Merge(other *List[T]) *List[T] {
|
func (l *List[T]) Merge(other *List[T]) *List[T] {
|
||||||
l1, l2 := len(l.data), len(other.data)
|
l1, l2 := len(l.data), len(other.data)
|
||||||
ml := NewList(make([]T, l1+l2, l1+l2))
|
ml := NewList(make([]T, l1+l2))
|
||||||
|
|
||||||
data := append([]T{}, append(l.data, other.data...)...)
|
data := append([]T{}, append(l.data, other.data...)...)
|
||||||
ml.data = data
|
ml.data = data
|
||||||
@@ -274,7 +274,7 @@ func (l *List[T]) Unique() {
|
|||||||
data := l.data
|
data := l.data
|
||||||
size := len(data)
|
size := len(data)
|
||||||
|
|
||||||
uniqueData := make([]T, 0, 0)
|
uniqueData := make([]T, 0)
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
value := data[i]
|
value := data[i]
|
||||||
skip := true
|
skip := true
|
||||||
@@ -305,7 +305,7 @@ func (l *List[T]) Union(other *List[T]) *List[T] {
|
|||||||
|
|
||||||
// Intersection creates a new list whose element both be contained in list l and other
|
// Intersection creates a new list whose element both be contained in list l and other
|
||||||
func (l *List[T]) Intersection(other *List[T]) *List[T] {
|
func (l *List[T]) Intersection(other *List[T]) *List[T] {
|
||||||
result := NewList(make([]T, 0, 0))
|
result := NewList(make([]T, 0))
|
||||||
|
|
||||||
for _, v := range l.data {
|
for _, v := range l.data {
|
||||||
if other.Contain(v) {
|
if other.Contain(v) {
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ func TestArrayQueue_Enqueue(t *testing.T) {
|
|||||||
data := queue.Data()
|
data := queue.Data()
|
||||||
size := queue.Size()
|
size := queue.Size()
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
|
|
||||||
assert.Equal(expected, data)
|
assert.Equal(expected, data)
|
||||||
assert.Equal(3, size)
|
assert.Equal(3, size)
|
||||||
}
|
}
|
||||||
@@ -35,7 +33,6 @@ func TestArrayQueue_Dequeue(t *testing.T) {
|
|||||||
val, ok := queue.Dequeue()
|
val, ok := queue.Dequeue()
|
||||||
assert.Equal(true, ok)
|
assert.Equal(true, ok)
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
assert.Equal(1, val)
|
assert.Equal(1, val)
|
||||||
assert.Equal([]int{2, 3}, queue.Data())
|
assert.Equal([]int{2, 3}, queue.Data())
|
||||||
}
|
}
|
||||||
@@ -50,8 +47,6 @@ func TestArrayQueue_Front(t *testing.T) {
|
|||||||
|
|
||||||
val := queue.Front()
|
val := queue.Front()
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
|
|
||||||
assert.Equal(1, val)
|
assert.Equal(1, val)
|
||||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||||
}
|
}
|
||||||
@@ -66,8 +61,6 @@ func TestArrayQueue_Back(t *testing.T) {
|
|||||||
|
|
||||||
val := queue.Back()
|
val := queue.Back()
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
|
|
||||||
assert.Equal(3, val)
|
assert.Equal(3, val)
|
||||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,31 +10,43 @@ func TestCircularQueue_Enqueue(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](6)
|
||||||
queue.Enqueue(1)
|
|
||||||
queue.Enqueue(2)
|
|
||||||
queue.Enqueue(3)
|
|
||||||
queue.Enqueue(4)
|
|
||||||
queue.Enqueue(5)
|
|
||||||
|
|
||||||
queue.Print()
|
err := queue.Enqueue(1)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = queue.Enqueue(2)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = queue.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = queue.Enqueue(4)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = queue.Enqueue(5)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
||||||
assert.Equal(5, queue.Size())
|
assert.Equal(5, queue.Size())
|
||||||
|
|
||||||
err := queue.Enqueue(6)
|
err = queue.Enqueue(6)
|
||||||
assert.IsNotNil(err)
|
assert.IsNotNil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Dequeue(t *testing.T) {
|
func TestCircularQueue_Dequeue(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](4)
|
||||||
assert.Equal(true, queue.IsEmpty())
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
|
||||||
queue.Enqueue(1)
|
err := queue.Enqueue(1)
|
||||||
queue.Enqueue(2)
|
assert.IsNil(err)
|
||||||
queue.Enqueue(3)
|
|
||||||
queue.Enqueue(4)
|
err = queue.Enqueue(2)
|
||||||
queue.Enqueue(5)
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = queue.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
val, err := queue.Dequeue()
|
val, err := queue.Dequeue()
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
@@ -43,11 +55,7 @@ func TestCircularQueue_Dequeue(t *testing.T) {
|
|||||||
assert.Equal(false, queue.IsFull())
|
assert.Equal(false, queue.IsFull())
|
||||||
|
|
||||||
val, _ = queue.Dequeue()
|
val, _ = queue.Dequeue()
|
||||||
queue.Print()
|
|
||||||
assert.Equal(2, *val)
|
assert.Equal(2, *val)
|
||||||
|
|
||||||
queue.Enqueue(6)
|
|
||||||
queue.Print()
|
|
||||||
assert.Equal(false, queue.IsFull())
|
assert.Equal(false, queue.IsFull())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,55 +63,52 @@ func TestCircularQueue_Front(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](6)
|
||||||
queue.Enqueue(1)
|
|
||||||
queue.Enqueue(2)
|
|
||||||
queue.Enqueue(3)
|
|
||||||
queue.Enqueue(4)
|
|
||||||
queue.Enqueue(5)
|
|
||||||
|
|
||||||
queue.Print()
|
err := queue.Enqueue(1)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
queue.Dequeue()
|
err = queue.Enqueue(2)
|
||||||
queue.Dequeue()
|
assert.IsNil(err)
|
||||||
queue.Enqueue(6)
|
|
||||||
queue.Enqueue(7)
|
|
||||||
|
|
||||||
queue.Print()
|
err = queue.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
val := queue.Front()
|
val := queue.Front()
|
||||||
assert.Equal(3, val)
|
assert.IsNil(err)
|
||||||
assert.Equal(5, queue.Size())
|
assert.Equal(1, val)
|
||||||
|
assert.Equal(3, queue.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Back(t *testing.T) {
|
func TestCircularQueue_Back(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](3)
|
||||||
assert.Equal(true, queue.IsEmpty())
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
|
||||||
queue.Enqueue(1)
|
err := queue.Enqueue(1)
|
||||||
queue.Enqueue(2)
|
assert.IsNil(err)
|
||||||
queue.Enqueue(3)
|
|
||||||
queue.Enqueue(4)
|
|
||||||
queue.Enqueue(5)
|
|
||||||
|
|
||||||
queue.Print()
|
err = queue.Enqueue(2)
|
||||||
assert.Equal(5, queue.Back())
|
assert.IsNil(err)
|
||||||
|
|
||||||
queue.Dequeue()
|
assert.Equal(2, queue.Back())
|
||||||
queue.Dequeue()
|
|
||||||
queue.Enqueue(6)
|
|
||||||
queue.Enqueue(7)
|
|
||||||
|
|
||||||
queue.Print()
|
val, _ := queue.Dequeue()
|
||||||
assert.Equal(7, queue.Back())
|
assert.Equal(1, *val)
|
||||||
|
|
||||||
|
err = queue.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
assert.Equal(3, queue.Back())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Contain(t *testing.T) {
|
func TestCircularQueue_Contain(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](2)
|
queue := NewCircularQueue[int](2)
|
||||||
queue.Enqueue(1)
|
err := queue.Enqueue(1)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal(true, queue.Contain(1))
|
assert.Equal(true, queue.Contain(1))
|
||||||
assert.Equal(false, queue.Contain(2))
|
assert.Equal(false, queue.Contain(2))
|
||||||
}
|
}
|
||||||
@@ -115,7 +120,9 @@ func TestCircularQueue_Clear(t *testing.T) {
|
|||||||
assert.Equal(true, queue.IsEmpty())
|
assert.Equal(true, queue.IsEmpty())
|
||||||
assert.Equal(0, queue.Size())
|
assert.Equal(0, queue.Size())
|
||||||
|
|
||||||
queue.Enqueue(1)
|
err := queue.Enqueue(1)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal(false, queue.IsEmpty())
|
assert.Equal(false, queue.IsEmpty())
|
||||||
assert.Equal(1, queue.Size())
|
assert.Equal(1, queue.Size())
|
||||||
|
|
||||||
@@ -127,22 +134,12 @@ func TestCircularQueue_Clear(t *testing.T) {
|
|||||||
func TestCircularQueue_Data(t *testing.T) {
|
func TestCircularQueue_Data(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](3)
|
||||||
queue.Enqueue(1)
|
err := queue.Enqueue(1)
|
||||||
queue.Enqueue(2)
|
assert.IsNil(err)
|
||||||
queue.Enqueue(3)
|
|
||||||
queue.Enqueue(4)
|
|
||||||
queue.Enqueue(5)
|
|
||||||
|
|
||||||
queue.Print()
|
err = queue.Enqueue(2)
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
|
assert.IsNil(err)
|
||||||
|
|
||||||
queue.Dequeue()
|
|
||||||
queue.Dequeue()
|
|
||||||
queue.Enqueue(6)
|
|
||||||
queue.Enqueue(7)
|
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
|
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2}, queue.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ func TestLinkedQueue_Enqueue(t *testing.T) {
|
|||||||
queue.Enqueue(2)
|
queue.Enqueue(2)
|
||||||
queue.Enqueue(3)
|
queue.Enqueue(3)
|
||||||
|
|
||||||
queue.Print()
|
|
||||||
|
|
||||||
assert.Equal([]int{1, 2, 3}, queue.Data())
|
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||||
assert.Equal(3, queue.Size())
|
assert.Equal(3, queue.Size())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,19 +23,24 @@ func TestPriorityQueue_Enqueue(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
|
||||||
|
|
||||||
comparator := &intComparator{}
|
comparator := &intComparator{}
|
||||||
pq := NewPriorityQueue[int](10, comparator)
|
pq := NewPriorityQueue[int](3, comparator)
|
||||||
|
|
||||||
assert.Equal(true, pq.IsEmpty())
|
assert.Equal(true, pq.IsEmpty())
|
||||||
assert.Equal(false, pq.IsFull())
|
assert.Equal(false, pq.IsFull())
|
||||||
|
|
||||||
for i := 1; i < 11; i++ {
|
err := pq.Enqueue(1)
|
||||||
pq.Enqueue(i)
|
assert.IsNil(err)
|
||||||
}
|
|
||||||
|
err = pq.Enqueue(2)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = pq.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal(true, pq.IsFull())
|
assert.Equal(true, pq.IsFull())
|
||||||
|
|
||||||
queueData := pq.Data()
|
queueData := pq.Data()
|
||||||
assert.Equal([]int{10, 9, 6, 7, 8, 2, 5, 1, 4, 3}, queueData)
|
assert.Equal([]int{3, 1, 2}, queueData)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,22 +48,23 @@ func TestPriorityQueue_Dequeue(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
|
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
|
||||||
|
|
||||||
comparator := &intComparator{}
|
comparator := &intComparator{}
|
||||||
pq := NewPriorityQueue[int](10, comparator)
|
pq := NewPriorityQueue[int](3, comparator)
|
||||||
|
|
||||||
_, ok := pq.Dequeue()
|
_, ok := pq.Dequeue()
|
||||||
assert.Equal(false, ok)
|
assert.Equal(false, ok)
|
||||||
|
|
||||||
for i := 1; i < 11; i++ {
|
err := pq.Enqueue(1)
|
||||||
pq.Enqueue(i)
|
assert.IsNil(err)
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(10, pq.Size())
|
err = pq.Enqueue(2)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
err = pq.Enqueue(3)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
assert.Equal(3, pq.Size())
|
||||||
|
|
||||||
val, ok := pq.Dequeue()
|
val, ok := pq.Dequeue()
|
||||||
assert.Equal(true, ok)
|
assert.Equal(true, ok)
|
||||||
assert.Equal(10, val)
|
assert.Equal(3, val)
|
||||||
|
|
||||||
assert.Equal([]int{9, 8, 6, 7, 3, 2, 5, 1, 4}, pq.Data())
|
|
||||||
|
|
||||||
assert.Equal(9, pq.Size())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,22 +4,59 @@ package datastructure
|
|||||||
type Set[T comparable] map[T]struct{}
|
type Set[T comparable] map[T]struct{}
|
||||||
|
|
||||||
// NewSet return a instance of set
|
// NewSet return a instance of set
|
||||||
func NewSet[T comparable](values ...T) Set[T] {
|
func NewSet[T comparable](items ...T) Set[T] {
|
||||||
set := make(Set[T])
|
set := make(Set[T])
|
||||||
set.Add(values...)
|
set.Add(items...)
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add value to set
|
// NewSetFromSlice create a set from slice
|
||||||
func (s Set[T]) Add(values ...T) {
|
func NewSetFromSlice[T comparable](items []T) Set[T] {
|
||||||
for _, v := range values {
|
set := make(Set[T])
|
||||||
|
for _, item := range items {
|
||||||
|
set.Add(item)
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add items to set
|
||||||
|
func (s Set[T]) Add(items ...T) {
|
||||||
|
for _, v := range items {
|
||||||
s[v] = struct{}{}
|
s[v] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contain checks if set contains value or not
|
// AddIfNotExist checks if item exists in the set,
|
||||||
func (s Set[T]) Contain(value T) bool {
|
// it adds the item to set and returns true if it does not exist in the set,
|
||||||
_, ok := s[value]
|
// or else it does nothing and returns false.
|
||||||
|
func (s Set[T]) AddIfNotExist(item T) bool {
|
||||||
|
if !s.Contain(item) {
|
||||||
|
if _, ok := s[item]; !ok {
|
||||||
|
s[item] = struct{}{}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIfNotExistBy checks if item exists in the set and pass the `checker` function
|
||||||
|
// it adds the item to set and returns true if it does not exists in the set and
|
||||||
|
// function `checker` returns true, or else it does nothing and returns false.
|
||||||
|
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool {
|
||||||
|
if !s.Contain(item) {
|
||||||
|
if checker(item) {
|
||||||
|
if _, ok := s[item]; !ok {
|
||||||
|
s[item] = struct{}{}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contain checks if set contains item or not
|
||||||
|
func (s Set[T]) Contain(item T) bool {
|
||||||
|
_, ok := s[item]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,9 +78,9 @@ func (s Set[T]) Clone() Set[T] {
|
|||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete value of set
|
// Delete item of set
|
||||||
func (s Set[T]) Delete(values ...T) {
|
func (s Set[T]) Delete(items ...T) {
|
||||||
for _, v := range values {
|
for _, v := range items {
|
||||||
delete(s, v)
|
delete(s, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +95,7 @@ func (s Set[T]) Equal(other Set[T]) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate call function by every element of set
|
// Iterate call function by every element of set
|
||||||
func (s Set[T]) Iterate(fn func(value T)) {
|
func (s Set[T]) Iterate(fn func(item T)) {
|
||||||
for v := range s {
|
for v := range s {
|
||||||
fn(v)
|
fn(v)
|
||||||
}
|
}
|
||||||
@@ -76,13 +113,13 @@ func (s Set[T]) Size() int {
|
|||||||
|
|
||||||
// Values return all values of set
|
// Values return all values of set
|
||||||
func (s Set[T]) Values() []T {
|
func (s Set[T]) Values() []T {
|
||||||
values := make([]T, 0, 0)
|
result := make([]T, 0, len(s))
|
||||||
|
|
||||||
s.Iterate(func(value T) {
|
s.Iterate(func(value T) {
|
||||||
values = append(values, value)
|
result = append(result, value)
|
||||||
})
|
})
|
||||||
|
|
||||||
return values
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Union creates a new set contain all element of set s and other
|
// Union creates a new set contain all element of set s and other
|
||||||
|
|||||||
@@ -6,6 +6,19 @@ import (
|
|||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestSet_NewSetFromSlice(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
|
||||||
|
|
||||||
|
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
|
||||||
|
assert.Equal(3, s1.Size())
|
||||||
|
assert.Equal(true, s1.Contain(1))
|
||||||
|
assert.Equal(true, s1.Contain(2))
|
||||||
|
assert.Equal(true, s1.Contain(3))
|
||||||
|
|
||||||
|
s2 := NewSetFromSlice([]int{})
|
||||||
|
assert.Equal(0, s2.Size())
|
||||||
|
}
|
||||||
|
|
||||||
func TestSet_Add(t *testing.T) {
|
func TestSet_Add(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestSet_Add")
|
assert := internal.NewAssert(t, "TestSet_Add")
|
||||||
|
|
||||||
@@ -17,6 +30,38 @@ func TestSet_Add(t *testing.T) {
|
|||||||
assert.Equal(true, set.Equal(expected))
|
assert.Equal(true, set.Equal(expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSet_AddIfNotExist(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
set.Add(1, 2, 3)
|
||||||
|
|
||||||
|
assert.Equal(false, set.AddIfNotExist(1))
|
||||||
|
assert.Equal(true, set.AddIfNotExist(4))
|
||||||
|
assert.Equal(NewSet(1, 2, 3, 4), set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
|
||||||
|
|
||||||
|
set := NewSet[int]()
|
||||||
|
set.Add(1, 2)
|
||||||
|
|
||||||
|
ok := set.AddIfNotExistBy(3, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
|
||||||
|
notOk := set.AddIfNotExistBy(4, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(true, ok)
|
||||||
|
assert.Equal(false, notOk)
|
||||||
|
|
||||||
|
assert.Equal(true, set.Contain(3))
|
||||||
|
assert.Equal(false, set.Contain(4))
|
||||||
|
}
|
||||||
|
|
||||||
func TestSet_Contain(t *testing.T) {
|
func TestSet_Contain(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestSet_Contain")
|
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ func TestLinkedStack_Push(t *testing.T) {
|
|||||||
stack.Push(2)
|
stack.Push(2)
|
||||||
stack.Push(3)
|
stack.Push(3)
|
||||||
|
|
||||||
stack.Print()
|
|
||||||
|
|
||||||
expected := []int{3, 2, 1}
|
expected := []int{3, 2, 1}
|
||||||
values := stack.Data()
|
values := stack.Data()
|
||||||
size := stack.Size()
|
size := stack.Size()
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ func TestBSTree_Insert(t *testing.T) {
|
|||||||
bstree.Insert(5)
|
bstree.Insert(5)
|
||||||
bstree.Insert(2)
|
bstree.Insert(2)
|
||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
bstree.Print()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_PreOrderTraverse(t *testing.T) {
|
func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||||
@@ -86,8 +84,6 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
|||||||
bstree.Insert(2)
|
bstree.Insert(2)
|
||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
bstree.Print()
|
|
||||||
|
|
||||||
acturl := bstree.LevelOrderTraverse()
|
acturl := bstree.LevelOrderTraverse()
|
||||||
t.Log(acturl)
|
t.Log(acturl)
|
||||||
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
||||||
@@ -103,10 +99,8 @@ func TestBSTree_Delete(t *testing.T) {
|
|||||||
bstree.Insert(2)
|
bstree.Insert(2)
|
||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
bstree.Print()
|
|
||||||
|
|
||||||
bstree.Delete(4)
|
bstree.Delete(4)
|
||||||
bstree.Print()
|
|
||||||
acturl1 := bstree.InOrderTraverse()
|
acturl1 := bstree.InOrderTraverse()
|
||||||
t.Log(acturl1)
|
t.Log(acturl1)
|
||||||
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
||||||
@@ -129,8 +123,6 @@ func TestBSTree_Depth(t *testing.T) {
|
|||||||
bstree.Insert(2)
|
bstree.Insert(2)
|
||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
bstree.Print()
|
|
||||||
|
|
||||||
assert.Equal(bstree.Depth(), 4)
|
assert.Equal(bstree.Depth(), 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,8 +142,6 @@ func TestBSTree_IsSubTree(t *testing.T) {
|
|||||||
subTree.Insert(4)
|
subTree.Insert(4)
|
||||||
subTree.Insert(6)
|
subTree.Insert(6)
|
||||||
|
|
||||||
subTree.Print()
|
|
||||||
|
|
||||||
assert.Equal(true, superTree.HasSubTree(subTree))
|
assert.Equal(true, superTree.HasSubTree(subTree))
|
||||||
assert.Equal(false, subTree.HasSubTree(superTree))
|
assert.Equal(false, subTree.HasSubTree(superTree))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,35 +38,35 @@ func inOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
func preOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
// func preOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||||
if node == nil {
|
// if node == nil {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
fmt.Printf("%v, ", node.Value)
|
// fmt.Printf("%v, ", node.Value)
|
||||||
preOrderPrint(node.Left)
|
// preOrderPrint(node.Left)
|
||||||
preOrderPrint(node.Right)
|
// preOrderPrint(node.Right)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func postOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
// func postOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||||
if node == nil {
|
// if node == nil {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
preOrderPrint(node.Left)
|
// postOrderPrint(node.Left)
|
||||||
preOrderPrint(node.Right)
|
// postOrderPrint(node.Right)
|
||||||
fmt.Printf("%v, ", node.Value)
|
// fmt.Printf("%v, ", node.Value)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func inOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
// func inOrderPrint[T any](node *datastructure.TreeNode[T]) {
|
||||||
if node == nil {
|
// if node == nil {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
inOrderPrint(node.Left)
|
// inOrderPrint(node.Left)
|
||||||
fmt.Printf("%v, ", node.Value)
|
// fmt.Printf("%v, ", node.Value)
|
||||||
inOrderPrint(node.Right)
|
// inOrderPrint(node.Right)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T) {
|
func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T) {
|
||||||
var q []*datastructure.TreeNode[T] // queue
|
var q []*datastructure.TreeNode[T] // queue
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Index
|
## Index
|
||||||
|
|
||||||
- [BubbleSort](#BubbleSort)
|
- [BubbleSort](#BubbleSort)
|
||||||
- [InsertionSort](#InsertionSort)
|
- [InsertionSort](#InsertionSort)
|
||||||
- [SelectionSort](#SelectionSort)
|
- [SelectionSort](#SelectionSort)
|
||||||
@@ -31,7 +32,6 @@ import (
|
|||||||
- [CountSort](#CountSort)
|
- [CountSort](#CountSort)
|
||||||
- [BinarySearch](#BinarySearch)
|
- [BinarySearch](#BinarySearch)
|
||||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||||
|
|
||||||
- [LinearSearch](#LinearSearch)
|
- [LinearSearch](#LinearSearch)
|
||||||
- [LRUCache](#LRUCache)
|
- [LRUCache](#LRUCache)
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import (
|
|||||||
- [QuickSort](#QuickSort)
|
- [QuickSort](#QuickSort)
|
||||||
- [HeapSort](#HeapSort)
|
- [HeapSort](#HeapSort)
|
||||||
- [MergeSort](#MergeSort)
|
- [MergeSort](#MergeSort)
|
||||||
|
|
||||||
- [CountSort](#CountSort)
|
- [CountSort](#CountSort)
|
||||||
- [BinarySearch](#BinarySearch)
|
- [BinarySearch](#BinarySearch)
|
||||||
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
- [BinaryIterativeSearch](#BinaryIterativeSearch)
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import (
|
|||||||
- [ToBytes](#ToBytes)
|
- [ToBytes](#ToBytes)
|
||||||
- [ToChar](#ToChar)
|
- [ToChar](#ToChar)
|
||||||
- [ToChannel](#ToChannel)
|
- [ToChannel](#ToChannel)
|
||||||
|
|
||||||
- [ToFloat](#ToFloat)
|
- [ToFloat](#ToFloat)
|
||||||
- [ToInt](#ToInt)
|
- [ToInt](#ToInt)
|
||||||
- [ToJson](#ToJson)
|
- [ToJson](#ToJson)
|
||||||
@@ -395,6 +394,32 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="ToString">ToString</span>
|
||||||
|
|
||||||
|
<p>ToString convert value to string, for number, string, []byte, will convert to string. For other type (slice, map, array, struct) will call json.Marshal</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToString(value any) string
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("%q", convertor.ToString(1)) //"1"
|
||||||
|
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
|
||||||
|
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="StructToMap">StructToMap</span>
|
### <span id="StructToMap">StructToMap</span>
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import (
|
|||||||
- [ToBytes](#ToBytes)
|
- [ToBytes](#ToBytes)
|
||||||
- [ToChar](#ToChar)
|
- [ToChar](#ToChar)
|
||||||
- [ToChannel](#ToChannel)
|
- [ToChannel](#ToChannel)
|
||||||
|
|
||||||
- [ToFloat](#ToFloat)
|
- [ToFloat](#ToFloat)
|
||||||
- [ToInt](#ToInt)
|
- [ToInt](#ToInt)
|
||||||
- [ToJson](#ToJson)
|
- [ToJson](#ToJson)
|
||||||
@@ -401,7 +400,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="ToString">ToString</span>
|
### <span id="ToString">ToString</span>
|
||||||
|
|
||||||
<p>将interface转成字符串</p>
|
<p>将值转换为字符串,对于数字、字符串、[]byte,将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ import (
|
|||||||
- [HmacSha1](#HmacSha1)
|
- [HmacSha1](#HmacSha1)
|
||||||
- [HmacSha256](#HmacSha256)
|
- [HmacSha256](#HmacSha256)
|
||||||
- [HmacSha512](#HmacSha512)
|
- [HmacSha512](#HmacSha512)
|
||||||
|
|
||||||
- [Md5String](#Md5String)
|
- [Md5String](#Md5String)
|
||||||
- [Md5File](#Md5File)
|
- [Md5File](#Md5File)
|
||||||
- [Sha1](#Sha1)
|
- [Sha1](#Sha1)
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import (
|
|||||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||||
- [Base64StdEncode](#Base64StdEncode)
|
- [Base64StdEncode](#Base64StdEncode)
|
||||||
- [Base64StdDecode](#Base64StdDecode)
|
- [Base64StdDecode](#Base64StdDecode)
|
||||||
|
|
||||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||||
- [DesEcbDecrypt](#DesEcbDecrypt)
|
- [DesEcbDecrypt](#DesEcbDecrypt)
|
||||||
- [DesCbcEncrypt](#DesCbcEncrypt)
|
- [DesCbcEncrypt](#DesCbcEncrypt)
|
||||||
@@ -43,7 +42,6 @@ import (
|
|||||||
- [DesCfbDecrypt](#DesCfbDecrypt)
|
- [DesCfbDecrypt](#DesCfbDecrypt)
|
||||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||||
|
|
||||||
- [HmacMd5](#HmacMd5)
|
- [HmacMd5](#HmacMd5)
|
||||||
- [HmacSha1](#HmacSha1)
|
- [HmacSha1](#HmacSha1)
|
||||||
- [HmacSha256](#HmacSha256)
|
- [HmacSha256](#HmacSha256)
|
||||||
|
|||||||
@@ -132,12 +132,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="SinglyLink_InsertAt">InsertAt</span>
|
### <span id="SinglyLink_InsertAt">InsertAt</span>
|
||||||
<p>Insert value into singly linklist at index, index shoud be great or equal 0 and less or equal number of link nodes</p>
|
<p>Insert value into singly linklist at index, param `index` should between [0, len(SinglyLink)], if index do not meet the conditions, do nothing</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) InsertAt(index int, value T) error
|
func (link *SinglyLink[T]) InsertAt(index int, value T)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -152,6 +152,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
lk := link.NewSinglyLink[int]()
|
lk := link.NewSinglyLink[int]()
|
||||||
|
|
||||||
|
lk.InsertAt(1, 1) //do nothing
|
||||||
|
|
||||||
lk.InsertAt(0, 1)
|
lk.InsertAt(0, 1)
|
||||||
lk.InsertAt(1, 2)
|
lk.InsertAt(1, 2)
|
||||||
lk.InsertAt(2, 3)
|
lk.InsertAt(2, 3)
|
||||||
@@ -228,12 +230,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="SinglyLink_DeleteAt">DeleteAt</span>
|
### <span id="SinglyLink_DeleteAt">DeleteAt</span>
|
||||||
<p>Delete value at specific index, index shoud be great or equal 0 and less or less than number of link nodes - 1</p>
|
<p>Delete value at specific index, param `index` should be [0, len(SinglyLink)-1]</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAt(index int) error
|
func (link *SinglyLink[T]) DeleteAt(index int)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -253,9 +255,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAt(3)
|
lk.DeleteAt(3)
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -268,7 +269,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAtHead() error
|
func (link *SinglyLink[T]) DeleteAtHead()
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -288,9 +289,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAtHead()
|
lk.DeleteAtHead()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -304,7 +304,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAtTail() error
|
func (link *SinglyLink[T]) DeleteAtTail()
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -323,9 +323,8 @@ func main() {
|
|||||||
lk.InsertAtTail(2)
|
lk.InsertAtTail(2)
|
||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
|
|
||||||
err := lk.DeleteAtTail()
|
lk.DeleteAtTail()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2}
|
fmt.Println(lk.Values()) //[]int{1, 2}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -628,12 +627,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="DoublyLink_InsertAt">InsertAt</span>
|
### <span id="DoublyLink_InsertAt">InsertAt</span>
|
||||||
<p>Insert value into doubly linklist at index, index shoud be great or equal 0 and less or equal number of link nodes</p>
|
<p>Insert value into doubly linklist at index, param `index` should between [0, len(DoublyLink)], if index do not meet the conditions, do nothing</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) InsertAt(index int, value T) error
|
func (link *DoublyLink[T]) InsertAt(index int, value T)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -648,6 +647,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
lk := link.NewDoublyLink[int]()
|
lk := link.NewDoublyLink[int]()
|
||||||
|
|
||||||
|
lk.InsertAt(1, 1) //do nothing
|
||||||
|
|
||||||
lk.InsertAt(0, 1)
|
lk.InsertAt(0, 1)
|
||||||
lk.InsertAt(1, 2)
|
lk.InsertAt(1, 2)
|
||||||
lk.InsertAt(2, 3)
|
lk.InsertAt(2, 3)
|
||||||
@@ -724,12 +725,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="DoublyLink_DeleteAt">DeleteAt</span>
|
### <span id="DoublyLink_DeleteAt">DeleteAt</span>
|
||||||
<p>Delete value at specific index, index shoud be great or equal 0 and less or less than number of link nodes - 1</p>
|
<p>Delete value at specific index, param `index` should be [0, len(DoublyLink)-1]</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) DeleteAt(index int) error
|
func (link *DoublyLink[T]) DeleteAt(index int)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -749,9 +750,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAt(3)
|
lk.DeleteAt(3)
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -764,7 +764,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) DeleteAtHead() error
|
func (link *DoublyLink[T]) DeleteAtHead()
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -784,9 +784,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAtHead()
|
lk.DeleteAtHead()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -132,12 +132,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="SinglyLink_InsertAt">InsertAt</span>
|
### <span id="SinglyLink_InsertAt">InsertAt</span>
|
||||||
<p>将值插入到索引处的链表中,索引应大于或等于 0 且小于或等于链表节点数</p>
|
<p>将值插入到索引处的链表中,索引应大于或等于0且小于或等于链表节点数</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) InsertAt(index int, value T) error
|
func (link *SinglyLink[T]) InsertAt(index int, value T)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -152,6 +152,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
lk := link.NewSinglyLink[int]()
|
lk := link.NewSinglyLink[int]()
|
||||||
|
|
||||||
|
lk.InsertAt(1, 1) //do nothing
|
||||||
|
|
||||||
lk.InsertAt(0, 1)
|
lk.InsertAt(0, 1)
|
||||||
lk.InsertAt(1, 2)
|
lk.InsertAt(1, 2)
|
||||||
lk.InsertAt(2, 3)
|
lk.InsertAt(2, 3)
|
||||||
@@ -228,12 +230,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="SinglyLink_DeleteAt">DeleteAt</span>
|
### <span id="SinglyLink_DeleteAt">DeleteAt</span>
|
||||||
<p>删除特定索引处的值,索引应大于或等于0且小于或等于链接节点数 - 1</p>
|
<p>删除特定索引处的值,索引应大于或等于0且小于或等于链接节点数-1</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAt(index int) error
|
func (link *SinglyLink[T]) DeleteAt(index int)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -253,9 +255,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAt(3)
|
lk.DeleteAt(3)
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -268,7 +269,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAtHead() error
|
func (link *SinglyLink[T]) DeleteAtHead()
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -288,9 +289,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAtHead()
|
lk.DeleteAtHead()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -304,7 +304,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *SinglyLink[T]) DeleteAtTail() error
|
func (link *SinglyLink[T]) DeleteAtTail()
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -323,9 +323,8 @@ func main() {
|
|||||||
lk.InsertAtTail(2)
|
lk.InsertAtTail(2)
|
||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
|
|
||||||
err := lk.DeleteAtTail()
|
lk.DeleteAtTail()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2}
|
fmt.Println(lk.Values()) //[]int{1, 2}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -628,12 +627,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="DoublyLink_InsertAt">InsertAt</span>
|
### <span id="DoublyLink_InsertAt">InsertAt</span>
|
||||||
<p>将值插入到索引处的链表中,索引应大于或等于 0 且小于或等于链表节点数</p>
|
<p>将值插入到索引处的链表中,索引应大于或等于0且小于或等于链表节点数</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) InsertAt(index int, value T) error
|
func (link *DoublyLink[T]) InsertAt(index int, value T)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -648,6 +647,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
lk := link.NewDoublyLink[int]()
|
lk := link.NewDoublyLink[int]()
|
||||||
|
|
||||||
|
lk.InsertAt(1, 1) //do nothing
|
||||||
|
|
||||||
lk.InsertAt(0, 1)
|
lk.InsertAt(0, 1)
|
||||||
lk.InsertAt(1, 2)
|
lk.InsertAt(1, 2)
|
||||||
lk.InsertAt(2, 3)
|
lk.InsertAt(2, 3)
|
||||||
@@ -724,12 +725,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="DoublyLink_DeleteAt">DeleteAt</span>
|
### <span id="DoublyLink_DeleteAt">DeleteAt</span>
|
||||||
<p>删除特定索引处的值,索引应大于或等于0且小于或等于链接节点数 - 1</p>
|
<p>删除特定索引处的值,索引应大于或等于0且小于或等于链接节点数-1</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) DeleteAt(index int) error
|
func (link *DoublyLink[T]) DeleteAt(index int)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -749,9 +750,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAt(3)
|
lk.DeleteAt(3)
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
fmt.Println(lk.Values()) //[]int{1, 2, 3}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -764,7 +764,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) DeleteAtHead() error
|
func (link *DoublyLink[T]) DeleteAtHead()
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -784,9 +784,8 @@ func main() {
|
|||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
lk.InsertAtTail(4)
|
lk.InsertAtTail(4)
|
||||||
|
|
||||||
err := lk.DeleteAtHead()
|
lk.DeleteAtHead()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
fmt.Println(lk.Values()) //[]int{2, 3, 4}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -800,7 +799,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (link *DoublyLink[T]) DeleteAtTail() error
|
func (link *DoublyLink[T]) DeleteAtTail()
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -819,9 +818,8 @@ func main() {
|
|||||||
lk.InsertAtTail(2)
|
lk.InsertAtTail(2)
|
||||||
lk.InsertAtTail(3)
|
lk.InsertAtTail(3)
|
||||||
|
|
||||||
err := lk.DeleteAtTail()
|
lk.DeleteAtTail()
|
||||||
|
|
||||||
fmt.Println(err) //nil
|
|
||||||
fmt.Println(lk.Values()) //[]int{1, 2}
|
fmt.Println(lk.Values()) //[]int{1, 2}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ import (
|
|||||||
## Index
|
## Index
|
||||||
|
|
||||||
- [NewSet](#NewSet)
|
- [NewSet](#NewSet)
|
||||||
|
- [NewSetFromSlice](#NewSetFromSlice)
|
||||||
- [Values](#Values)
|
- [Values](#Values)
|
||||||
- [Add](#Add)
|
- [Add](#Add)
|
||||||
|
- [AddIfNotExist](#AddIfNotExist)
|
||||||
|
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||||
- [Delete](#Delete)
|
- [Delete](#Delete)
|
||||||
- [Contain](#Contain)
|
- [Contain](#Contain)
|
||||||
- [ContainAll](#ContainAll)
|
- [ContainAll](#ContainAll)
|
||||||
@@ -34,7 +37,6 @@ import (
|
|||||||
- [IsEmpty](#IsEmpty)
|
- [IsEmpty](#IsEmpty)
|
||||||
- [Union](#Union)
|
- [Union](#Union)
|
||||||
- [Intersection](#Intersection)
|
- [Intersection](#Intersection)
|
||||||
|
|
||||||
- [SymmetricDifference](#SymmetricDifference)
|
- [SymmetricDifference](#SymmetricDifference)
|
||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
|
|
||||||
@@ -45,13 +47,13 @@ import (
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
### <span id="NewSet">NewSet</span>
|
### <span id="NewSet">NewSet</span>
|
||||||
<p>Make a Set instance</p>
|
<p>Create a set instance</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Set[T comparable] map[T]bool
|
type Set[T comparable] map[T]bool
|
||||||
func NewSet[T comparable](values ...T) Set[T]
|
func NewSet[T comparable](items ...T) Set[T]
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -70,6 +72,30 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="NewSetFromSlice">NewSetFromSlice</span>
|
||||||
|
<p>Create a set from slice</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func NewSetFromSlice[T comparable](items []T) Set[T]
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSetFromSlice([]int{1, 2, 2, 3})
|
||||||
|
fmt.Println(st.Values()) //1,2,3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <span id="Values">Values</span>
|
### <span id="Values">Values</span>
|
||||||
@@ -100,12 +126,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="Add">Add</span>
|
### <span id="Add">Add</span>
|
||||||
<p>Add value to set</p>
|
<p>Add items to set</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Add(values ...T)
|
func (s Set[T]) Add(items ...T)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -126,14 +152,83 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="AddIfNotExist">AddIfNotExist</span>
|
||||||
### <span id="Delete">Delete</span>
|
<p>AddIfNotExist checks if item exists in the set, it adds the item to set and returns true if it does not exist in the set, or else it does nothing and returns false.</p>
|
||||||
<p>Delete value in set</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Delete(values ...T)
|
func (s Set[T]) AddIfNotExist(item T) bool
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSet[int]()
|
||||||
|
st.Add(1, 2, 3)
|
||||||
|
|
||||||
|
r1 := st.AddIfNotExist(1)
|
||||||
|
r2 := st.AddIfNotExist(4)
|
||||||
|
|
||||||
|
fmt.Println(r1) // false
|
||||||
|
fmt.Println(r2) // true
|
||||||
|
fmt.Println(st.Values()) // 1,2,3,4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="AddIfNotExistBy">AddIfNotExistBy</span>
|
||||||
|
<p>AddIfNotExistBy checks if item exists in the set and pass the `checker` function it adds the item to set and returns true if it does not exists in the set and function `checker` returns true, or else it does nothing and returns false.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSet[int]()
|
||||||
|
st.Add(1, 2)
|
||||||
|
|
||||||
|
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
fmt.Println(ok) // true
|
||||||
|
|
||||||
|
|
||||||
|
notOk := st.AddIfNotExistBy(4, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
fmt.Println(notOk) // false
|
||||||
|
|
||||||
|
fmt.Println(st.Values()) // 1, 2, 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Delete">Delete</span>
|
||||||
|
<p>Delete item in set</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s Set[T]) Delete(items ...T)
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -157,12 +252,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="Contain">Contain</span>
|
### <span id="Contain">Contain</span>
|
||||||
<p>Check if value is in set or not</p>
|
<p>Check if item is in set or not</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Contain(value T) bool
|
func (s Set[T]) Contain(item T) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -309,7 +404,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Iterate(fn func(value T))
|
func (s Set[T]) Iterate(fn func(item T))
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -324,8 +419,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
set1 := set.NewSet(1, 2, 3)
|
set1 := set.NewSet(1, 2, 3)
|
||||||
arr := []int{}
|
arr := []int{}
|
||||||
set.Iterate(func(value int) {
|
set.Iterate(func(item int) {
|
||||||
arr = append(arr, value)
|
arr = append(arr, item)
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(arr) //1,2,3
|
fmt.Println(arr) //1,2,3
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ import (
|
|||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
- [NewSet](#NewSet)
|
- [NewSet](#NewSet)
|
||||||
|
- [NewSetFromSlice](#NewSetFromSlice)
|
||||||
- [Values](#Values)
|
- [Values](#Values)
|
||||||
- [Add](#Add)
|
- [Add](#Add)
|
||||||
|
- [AddIfNotExist](#AddIfNotExist)
|
||||||
|
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||||
- [Delete](#Delete)
|
- [Delete](#Delete)
|
||||||
- [Contain](#Contain)
|
- [Contain](#Contain)
|
||||||
- [ContainAll](#ContainAll)
|
- [ContainAll](#ContainAll)
|
||||||
@@ -34,7 +37,6 @@ import (
|
|||||||
- [IsEmpty](#IsEmpty)
|
- [IsEmpty](#IsEmpty)
|
||||||
- [Union](#Union)
|
- [Union](#Union)
|
||||||
- [Intersection](#Intersection)
|
- [Intersection](#Intersection)
|
||||||
|
|
||||||
- [SymmetricDifference](#SymmetricDifference)
|
- [SymmetricDifference](#SymmetricDifference)
|
||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
|
|
||||||
@@ -51,7 +53,7 @@ import (
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
type Set[T comparable] map[T]bool
|
type Set[T comparable] map[T]bool
|
||||||
func NewSet[T comparable](values ...T) Set[T]
|
func NewSet[T comparable](items ...T) Set[T]
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -71,6 +73,31 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="NewSetFromSlice">NewSetFromSlice</span>
|
||||||
|
<p>基于切片创建集合</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func NewSetFromSlice[T comparable](items []T) Set[T]
|
||||||
|
```
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSetFromSlice([]int{1, 2, 2, 3})
|
||||||
|
fmt.Println(st.Values()) //1,2,3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <span id="Values">Values</span>
|
### <span id="Values">Values</span>
|
||||||
<p>获取集合中所有元素的切片</p>
|
<p>获取集合中所有元素的切片</p>
|
||||||
@@ -105,7 +132,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Add(values ...T)
|
func (s Set[T]) Add(items ...T)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -126,6 +153,76 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="AddIfNotExist">AddIfNotExist</span>
|
||||||
|
<p>如果集合中不存在元素,则添加该元素返回true, 如果集合中存在元素, 不做任何操作,返回false</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s Set[T]) AddIfNotExist(item T) bool
|
||||||
|
```
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSet[int]()
|
||||||
|
st.Add(1, 2, 3)
|
||||||
|
|
||||||
|
r1 := st.AddIfNotExist(1)
|
||||||
|
r2 := st.AddIfNotExist(4)
|
||||||
|
|
||||||
|
fmt.Println(r1) // false
|
||||||
|
fmt.Println(r2) // true
|
||||||
|
fmt.Println(st.Values()) // 1,2,3,4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="AddIfNotExistBy">AddIfNotExistBy</span>
|
||||||
|
<p>根据checker函数判断元素是否在集合中,如果集合中不存在元素且checker返回true,则添加该元素返回true, 否则不做任何操作,返回false</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
|
||||||
|
```
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
st := set.NewSet[int]()
|
||||||
|
st.Add(1, 2)
|
||||||
|
|
||||||
|
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
fmt.Println(ok) // true
|
||||||
|
|
||||||
|
|
||||||
|
notOk := st.AddIfNotExistBy(4, func(val int) bool {
|
||||||
|
return val%2 != 0
|
||||||
|
})
|
||||||
|
fmt.Println(notOk) // false
|
||||||
|
|
||||||
|
fmt.Println(st.Values()) // 1, 2, 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <span id="Delete">Delete</span>
|
### <span id="Delete">Delete</span>
|
||||||
<p>删除集合中元素</p>
|
<p>删除集合中元素</p>
|
||||||
@@ -133,7 +230,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Delete(values ...T)
|
func (s Set[T]) Delete(items ...T)
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -162,7 +259,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Contain(value T) bool
|
func (s Set[T]) Contain(item T) bool
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -309,7 +406,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (s Set[T]) Iterate(fn func(value T))
|
func (s Set[T]) Iterate(fn func(item T))
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -324,8 +421,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
set1 := set.NewSet(1, 2, 3)
|
set1 := set.NewSet(1, 2, 3)
|
||||||
arr := []int{}
|
arr := []int{}
|
||||||
set.Iterate(func(value int) {
|
set.Iterate(func(item int) {
|
||||||
arr = append(arr, value)
|
arr = append(arr, item)
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(arr) //1,2,3
|
fmt.Println(arr) //1,2,3
|
||||||
@@ -420,9 +517,6 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||||
<p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p>
|
<p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p>
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import (
|
|||||||
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
||||||
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
||||||
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
||||||
|
|
||||||
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
||||||
- [Depth](#BSTree_Depth)
|
- [Depth](#BSTree_Depth)
|
||||||
- [HasSubTree](#BSTree_HasSubTree)
|
- [HasSubTree](#BSTree_HasSubTree)
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import (
|
|||||||
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
- [PreOrderTraverse](#BSTree_PreOrderTraverse)
|
||||||
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
- [InOrderTraverse](#BSTree_InOrderTraverse)
|
||||||
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
- [PostOrderTraverse](#BSTree_PostOrderTraverse)
|
||||||
|
|
||||||
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
- [LevelOrderTraverse](#BSTree_LevelOrderTraverse)
|
||||||
- [Depth](#BSTree_Depth)
|
- [Depth](#BSTree_Depth)
|
||||||
- [HasSubTree](#BSTree_HasSubTree)
|
- [HasSubTree](#BSTree_HasSubTree)
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ import (
|
|||||||
- [GetNightTimestamp](#GetNightTimestamp)
|
- [GetNightTimestamp](#GetNightTimestamp)
|
||||||
- [FormatTimeToStr](#FormatTimeToStr)
|
- [FormatTimeToStr](#FormatTimeToStr)
|
||||||
- [FormatStrToTime](#FormatStrToTime)
|
- [FormatStrToTime](#FormatStrToTime)
|
||||||
|
|
||||||
- [NewUnixNow](#NewUnixNow)
|
- [NewUnixNow](#NewUnixNow)
|
||||||
- [NewUnix](#NewUnix)
|
- [NewUnix](#NewUnix)
|
||||||
- [NewFormat](#NewFormat)
|
- [NewFormat](#NewFormat)
|
||||||
@@ -251,7 +250,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func BeginOfWeek(t time.Time) time.Time
|
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -414,7 +413,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EndOfWeek(t time.Time) time.Time
|
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import (
|
|||||||
- [GetNightTimestamp](#GetNightTimestamp)
|
- [GetNightTimestamp](#GetNightTimestamp)
|
||||||
- [FormatTimeToStr](#FormatTimeToStr)
|
- [FormatTimeToStr](#FormatTimeToStr)
|
||||||
- [FormatStrToTime](#FormatStrToTime)
|
- [FormatStrToTime](#FormatStrToTime)
|
||||||
|
|
||||||
- [NewUnixNow](#NewUnixNow)
|
- [NewUnixNow](#NewUnixNow)
|
||||||
- [NewUnix](#NewUnix)
|
- [NewUnix](#NewUnix)
|
||||||
- [NewFormat](#NewFormat)
|
- [NewFormat](#NewFormat)
|
||||||
@@ -243,12 +242,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="BeginOfWeek">BeginOfWeek</span>
|
### <span id="BeginOfWeek">BeginOfWeek</span>
|
||||||
<p>返回指定时间的星期开始时间</p>
|
<p>返回指定时间的每周开始时间,默认开始时间星期日</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func BeginOfWeek(t time.Time) time.Time
|
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -406,12 +405,12 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="EndOfWeek">EndOfWeek</span>
|
### <span id="EndOfWeek">EndOfWeek</span>
|
||||||
<p>返回指定时间的星期结束时间</p>
|
<p>返回指定时间的星期结束时间,默认结束时间星期六</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EndOfWeek(t time.Time) time.Time
|
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
- [IsLink](#IsLink)
|
- [IsLink](#IsLink)
|
||||||
- [IsDir](#IsDir)
|
- [IsDir](#IsDir)
|
||||||
|
|
||||||
- [ListFileNames](#ListFileNames)
|
- [ListFileNames](#ListFileNames)
|
||||||
- [RemoveFile](#RemoveFile)
|
- [RemoveFile](#RemoveFile)
|
||||||
- [ReadFileToString](#ReadFileToString)
|
- [ReadFileToString](#ReadFileToString)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
- [IsLink](#IsLink)
|
- [IsLink](#IsLink)
|
||||||
- [IsDir](#IsDir)
|
- [IsDir](#IsDir)
|
||||||
|
|
||||||
- [ListFileNames](#ListFileNames)
|
- [ListFileNames](#ListFileNames)
|
||||||
- [RemoveFile](#RemoveFile)
|
- [RemoveFile](#RemoveFile)
|
||||||
- [ReadFileToString](#ReadFileToString)
|
- [ReadFileToString](#ReadFileToString)
|
||||||
|
|||||||
@@ -28,13 +28,12 @@ import (
|
|||||||
|
|
||||||
|
|
||||||
### <span id="Comma">Comma</span>
|
### <span id="Comma">Comma</span>
|
||||||
<p>Add comma to number by every 3 numbers from right. ahead by symbol char.
|
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
||||||
Param should be number or numberic string.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma(v any, symbol string) string
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ import (
|
|||||||
|
|
||||||
|
|
||||||
### <span id="Comma">Comma</span>
|
### <span id="Comma">Comma</span>
|
||||||
<p>用逗号每隔3位分割数字/字符串,签名添加符号。参数必须是数字或者可以转为数字的字符串</p>
|
<p>用逗号每隔3位分割数字/字符串,支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma(v any, symbol string) string
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [Compose](#Compose)
|
- [Compose](#Compose)
|
||||||
- [Debounced](#Debounced)
|
- [Debounced](#Debounced)
|
||||||
- [Delay](#Delay)
|
- [Delay](#Delay)
|
||||||
|
- [Pipeline](#Pipeline)
|
||||||
- [Watcher](#Watcher)
|
- [Watcher](#Watcher)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -300,6 +301,43 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Pipeline">Pipeline</span>
|
||||||
|
|
||||||
|
<p>Pipeline takes a list of functions and returns a function whose param will be passed into
|
||||||
|
the functions one by one.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pipeline[T any](funcs ...func(T) T) func(T) T
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
addOne := func(x int) int {
|
||||||
|
return x + 1
|
||||||
|
}
|
||||||
|
double := func(x int) int {
|
||||||
|
return 2 * x
|
||||||
|
}
|
||||||
|
square := func(x int) int {
|
||||||
|
return x * x
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Pipeline(addOne, double, square)
|
||||||
|
|
||||||
|
fmt.Println(f(2)) //36
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Watcher">Watcher</span>
|
### <span id="Watcher">Watcher</span>
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [Compose](#Compose)
|
- [Compose](#Compose)
|
||||||
- [Debounced](#Debounced)
|
- [Debounced](#Debounced)
|
||||||
- [Delay](#Delay)
|
- [Delay](#Delay)
|
||||||
|
- [Pipeline](#Pipeline)
|
||||||
- [Watcher](#Watcher)
|
- [Watcher](#Watcher)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -300,6 +301,44 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Pipeline">Pipeline</span>
|
||||||
|
|
||||||
|
<p>执行函数pipeline.</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pipeline[T any](funcs ...func(T) T) func(T) T
|
||||||
|
```
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
addOne := func(x int) int {
|
||||||
|
return x + 1
|
||||||
|
}
|
||||||
|
double := func(x int) int {
|
||||||
|
return 2 * x
|
||||||
|
}
|
||||||
|
square := func(x int) int {
|
||||||
|
return x * x
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Pipeline(addOne, double, square)
|
||||||
|
|
||||||
|
fmt.Println(f(2)) //36
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### <span id="Watcher">Watcher</span>
|
### <span id="Watcher">Watcher</span>
|
||||||
|
|
||||||
<p>Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。 </p>
|
<p>Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。 </p>
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
- [MaxBy](#MaxBy)
|
- [MaxBy](#MaxBy)
|
||||||
- [Min](#Min)
|
- [Min](#Min)
|
||||||
- [MinBy](#MaxBy)
|
- [MinBy](#MaxBy)
|
||||||
|
|
||||||
- [Percent](#Percent)
|
- [Percent](#Percent)
|
||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
@@ -46,7 +45,7 @@ import (
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Average[T lancetconstraints.Number](numbers ...T) T
|
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -158,7 +157,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Max[T lancetconstraints.Number](numbers ...T) T
|
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
@@ -224,7 +223,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Min[T lancetconstraints.Number](numbers ...T) T
|
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
- [MaxBy](#MaxBy)
|
- [MaxBy](#MaxBy)
|
||||||
- [Min](#Min)
|
- [Min](#Min)
|
||||||
- [MinBy](#MaxBy)
|
- [MinBy](#MaxBy)
|
||||||
|
|
||||||
- [Percent](#Percent)
|
- [Percent](#Percent)
|
||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
@@ -45,7 +44,7 @@ import (
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Average[T lancetconstraints.Number](numbers ...T) T
|
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -155,7 +154,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Max[T lancetconstraints.Number](numbers ...T) T
|
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
@@ -221,7 +220,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Min[T lancetconstraints.Number](numbers ...T) T
|
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||||
```
|
```
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import (
|
|||||||
## Index
|
## Index
|
||||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||||
- [EncodeUrl](#EncodeUrl)
|
- [EncodeUrl](#EncodeUrl)
|
||||||
|
|
||||||
- [GetInternalIp](#GetInternalIp)
|
- [GetInternalIp](#GetInternalIp)
|
||||||
- [GetIps](#GetIps)
|
- [GetIps](#GetIps)
|
||||||
- [GetMacAddrs](#GetMacAddrs)
|
- [GetMacAddrs](#GetMacAddrs)
|
||||||
@@ -38,7 +37,6 @@ import (
|
|||||||
- [SendRequest](#SendRequest)
|
- [SendRequest](#SendRequest)
|
||||||
- [DecodeResponse](#DecodeResponse)
|
- [DecodeResponse](#DecodeResponse)
|
||||||
- [StructToUrlValues](#StructToUrlValues)
|
- [StructToUrlValues](#StructToUrlValues)
|
||||||
|
|
||||||
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
||||||
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
||||||
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import (
|
|||||||
- [GetMacAddrs](#GetMacAddrs)
|
- [GetMacAddrs](#GetMacAddrs)
|
||||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||||
- [GetRequestPublicIp](#GetRequestPublicIp)
|
- [GetRequestPublicIp](#GetRequestPublicIp)
|
||||||
|
|
||||||
- [IsPublicIP](#IsPublicIP)
|
- [IsPublicIP](#IsPublicIP)
|
||||||
- [IsInternalIP](#IsInternalIP)
|
- [IsInternalIP](#IsInternalIP)
|
||||||
- [HttpRequest](#HttpRequest)
|
- [HttpRequest](#HttpRequest)
|
||||||
@@ -38,13 +37,11 @@ import (
|
|||||||
- [SendRequest](#SendRequest)
|
- [SendRequest](#SendRequest)
|
||||||
- [DecodeResponse](#DecodeResponse)
|
- [DecodeResponse](#DecodeResponse)
|
||||||
- [StructToUrlValues](#StructToUrlValues)
|
- [StructToUrlValues](#StructToUrlValues)
|
||||||
|
|
||||||
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
||||||
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
||||||
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
||||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||||
|
|
||||||
- [ParseHttpResponse](#ParseHttpResponse)
|
- [ParseHttpResponse](#ParseHttpResponse)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|||||||
137
docs/random.md
137
docs/random.md
@@ -1,16 +1,17 @@
|
|||||||
# Random
|
# Random
|
||||||
|
|
||||||
Package random implements some basic functions to generate random int and string.
|
Package random implements some basic functions to generate random int and string.
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Source:
|
## Source:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Usage:
|
## Usage:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/v2/random"
|
"github.com/duke-git/lancet/v2/random"
|
||||||
@@ -20,17 +21,22 @@ import (
|
|||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Index
|
## Index
|
||||||
- [RandBytes](#RandBytes)
|
|
||||||
- [RandInt](#RandInt)
|
- [RandBytes](#RandBytes)
|
||||||
- [RandString](#RandString)
|
- [RandInt](#RandInt)
|
||||||
- [UUIdV4](#UUIdV4)
|
- [RandString](#RandString)
|
||||||
|
- [RandUpper](#RandUpper)
|
||||||
|
- [RandLower](#RandLower)
|
||||||
|
- [RandNumeral](#RandNumeral)
|
||||||
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
|
- [UUIdV4](#UUIdV4)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|
||||||
### <span id="RandBytes">RandBytes</span>
|
### <span id="RandBytes">RandBytes</span>
|
||||||
|
|
||||||
<p>Generate random byte slice.</p>
|
<p>Generate random byte slice.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
@@ -38,6 +44,7 @@ import (
|
|||||||
```go
|
```go
|
||||||
func RandBytes(length int) []byte
|
func RandBytes(length int) []byte
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -54,8 +61,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="RandInt">RandInt</span>
|
### <span id="RandInt">RandInt</span>
|
||||||
|
|
||||||
<p>Generate random int between min and max, may contain min, not max.</p>
|
<p>Generate random int between min and max, may contain min, not max.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
@@ -63,6 +70,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func RandInt(min, max int) int
|
func RandInt(min, max int) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -79,16 +87,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandString">RandString</span>
|
||||||
|
|
||||||
|
<p>Generate random given length string. only contains letter (a-zA-Z)</p>
|
||||||
### <span id="RandString">RandInt</span>
|
|
||||||
<p>Generate random given length string.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func RandString(length int) string
|
func RandString(length int) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -101,14 +109,116 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
randStr := random.RandString(6)
|
randStr := random.RandString(6)
|
||||||
fmt.Println(randStr)
|
fmt.Println(randStr) //pGWsze
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandUpper">RandUpper</span>
|
||||||
|
|
||||||
|
<p>Generate a random upper case string</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandUpper(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandString(6)
|
||||||
|
fmt.Println(randStr) //PACWGF
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandLower">RandLower</span>
|
||||||
|
|
||||||
|
<p>Generate a random lower case string</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandLower(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandLower(6)
|
||||||
|
fmt.Println(randStr) //siqbew
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandNumeral">RandNumeral</span>
|
||||||
|
|
||||||
|
<p>Generate a random numeral string</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandNumeral(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandNumeral(6)
|
||||||
|
fmt.Println(randStr) //035172
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandNumeralOrLetter">RandNumeralOrLetter</span>
|
||||||
|
|
||||||
|
<p>generate a random numeral or letter string</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandNumeralOrLetter(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandNumeralOrLetter(6)
|
||||||
|
fmt.Println(randStr) //0aW7cQ
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="UUIdV4">UUIdV4</span>
|
### <span id="UUIdV4">UUIdV4</span>
|
||||||
|
|
||||||
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
@@ -116,6 +226,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func UUIdV4() (string, error)
|
func UUIdV4() (string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -134,5 +245,3 @@ func main() {
|
|||||||
fmt.Println(uuid)
|
fmt.Println(uuid)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
# Random
|
# Random
|
||||||
random随机数生成器包,可以生成随机[]bytes, int, string。
|
|
||||||
|
random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 源码:
|
## 源码:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
- [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 用法:
|
## 用法:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/v2/random"
|
"github.com/duke-git/lancet/v2/random"
|
||||||
@@ -20,18 +21,22 @@ import (
|
|||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
- [RandBytes](#RandBytes)
|
|
||||||
- [RandInt](#RandInt)
|
|
||||||
- [RandString](#RandString)
|
|
||||||
- [UUIdV4](#UUIdV4)
|
|
||||||
|
|
||||||
|
- [RandBytes](#RandBytes)
|
||||||
|
- [RandInt](#RandInt)
|
||||||
|
- [RandString](#RandString)
|
||||||
|
- [RandUpper](#RandUpper)
|
||||||
|
- [RandLower](#RandLower)
|
||||||
|
- [RandNumeral](#RandNumeral)
|
||||||
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
|
- [UUIdV4](#UUIdV4)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|
||||||
|
|
||||||
### <span id="RandBytes">RandBytes</span>
|
### <span id="RandBytes">RandBytes</span>
|
||||||
|
|
||||||
<p>生成随机字节切片</p>
|
<p>生成随机字节切片</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
@@ -39,6 +44,7 @@ import (
|
|||||||
```go
|
```go
|
||||||
func RandBytes(length int) []byte
|
func RandBytes(length int) []byte
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -55,8 +61,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="RandInt">RandInt</span>
|
### <span id="RandInt">RandInt</span>
|
||||||
|
|
||||||
<p>生成随机int, 范围[min, max)</p>
|
<p>生成随机int, 范围[min, max)</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
@@ -64,6 +70,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func RandInt(min, max int) int
|
func RandInt(min, max int) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -80,16 +87,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandString">RandString</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机字符串,只包含字母(a-zA-Z)</p>
|
||||||
### <span id="RandString">RandInt</span>
|
|
||||||
<p>生成随机给定长度的随机字符串</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func RandString(length int) string
|
func RandString(length int) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -102,13 +109,116 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
randStr := random.RandString(6)
|
randStr := random.RandString(6)
|
||||||
fmt.Println(randStr)
|
fmt.Println(randStr) //pGWsze
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandUpper">RandUpper</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机大写字母字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandUpper(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandString(6)
|
||||||
|
fmt.Println(randStr) //PACWGF
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandLower">RandLower</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机小写字母字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandLower(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandLower(6)
|
||||||
|
fmt.Println(randStr) //siqbew
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandNumeral">RandNumeral</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机数字字符串</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandNumeral(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandNumeral(6)
|
||||||
|
fmt.Println(randStr) //035172
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandNumeralOrLetter">RandNumeralOrLetter</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机字符串(数字+字母)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandNumeralOrLetter(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandNumeralOrLetter(6)
|
||||||
|
fmt.Println(randStr) //0aW7cQ
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="UUIdV4">UUIdV4</span>
|
### <span id="UUIdV4">UUIdV4</span>
|
||||||
|
|
||||||
<p>生成UUID v4字符串</p>
|
<p>生成UUID v4字符串</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
@@ -116,6 +226,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func UUIdV4() (string, error)
|
func UUIdV4() (string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -134,5 +245,3 @@ func main() {
|
|||||||
fmt.Println(uuid)
|
fmt.Println(uuid)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
589
docs/slice.md
589
docs/slice.md
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,6 @@ import (
|
|||||||
- [SnakeCase](#SnakeCase)
|
- [SnakeCase](#SnakeCase)
|
||||||
- [SplitEx](#SplitEx)
|
- [SplitEx](#SplitEx)
|
||||||
- [Wrap](#Wrap)
|
- [Wrap](#Wrap)
|
||||||
|
|
||||||
- [Unwrap](#Unwrap)
|
- [Unwrap](#Unwrap)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import (
|
|||||||
- [SnakeCase](#SnakeCase)
|
- [SnakeCase](#SnakeCase)
|
||||||
- [SplitEx](#SplitEx)
|
- [SplitEx](#SplitEx)
|
||||||
- [Wrap](#Wrap)
|
- [Wrap](#Wrap)
|
||||||
|
|
||||||
- [Unwrap](#Unwrap)
|
- [Unwrap](#Unwrap)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="ExecCommand">CompareOsEnv</span>
|
### <span id="ExecCommand">CompareOsEnv</span>
|
||||||
<p>Use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -227,10 +227,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
out, errout, err := system.ExecCommand("ls")
|
// linux or mac
|
||||||
fmt.Println(out)
|
stdout, stderr, err := system.ExecCommand("ls")
|
||||||
fmt.Println(errout)
|
fmt.Println("std out: ", stdout)
|
||||||
fmt.Println(err)
|
fmt.Println("std err: ", stderr)
|
||||||
|
assert.Equal("", stderr)
|
||||||
|
|
||||||
|
// windows
|
||||||
|
stdout, stderr, err = system.ExecCommand("dir")
|
||||||
|
fmt.Println("std out: ", stdout)
|
||||||
|
fmt.Println("std err: ", stderr)
|
||||||
|
|
||||||
|
// error command
|
||||||
|
stdout, stderr, err = system.ExecCommand("abc")
|
||||||
|
fmt.Println("std out: ", stdout)
|
||||||
|
fmt.Println("std err: ", stderr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
### <span id="ExecCommand">ExecCommand</span>
|
### <span id="ExecCommand">ExecCommand</span>
|
||||||
<p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p>
|
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-a(linux),dir(windows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -228,10 +228,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
out, errout, err := system.ExecCommand("ls")
|
// linux or mac
|
||||||
fmt.Println(out)
|
stdout, stderr, err := system.ExecCommand("ls")
|
||||||
fmt.Println(errout)
|
fmt.Println("std out: ", stdout)
|
||||||
fmt.Println(err)
|
fmt.Println("std err: ", stderr)
|
||||||
|
assert.Equal("", stderr)
|
||||||
|
|
||||||
|
// windows
|
||||||
|
stdout, stderr, err = system.ExecCommand("dir")
|
||||||
|
fmt.Println("std out: ", stdout)
|
||||||
|
fmt.Println("std err: ", stderr)
|
||||||
|
|
||||||
|
// error command
|
||||||
|
stdout, stderr, err = system.ExecCommand("abc")
|
||||||
|
fmt.Println("std out: ", stdout)
|
||||||
|
fmt.Println("std err: ", stderr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import (
|
|||||||
- [IsCreditCard](#IsCreditCard)
|
- [IsCreditCard](#IsCreditCard)
|
||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
|
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
@@ -48,6 +47,7 @@ import (
|
|||||||
- [IsUrl](#IsUrl)
|
- [IsUrl](#IsUrl)
|
||||||
- [IsWeakPassword](#IsWeakPassword)
|
- [IsWeakPassword](#IsWeakPassword)
|
||||||
- [IsZeroValue](#IsZeroValue)
|
- [IsZeroValue](#IsZeroValue)
|
||||||
|
- [IsGBK](#IsGBK)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -822,7 +822,34 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="IsGBK">IsGBK</span>
|
||||||
|
<p>Checks if data encoding is gbk(Chinese character internal code extension specification). this function is implemented by whether double bytes fall within the encoding range of gbk,while each byte of utf-8 encoding format falls within the encoding range of gbk.Therefore, utf8.valid() should be called first to check whether it is not utf-8 encoding and then call IsGBK() to check gbk encoding. like the example.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsGBK(data []byte) bool
|
||||||
|
```
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := []byte("你好")
|
||||||
|
|
||||||
|
// check utf8 first
|
||||||
|
if utf8.Valid(data) {
|
||||||
|
fmt.Println("data encoding is utf-8")
|
||||||
|
}else if(validator.IsGBK(data)) {
|
||||||
|
fmt.Println("data encoding is GBK")
|
||||||
|
}
|
||||||
|
fmt.Println("data encoding is unknown")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import (
|
|||||||
- [IsCreditCard](#IsCreditCard)
|
- [IsCreditCard](#IsCreditCard)
|
||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
|
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
@@ -48,6 +47,7 @@ import (
|
|||||||
- [IsUrl](#IsUrl)
|
- [IsUrl](#IsUrl)
|
||||||
- [IsWeakPassword](#IsWeakPassword)
|
- [IsWeakPassword](#IsWeakPassword)
|
||||||
- [IsZeroValue](#IsZeroValue)
|
- [IsZeroValue](#IsZeroValue)
|
||||||
|
- [IsGBK](#IsGBK)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -821,3 +821,31 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsGBK">IsGBK</span>
|
||||||
|
<p>检查数据编码是否为gbk(汉字内部代码扩展规范)。该函数的实现取决于双字节是否在gbk的编码范围内,而utf-8编码格式的每个字节都在gbk编码范围内。因此,应该首先调用utf8.valid检查它是否是utf-8编码,然后调用IsGBK检查gbk编码。如示例所示。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsGBK(data []byte) bool
|
||||||
|
```
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
data := []byte("你好")
|
||||||
|
|
||||||
|
// 先检查utf8编码
|
||||||
|
if utf8.Valid(data) {
|
||||||
|
fmt.Println("data encoding is utf-8")
|
||||||
|
}else if(validator.IsGBK(data)) {
|
||||||
|
fmt.Println("data encoding is GBK")
|
||||||
|
}
|
||||||
|
fmt.Println("data encoding is unknown")
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -8,9 +8,9 @@ import (
|
|||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -77,13 +77,16 @@ func CopyFile(srcFilePath string, dstFilePath string) error {
|
|||||||
var tmp = make([]byte, 1024*4)
|
var tmp = make([]byte, 1024*4)
|
||||||
for {
|
for {
|
||||||
n, err := srcFile.Read(tmp)
|
n, err := srcFile.Read(tmp)
|
||||||
distFile.Write(tmp[:n])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = distFile.Write(tmp[:n])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +104,7 @@ func ClearFile(path string) error {
|
|||||||
|
|
||||||
//ReadFileToString return string of file content
|
//ReadFileToString return string of file content
|
||||||
func ReadFileToString(path string) (string, error) {
|
func ReadFileToString(path string) (string, error) {
|
||||||
bytes, err := ioutil.ReadFile(path)
|
bytes, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -140,7 +143,7 @@ func ListFileNames(path string) ([]string, error) {
|
|||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fs, err := ioutil.ReadDir(path)
|
fs, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
@@ -171,7 +174,7 @@ func Zip(fpath string, destPath string) error {
|
|||||||
archive := zip.NewWriter(zipFile)
|
archive := zip.NewWriter(zipFile)
|
||||||
defer archive.Close()
|
defer archive.Close()
|
||||||
|
|
||||||
filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
err = filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -208,11 +211,16 @@ func Zip(fpath string, destPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnZip unzip the file and save it to destPath
|
// UnZip unzip the file and save it to destPath
|
||||||
func UnZip(zipFile string, destPath string) error {
|
func UnZip(zipFile string, destPath string) error {
|
||||||
|
|
||||||
zipReader, err := zip.OpenReader(zipFile)
|
zipReader, err := zip.OpenReader(zipFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -220,11 +228,20 @@ func UnZip(zipFile string, destPath string) error {
|
|||||||
defer zipReader.Close()
|
defer zipReader.Close()
|
||||||
|
|
||||||
for _, f := range zipReader.File {
|
for _, f := range zipReader.File {
|
||||||
path := filepath.Join(destPath, f.Name)
|
//issue#62: fix ZipSlip bug
|
||||||
|
path, err := safeFilepathJoin(destPath, f.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if f.FileInfo().IsDir() {
|
if f.FileInfo().IsDir() {
|
||||||
os.MkdirAll(path, os.ModePerm)
|
err = os.MkdirAll(path, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if err = os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
|
err = os.MkdirAll(filepath.Dir(path), os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +266,17 @@ func UnZip(zipFile string, destPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func safeFilepathJoin(path1, path2 string) (string, error) {
|
||||||
|
relPath, err := filepath.Rel(".", path2)
|
||||||
|
if err != nil || strings.HasPrefix(relPath, "..") {
|
||||||
|
return "", fmt.Errorf("(zipslip) filepath is unsafe %q: %v", path2, err)
|
||||||
|
}
|
||||||
|
if path1 == "" {
|
||||||
|
path1 = "."
|
||||||
|
}
|
||||||
|
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
|
||||||
func IsLink(path string) bool {
|
func IsLink(path string) bool {
|
||||||
fi, err := os.Lstat(path)
|
fi, err := os.Lstat(path)
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ func TestCreateFile(t *testing.T) {
|
|||||||
f := "./text.txt"
|
f := "./text.txt"
|
||||||
if CreateFile(f) {
|
if CreateFile(f) {
|
||||||
file, err := os.Open(f)
|
file, err := os.Open(f)
|
||||||
defer file.Close()
|
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal(f, file.Name())
|
assert.Equal(f, file.Name())
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
} else {
|
} else {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,11 @@ func TestReadFileToString(t *testing.T) {
|
|||||||
|
|
||||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
f.WriteString("hello world")
|
|
||||||
|
_, err := f.WriteString("hello world")
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
content, _ := ReadFileToString(path)
|
content, _ := ReadFileToString(path)
|
||||||
assert.Equal("hello world", content)
|
assert.Equal("hello world", content)
|
||||||
@@ -130,9 +135,12 @@ func TestClearFile(t *testing.T) {
|
|||||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
f.WriteString("hello world")
|
_, err := f.WriteString("hello world")
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
err := ClearFile(path)
|
err = ClearFile(path)
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
content, _ := ReadFileToString(path)
|
content, _ := ReadFileToString(path)
|
||||||
@@ -148,8 +156,13 @@ func TestReadFileByLine(t *testing.T) {
|
|||||||
CreateFile(path)
|
CreateFile(path)
|
||||||
|
|
||||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
f.WriteString("hello\nworld")
|
|
||||||
|
_, err := f.WriteString("hello\nworld")
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
expected := []string{"hello", "world"}
|
expected := []string{"hello", "world"}
|
||||||
actual, _ := ReadFileByLine(path)
|
actual, _ := ReadFileByLine(path)
|
||||||
@@ -166,10 +179,14 @@ func TestZipAndUnZip(t *testing.T) {
|
|||||||
|
|
||||||
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, 0777)
|
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
file.WriteString("hello\nworld")
|
|
||||||
|
_, err := file.WriteString("hello\nworld")
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
zipFile := "./text.zip"
|
zipFile := "./text.zip"
|
||||||
err := Zip(srcFile, zipFile)
|
err = Zip(srcFile, zipFile)
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
unZipPath := "./unzip"
|
unZipPath := "./unzip"
|
||||||
|
|||||||
@@ -4,14 +4,25 @@
|
|||||||
// Package formatter implements some functions to format string, struct.
|
// Package formatter implements some functions to format string, struct.
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/exp/constraints"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
||||||
|
s, err := numberToString(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Comma add comma to number by every 3 numbers from right. ahead by symbol char
|
|
||||||
func Comma(v any, symbol string) string {
|
|
||||||
s := numString(v)
|
|
||||||
dotIndex := strings.Index(s, ".")
|
dotIndex := strings.Index(s, ".")
|
||||||
if dotIndex != -1 {
|
if dotIndex != -1 {
|
||||||
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbol + commaString(s)
|
return symbol + commaString(s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,27 +14,34 @@ func commaString(s string) string {
|
|||||||
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func numString(value any) string {
|
func numberToString(value any) (string, error) {
|
||||||
switch reflect.TypeOf(value).Kind() {
|
switch reflect.TypeOf(value).Kind() {
|
||||||
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
return fmt.Sprintf("%v", value)
|
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:
|
case reflect.String:
|
||||||
{
|
{
|
||||||
sv := fmt.Sprintf("%v", value)
|
sv := fmt.Sprintf("%v", value)
|
||||||
if strings.Contains(sv, ".") {
|
if strings.Contains(sv, ".") {
|
||||||
_, err := strconv.ParseFloat(sv, 64)
|
_, err := strconv.ParseFloat(sv, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
return sv
|
return "", err
|
||||||
}
|
}
|
||||||
|
return sv, nil
|
||||||
} else {
|
} else {
|
||||||
_, err := strconv.ParseInt(sv, 10, 64)
|
_, err := strconv.ParseInt(sv, 10, 64)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
return sv
|
return "", nil
|
||||||
}
|
}
|
||||||
|
return sv, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return ""
|
return "", nil
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ func TestComma(t *testing.T) {
|
|||||||
assert.Equal("", Comma("", ""))
|
assert.Equal("", Comma("", ""))
|
||||||
assert.Equal("", Comma("aa", ""))
|
assert.Equal("", Comma("aa", ""))
|
||||||
assert.Equal("", Comma("aa.a", ""))
|
assert.Equal("", Comma("aa.a", ""))
|
||||||
assert.Equal("", Comma([]int{1}, ""))
|
|
||||||
assert.Equal("123", Comma("123", ""))
|
assert.Equal("123", Comma("123", ""))
|
||||||
assert.Equal("12,345", Comma("12345", ""))
|
assert.Equal("12,345", Comma("12345", ""))
|
||||||
|
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
||||||
|
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
||||||
|
|
||||||
assert.Equal("12,345", Comma(12345, ""))
|
assert.Equal("12,345", Comma(12345, ""))
|
||||||
assert.Equal("$12,345", Comma(12345, "$"))
|
assert.Equal("$12,345", Comma(12345, "$"))
|
||||||
assert.Equal("¥12,345", Comma(12345, "¥"))
|
assert.Equal("¥12,345", Comma(12345, "¥"))
|
||||||
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
||||||
|
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
||||||
|
// assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
||||||
|
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,10 +84,8 @@ func Debounced(fn func(), duration time.Duration) func() {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
<-timer.C
|
||||||
case <-timer.C:
|
go fn()
|
||||||
go fn()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -113,3 +111,15 @@ func Schedule(d time.Duration, fn any, args ...any) chan bool {
|
|||||||
|
|
||||||
return quit
|
return quit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pipeline takes a list of functions and returns a function whose param will be passed into
|
||||||
|
// the functions one by one.
|
||||||
|
func Pipeline[T any](funcs ...func(T) T) func(T) T {
|
||||||
|
return func(arg T) (result T) {
|
||||||
|
result = arg
|
||||||
|
for _, fn := range funcs {
|
||||||
|
result = fn(result)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -134,3 +134,21 @@ func TestSchedule(t *testing.T) {
|
|||||||
// expected := []string{"*", "*", "*", "*", "*"}
|
// expected := []string{"*", "*", "*", "*", "*"}
|
||||||
// assert.Equal(expected, res)
|
// assert.Equal(expected, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPipeline(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPipeline")
|
||||||
|
|
||||||
|
addOne := func(x int) int {
|
||||||
|
return x + 1
|
||||||
|
}
|
||||||
|
double := func(x int) int {
|
||||||
|
return 2 * x
|
||||||
|
}
|
||||||
|
square := func(x int) int {
|
||||||
|
return x * x
|
||||||
|
}
|
||||||
|
|
||||||
|
f := Pipeline(addOne, double, square)
|
||||||
|
|
||||||
|
assert.Equal(36, f(2))
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ func TestWatcher(t *testing.T) {
|
|||||||
assert.Equal(int64(0), w.stopTime)
|
assert.Equal(int64(0), w.stopTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
func longRunningTask() {
|
func longRunningTask() []int64 {
|
||||||
var slice []int64
|
var data []int64
|
||||||
for i := 0; i < 10000000; i++ {
|
for i := 0; i < 10000000; i++ {
|
||||||
slice = append(slice, int64(i))
|
data = append(data, int64(i))
|
||||||
}
|
}
|
||||||
|
return data
|
||||||
}
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -1,3 +1,8 @@
|
|||||||
module github.com/duke-git/lancet/v2
|
module github.com/duke-git/lancet/v2
|
||||||
|
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/exp v0.0.0-20221208152030-732eee02a75a
|
||||||
|
golang.org/x/text v0.5.0
|
||||||
|
)
|
||||||
|
|||||||
4
go.sum
Normal file
4
go.sum
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
golang.org/x/exp v0.0.0-20221208152030-732eee02a75a h1:4iLhBPcpqFmylhnkbY3W0ONLUYYkDAW9xMFLfxgsvCw=
|
||||||
|
golang.org/x/exp v0.0.0-20221208152030-732eee02a75a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
|
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||||
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
173
iterator/iterator.go
Normal file
173
iterator/iterator.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
// 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 (
|
||||||
|
"golang.org/x/exp/constraints"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Iterator supports iterating over a sequence of values of type `E`.
|
||||||
|
type Iterator[T any] interface {
|
||||||
|
// Next checks if there is a next value in the iteration or not
|
||||||
|
HasNext() bool
|
||||||
|
// Next returns the next value in the iteration if there is one,
|
||||||
|
// and reports whether the returned value is valid.
|
||||||
|
// Once Next returns ok==false, the iteration is over,
|
||||||
|
// and all subsequent calls will return ok==false.
|
||||||
|
Next() (item T, ok bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopIterator is an interface for stopping Iterator.
|
||||||
|
type StopIterator[T any] interface {
|
||||||
|
Iterator[T]
|
||||||
|
|
||||||
|
// Stop indicates that the iterator will no longer be used.
|
||||||
|
// After a call to Stop, future calls to Next may panic.
|
||||||
|
// Stop may be called multiple times;
|
||||||
|
// all calls after the first will have no effect.
|
||||||
|
Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteIter is an Iter that implements a Delete method.
|
||||||
|
type DeleteIterator[T any] interface {
|
||||||
|
Iterator[T]
|
||||||
|
|
||||||
|
// Delete deletes the current iterator element;
|
||||||
|
// that is, the one returned by the last call to Next.
|
||||||
|
// Delete should panic if called before Next or after
|
||||||
|
// Next returns false.
|
||||||
|
Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIterator is an Iter that implements a Set method.
|
||||||
|
type SetIterator[T any] interface {
|
||||||
|
Iterator[T]
|
||||||
|
|
||||||
|
// Set replaces the current iterator element with v.
|
||||||
|
// Set should panic if called before Next or after
|
||||||
|
// Next returns false.
|
||||||
|
Set(v T)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevIterator is an iterator with a Prev method.
|
||||||
|
type PrevIterator[T any] interface {
|
||||||
|
Iterator[T]
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous position.
|
||||||
|
// After calling Prev, Next will return the value at
|
||||||
|
// that position in the container. For example, after
|
||||||
|
// it.Next() returning (v, true)
|
||||||
|
// it.Prev()
|
||||||
|
// another call to it.Next will again return (v, true).
|
||||||
|
// Calling Prev before calling Next may panic.
|
||||||
|
// Calling Prev after Next returns false will move
|
||||||
|
// to the last element, or, if there are no elements,
|
||||||
|
// to the iterator's initial state.
|
||||||
|
Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions that create an Iterator from some other type. //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// FromSlice returns an iterator over a slice of data.
|
||||||
|
func FromSlice[T any](slice []T) Iterator[T] {
|
||||||
|
return &sliceIterator[T]{slice: slice, index: -1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSlice[T any](iter Iterator[T]) []T {
|
||||||
|
result := []T{}
|
||||||
|
for item, ok := iter.Next(); ok; item, ok = iter.Next() {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
type sliceIterator[T any] struct {
|
||||||
|
slice []T
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iter *sliceIterator[T]) HasNext() bool {
|
||||||
|
return iter.index < len(iter.slice)-1
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev implements PrevIterator.
|
||||||
|
func (iter *sliceIterator[T]) Prev() {
|
||||||
|
if iter.index == -1 {
|
||||||
|
panic("Next function should be called Prev")
|
||||||
|
}
|
||||||
|
if iter.HasNext() {
|
||||||
|
iter.index--
|
||||||
|
} else {
|
||||||
|
iter.index = len(iter.slice) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set implements SetIterator.
|
||||||
|
func (iter *sliceIterator[T]) Set(value T) {
|
||||||
|
if iter.index == -1 {
|
||||||
|
panic("Next function should be called Set")
|
||||||
|
}
|
||||||
|
if iter.index >= len(iter.slice) || len(iter.slice) == 0 {
|
||||||
|
panic("No element in current iterator")
|
||||||
|
}
|
||||||
|
iter.slice[iter.index] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 FromRange[T constraints.Integer | constraints.Float](start, end, step T) Iterator[T] {
|
||||||
|
if end < start {
|
||||||
|
panic("RangeIterator: start should be before end")
|
||||||
|
} else if step <= 0 {
|
||||||
|
panic("RangeIterator: step should be positive")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rangeIterator[T]{start: start, end: end, step: step}
|
||||||
|
}
|
||||||
|
|
||||||
|
type rangeIterator[T constraints.Integer | constraints.Float] struct {
|
||||||
|
start, end, step T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iter *rangeIterator[T]) HasNext() bool {
|
||||||
|
return iter.start < iter.end
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iter *rangeIterator[T]) Next() (T, bool) {
|
||||||
|
if iter.start >= iter.end {
|
||||||
|
var zero T
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
num := iter.start
|
||||||
|
iter.start += iter.step
|
||||||
|
return num, true
|
||||||
|
}
|
||||||
50
iterator/iterator_test.go
Normal file
50
iterator/iterator_test.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2022 dudaodong@gmail.com. All rights resulterved.
|
||||||
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
|
// Package iterator implements some feature of C++ STL iterators
|
||||||
|
package iterator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSliceIterator(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSliceIterator")
|
||||||
|
|
||||||
|
// HashNext
|
||||||
|
t.Run("slice iterator HasNext: ", func(t *testing.T) {
|
||||||
|
iter1 := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
for {
|
||||||
|
item, _ := iter1.Next()
|
||||||
|
|
||||||
|
if item == 4 {
|
||||||
|
assert.Equal(false, iter1.HasNext())
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
assert.Equal(true, iter1.HasNext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iter2 := FromSlice([]int{})
|
||||||
|
assert.Equal(false, iter2.HasNext())
|
||||||
|
})
|
||||||
|
|
||||||
|
//Next
|
||||||
|
t.Run("slice iterator Next: ", func(t *testing.T) {
|
||||||
|
iter1 := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
item, ok := iter1.Next()
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
assert.Equal(i+1, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
iter2 := FromSlice([]int{})
|
||||||
|
_, ok := iter2.Next()
|
||||||
|
assert.Equal(false, ok)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
61
iterator/operation.go
Normal file
61
iterator/operation.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
// Map creates a new iterator which applies a function to all items of input iterator.
|
||||||
|
func Map[T any, U any](iter Iterator[T], iteratee func(item T) U) Iterator[U] {
|
||||||
|
return &mapIterator[T, U]{
|
||||||
|
iter: iter,
|
||||||
|
iteratee: iteratee,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mapIterator[T any, U any] struct {
|
||||||
|
iter Iterator[T]
|
||||||
|
iteratee func(T) U
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *mapIterator[T, U]) HasNext() bool {
|
||||||
|
return mr.iter.HasNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr *mapIterator[T, U]) Next() (U, bool) {
|
||||||
|
var zero U
|
||||||
|
item, ok := mr.iter.Next()
|
||||||
|
if !ok {
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
return mr.iteratee(item), true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter creates a new iterator that returns only the items that pass specified predicate function.
|
||||||
|
func Filter[T any](iter Iterator[T], predicateFunc func(item T) bool) Iterator[T] {
|
||||||
|
return &filterIterator[T]{iter: iter, predicateFunc: predicateFunc}
|
||||||
|
}
|
||||||
|
|
||||||
|
type filterIterator[T any] struct {
|
||||||
|
iter Iterator[T]
|
||||||
|
predicateFunc func(T) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *filterIterator[T]) Next() (T, bool) {
|
||||||
|
for item, ok := fr.iter.Next(); ok; item, ok = fr.iter.Next() {
|
||||||
|
if fr.predicateFunc(item) {
|
||||||
|
return item, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var zero T
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *filterIterator[T]) HasNext() bool {
|
||||||
|
return fr.iter.HasNext()
|
||||||
|
}
|
||||||
@@ -11,8 +11,3 @@ type Comparator interface {
|
|||||||
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
|
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
|
||||||
Compare(v1, v2 any) int
|
Compare(v1, v2 any) int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number contains all types of number and uintptr, used for generics constraint
|
|
||||||
type Number interface {
|
|
||||||
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
reduceMaps := make([]map[K]V, 2, 2)
|
reduceMaps := make([]map[K]V, 2)
|
||||||
result = reducer(maps[0], maps[1])
|
result = reducer(maps[0], maps[1])
|
||||||
|
|
||||||
for i := 2; i < len(maps); i++ {
|
for i := 2; i < len(maps); i++ {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exponent calculate x^n
|
// Exponent calculate x^n
|
||||||
@@ -94,7 +94,7 @@ func TruncRound(x float64, n int) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Max return max value of params
|
// Max return max value of params
|
||||||
func Max[T lancetconstraints.Number](numbers ...T) T {
|
func Max[T constraints.Integer | constraints.Float](numbers ...T) T {
|
||||||
max := numbers[0]
|
max := numbers[0]
|
||||||
|
|
||||||
for _, v := range numbers {
|
for _, v := range numbers {
|
||||||
@@ -128,7 +128,7 @@ func MaxBy[T any](slice []T, comparator func(T, T) bool) T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Min return min value of params
|
// Min return min value of params
|
||||||
func Min[T lancetconstraints.Number](numbers ...T) T {
|
func Min[T constraints.Integer | constraints.Float](numbers ...T) T {
|
||||||
min := numbers[0]
|
min := numbers[0]
|
||||||
|
|
||||||
for _, v := range numbers {
|
for _, v := range numbers {
|
||||||
@@ -161,8 +161,8 @@ func MinBy[T any](slice []T, comparator func(T, T) bool) T {
|
|||||||
return min
|
return min
|
||||||
}
|
}
|
||||||
|
|
||||||
// Average return average value of params
|
// Average return average value of numbers
|
||||||
func Average[T lancetconstraints.Number](numbers ...T) T {
|
func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
|
||||||
var sum T
|
var sum T
|
||||||
n := T(len(numbers))
|
n := T(len(numbers))
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ func TestMax(t *testing.T) {
|
|||||||
assert.Equal(Max(0, 0), 0)
|
assert.Equal(Max(0, 0), 0)
|
||||||
assert.Equal(Max(1, 2, 3), 3)
|
assert.Equal(Max(1, 2, 3), 3)
|
||||||
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
|
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
|
||||||
|
|
||||||
|
type Integer int
|
||||||
|
assert.Equal(Max(Integer(1), Integer(0)), Integer(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxBy(t *testing.T) {
|
func TestMaxBy(t *testing.T) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -108,7 +108,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
|
|||||||
|
|
||||||
client.setTLS(rawUrl)
|
client.setTLS(rawUrl)
|
||||||
client.setHeader(req, request.Headers)
|
client.setHeader(req, request.Headers)
|
||||||
client.setQueryParam(req, rawUrl, request.QueryParams)
|
|
||||||
|
err = client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if request.FormData != nil {
|
if request.FormData != nil {
|
||||||
client.setFormData(req, request.FormData)
|
client.setFormData(req, request.FormData)
|
||||||
@@ -177,7 +181,7 @@ func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryP
|
|||||||
|
|
||||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||||
formData := []byte(values.Encode())
|
formData := []byte(values.Encode())
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
req.Body = io.NopCloser(bytes.NewReader(formData))
|
||||||
req.ContentLength = int64(len(formData))
|
req.ContentLength = int64(len(formData))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -32,7 +32,10 @@ func TestHttpClient_Get(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var todo Todo
|
var todo Todo
|
||||||
httpClient.DecodeResponse(resp, &todo)
|
err = httpClient.DecodeResponse(resp, &todo)
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal(1, todo.Id)
|
assert.Equal(1, todo.Id)
|
||||||
}
|
}
|
||||||
@@ -58,7 +61,7 @@ func TestHttpClent_Post(t *testing.T) {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +93,6 @@ func TestStructToUrlValues(t *testing.T) {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", string(body))
|
t.Log("response: ", string(body))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package netutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -20,7 +21,7 @@ func TestHttpGet(t *testing.T) {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ func TestHttpPost(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,23 +51,20 @@ func TestHttpPostFormData(t *testing.T) {
|
|||||||
// "Content-Type": "application/x-www-form-urlencoded",
|
// "Content-Type": "application/x-www-form-urlencoded",
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
}
|
}
|
||||||
type Todo struct {
|
|
||||||
UserId int `json:"userId"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
}
|
|
||||||
// postData := url.Values{}
|
|
||||||
// postData.Add("userId", "1")
|
|
||||||
// postData.Add("title", "TestAddToDo")
|
|
||||||
|
|
||||||
postData := make(map[string]string)
|
postData := url.Values{}
|
||||||
postData["userId"] = "1"
|
postData.Add("userId", "1")
|
||||||
postData["title"] = "title"
|
postData.Add("title", "TestToDo")
|
||||||
|
|
||||||
|
// postData := make(map[string]string)
|
||||||
|
// postData["userId"] = "1"
|
||||||
|
// postData["title"] = "title"
|
||||||
|
|
||||||
resp, err := HttpPost(apiUrl, header, postData, nil)
|
resp, err := HttpPost(apiUrl, header, postData, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +85,7 @@ func TestHttpPut(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +106,7 @@ func TestHttpPatch(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +116,7 @@ func TestHttpDelete(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package netutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -55,7 +55,7 @@ func GetPublicIpInfo() (*PublicIpInfo, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package netutil
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -173,7 +173,7 @@ func setBodyByte(req *http.Request, body any) error {
|
|||||||
if body != nil {
|
if body != nil {
|
||||||
switch b := body.(type) {
|
switch b := body.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
req.Body = io.NopCloser(bytes.NewReader(b))
|
||||||
req.ContentLength = int64(len(b))
|
req.ContentLength = int64(len(b))
|
||||||
default:
|
default:
|
||||||
return errors.New("body type should be []byte")
|
return errors.New("body type should be []byte")
|
||||||
|
|||||||
@@ -12,18 +12,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RandString generate random string
|
const (
|
||||||
// see https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
|
NUMERAL = "0123456789"
|
||||||
func RandString(length int) string {
|
LOWER_LETTERS = "abcdefghijklmnopqrstuvwxyz"
|
||||||
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
UPPER_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
b := make([]byte, length)
|
)
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
||||||
for i := range b {
|
|
||||||
b[i] = letters[r.Int63()%int64(len(letters))]
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
func RandInt(min, max int) int {
|
func RandInt(min, max int) int {
|
||||||
@@ -50,6 +44,41 @@ func RandBytes(length int) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandString generate random string
|
||||||
|
func RandString(length int) string {
|
||||||
|
return random(LETTERS, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandUpper generate a random upper case string
|
||||||
|
func RandUpper(length int) string {
|
||||||
|
return random(UPPER_LETTERS, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandLower generate a random lower case string
|
||||||
|
func RandLower(length int) string {
|
||||||
|
return random(LOWER_LETTERS, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandNumeral generate a random numeral string
|
||||||
|
func RandNumeral(length int) string {
|
||||||
|
return random(NUMERAL, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandNumeralOrLetter generate a random numeral or letter string
|
||||||
|
func RandNumeralOrLetter(length int) string {
|
||||||
|
return random(NUMERAL+LETTERS, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
func UUIdV4() (string, error) {
|
func UUIdV4() (string, error) {
|
||||||
uuid := make([]byte, 16)
|
uuid := make([]byte, 16)
|
||||||
|
|||||||
@@ -19,6 +19,51 @@ func TestRandString(t *testing.T) {
|
|||||||
assert.Equal(true, reg.MatchString(randStr))
|
assert.Equal(true, reg.MatchString(randStr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRandUpper(t *testing.T) {
|
||||||
|
pattern := `^[A-Z]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
randStr := RandUpper(6)
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandUpper")
|
||||||
|
assert.Equal(6, len(randStr))
|
||||||
|
assert.Equal(true, reg.MatchString(randStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandLower(t *testing.T) {
|
||||||
|
pattern := `^[a-z]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
randStr := RandLower(6)
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandLower")
|
||||||
|
assert.Equal(6, len(randStr))
|
||||||
|
assert.Equal(true, reg.MatchString(randStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandNumeral(t *testing.T) {
|
||||||
|
pattern := `^[0-9]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
randStr := RandNumeral(12)
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandNumeral")
|
||||||
|
assert.Equal(12, len(randStr))
|
||||||
|
assert.Equal(true, reg.MatchString(randStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandNumeralOrLetter(t *testing.T) {
|
||||||
|
pattern := `^[0-9a-zA-Z]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
randStr := RandNumeralOrLetter(10)
|
||||||
|
t.Log(randStr)
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandNumeralOrLetter")
|
||||||
|
assert.Equal(10, len(randStr))
|
||||||
|
assert.Equal(true, reg.MatchString(randStr))
|
||||||
|
}
|
||||||
|
|
||||||
func TestRandInt(t *testing.T) {
|
func TestRandInt(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestRandInt")
|
assert := internal.NewAssert(t, "TestRandInt")
|
||||||
|
|
||||||
|
|||||||
433
slice/slice.go
433
slice/slice.go
@@ -10,22 +10,31 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Contain check if the value is in the slice or not
|
// Create a static variable to store the hash table.
|
||||||
func Contain[T comparable](slice []T, value T) bool {
|
// This variable has the same lifetime as the entire program and can be shared by functions that are called more than once.
|
||||||
set := make(map[T]struct{}, len(slice))
|
var (
|
||||||
for _, v := range slice {
|
memoryHashMap = make(map[string]map[any]int)
|
||||||
set[v] = struct{}{}
|
memoryHashCounter = make(map[string]int)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Contain check if the target value is in the slice or not
|
||||||
|
func Contain[T comparable](slice []T, target T) bool {
|
||||||
|
for _, item := range slice {
|
||||||
|
if item == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := set[value]
|
return false
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainSubSlice check if the slice contain subslice or not
|
// ContainSubSlice check if the slice contain a given subslice or not
|
||||||
func ContainSubSlice[T comparable](slice, subslice []T) bool {
|
func ContainSubSlice[T comparable](slice, subSlice []T) bool {
|
||||||
for _, v := range subslice {
|
for _, v := range subSlice {
|
||||||
if !Contain(slice, v) {
|
if !Contain(slice, v) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -34,47 +43,35 @@ func ContainSubSlice[T comparable](slice, subslice []T) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chunk creates an slice of elements split into groups the length of size.
|
// Chunk creates a slice of elements split into groups the length of size
|
||||||
func Chunk[T any](slice []T, size int) [][]T {
|
func Chunk[T any](slice []T, size int) [][]T {
|
||||||
var result [][]T
|
result := [][]T{}
|
||||||
|
|
||||||
if len(slice) == 0 || size <= 0 {
|
if len(slice) == 0 || size <= 0 {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
length := len(slice)
|
for _, item := range slice {
|
||||||
if size == 1 || size >= length {
|
l := len(result)
|
||||||
for _, v := range slice {
|
if l == 0 || len(result[l-1]) == size {
|
||||||
var tmp []T
|
result = append(result, []T{})
|
||||||
tmp = append(tmp, v)
|
l++
|
||||||
result = append(result, tmp)
|
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// divide slice equally
|
result[l-1] = append(result[l-1], item)
|
||||||
divideNum := length/size + 1
|
|
||||||
for i := 0; i < divideNum; i++ {
|
|
||||||
if i == divideNum-1 {
|
|
||||||
if len(slice[i*size:]) > 0 {
|
|
||||||
result = append(result, slice[i*size:])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = append(result, slice[i*size:(i+1)*size])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
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
|
||||||
func Compact[T any](slice []T) []T {
|
func Compact[T comparable](slice []T) []T {
|
||||||
result := make([]T, 0, 0)
|
var zero T
|
||||||
|
|
||||||
|
result := []T{}
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
if !reflect.DeepEqual(v, nil) &&
|
if v != zero {
|
||||||
!reflect.DeepEqual(v, false) &&
|
|
||||||
!reflect.DeepEqual(v, "") &&
|
|
||||||
!reflect.DeepEqual(v, 0) {
|
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,11 +79,11 @@ func Compact[T any](slice []T) []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat creates a new slice concatenating slice with any additional slices and/or values.
|
// Concat creates a new slice concatenating slice with any additional slices.
|
||||||
func Concat[T any](slice []T, values ...[]T) []T {
|
func Concat[T any](slice []T, slices ...[]T) []T {
|
||||||
result := append([]T{}, slice...)
|
result := append([]T{}, slice...)
|
||||||
|
|
||||||
for _, v := range values {
|
for _, v := range slices {
|
||||||
result = append(result, v...)
|
result = append(result, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +92,8 @@ func Concat[T any](slice []T, values ...[]T) []T {
|
|||||||
|
|
||||||
// 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
|
||||||
func Difference[T comparable](slice, comparedSlice []T) []T {
|
func Difference[T comparable](slice, comparedSlice []T) []T {
|
||||||
var result []T
|
result := []T{}
|
||||||
|
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
if !Contain(comparedSlice, v) {
|
if !Contain(comparedSlice, v) {
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
@@ -112,7 +110,7 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
|
|||||||
orginSliceAfterMap := Map(slice, iteratee)
|
orginSliceAfterMap := Map(slice, iteratee)
|
||||||
comparedSliceAfterMap := Map(comparedSlice, iteratee)
|
comparedSliceAfterMap := Map(comparedSlice, iteratee)
|
||||||
|
|
||||||
result := make([]T, 0, 0)
|
result := make([]T, 0)
|
||||||
for i, v := range orginSliceAfterMap {
|
for i, v := range orginSliceAfterMap {
|
||||||
if !Contain(comparedSliceAfterMap, v) {
|
if !Contain(comparedSliceAfterMap, v) {
|
||||||
result = append(result, slice[i])
|
result = append(result, slice[i])
|
||||||
@@ -122,9 +120,9 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
|
|||||||
return result
|
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).
|
||||||
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T {
|
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1, item2 T) bool) []T {
|
||||||
result := make([]T, 0, 0)
|
result := make([]T, 0)
|
||||||
|
|
||||||
getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int {
|
getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int {
|
||||||
index := -1
|
index := -1
|
||||||
@@ -168,9 +166,8 @@ func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) boo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v1 := range slice1 {
|
for i, v := range slice1 {
|
||||||
v2 := slice2[i]
|
if !comparator(v, slice2[i]) {
|
||||||
if !comparator(v1, v2) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,76 +177,68 @@ 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.
|
// Every return true if all of the values in the slice pass the predicate function.
|
||||||
func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
|
func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||||
if predicate == nil {
|
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentLength int
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if predicate(i, v) {
|
if !predicate(i, v) {
|
||||||
currentLength++
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentLength == len(slice)
|
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
|
||||||
func None[T any](slice []T, predicate func(index int, item T) bool) bool {
|
func None[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||||
if predicate == nil {
|
l := 0
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentLength int
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if !predicate(i, v) {
|
if !predicate(i, v) {
|
||||||
currentLength++
|
l++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentLength == len(slice)
|
return l == len(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some return true if any of the values in the list pass the predicate function.
|
// Some return true if any of the values in the list pass the predicate function.
|
||||||
func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
|
func Some[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||||
if predicate == nil {
|
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if predicate(i, v) {
|
if predicate(i, v) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
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
|
||||||
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
|
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T {
|
||||||
if predicate == nil {
|
result := make([]T, 0)
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([]T, 0, 0)
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if predicate(i, v) {
|
if predicate(i, v) {
|
||||||
result = append(result, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count iterates over elements of slice, returns a count of all matched elements
|
// Count returns the number of occurrences of the given item in the slice
|
||||||
func Count[T any](slice []T, predicate func(index int, item T) bool) int {
|
func Count[T comparable](slice []T, item T) int {
|
||||||
if predicate == nil {
|
count := 0
|
||||||
panic("predicate func is missing")
|
|
||||||
|
for _, v := range slice {
|
||||||
|
if item == v {
|
||||||
|
count++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(slice) == 0 {
|
return count
|
||||||
return 0
|
}
|
||||||
}
|
|
||||||
|
// CountBy iterates over elements of slice with predicate function, returns the number of all matched elements
|
||||||
|
func CountBy[T any](slice []T, predicate func(index int, item T) bool) int {
|
||||||
|
count := 0
|
||||||
|
|
||||||
var count int
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if predicate(i, v) {
|
if predicate(i, v) {
|
||||||
count++
|
count++
|
||||||
@@ -261,10 +250,6 @@ func Count[T any](slice []T, predicate func(index int, item T) bool) int {
|
|||||||
|
|
||||||
// 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
|
||||||
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) {
|
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) {
|
||||||
if groupFn == nil {
|
|
||||||
panic("groupFn func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(slice) == 0 {
|
if len(slice) == 0 {
|
||||||
return make([]T, 0), make([]T, 0)
|
return make([]T, 0), make([]T, 0)
|
||||||
}
|
}
|
||||||
@@ -285,11 +270,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.
|
// GroupWith return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
|
||||||
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
|
func GroupWith[T any, U comparable](slice []T, iteratee func(item T) U) map[U][]T {
|
||||||
if iteratee == nil {
|
|
||||||
panic("iteratee func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make(map[U][]T)
|
result := make(map[U][]T)
|
||||||
|
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
@@ -306,15 +287,8 @@ func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
|
|||||||
// Find iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
// 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
|
||||||
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
||||||
if predicate == nil {
|
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(slice) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
index := -1
|
index := -1
|
||||||
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
if predicate(i, v) {
|
if predicate(i, v) {
|
||||||
index = i
|
index = i
|
||||||
@@ -332,15 +306,8 @@ func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
|||||||
// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on predicate function.
|
// 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
|
// If return T is nil then no items matched the predicate func
|
||||||
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) {
|
||||||
if predicate == nil {
|
|
||||||
panic("predicate func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(slice) == 0 {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
index := -1
|
index := -1
|
||||||
|
|
||||||
for i := len(slice) - 1; i >= 0; i-- {
|
for i := len(slice) - 1; i >= 0; i-- {
|
||||||
if predicate(i, slice[i]) {
|
if predicate(i, slice[i]) {
|
||||||
index = i
|
index = i
|
||||||
@@ -386,8 +353,11 @@ func Flatten(slice any) any {
|
|||||||
func FlattenDeep(slice any) any {
|
func FlattenDeep(slice any) any {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
st := sliceElemType(sv.Type())
|
st := sliceElemType(sv.Type())
|
||||||
|
|
||||||
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
|
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
|
||||||
|
|
||||||
result := flattenRecursive(sv, tmp)
|
result := flattenRecursive(sv, tmp)
|
||||||
|
|
||||||
return result.Interface()
|
return result.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,10 +378,6 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
|||||||
|
|
||||||
// ForEach iterates over elements of slice and invokes function for each element
|
// ForEach iterates over elements of slice and invokes function for each element
|
||||||
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
||||||
if iteratee == nil {
|
|
||||||
panic("iteratee func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
iteratee(i, v)
|
iteratee(i, v)
|
||||||
}
|
}
|
||||||
@@ -419,11 +385,8 @@ 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.
|
// Map creates an slice of values by running each element of slice thru iteratee function.
|
||||||
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
|
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
|
||||||
if iteratee == nil {
|
|
||||||
panic("iteratee func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([]U, len(slice), cap(slice))
|
result := make([]U, len(slice), cap(slice))
|
||||||
|
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
result[i] = iteratee(i, v)
|
result[i] = iteratee(i, v)
|
||||||
}
|
}
|
||||||
@@ -433,17 +396,13 @@ 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.
|
// Reduce creates an slice of values by running each element of slice thru iteratee function.
|
||||||
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
|
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T {
|
||||||
if iteratee == nil {
|
|
||||||
panic("iteratee func is missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(slice) == 0 {
|
if len(slice) == 0 {
|
||||||
return initial
|
return initial
|
||||||
}
|
}
|
||||||
|
|
||||||
result := iteratee(0, initial, slice[0])
|
result := iteratee(0, initial, slice[0])
|
||||||
|
|
||||||
tmp := make([]T, 2, 2)
|
tmp := make([]T, 2)
|
||||||
for i := 1; i < len(slice); i++ {
|
for i := 1; i < len(slice); i++ {
|
||||||
tmp[0] = result
|
tmp[0] = result
|
||||||
tmp[1] = slice[i]
|
tmp[1] = slice[i]
|
||||||
@@ -453,7 +412,39 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new
|
||||||
|
func Replace[T comparable](slice []T, old T, new T, n int) []T {
|
||||||
|
result := make([]T, len(slice))
|
||||||
|
copy(result, slice)
|
||||||
|
|
||||||
|
for i := range result {
|
||||||
|
if result[i] == old && n != 0 {
|
||||||
|
result[i] = new
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new.
|
||||||
|
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`.
|
||||||
|
func Repeat[T any](item T, n int) []T {
|
||||||
|
result := make([]T, n)
|
||||||
|
|
||||||
|
for i := range result {
|
||||||
|
result[i] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// InterfaceSlice convert param to slice of interface.
|
// InterfaceSlice convert param to slice of interface.
|
||||||
|
// This function is deprecated, use generics feature of go1.18+ for replacement
|
||||||
func InterfaceSlice(slice any) []any {
|
func InterfaceSlice(slice any) []any {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
if sv.IsNil() {
|
if sv.IsNil() {
|
||||||
@@ -469,35 +460,37 @@ func InterfaceSlice(slice any) []any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StringSlice convert param to slice of string.
|
// StringSlice convert param to slice of string.
|
||||||
|
// This function is deprecated, use generics feature of go1.18+ for replacement
|
||||||
func StringSlice(slice any) []string {
|
func StringSlice(slice any) []string {
|
||||||
v := sliceValue(slice)
|
v := sliceValue(slice)
|
||||||
|
|
||||||
out := make([]string, v.Len())
|
result := make([]string, v.Len())
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
v, ok := v.Index(i).Interface().(string)
|
v, ok := v.Index(i).Interface().(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("invalid element type")
|
panic("invalid element type")
|
||||||
}
|
}
|
||||||
out[i] = v
|
result[i] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntSlice convert param to slice of int.
|
// IntSlice convert param to slice of int.
|
||||||
|
// This function is deprecated, use generics feature of go1.18+ for replacement
|
||||||
func IntSlice(slice any) []int {
|
func IntSlice(slice any) []int {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
|
|
||||||
out := make([]int, sv.Len())
|
result := make([]int, sv.Len())
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
v, ok := sv.Index(i).Interface().(int)
|
v, ok := sv.Index(i).Interface().(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("invalid element type")
|
panic("invalid element type")
|
||||||
}
|
}
|
||||||
out[i] = v
|
result[i] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAt delete the element of slice from start index to end index - 1.
|
// DeleteAt delete the element of slice from start index to end index - 1.
|
||||||
@@ -522,7 +515,7 @@ func DeleteAt[T any](slice []T, start int, end ...int) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if start == size-1 {
|
if start == size-1 {
|
||||||
slice = append(slice[:start])
|
slice = slice[:start]
|
||||||
} else {
|
} else {
|
||||||
slice = append(slice[:start], slice[start+1:]...)
|
slice = append(slice[:start], slice[start+1:]...)
|
||||||
}
|
}
|
||||||
@@ -584,12 +577,8 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
|
|||||||
|
|
||||||
// Unique remove duplicate elements in slice.
|
// Unique remove duplicate elements in slice.
|
||||||
func Unique[T comparable](slice []T) []T {
|
func Unique[T comparable](slice []T) []T {
|
||||||
if len(slice) == 0 {
|
result := []T{}
|
||||||
return []T{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
|
|
||||||
var result []T
|
|
||||||
for i := 0; i < len(slice); i++ {
|
for i := 0; i < len(slice); i++ {
|
||||||
v := slice[i]
|
v := slice[i]
|
||||||
skip := true
|
skip := true
|
||||||
@@ -609,11 +598,8 @@ func Unique[T comparable](slice []T) []T {
|
|||||||
|
|
||||||
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
|
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
|
||||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
|
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
|
||||||
if len(slice) == 0 {
|
result := []T{}
|
||||||
return []T{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []T
|
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
val := iteratee(v)
|
val := iteratee(v)
|
||||||
result = append(result, val)
|
result = append(result, val)
|
||||||
@@ -622,25 +608,53 @@ func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
|
|||||||
return Unique(result)
|
return Unique(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
|
// Union creates a slice of unique elements, in order, from all given slices.
|
||||||
func Union[T comparable](slices ...[]T) []T {
|
func Union[T comparable](slices ...[]T) []T {
|
||||||
if len(slices) == 0 {
|
result := []T{}
|
||||||
return []T{}
|
contain := map[T]struct{}{}
|
||||||
}
|
|
||||||
|
|
||||||
// append all slices, then unique it
|
|
||||||
var allElements []T
|
|
||||||
|
|
||||||
for _, slice := range slices {
|
for _, slice := range slices {
|
||||||
for _, v := range slice {
|
for _, item := range slice {
|
||||||
allElements = append(allElements, v)
|
if _, ok := contain[item]; !ok {
|
||||||
|
contain[item] = struct{}{}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Unique(allElements)
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection creates a slice of unique values that included by all slices.
|
// UnionBy is like Union, what's more it accepts iteratee which is invoked for each element of each slice
|
||||||
|
func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T {
|
||||||
|
result := []T{}
|
||||||
|
contain := map[V]struct{}{}
|
||||||
|
|
||||||
|
for _, slice := range slices {
|
||||||
|
for _, item := range slice {
|
||||||
|
val := predicate(item)
|
||||||
|
if _, ok := contain[val]; !ok {
|
||||||
|
contain[val] = struct{}{}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge all given slices into one slice
|
||||||
|
func Merge[T any](slices ...[]T) []T {
|
||||||
|
result := make([]T, 0)
|
||||||
|
|
||||||
|
for _, v := range slices {
|
||||||
|
result = append(result, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection creates a slice of unique elements that included by all slices.
|
||||||
func Intersection[T comparable](slices ...[]T) []T {
|
func Intersection[T comparable](slices ...[]T) []T {
|
||||||
if len(slices) == 0 {
|
if len(slices) == 0 {
|
||||||
return []T{}
|
return []T{}
|
||||||
@@ -649,12 +663,10 @@ func Intersection[T comparable](slices ...[]T) []T {
|
|||||||
return Unique(slices[0])
|
return Unique(slices[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
var result []T
|
|
||||||
|
|
||||||
reducer := func(sliceA, sliceB []T) []T {
|
reducer := func(sliceA, sliceB []T) []T {
|
||||||
hashMap := make(map[T]int)
|
hashMap := make(map[T]int)
|
||||||
for _, val := range sliceA {
|
for _, v := range sliceA {
|
||||||
hashMap[val] = 1
|
hashMap[v] = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]T, 0)
|
out := make([]T, 0)
|
||||||
@@ -667,9 +679,9 @@ func Intersection[T comparable](slices ...[]T) []T {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
result = reducer(slices[0], slices[1])
|
result := reducer(slices[0], slices[1])
|
||||||
|
|
||||||
reduceSlice := make([][]T, 2, 2)
|
reduceSlice := make([][]T, 2)
|
||||||
for i := 2; i < len(slices); i++ {
|
for i := 2; i < len(slices); i++ {
|
||||||
reduceSlice[0] = result
|
reduceSlice[0] = result
|
||||||
reduceSlice[1] = slices[i]
|
reduceSlice[1] = slices[i]
|
||||||
@@ -722,9 +734,26 @@ func Shuffle[T any](slice []T) []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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`
|
||||||
|
func Sort[T constraints.Ordered](slice []T, sortOrder ...string) {
|
||||||
|
if len(sortOrder) > 0 && sortOrder[0] == "desc" {
|
||||||
|
quickSort(slice, 0, len(slice)-1, "desc")
|
||||||
|
} else {
|
||||||
|
quickSort(slice, 0, len(slice)-1, "asc")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortBy sorts the slice in ascending order as determined by the less function.
|
||||||
|
// This sort is not guaranteed to be stable
|
||||||
|
func SortBy[T any](slice []T, less func(a, b T) bool) {
|
||||||
|
quickSortBy(slice, 0, len(slice)-1, less)
|
||||||
|
}
|
||||||
|
|
||||||
// SortByField return sorted slice by field
|
// SortByField return sorted slice by field
|
||||||
// Slice element should be struct, field type should be int, uint, string, or bool
|
// 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
|
// default sortType is ascending (asc), if descending order, set sortType to desc
|
||||||
|
// This function is deprecated, use Sort and SortBy for replacement
|
||||||
func SortByField(slice any, field string, sortType ...string) error {
|
func SortByField(slice any, field string, sortType ...string) error {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
t := sv.Type().Elem()
|
t := sv.Type().Elem()
|
||||||
@@ -794,39 +823,67 @@ func SortByField(slice any, field string, sortType ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without creates a slice excluding all given values
|
// Without creates a slice excluding all given items
|
||||||
func Without[T comparable](slice []T, values ...T) []T {
|
func Without[T comparable](slice []T, items ...T) []T {
|
||||||
if len(values) == 0 || len(slice) == 0 {
|
if len(items) == 0 || len(slice) == 0 {
|
||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]T, 0, len(slice))
|
result := make([]T, 0, len(slice))
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
if !Contain(values, v) {
|
if !Contain(items, v) {
|
||||||
out = append(out, v)
|
result = append(result, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexOf returns the index at which the first occurrence of a value is found in a slice or return -1
|
// 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.
|
||||||
// if the value cannot be found.
|
func IndexOf[T comparable](arr []T, val T) int {
|
||||||
func IndexOf[T comparable](slice []T, value T) int {
|
limit := 10
|
||||||
for i, v := range slice {
|
// gets the hash value of the array as the key of the hash table.
|
||||||
if v == value {
|
key := fmt.Sprintf("%p", arr)
|
||||||
return i
|
// determines whether the hash table is empty. If so, the hash table is created.
|
||||||
|
if memoryHashMap[key] == nil {
|
||||||
|
memoryHashMap[key] = make(map[any]int)
|
||||||
|
// iterate through the array, adding the value and index of each element to the hash table.
|
||||||
|
for i := len(arr) - 1; i >= 0; i-- {
|
||||||
|
memoryHashMap[key][arr[i]] = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// update the hash table counter.
|
||||||
|
memoryHashCounter[key]++
|
||||||
|
|
||||||
|
// use the hash table to find the specified value. If found, the index is returned.
|
||||||
|
if index, ok := memoryHashMap[key][val]; ok {
|
||||||
|
// calculate the memory usage of the hash table.
|
||||||
|
size := len(memoryHashMap)
|
||||||
|
// If the memory usage of the hash table exceeds the memory limit, the hash table with the lowest counter is cleared.
|
||||||
|
if size > limit {
|
||||||
|
var minKey string
|
||||||
|
var minVal int
|
||||||
|
for k, v := range memoryHashCounter {
|
||||||
|
if k == key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if minVal == 0 || v < minVal {
|
||||||
|
minKey = k
|
||||||
|
minVal = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete(memoryHashMap, minKey)
|
||||||
|
delete(memoryHashCounter, minKey)
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastIndexOf returns the index at which the last occurrence of a value is found in a slice or return -1
|
// 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.
|
||||||
// if the value cannot be found.
|
func LastIndexOf[T comparable](slice []T, item T) int {
|
||||||
func LastIndexOf[T comparable](slice []T, value T) int {
|
|
||||||
for i := len(slice) - 1; i > 0; i-- {
|
for i := len(slice) - 1; i > 0; i-- {
|
||||||
if value == slice[i] {
|
if item == slice[i] {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,27 +892,39 @@ func LastIndexOf[T comparable](slice []T, value T) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
|
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
|
||||||
func ToSlicePointer[T any](value ...T) []*T {
|
func ToSlicePointer[T any](items ...T) []*T {
|
||||||
out := make([]*T, len(value))
|
result := make([]*T, len(items))
|
||||||
for i := range value {
|
for i := range items {
|
||||||
out[i] = &value[i]
|
result[i] = &items[i]
|
||||||
}
|
}
|
||||||
return out
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSlice returns a slices of a variable parameter transformation
|
// ToSlice returns a slices of a variable parameter transformation
|
||||||
func ToSlice[T any](value ...T) []T {
|
func ToSlice[T any](items ...T) []T {
|
||||||
out := make([]T, len(value))
|
result := make([]T, len(items))
|
||||||
for i := range value {
|
copy(result, items)
|
||||||
out[i] = value[i]
|
|
||||||
}
|
return result
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendIfAbsent only absent append the value
|
// AppendIfAbsent only absent append the item
|
||||||
func AppendIfAbsent[T comparable](slice []T, value T) []T {
|
func AppendIfAbsent[T comparable](slice []T, item T) []T {
|
||||||
if !Contain(slice, value) {
|
if !Contain(slice, item) {
|
||||||
slice = append(slice, value)
|
slice = append(slice, item)
|
||||||
}
|
}
|
||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyBy converts a slice to a map based on a callback function
|
||||||
|
func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T {
|
||||||
|
result := make(map[U]T, len(slice))
|
||||||
|
|
||||||
|
for _, v := range slice {
|
||||||
|
k := iteratee(v)
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package slice
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sliceValue return the reflect value of a slice
|
// sliceValue return the reflect value of a slice
|
||||||
@@ -14,45 +16,6 @@ func sliceValue(slice any) reflect.Value {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// functionValue return the reflect value of a function
|
|
||||||
func functionValue(function any) reflect.Value {
|
|
||||||
v := reflect.ValueOf(function)
|
|
||||||
if v.Kind() != reflect.Func {
|
|
||||||
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkSliceCallbackFuncSignature Check func sign : s :[]type1{} -> func(i int, data type1) type2
|
|
||||||
// see https://coolshell.cn/articles/21164.html#%E6%B3%9B%E5%9E%8BMap-Reduce
|
|
||||||
func checkSliceCallbackFuncSignature(fn reflect.Value, types ...reflect.Type) bool {
|
|
||||||
//Check it is a function
|
|
||||||
if fn.Kind() != reflect.Func {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// NumIn() - returns a function type's input parameter count.
|
|
||||||
// NumOut() - returns a function type's output parameter count.
|
|
||||||
if (fn.Type().NumIn() != len(types)-1) || (fn.Type().NumOut() != 1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// In() - returns the type of a function type's i'th input parameter.
|
|
||||||
// first input param type should be int
|
|
||||||
if fn.Type().In(0) != reflect.TypeOf(1) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := 0; i < len(types)-1; i++ {
|
|
||||||
if fn.Type().In(i) != types[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Out() - returns the type of a function type's i'th output parameter.
|
|
||||||
outType := types[len(types)-1]
|
|
||||||
if outType != nil && fn.Type().Out(0) != outType {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// sliceElemType get slice element type
|
// sliceElemType get slice element type
|
||||||
func sliceElemType(reflectType reflect.Type) reflect.Type {
|
func sliceElemType(reflectType reflect.Type) reflect.Type {
|
||||||
for {
|
for {
|
||||||
@@ -63,3 +26,66 @@ func sliceElemType(reflectType reflect.Type) reflect.Type {
|
|||||||
reflectType = reflectType.Elem()
|
reflectType = reflectType.Elem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func quickSort[T constraints.Ordered](slice []T, lowIndex, highIndex int, order string) {
|
||||||
|
if lowIndex < highIndex {
|
||||||
|
p := partitionOrderedSlice(slice, lowIndex, highIndex, order)
|
||||||
|
quickSort(slice, lowIndex, p-1, order)
|
||||||
|
quickSort(slice, p+1, highIndex, order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// partitionOrderedSlice split ordered slice into two parts for quick sort
|
||||||
|
func partitionOrderedSlice[T constraints.Ordered](slice []T, lowIndex, highIndex int, order string) int {
|
||||||
|
p := slice[highIndex]
|
||||||
|
i := lowIndex
|
||||||
|
|
||||||
|
for j := lowIndex; j < highIndex; j++ {
|
||||||
|
if order == "desc" {
|
||||||
|
if slice[j] > p {
|
||||||
|
swap(slice, i, j)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if slice[j] < p {
|
||||||
|
swap(slice, i, j)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(slice, i, highIndex)
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func quickSortBy[T any](slice []T, lowIndex, highIndex int, less func(a, b T) bool) {
|
||||||
|
if lowIndex < highIndex {
|
||||||
|
p := partitionAnySlice(slice, lowIndex, highIndex, less)
|
||||||
|
quickSortBy(slice, lowIndex, p-1, less)
|
||||||
|
quickSortBy(slice, p+1, highIndex, less)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// partitionAnySlice split any slice into two parts for quick sort
|
||||||
|
func partitionAnySlice[T any](slice []T, lowIndex, highIndex int, less func(a, b T) bool) int {
|
||||||
|
p := slice[highIndex]
|
||||||
|
i := lowIndex
|
||||||
|
|
||||||
|
for j := lowIndex; j < highIndex; j++ {
|
||||||
|
|
||||||
|
if less(slice[j], p) {
|
||||||
|
swap(slice, i, j)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(slice, i, highIndex)
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap two slice value at index i and j
|
||||||
|
func swap[T any](slice []T, i, j int) {
|
||||||
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package slice
|
package slice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -31,6 +32,10 @@ func TestChunk(t *testing.T) {
|
|||||||
|
|
||||||
arr := []string{"a", "b", "c", "d", "e"}
|
arr := []string{"a", "b", "c", "d", "e"}
|
||||||
|
|
||||||
|
assert.Equal([][]string{}, Chunk(arr, -1))
|
||||||
|
|
||||||
|
assert.Equal([][]string{}, Chunk(arr, 0))
|
||||||
|
|
||||||
r1 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
|
r1 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
|
||||||
assert.Equal(r1, Chunk(arr, 1))
|
assert.Equal(r1, Chunk(arr, 1))
|
||||||
|
|
||||||
@@ -43,8 +48,11 @@ func TestChunk(t *testing.T) {
|
|||||||
r4 := [][]string{{"a", "b", "c", "d"}, {"e"}}
|
r4 := [][]string{{"a", "b", "c", "d"}, {"e"}}
|
||||||
assert.Equal(r4, Chunk(arr, 4))
|
assert.Equal(r4, Chunk(arr, 4))
|
||||||
|
|
||||||
r5 := [][]string{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
|
r5 := [][]string{{"a", "b", "c", "d", "e"}}
|
||||||
assert.Equal(r5, Chunk(arr, 5))
|
assert.Equal(r5, Chunk(arr, 5))
|
||||||
|
|
||||||
|
r6 := [][]string{{"a", "b", "c", "d", "e"}}
|
||||||
|
assert.Equal(r6, Chunk(arr, 6))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompact(t *testing.T) {
|
func TestCompact(t *testing.T) {
|
||||||
@@ -186,13 +194,22 @@ func TestGroupWith(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCount(t *testing.T) {
|
func TestCount(t *testing.T) {
|
||||||
|
numbers := []int{1, 2, 3, 3, 5, 6}
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestCountBy")
|
||||||
|
|
||||||
|
assert.Equal(1, Count(numbers, 1))
|
||||||
|
assert.Equal(2, Count(numbers, 3))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCountBy(t *testing.T) {
|
||||||
nums := []int{1, 2, 3, 4, 5, 6}
|
nums := []int{1, 2, 3, 4, 5, 6}
|
||||||
evenFunc := func(i, num int) bool {
|
evenFunc := func(i, num int) bool {
|
||||||
return (num % 2) == 0
|
return (num % 2) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCount")
|
assert := internal.NewAssert(t, "TestCountBy")
|
||||||
assert.Equal(3, Count(nums, evenFunc))
|
assert.Equal(3, CountBy(nums, evenFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
func TestFind(t *testing.T) {
|
||||||
@@ -428,6 +445,29 @@ func TestUnion(t *testing.T) {
|
|||||||
assert.Equal([]int{1, 3, 4, 6}, Union(s1))
|
assert.Equal([]int{1, 3, 4, 6}, Union(s1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnionBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestUnionBy")
|
||||||
|
|
||||||
|
testFunc := func(i int) int {
|
||||||
|
return i / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
result := UnionBy(testFunc, []int{0, 1, 2, 3, 4, 5}, []int{0, 2, 10})
|
||||||
|
assert.Equal(result, []int{0, 2, 4, 10})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMerge(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestMerge")
|
||||||
|
|
||||||
|
s1 := []int{1, 2, 3, 4}
|
||||||
|
s2 := []int{2, 3, 4, 5}
|
||||||
|
s3 := []int{4, 5, 6}
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 2, 3, 4, 5, 4, 5, 6}, Merge(s1, s2, s3))
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 2, 3, 4, 5}, Merge(s1, s2))
|
||||||
|
assert.Equal([]int{2, 3, 4, 5, 4, 5, 6}, Merge(s2, s3))
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntersection(t *testing.T) {
|
func TestIntersection(t *testing.T) {
|
||||||
s1 := []int{1, 2, 2, 3}
|
s1 := []int{1, 2, 2, 3}
|
||||||
s2 := []int{1, 2, 3, 4}
|
s2 := []int{1, 2, 3, 4}
|
||||||
@@ -508,6 +548,56 @@ func TestDifferenceBy(t *testing.T) {
|
|||||||
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSort(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSort")
|
||||||
|
|
||||||
|
numbers := []int{1, 4, 3, 2, 5}
|
||||||
|
|
||||||
|
Sort(numbers)
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5}, numbers)
|
||||||
|
|
||||||
|
Sort(numbers, "desc")
|
||||||
|
assert.Equal([]int{5, 4, 3, 2, 1}, numbers)
|
||||||
|
|
||||||
|
strings := []string{"a", "d", "c", "b", "e"}
|
||||||
|
|
||||||
|
Sort(strings)
|
||||||
|
assert.Equal([]string{"a", "b", "c", "d", "e"}, strings)
|
||||||
|
|
||||||
|
Sort(strings, "desc")
|
||||||
|
assert.Equal([]string{"e", "d", "c", "b", "a"}, strings)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSortBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSortBy")
|
||||||
|
|
||||||
|
numbers := []int{1, 4, 3, 2, 5}
|
||||||
|
|
||||||
|
SortBy(numbers, func(a, b int) bool {
|
||||||
|
return a < b
|
||||||
|
})
|
||||||
|
assert.Equal([]int{1, 2, 3, 4, 5}, numbers)
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Logf("sort users by age: %v", users)
|
||||||
|
|
||||||
|
// output
|
||||||
|
// [{b 15} {a 21} {c 100}]
|
||||||
|
}
|
||||||
|
|
||||||
func TestSortByFielDesc(t *testing.T) {
|
func TestSortByFielDesc(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestSortByFielDesc")
|
assert := internal.NewAssert(t, "TestSortByFielDesc")
|
||||||
|
|
||||||
@@ -580,8 +670,39 @@ func TestIndexOf(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestIndexOf")
|
assert := internal.NewAssert(t, "TestIndexOf")
|
||||||
|
|
||||||
arr := []string{"a", "a", "b", "c"}
|
arr := []string{"a", "a", "b", "c"}
|
||||||
|
key := fmt.Sprintf("%p", arr)
|
||||||
assert.Equal(0, IndexOf(arr, "a"))
|
assert.Equal(0, IndexOf(arr, "a"))
|
||||||
assert.Equal(-1, IndexOf(arr, "d"))
|
assert.Equal(-1, IndexOf(arr, "d"))
|
||||||
|
assert.Equal(2, memoryHashCounter[key])
|
||||||
|
|
||||||
|
arr1 := []int{1, 2, 3, 4, 5}
|
||||||
|
key1 := fmt.Sprintf("%p", arr1)
|
||||||
|
assert.Equal(3, IndexOf(arr1, 4))
|
||||||
|
assert.Equal(-1, IndexOf(arr1, 6))
|
||||||
|
assert.Equal(2, memoryHashCounter[key1])
|
||||||
|
|
||||||
|
arr2 := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
|
||||||
|
key2 := fmt.Sprintf("%p", arr2)
|
||||||
|
assert.Equal(2, IndexOf(arr2, 3.3))
|
||||||
|
assert.Equal(3, IndexOf(arr2, 4.4))
|
||||||
|
assert.Equal(-1, IndexOf(arr2, 6.6))
|
||||||
|
assert.Equal(3, memoryHashCounter[key2])
|
||||||
|
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
a := []string{"a", "b", "c"}
|
||||||
|
IndexOf(a, "a")
|
||||||
|
IndexOf(a, "b")
|
||||||
|
}
|
||||||
|
minArr := []string{"c", "b", "a"}
|
||||||
|
minKey := fmt.Sprintf("%p", minArr)
|
||||||
|
assert.Equal(0, IndexOf(minArr, "c"))
|
||||||
|
|
||||||
|
arr3 := []string{"q", "w", "e"}
|
||||||
|
key3 := fmt.Sprintf("%p", arr3)
|
||||||
|
assert.Equal(1, IndexOf(arr3, "w"))
|
||||||
|
assert.Equal(-1, IndexOf(arr3, "r"))
|
||||||
|
assert.Equal(2, memoryHashCounter[key3])
|
||||||
|
assert.Equal(0, memoryHashCounter[minKey])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLastIndexOf(t *testing.T) {
|
func TestLastIndexOf(t *testing.T) {
|
||||||
@@ -617,3 +738,48 @@ func TestAppendIfAbsent(t *testing.T) {
|
|||||||
assert.Equal([]string{"a", "b"}, AppendIfAbsent(str1, "a"))
|
assert.Equal([]string{"a", "b"}, AppendIfAbsent(str1, "a"))
|
||||||
assert.Equal([]string{"a", "b", "c"}, AppendIfAbsent(str1, "c"))
|
assert.Equal([]string{"a", "b", "c"}, AppendIfAbsent(str1, "c"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplace(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestReplace")
|
||||||
|
|
||||||
|
strs := []string{"a", "b", "a", "c", "d", "a"}
|
||||||
|
|
||||||
|
assert.Equal([]string{"a", "b", "a", "c", "d", "a"}, Replace(strs, "a", "x", 0))
|
||||||
|
assert.Equal([]string{"x", "b", "a", "c", "d", "a"}, Replace(strs, "a", "x", 1))
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "a"}, Replace(strs, "a", "x", 2))
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, Replace(strs, "a", "x", 3))
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, Replace(strs, "a", "x", 4))
|
||||||
|
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, Replace(strs, "a", "x", -1))
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, Replace(strs, "a", "x", -2))
|
||||||
|
|
||||||
|
assert.Equal([]string{"a", "b", "a", "c", "d", "a"}, Replace(strs, "x", "y", 1))
|
||||||
|
assert.Equal([]string{"a", "b", "a", "c", "d", "a"}, Replace(strs, "x", "y", -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceAll(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestReplaceAll")
|
||||||
|
|
||||||
|
strs := []string{"a", "b", "a", "c", "d", "a"}
|
||||||
|
|
||||||
|
assert.Equal([]string{"x", "b", "x", "c", "d", "x"}, ReplaceAll(strs, "a", "x"))
|
||||||
|
assert.Equal([]string{"a", "b", "a", "c", "d", "a"}, ReplaceAll(strs, "e", "x"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKeyBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestKeyBy")
|
||||||
|
|
||||||
|
result := KeyBy([]string{"a", "ab", "abc"}, func(str string) int {
|
||||||
|
return len(str)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(result, map[int]string{1: "a", 2: "ab", 3: "abc"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepeat(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestRepeat")
|
||||||
|
|
||||||
|
result := Repeat("a", 6)
|
||||||
|
|
||||||
|
assert.Equal(result, []string{"a", "a", "a", "a", "a", "a"})
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,23 +12,70 @@ import (
|
|||||||
|
|
||||||
// CamelCase covert string to camelCase string.
|
// CamelCase covert string to camelCase string.
|
||||||
func CamelCase(s string) string {
|
func CamelCase(s string) string {
|
||||||
if len(s) == 0 {
|
s = strings.ReplaceAll(s, " ", "")
|
||||||
return ""
|
|
||||||
|
var runes [][]rune
|
||||||
|
lastCharType := 0
|
||||||
|
charType := 0
|
||||||
|
|
||||||
|
// split into fields based on type of unicode character
|
||||||
|
for _, r := range s {
|
||||||
|
switch true {
|
||||||
|
case unicode.IsLower(r):
|
||||||
|
charType = 1
|
||||||
|
case unicode.IsUpper(r):
|
||||||
|
charType = 2
|
||||||
|
case unicode.IsDigit(r):
|
||||||
|
charType = 3
|
||||||
|
default:
|
||||||
|
charType = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if charType == lastCharType {
|
||||||
|
runes[len(runes)-1] = append(runes[len(runes)-1], r)
|
||||||
|
} else {
|
||||||
|
runes = append(runes, []rune{r})
|
||||||
|
}
|
||||||
|
lastCharType = charType
|
||||||
}
|
}
|
||||||
|
|
||||||
result := ""
|
result := ""
|
||||||
blankSpace := " "
|
|
||||||
regex, _ := regexp.Compile("[-_&]+")
|
for i := 0; i < len(runes)-1; i++ {
|
||||||
ss := regex.ReplaceAllString(s, blankSpace)
|
if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) {
|
||||||
for i, v := range strings.Split(ss, blankSpace) {
|
runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
|
||||||
vv := []rune(v)
|
runes[i] = runes[i][:len(runes[i])-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter all non letters and none digit
|
||||||
|
var filterRunes [][]rune
|
||||||
|
for _, r := range runes {
|
||||||
|
if len(r) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if unicode.IsLetter(r[0]) || unicode.IsDigit(r[0]) {
|
||||||
|
filterRunes = append(filterRunes, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// capitalize
|
||||||
|
for i, r := range filterRunes {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if vv[i] >= 65 && vv[i] <= 96 {
|
for j := range r {
|
||||||
vv[0] += 32
|
r[j] = unicode.ToLower(r[j])
|
||||||
}
|
}
|
||||||
result += string(vv)
|
|
||||||
} else {
|
} else {
|
||||||
result += Capitalize(v)
|
for j := range r {
|
||||||
|
if j == 0 {
|
||||||
|
r[0] = unicode.ToUpper(r[0])
|
||||||
|
} else {
|
||||||
|
r[j] = unicode.ToLower(r[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(r) > 0 {
|
||||||
|
result = result + string(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,20 +84,16 @@ func CamelCase(s string) string {
|
|||||||
|
|
||||||
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
|
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
|
||||||
func Capitalize(s string) string {
|
func Capitalize(s string) string {
|
||||||
if len(s) == 0 {
|
result := make([]rune, len(s))
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make([]rune, len(s))
|
|
||||||
for i, v := range s {
|
for i, v := range s {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
out[i] = unicode.ToUpper(v)
|
result[i] = unicode.ToUpper(v)
|
||||||
} else {
|
} else {
|
||||||
out[i] = unicode.ToLower(v)
|
result[i] = unicode.ToLower(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(out)
|
return string(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpperFirst converts the first character of string to upper case.
|
// UpperFirst converts the first character of string to upper case.
|
||||||
|
|||||||
@@ -8,23 +8,41 @@ import (
|
|||||||
|
|
||||||
func TestCamelCase(t *testing.T) {
|
func TestCamelCase(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCamelCase")
|
assert := internal.NewAssert(t, "TestCamelCase")
|
||||||
|
cases := map[string]string{
|
||||||
|
"foobar": "foobar",
|
||||||
|
"&FOO:BAR$BAZ": "fooBarBaz",
|
||||||
|
"fooBar": "fooBar",
|
||||||
|
"FOObar": "foObar",
|
||||||
|
"$foo%": "foo",
|
||||||
|
" $#$Foo 22 bar ": "foo22Bar",
|
||||||
|
"Foo-#1😄$_%^&*(1bar": "foo11Bar",
|
||||||
|
}
|
||||||
|
|
||||||
assert.Equal("fooBar", CamelCase("foo_bar"))
|
for k, v := range cases {
|
||||||
assert.Equal("fooBar", CamelCase("Foo-Bar"))
|
assert.Equal(v, CamelCase(k))
|
||||||
assert.Equal("fooBar", CamelCase("Foo&bar"))
|
}
|
||||||
assert.Equal("fooBar", CamelCase("foo bar"))
|
|
||||||
|
|
||||||
assert.NotEqual("FooBar", CamelCase("foo_bar"))
|
assert.Equal("", CamelCase(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCapitalize(t *testing.T) {
|
func TestCapitalize(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCapitalize")
|
assert := internal.NewAssert(t, "TestCapitalize")
|
||||||
|
|
||||||
assert.Equal("Foo", Capitalize("foo"))
|
cases := map[string]string{
|
||||||
assert.Equal("Foo", Capitalize("Foo"))
|
"Foo": "Foo",
|
||||||
assert.Equal("Foo", Capitalize("Foo"))
|
"_foo": "_foo",
|
||||||
|
"foobar": "Foobar",
|
||||||
|
"fooBar": "Foobar",
|
||||||
|
"foo Bar": "Foo bar",
|
||||||
|
"foo-bar": "Foo-bar",
|
||||||
|
"$foo%": "$foo%",
|
||||||
|
}
|
||||||
|
|
||||||
assert.NotEqual("foo", Capitalize("Foo"))
|
for k, v := range cases {
|
||||||
|
assert.Equal(v, Capitalize(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal("", Capitalize(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKebabCase(t *testing.T) {
|
func TestKebabCase(t *testing.T) {
|
||||||
|
|||||||
50
system/os.go
50
system/os.go
@@ -9,6 +9,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsWindows check if current os is windows
|
// IsWindows check if current os is windows
|
||||||
@@ -50,27 +54,61 @@ func CompareOsEnv(key, comparedEnv string) bool {
|
|||||||
return env == comparedEnv
|
return env == comparedEnv
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExecCommand use shell /bin/bash -c to execute command
|
// ExecCommand execute command, return the stdout and stderr string of command, and error if error occur
|
||||||
|
// param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1
|
||||||
|
// in linux, use /bin/bash -c to execute command
|
||||||
|
// in windows, use powershell.exe to execute command
|
||||||
func ExecCommand(command string) (stdout, stderr string, err error) {
|
func ExecCommand(command string) (stdout, stderr string, err error) {
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
var errout bytes.Buffer
|
var errOut bytes.Buffer
|
||||||
|
|
||||||
cmd := exec.Command("/bin/bash", "-c", command)
|
cmd := exec.Command("/bin/bash", "-c", command)
|
||||||
if IsWindows() {
|
if IsWindows() {
|
||||||
cmd = exec.Command("cmd")
|
cmd = exec.Command("powershell.exe", command)
|
||||||
}
|
}
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Stderr = &errout
|
cmd.Stderr = &errOut
|
||||||
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
stderr = string(errout.Bytes())
|
if utf8.Valid(errOut.Bytes()) {
|
||||||
|
stderr = byteToString(errOut.Bytes(), "UTF8")
|
||||||
|
} else if validator.IsGBK(errOut.Bytes()) {
|
||||||
|
stderr = byteToString(errOut.Bytes(), "GBK")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := out.Bytes()
|
||||||
|
if utf8.Valid(data) {
|
||||||
|
stdout = byteToString(data, "UTF8")
|
||||||
|
} else if validator.IsGBK(data) {
|
||||||
|
stdout = byteToString(data, "GBK")
|
||||||
}
|
}
|
||||||
stdout = string(out.Bytes())
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func byteToString(data []byte, charset string) string {
|
||||||
|
var result string
|
||||||
|
|
||||||
|
switch charset {
|
||||||
|
case "GBK":
|
||||||
|
decodeBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(data)
|
||||||
|
result = string(decodeBytes)
|
||||||
|
case "GB18030":
|
||||||
|
decodeBytes, _ := simplifiedchinese.GB18030.NewDecoder().Bytes(data)
|
||||||
|
result = string(decodeBytes)
|
||||||
|
case "UTF8":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
result = string(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// GetOsBits get this system bits 32bit or 64bit
|
// GetOsBits get this system bits 32bit or 64bit
|
||||||
// return bit int (32/64)
|
// return bit int (32/64)
|
||||||
func GetOsBits() int {
|
func GetOsBits() int {
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ func TestOsDetection(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestOsJudgment")
|
assert := internal.NewAssert(t, "TestOsJudgment")
|
||||||
|
|
||||||
osType, _, _ := ExecCommand("echo $OSTYPE")
|
osType, _, _ := ExecCommand("echo $OSTYPE")
|
||||||
if strings.Index(osType, "linux") != -1 {
|
if strings.Contains(osType, "linux") {
|
||||||
assert.Equal(true, IsLinux())
|
assert.Equal(true, IsLinux())
|
||||||
}
|
}
|
||||||
if strings.Index(osType, "darwin") != -1 {
|
if strings.Contains(osType, "darwin") {
|
||||||
assert.Equal(true, IsMac())
|
assert.Equal(true, IsMac())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,9 @@ func TestOsEnvOperation(t *testing.T) {
|
|||||||
envNotExist := GetOsEnv("foo")
|
envNotExist := GetOsEnv("foo")
|
||||||
assert.Equal("", envNotExist)
|
assert.Equal("", envNotExist)
|
||||||
|
|
||||||
SetOsEnv("foo", "foo_value")
|
err := SetOsEnv("foo", "foo_value")
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
envExist := GetOsEnv("foo")
|
envExist := GetOsEnv("foo")
|
||||||
assert.Equal("foo_value", envExist)
|
assert.Equal("foo_value", envExist)
|
||||||
|
|
||||||
@@ -34,7 +36,7 @@ func TestOsEnvOperation(t *testing.T) {
|
|||||||
assert.Equal(false, CompareOsEnv("abc", "abc"))
|
assert.Equal(false, CompareOsEnv("abc", "abc"))
|
||||||
assert.Equal(false, CompareOsEnv("abc", "abc"))
|
assert.Equal(false, CompareOsEnv("abc", "abc"))
|
||||||
|
|
||||||
err := RemoveOsEnv("foo")
|
err = RemoveOsEnv("foo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
@@ -44,21 +46,26 @@ func TestOsEnvOperation(t *testing.T) {
|
|||||||
func TestExecCommand(t *testing.T) {
|
func TestExecCommand(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestExecCommand")
|
assert := internal.NewAssert(t, "TestExecCommand")
|
||||||
|
|
||||||
out, errout, err := ExecCommand("ls")
|
// linux or mac
|
||||||
t.Log("std out: ", out)
|
stdout, stderr, err := ExecCommand("ls")
|
||||||
t.Log("std err: ", errout)
|
t.Log("std out: ", stdout)
|
||||||
|
t.Log("std err: ", stderr)
|
||||||
|
assert.Equal("", stderr)
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
out, errout, err = ExecCommand("abc")
|
// windows
|
||||||
t.Log("std out: ", out)
|
stdout, stderr, err = ExecCommand("dir")
|
||||||
t.Log("std err: ", errout)
|
t.Log("std out: ", stdout)
|
||||||
if err != nil {
|
t.Log("std err: ", stderr)
|
||||||
t.Logf("error: %v\n", err)
|
if IsWindows() {
|
||||||
|
assert.IsNil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !IsWindows() {
|
// error command
|
||||||
assert.IsNotNil(err)
|
stdout, stderr, err = ExecCommand("abc")
|
||||||
}
|
t.Log("std out: ", stdout)
|
||||||
|
t.Log("std err: ", stderr)
|
||||||
|
assert.IsNotNil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOsBits(t *testing.T) {
|
func TestGetOsBits(t *testing.T) {
|
||||||
|
|||||||
@@ -15,11 +15,24 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var isAlphaRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`)
|
var (
|
||||||
|
alphaMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`)
|
||||||
|
letterRegexMatcher *regexp.Regexp = regexp.MustCompile(`[a-zA-Z]`)
|
||||||
|
intStrMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
||||||
|
urlMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
|
||||||
|
dnsMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
|
||||||
|
emailMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
|
||||||
|
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
|
||||||
|
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
|
||||||
|
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
|
||||||
|
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}`)
|
||||||
|
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
|
||||||
|
base64Matcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
|
||||||
|
)
|
||||||
|
|
||||||
// IsAlpha checks if the string contains only letters (a-zA-Z)
|
// IsAlpha checks if the string contains only letters (a-zA-Z)
|
||||||
func IsAlpha(str string) bool {
|
func IsAlpha(str string) bool {
|
||||||
return isAlphaRegexMatcher.MatchString(str)
|
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
|
||||||
@@ -62,11 +75,9 @@ func ContainLower(str string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var containLetterRegexMatcher *regexp.Regexp = regexp.MustCompile(`[a-zA-Z]`)
|
|
||||||
|
|
||||||
// ContainLetter check if the string contain at least one letter
|
// ContainLetter check if the string contain at least one letter
|
||||||
func ContainLetter(str string) bool {
|
func ContainLetter(str string) bool {
|
||||||
return containLetterRegexMatcher.MatchString(str)
|
return letterRegexMatcher.MatchString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsJSON checks if the string is valid JSON
|
// IsJSON checks if the string is valid JSON
|
||||||
@@ -86,11 +97,9 @@ func IsFloatStr(str string) bool {
|
|||||||
return e == nil
|
return e == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var isIntStrRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
|
||||||
|
|
||||||
// IsIntStr check if the string can convert to a integer.
|
// IsIntStr check if the string can convert to a integer.
|
||||||
func IsIntStr(str string) bool {
|
func IsIntStr(str string) bool {
|
||||||
return isIntStrRegexMatcher.MatchString(str)
|
return intStrMatcher.MatchString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIp check if the string is a ip address.
|
// IsIp check if the string is a ip address.
|
||||||
@@ -125,8 +134,6 @@ func IsPort(str string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var isUrlRegexMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
|
|
||||||
|
|
||||||
// IsUrl check if the string is url.
|
// IsUrl check if the string is url.
|
||||||
func IsUrl(str string) bool {
|
func IsUrl(str string) bool {
|
||||||
if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
|
if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
|
||||||
@@ -143,64 +150,48 @@ func IsUrl(str string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return isUrlRegexMatcher.MatchString(str)
|
return urlMatcher.MatchString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDnsRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
|
|
||||||
|
|
||||||
// IsDns check if the string is dns.
|
// IsDns check if the string is dns.
|
||||||
func IsDns(dns string) bool {
|
func IsDns(dns string) bool {
|
||||||
return isDnsRegexMatcher.MatchString(dns)
|
return dnsMatcher.MatchString(dns)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isEmailRegexMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
|
|
||||||
|
|
||||||
// IsEmail check if the string is a email address.
|
// IsEmail check if the string is a email address.
|
||||||
func IsEmail(email string) bool {
|
func IsEmail(email string) bool {
|
||||||
return isEmailRegexMatcher.MatchString(email)
|
return emailMatcher.MatchString(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isChineseMobileRegexMatcher *regexp.Regexp = regexp.MustCompile("^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$")
|
|
||||||
|
|
||||||
// IsChineseMobile check if the string is chinese mobile number.
|
// IsChineseMobile check if the string is chinese mobile number.
|
||||||
func IsChineseMobile(mobileNum string) bool {
|
func IsChineseMobile(mobileNum string) bool {
|
||||||
return isChineseMobileRegexMatcher.MatchString(mobileNum)
|
return chineseMobileMatcher.MatchString(mobileNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isChineseIdNumRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
|
|
||||||
|
|
||||||
// IsChineseIdNum check if the string is chinese id number.
|
// IsChineseIdNum check if the string is chinese id number.
|
||||||
func IsChineseIdNum(id string) bool {
|
func IsChineseIdNum(id string) bool {
|
||||||
return isChineseIdNumRegexMatcher.MatchString(id)
|
return chineseIdMatcher.MatchString(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
var containChineseRegexMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
|
|
||||||
|
|
||||||
// ContainChinese check if the string contain mandarin chinese.
|
// ContainChinese check if the string contain mandarin chinese.
|
||||||
func ContainChinese(s string) bool {
|
func ContainChinese(s string) bool {
|
||||||
return containChineseRegexMatcher.MatchString(s)
|
return chineseMatcher.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isChinesePhoneRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}`)
|
|
||||||
|
|
||||||
// IsChinesePhone check if the string is chinese phone number.
|
// 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
|
||||||
func IsChinesePhone(phone string) bool {
|
func IsChinesePhone(phone string) bool {
|
||||||
return isChinesePhoneRegexMatcher.MatchString(phone)
|
return chinesePhoneMatcher.MatchString(phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isCreditCardRegexMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
|
|
||||||
|
|
||||||
// IsCreditCard check if the string is credit card.
|
// IsCreditCard check if the string is credit card.
|
||||||
func IsCreditCard(creditCart string) bool {
|
func IsCreditCard(creditCart string) bool {
|
||||||
return isCreditCardRegexMatcher.MatchString(creditCart)
|
return creditCardMatcher.MatchString(creditCart)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isBase64RegexMatcher *regexp.Regexp = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
|
|
||||||
|
|
||||||
// IsBase64 check if the string is base64 string.
|
// IsBase64 check if the string is base64 string.
|
||||||
func IsBase64(base64 string) bool {
|
func IsBase64(base64 string) bool {
|
||||||
return isBase64RegexMatcher.MatchString(base64)
|
return base64Matcher.MatchString(base64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmptyString check if the string is empty.
|
// IsEmptyString check if the string is empty.
|
||||||
@@ -283,3 +274,40 @@ func IsZeroValue(value any) bool {
|
|||||||
|
|
||||||
return reflect.DeepEqual(rv.Interface(), reflect.Zero(rv.Type()).Interface())
|
return reflect.DeepEqual(rv.Interface(), reflect.Zero(rv.Type()).Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsGBK check if data encoding is gbk
|
||||||
|
// Note: this function is implemented by whether double bytes fall within the encoding range of gbk,
|
||||||
|
// while each byte of utf-8 encoding format falls within the encoding range of gbk.
|
||||||
|
// Therefore, utf8.valid() should be called first to check whether it is not utf-8 encoding,
|
||||||
|
// and then call IsGBK() to check gbk encoding. like below
|
||||||
|
/**
|
||||||
|
data := []byte("你好")
|
||||||
|
if utf8.Valid(data) {
|
||||||
|
fmt.Println("data encoding is utf-8")
|
||||||
|
}else if(IsGBK(data)) {
|
||||||
|
fmt.Println("data encoding is GBK")
|
||||||
|
}
|
||||||
|
fmt.Println("data encoding is unknown")
|
||||||
|
**/
|
||||||
|
func IsGBK(data []byte) bool {
|
||||||
|
i := 0
|
||||||
|
for i < len(data) {
|
||||||
|
if data[i] <= 0xff {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
if data[i] >= 0x81 &&
|
||||||
|
data[i] <= 0xfe &&
|
||||||
|
data[i+1] >= 0x40 &&
|
||||||
|
data[i+1] <= 0xfe &&
|
||||||
|
data[i+1] != 0xf7 {
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsAllUpper(t *testing.T) {
|
func TestIsAllUpper(t *testing.T) {
|
||||||
@@ -388,3 +390,13 @@ func TestIsZeroValue(t *testing.T) {
|
|||||||
assert.Equal(false, IsZeroValue(value))
|
assert.Equal(false, IsZeroValue(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsGBK(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsGBK")
|
||||||
|
|
||||||
|
str := "你好"
|
||||||
|
gbkData, _ := simplifiedchinese.GBK.NewEncoder().Bytes([]byte(str))
|
||||||
|
|
||||||
|
assert.Equal(true, IsGBK(gbkData))
|
||||||
|
assert.Equal(false, utf8.Valid(gbkData))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user