mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-05 05:12:26 +08:00
Compare commits
161 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b17329094 | ||
|
|
f869a0a670 | ||
|
|
be000a4bd6 | ||
|
|
81efa800ea | ||
|
|
a783de57a8 | ||
|
|
a622959a78 | ||
|
|
f709dd53ce | ||
|
|
ee9e9625e2 | ||
|
|
84da7d4f27 | ||
|
|
089fd4e13c | ||
|
|
6c40e02324 | ||
|
|
a270b1b634 | ||
|
|
260fb795d3 | ||
|
|
8c036f830c | ||
|
|
bf332b9f1c | ||
|
|
6b6cd66f9f | ||
|
|
5399c2290e | ||
|
|
6248293c49 | ||
|
|
eced25b76d | ||
|
|
96a4327aa7 | ||
|
|
fcfbdea597 | ||
|
|
87896f917a | ||
|
|
b8563ed646 | ||
|
|
1ccf0af2b3 | ||
|
|
6314889c6a | ||
|
|
294bd5a5ed | ||
|
|
ca44815fd5 | ||
|
|
bcd1cabf80 | ||
|
|
4edefcca67 | ||
|
|
fab24c8d12 | ||
|
|
604acd9b07 | ||
|
|
531cb19fd1 | ||
|
|
4f0161ca53 | ||
|
|
73362b7f69 | ||
|
|
b289f2975b | ||
|
|
90ce2705ca | ||
|
|
35e1d09ce3 | ||
|
|
d67d8fad3a | ||
|
|
c5e6d01a31 | ||
|
|
6d6c3f692f | ||
|
|
c695837b16 | ||
|
|
ef28b52963 | ||
|
|
18b2b6ff7c | ||
|
|
6a05a123f4 | ||
|
|
f7c33f258d | ||
|
|
04058dd7da | ||
|
|
72e1d92fa1 | ||
|
|
063df0f0d1 | ||
|
|
fc10689b25 | ||
|
|
9239bcfdc3 | ||
|
|
c984815dea | ||
|
|
301cb5db87 | ||
|
|
cc1bacff74 | ||
|
|
f49f75b371 | ||
|
|
b30f4a7bab | ||
|
|
982cb8932b | ||
|
|
9107eb4b32 | ||
|
|
1acf977b24 | ||
|
|
5c878d0873 | ||
|
|
ab0716a472 | ||
|
|
3c2e0ca5b3 | ||
|
|
551e66ba29 | ||
|
|
4eeeabb227 | ||
|
|
b3437fdddf | ||
|
|
312dcab369 | ||
|
|
0cb89f4f46 | ||
|
|
a2dec87995 | ||
|
|
9094cb29bf | ||
|
|
ddb992ad2f | ||
|
|
24f18aaaec | ||
|
|
36169874e5 | ||
|
|
23aeb6ac99 | ||
|
|
a1984f0a59 | ||
|
|
c95db23d2c | ||
|
|
fbf251d805 | ||
|
|
337f08a04b | ||
|
|
c6a7371049 | ||
|
|
b697858038 | ||
|
|
5446f7e33c | ||
|
|
553f63e76b | ||
|
|
fc3e94df58 | ||
|
|
5c66f38a5b | ||
|
|
70e213b3f7 | ||
|
|
c1b7500bcb | ||
|
|
3d7600a9e4 | ||
|
|
0299c454ab | ||
|
|
741af66404 | ||
|
|
ef5d0379a1 | ||
|
|
105ab49763 | ||
|
|
b5ba9ba573 | ||
|
|
ac3baac5c6 | ||
|
|
a82b5dd206 | ||
|
|
ac0fb5ef25 | ||
|
|
9bd1c205fe | ||
|
|
6ccf9fd3cf | ||
|
|
c02ef2c62d | ||
|
|
6414031754 | ||
|
|
5336130570 | ||
|
|
bfa46d46a2 | ||
|
|
aab28b914c | ||
|
|
336e454ce7 | ||
|
|
35a50bd792 | ||
|
|
2fd23f02f6 | ||
|
|
aad5b447c9 | ||
|
|
cece13e929 | ||
|
|
ecf325a06c | ||
|
|
44370aef5e | ||
|
|
1782b11ec4 | ||
|
|
fe6495123c | ||
|
|
d442f564ce | ||
|
|
f35446cc13 | ||
|
|
506a8b4776 | ||
|
|
47ecfbfd5f | ||
|
|
82f7401368 | ||
|
|
068c878d1e | ||
|
|
47b2402345 | ||
|
|
a245716f99 | ||
|
|
71c85bb8f0 | ||
|
|
5edafec393 | ||
|
|
957878dd98 | ||
|
|
12e979cf3c | ||
|
|
ded42f8ff5 | ||
|
|
d06cde3fcf | ||
|
|
9cd8bfb8e0 | ||
|
|
51c9877224 | ||
|
|
f7f6427919 | ||
|
|
56b6844a2d | ||
|
|
cce56f0479 | ||
|
|
3dbd7d8980 | ||
|
|
3625921912 | ||
|
|
1faaf54986 | ||
|
|
efe1fba267 | ||
|
|
0c43cb3f68 | ||
|
|
c25111e349 | ||
|
|
a61ab5716e | ||
|
|
628404dc7f | ||
|
|
bab0a27e40 | ||
|
|
fc0e104591 | ||
|
|
e83e9a1651 | ||
|
|
3d2e6295c4 | ||
|
|
221fe44e63 | ||
|
|
7930f517ae | ||
|
|
0f61321d5b | ||
|
|
7ddeeb51e5 | ||
|
|
484d2845b3 | ||
|
|
bbbc6b6941 | ||
|
|
acf028cdcd | ||
|
|
31e43ec356 | ||
|
|
9f45e68fef | ||
|
|
d2df99a6f0 | ||
|
|
713c341831 | ||
|
|
0b05a6dd6f | ||
|
|
d21c101caf | ||
|
|
bf49db60d9 | ||
|
|
d57fa3b603 | ||
|
|
b3a29ce82d | ||
|
|
1d8a37d6e8 | ||
|
|
ef2d8e14b0 | ||
|
|
0cbb3dd97e | ||
|
|
38a7f9423f | ||
|
|
2c0ab9e922 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,5 @@ fileutil/*.txt
|
||||
fileutil/*.zip
|
||||
fileutil/*.link
|
||||
fileutil/unzip/*
|
||||
slice/testdata/*
|
||||
cryptor/*.pem
|
||||
651
README.md
651
README.md
@@ -1,15 +1,16 @@
|
||||
<div align=center>
|
||||
<img src="./logo.png" width="200" height="200"/>
|
||||
<a href="https://uvdream.github.io/lancet-docs/en/"><img src="./logo.png" width="200" height="200"/></a>
|
||||
|
||||
<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://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
|
||||
</div>
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -22,22 +23,25 @@ English | [简体中文](./README_zh-CN.md)
|
||||
|
||||
## Feature
|
||||
|
||||
- 👏 Comprehensive, efficient and reusable.
|
||||
- 💪 300+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💅 Only depend on the go standard library.
|
||||
- 🌍 Unit test for every exported function.
|
||||
- 👏 Comprehensive, efficient and reusable.
|
||||
- 💪 300+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💅 Only depend on the go standard library.
|
||||
- 🌍 Unit test for every exported function.
|
||||
|
||||
## Installation
|
||||
|
||||
### 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>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||
```
|
||||
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.2.9. </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 get github.com/duke-git/lancet@v1.2.9 // 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
|
||||
@@ -50,7 +54,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
|
||||
## Example
|
||||
|
||||
Here takes the string function ReverseStr (reverse order string) as an example, and the strutil package needs to be imported.
|
||||
Here takes the string function Reverse (reverse order string) as an example, and the strutil package needs to be imported.
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -62,149 +66,177 @@ import (
|
||||
|
||||
func main() {
|
||||
s := "hello"
|
||||
rs := strutil.ReverseStr(s)
|
||||
rs := strutil.Reverse(s)
|
||||
fmt.Println(rs) //olleh
|
||||
}
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
## [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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/algorithm"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)
|
||||
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)
|
||||
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)
|
||||
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)
|
||||
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)
|
||||
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)
|
||||
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)
|
||||
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)
|
||||
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)
|
||||
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)
|
||||
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)
|
||||
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)
|
||||
|
||||
|
||||
- [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.
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 3. Convertor package contains some functions for data convertion.
|
||||
#### 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...
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/condition"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
|
||||
- [Bool](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Bool)
|
||||
- [And](https://github.com/duke-git/lancet/blob/main/docs/condition.md#And)
|
||||
- [Or](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)
|
||||
- [Xor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)
|
||||
- [Nor](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)
|
||||
- [Nand](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nand)
|
||||
- [TernaryOperator](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)
|
||||
|
||||
### 4. Convertor package contains some functions for data convertion.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/convertor"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
|
||||
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
||||
|
||||
### 4. Cryptor package is for data encryption and decryption.
|
||||
|
||||
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
|
||||
- [ColorRGBToHex](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorRGBToHex)
|
||||
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
|
||||
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
|
||||
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
|
||||
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
|
||||
- [ToFloat](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToFloat)
|
||||
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
|
||||
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
|
||||
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToMap)
|
||||
- [ToPointer](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToPointer)
|
||||
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
|
||||
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
|
||||
- [MapToSlice](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#MapToSlice)
|
||||
- [EncodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#EncodeByte)
|
||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)
|
||||
|
||||
### 5. Cryptor package is for data encryption and decryption.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/cryptor"
|
||||
```
|
||||
|
||||
#### 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)
|
||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)
|
||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)
|
||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)
|
||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)
|
||||
- [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)
|
||||
|
||||
### 5. Datetime package supports date and time format and compare.
|
||||
- [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)
|
||||
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)
|
||||
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)
|
||||
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)
|
||||
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)
|
||||
- [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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/datetime"
|
||||
```
|
||||
|
||||
#### 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)
|
||||
|
||||
|
||||
### 6. 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
|
||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
@@ -213,17 +245,22 @@ import stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
|
||||
import set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
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)
|
||||
|
||||
- [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)
|
||||
|
||||
### 7. Fileutil package implements some basic functions for file operations.
|
||||
### 8. Fileutil package implements some basic functions for file operations.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
@@ -231,213 +268,250 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
|
||||
#### Function list:
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
|
||||
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateDir)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
|
||||
|
||||
### 8. Formatter contains some functions for data formatting.
|
||||
### 9. Formatter contains some functions for data formatting.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
```
|
||||
#### Function list:
|
||||
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
|
||||
|
||||
### 9. Function package can control the flow of function execution and support part of functional programming
|
||||
#### Function list:
|
||||
|
||||
- [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
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
```
|
||||
|
||||
#### 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)
|
||||
|
||||
### 10. Maputil package includes some functions to manipulate map.
|
||||
### 11. Maputil package includes some functions to manipulate map.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
|
||||
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
|
||||
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
|
||||
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
|
||||
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
|
||||
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
|
||||
|
||||
- [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)
|
||||
|
||||
### 11. Mathutil package implements some functions for math calculation.
|
||||
### 12. Mathutil package implements some functions for math calculation.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)
|
||||
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
|
||||
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
|
||||
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
|
||||
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)
|
||||
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MaxBy)
|
||||
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)
|
||||
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MinBy)
|
||||
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
|
||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
|
||||
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
|
||||
|
||||
- [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)
|
||||
|
||||
### 12. 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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
|
||||
- [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)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
|
||||
- [HttpPut](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)
|
||||
- [HttpPatch](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)
|
||||
|
||||
### 13. Random package implements some basic functions to generate random int and string.
|
||||
- [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)
|
||||
- [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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
|
||||
### 14. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
|
||||
- [RandUpper](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUpper)
|
||||
- [RandLower](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandLower)
|
||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeral)
|
||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeralOrLetter)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
|
||||
### 15. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
```
|
||||
|
||||
#### 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)
|
||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)
|
||||
- [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)
|
||||
|
||||
### 15. Slice contains some functions to manipulate slice.
|
||||
- [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)
|
||||
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)
|
||||
- [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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
|
||||
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
|
||||
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
|
||||
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
|
||||
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
|
||||
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
|
||||
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
|
||||
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
|
||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
||||
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
|
||||
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
|
||||
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
|
||||
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
|
||||
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
|
||||
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
|
||||
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
|
||||
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
|
||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||
- [StringSlice](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)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
|
||||
- [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)
|
||||
|
||||
### 16. Strutil package contains some functions to manipulate string.
|
||||
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice.md#AppendIfAbsent)
|
||||
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
|
||||
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
|
||||
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
|
||||
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Compact)
|
||||
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Concat)
|
||||
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
|
||||
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
|
||||
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
|
||||
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
|
||||
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
|
||||
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
|
||||
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
|
||||
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
|
||||
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
|
||||
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
|
||||
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
|
||||
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)
|
||||
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
|
||||
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
|
||||
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
|
||||
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
|
||||
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
|
||||
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
|
||||
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
|
||||
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
|
||||
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
|
||||
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
|
||||
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
|
||||
- [Replace](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)
|
||||
- [ReplaceAll](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReplaceAll)
|
||||
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||
- [StringSlice](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.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
|
||||
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReverseStr)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
### 17. System package contain some functions about os, runtime, shell command.
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Reverse)
|
||||
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
|
||||
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
|
||||
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
|
||||
|
||||
### 19. System package contain some functions about os, runtime, shell command.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
```
|
||||
#### Function list:
|
||||
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
|
||||
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
|
||||
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
|
||||
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
|
||||
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
|
||||
|
||||
### 18. Validator package contains some functions for data validation.
|
||||
#### Function list:
|
||||
|
||||
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
|
||||
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
|
||||
- [IsMac](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsMac)
|
||||
- [GetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsEnv)
|
||||
- [SetOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#SetOsEnv)
|
||||
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
|
||||
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
|
||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
|
||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
|
||||
|
||||
### 19. Validator package contains some functions for data validation.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
@@ -445,40 +519,43 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
|
||||
#### Function list:
|
||||
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
|
||||
### 19. xerror package implements helpers for errors.
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
|
||||
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue)
|
||||
|
||||
### 20. xerror package implements helpers for errors.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
|
||||
|
||||
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
|
||||
|
||||
## How to Contribute
|
||||
|
||||
|
||||
661
README_zh-CN.md
661
README_zh-CN.md
@@ -1,15 +1,16 @@
|
||||
<div align=center>
|
||||
<img src="./logo.png" width="200" height="200"/>
|
||||
<a href="https://uvdream.github.io/lancet-docs/"><img src="./logo.png" width="200" height="200"/><a/>
|
||||
|
||||
<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://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
|
||||
</div>
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -19,30 +20,32 @@
|
||||
|
||||
简体中文 | [English](./README.md)
|
||||
|
||||
|
||||
## 特性
|
||||
|
||||
- 👏 全面、高效、可复用
|
||||
- 💪 300+常用go工具函数,支持string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖go标准库
|
||||
- 🌍 所有导出函数单元测试覆盖率100%
|
||||
- 👏 全面、高效、可复用
|
||||
- 💪 300+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖 go 标准库
|
||||
- 🌍 所有导出函数单元测试覆盖率 100%
|
||||
|
||||
## 安装
|
||||
### Note:
|
||||
1. <b>对于使用go1.18及以上的用户,建议安装v2.x.x。 因为v2.x.x用go1.18的泛型重写了大部分函数。</b>
|
||||
|
||||
### Note:
|
||||
|
||||
1. <b>对于使用 go1.18 及以上的用户,建议安装 v2.x.x。 因为 v2.x.x 用 go1.18 的泛型重写了大部分函数。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
2. <b>使用go1.18以下版本的用户,必须安装v1.x.x。目前最新的v1版本是v1.2.9。</b>
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.4。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet@v1.2.9 // 使用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
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
@@ -50,7 +53,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
|
||||
## 例子
|
||||
|
||||
此处以字符串工具函数ReverseStr(逆序字符串)为例,需要导入strutil包:
|
||||
此处以字符串工具函数 Reverse(逆序字符串)为例,需要导入 strutil 包:
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -62,147 +65,177 @@ import (
|
||||
|
||||
func main() {
|
||||
s := "hello"
|
||||
rs := strutil.ReverseStr(s)
|
||||
rs := strutil.Reverse(s)
|
||||
fmt.Println(rs) //olleh
|
||||
}
|
||||
```
|
||||
|
||||
## API文档
|
||||
## API 文档
|
||||
|
||||
### 1. algorithm算法包实现一些基本算法。eg. sort, search.
|
||||
## [lancet API doc](https://uvdream.github.io/lancet-docs/) 感谢[@UvDream](https://github.com/UvDream)整理
|
||||
|
||||
### 1. algorithm 算法包实现一些基本算法。eg. sort, search.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/algorithm"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)
|
||||
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)
|
||||
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)
|
||||
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)
|
||||
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)
|
||||
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)
|
||||
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)
|
||||
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)
|
||||
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)
|
||||
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)
|
||||
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)
|
||||
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)
|
||||
|
||||
- [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. 并发包包含一些支持并发编程的功能。例如:goroutine, channel, async等。
|
||||
### 2. concurrency 并发包包含一些支持并发编程的功能。例如:goroutine, channel, async 等。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/concurrency"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [NewChannel](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#NewChannel)
|
||||
- [Bridge](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Bridge)
|
||||
- [FanIn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#FanIn)
|
||||
- [Generate](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Generate)
|
||||
- [Or](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Or)
|
||||
- [OrDone](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#OrDone)
|
||||
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Repeat)
|
||||
- [RepeatFn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#RepeatFn)
|
||||
- [Take](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Take)
|
||||
- [Tee](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)
|
||||
|
||||
### 3. convertor转换器包支持一些常见的数据类型转换。
|
||||
|
||||
- [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...
|
||||
|
||||
```go
|
||||
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 转换器包支持一些常见的数据类型转换。
|
||||
|
||||
```go
|
||||
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)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
### 4. 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
|
||||
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)
|
||||
|
||||
### 5. 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
|
||||
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)
|
||||
|
||||
### 6. datastructure包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
### 7. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
```go
|
||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
@@ -211,17 +244,22 @@ import stack "github.com/duke-git/lancet/v2/datastructure/stack"
|
||||
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
|
||||
import set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
```
|
||||
|
||||
#### 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)
|
||||
|
||||
- [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)
|
||||
|
||||
### 7. fileutil包支持文件基本操作。
|
||||
### 8. fileutil 包支持文件基本操作。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
@@ -229,173 +267,204 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
|
||||
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
|
||||
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
|
||||
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateDir)
|
||||
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
|
||||
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
|
||||
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
|
||||
- [IsExist](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsExist)
|
||||
- [IsLink](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsLink)
|
||||
- [IsDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsDir)
|
||||
- [ListFileNames](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ListFileNames)
|
||||
- [RemoveFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#RemoveFile)
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
|
||||
|
||||
### 8. formatter格式化器包含一些数据格式化处理方法。
|
||||
### 9. formatter 格式化器包含一些数据格式化处理方法。
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 9. function函数包控制函数执行流程,包含部分函数式编程。
|
||||
### 10. function 函数包控制函数执行流程,包含部分函数式编程。
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 10. maputil包包括一些操作map的函数.
|
||||
### 11. maputil 包包括一些操作 map 的函数.
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 11. 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
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)
|
||||
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
|
||||
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
|
||||
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
|
||||
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)
|
||||
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MaxBy)
|
||||
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)
|
||||
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MinBy)
|
||||
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
|
||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
|
||||
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
|
||||
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
|
||||
|
||||
### 12. 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
|
||||
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)
|
||||
- [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)
|
||||
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
|
||||
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
|
||||
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
|
||||
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
|
||||
- [HttpPut](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)
|
||||
- [HttpPatch](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)
|
||||
|
||||
### 13. random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
- [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)
|
||||
- [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
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
### 14. retry重试执行函数直到函数运行成功或被context cancel。
|
||||
|
||||
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
|
||||
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
|
||||
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
|
||||
- [RandUpper](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUpper)
|
||||
- [RandLower](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandLower)
|
||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeral)
|
||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandNumeralOrLetter)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
|
||||
|
||||
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 15. slice包包含操作切片的方法集合。
|
||||
### 16. slice 包包含操作切片的方法集合。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
- [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)
|
||||
- [FlattenDeep](#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)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
### 16. strutil包含处理字符串的相关函数。
|
||||
### 17. strutil 包含处理字符串的相关函数。
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
@@ -403,90 +472,94 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
|
||||
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReverseStr)
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
- [After](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#After)
|
||||
- [AfterLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#AfterLast)
|
||||
- [Before](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Before)
|
||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BeforeLast)
|
||||
- [CamelCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#CamelCase)
|
||||
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)
|
||||
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)
|
||||
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
|
||||
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
|
||||
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)
|
||||
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)
|
||||
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
|
||||
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Reverse)
|
||||
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
|
||||
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
|
||||
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
|
||||
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
|
||||
|
||||
### 17. system包含os, runtime, shell command相关函数。
|
||||
### 18. system 包含 os, runtime, shell command 相关函数。
|
||||
|
||||
```go
|
||||
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)
|
||||
|
||||
### 18. 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
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
|
||||
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainChinese)
|
||||
- [ContainLetter](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLetter)
|
||||
- [ContainLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainLower)
|
||||
- [ContainUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#ContainUpper)
|
||||
- [IsAlpha](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAlpha)
|
||||
- [IsAllUpper](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllUpper)
|
||||
- [IsAllLower](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsAllLower)
|
||||
- [IsBase64](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsBase64)
|
||||
- [IsChineseMobile](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseMobile)
|
||||
- [IsChineseIdNum](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChineseIdNum)
|
||||
- [IsChinesePhone](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsChinesePhone)
|
||||
- [IsCreditCard](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsCreditCard)
|
||||
- [IsDns](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsDns)
|
||||
- [IsEmail](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmail)
|
||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)
|
||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)
|
||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)
|
||||
- [IsJSON](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)
|
||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)
|
||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)
|
||||
- [IsIp](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIp)
|
||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV4)
|
||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)
|
||||
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)
|
||||
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
|
||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
|
||||
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)
|
||||
|
||||
validator.md#IsWeakPassword)
|
||||
### 19. xerror包实现一些错误处理函数
|
||||
### 20. xerror 包实现一些错误处理函数
|
||||
|
||||
```go
|
||||
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. 创建自己的特性分支。
|
||||
3. 提交变更。
|
||||
4. Push分支。
|
||||
5. 创建新的pull request。
|
||||
4. Push 分支。
|
||||
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.
|
||||
@@ -65,11 +65,15 @@ func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
}
|
||||
|
||||
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
quickSort(slice, 0, len(slice)-1, comparator)
|
||||
}
|
||||
|
||||
func quickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
if lowIndex < highIndex {
|
||||
p := partition(slice, lowIndex, highIndex, comparator)
|
||||
QuickSort(slice, lowIndex, p-1, comparator)
|
||||
QuickSort(slice, p+1, highIndex, comparator)
|
||||
quickSort(slice, lowIndex, p-1, comparator)
|
||||
quickSort(slice, p+1, highIndex, comparator)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,14 +30,6 @@ func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// var peoples = []people{
|
||||
// {Name: "a", Age: 20},
|
||||
// {Name: "b", Age: 10},
|
||||
// {Name: "c", Age: 17},
|
||||
// {Name: "d", Age: 8},
|
||||
// {Name: "e", Age: 28},
|
||||
// }
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
@@ -53,8 +45,6 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// var intSlice = []int{2, 1, 5, 3, 6, 4}
|
||||
|
||||
func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||
|
||||
@@ -151,7 +141,7 @@ func TestQuickSort(t *testing.T) {
|
||||
{Name: "e", Age: 28},
|
||||
}
|
||||
comparator := &peopleAgeComparator{}
|
||||
QuickSort(peoples, 0, len(peoples)-1, comparator)
|
||||
QuickSort(peoples, comparator)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
77
condition/condition.go
Normal file
77
condition/condition.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package condition contains some functions for conditional judgment. eg. And, Or, TernaryOperator ...
|
||||
// The implementation of this package refers to the implementation of carlmjohnson's truthy package, you may find more
|
||||
// useful information in truthy(https://github.com/carlmjohnson/truthy), thanks carlmjohnson.
|
||||
package condition
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Bool returns the truthy value of anything.
|
||||
// If the value's type has a Bool() bool method, the method is called and returned.
|
||||
// If the type has an IsZero() bool method, the opposite value is returned.
|
||||
// Slices and maps are truthy if they have a length greater than zero.
|
||||
// All other types are truthy if they are not their zero value.
|
||||
func Bool[T any](value T) bool {
|
||||
switch m := any(value).(type) {
|
||||
case interface{ Bool() bool }:
|
||||
return m.Bool()
|
||||
case interface{ IsZero() bool }:
|
||||
return !m.IsZero()
|
||||
}
|
||||
return reflectValue(&value)
|
||||
}
|
||||
|
||||
func reflectValue(vp any) bool {
|
||||
switch rv := reflect.ValueOf(vp).Elem(); rv.Kind() {
|
||||
case reflect.Map, reflect.Slice:
|
||||
return rv.Len() != 0
|
||||
default:
|
||||
is := rv.IsZero()
|
||||
return !is
|
||||
}
|
||||
}
|
||||
|
||||
// And returns true if both a and b are truthy.
|
||||
func And[T, U any](a T, b U) bool {
|
||||
return Bool(a) && Bool(b)
|
||||
}
|
||||
|
||||
// Or returns false iff neither a nor b is truthy.
|
||||
func Or[T, U any](a T, b U) bool {
|
||||
return Bool(a) || Bool(b)
|
||||
}
|
||||
|
||||
// Xor returns true iff a or b but not both is truthy.
|
||||
func Xor[T, U any](a T, b U) bool {
|
||||
valA := Bool(a)
|
||||
valB := Bool(b)
|
||||
return (valA || valB) && valA != valB
|
||||
}
|
||||
|
||||
// Nor returns true iff neither a nor b is truthy.
|
||||
func Nor[T, U any](a T, b U) bool {
|
||||
return !(Bool(a) || Bool(b))
|
||||
}
|
||||
|
||||
// Xnor returns true iff both a and b or neither a nor b are truthy.
|
||||
func Xnor[T, U any](a T, b U) bool {
|
||||
valA := Bool(a)
|
||||
valB := Bool(b)
|
||||
return (valA && valB) || (!valA && !valB)
|
||||
}
|
||||
|
||||
// Nand returns false iff both a and b are truthy.
|
||||
func Nand[T, U any](a T, b U) bool {
|
||||
return !Bool(a) || !Bool(b)
|
||||
}
|
||||
|
||||
// TernaryOperator checks the value of param `isTrue`, if true return ifValue else return elseValue
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U {
|
||||
if Bool(isTrue) {
|
||||
return ifValue
|
||||
} else {
|
||||
return elseValue
|
||||
}
|
||||
}
|
||||
119
condition/condition_test.go
Normal file
119
condition/condition_test.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package condition
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
type TestStruct struct{}
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBool")
|
||||
|
||||
// bool
|
||||
assert.Equal(false, Bool(false))
|
||||
assert.Equal(true, Bool(true))
|
||||
|
||||
// integer
|
||||
assert.Equal(false, Bool(0))
|
||||
assert.Equal(true, Bool(1))
|
||||
|
||||
// float
|
||||
assert.Equal(false, Bool(0.0))
|
||||
assert.Equal(true, Bool(0.1))
|
||||
|
||||
// string
|
||||
assert.Equal(false, Bool(""))
|
||||
assert.Equal(true, Bool(" "))
|
||||
assert.Equal(true, Bool("0"))
|
||||
|
||||
// slice
|
||||
var nums [2]int
|
||||
assert.Equal(false, Bool(nums))
|
||||
nums = [2]int{0, 1}
|
||||
assert.Equal(true, Bool(nums))
|
||||
|
||||
// map
|
||||
assert.Equal(false, Bool(map[string]string{}))
|
||||
assert.Equal(true, Bool(map[string]string{"a": "a"}))
|
||||
|
||||
// channel
|
||||
var ch chan int
|
||||
assert.Equal(false, Bool(ch))
|
||||
ch = make(chan int)
|
||||
assert.Equal(true, Bool(ch))
|
||||
|
||||
// interface
|
||||
var err error
|
||||
assert.Equal(false, Bool(err))
|
||||
err = errors.New("error message")
|
||||
assert.Equal(true, Bool(err))
|
||||
|
||||
// struct
|
||||
assert.Equal(false, Bool(struct{}{}))
|
||||
assert.Equal(true, Bool(time.Now()))
|
||||
|
||||
// struct pointer
|
||||
ts := TestStruct{}
|
||||
assert.Equal(false, Bool(ts))
|
||||
assert.Equal(true, Bool(&ts))
|
||||
}
|
||||
|
||||
func TestAnd(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAnd")
|
||||
assert.Equal(false, And(0, 1))
|
||||
assert.Equal(false, And(0, ""))
|
||||
assert.Equal(false, And(0, "0"))
|
||||
assert.Equal(true, And(1, "0"))
|
||||
}
|
||||
|
||||
func TestOr(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOr")
|
||||
assert.Equal(false, Or(0, ""))
|
||||
assert.Equal(true, Or(0, 1))
|
||||
assert.Equal(true, Or(0, "0"))
|
||||
assert.Equal(true, Or(1, "0"))
|
||||
}
|
||||
|
||||
func TestXor(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOr")
|
||||
assert.Equal(false, Xor(0, 0))
|
||||
assert.Equal(true, Xor(0, 1))
|
||||
assert.Equal(true, Xor(1, 0))
|
||||
assert.Equal(false, Xor(1, 1))
|
||||
}
|
||||
|
||||
func TestNor(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestNor")
|
||||
assert.Equal(true, Nor(0, 0))
|
||||
assert.Equal(false, Nor(0, 1))
|
||||
assert.Equal(false, Nor(1, 0))
|
||||
assert.Equal(false, Nor(1, 1))
|
||||
}
|
||||
|
||||
func TestXnor(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestXnor")
|
||||
assert.Equal(true, Xnor(0, 0))
|
||||
assert.Equal(false, Xnor(0, 1))
|
||||
assert.Equal(false, Xnor(1, 0))
|
||||
assert.Equal(true, Xnor(1, 1))
|
||||
}
|
||||
|
||||
func TestNand(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestNand")
|
||||
assert.Equal(true, Nand(0, 0))
|
||||
assert.Equal(true, Nand(0, 1))
|
||||
assert.Equal(true, Nand(1, 0))
|
||||
assert.Equal(false, Nand(1, 1))
|
||||
}
|
||||
|
||||
func TestTernaryOperator(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TernaryOperator")
|
||||
trueValue := "1"
|
||||
falseValue := "0"
|
||||
|
||||
assert.Equal(trueValue, TernaryOperator(true, trueValue, falseValue))
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package convertor
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -74,72 +75,86 @@ func ToChar(s string) []string {
|
||||
return c
|
||||
}
|
||||
|
||||
// ToChannel convert a array of elements to a read-only channels
|
||||
func ToChannel[T any](array []T) <-chan T {
|
||||
ch := make(chan T)
|
||||
|
||||
go func() {
|
||||
for _, item := range array {
|
||||
ch <- item
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// ToString convert value to string
|
||||
func ToString(value any) string {
|
||||
res := ""
|
||||
result := ""
|
||||
if value == nil {
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch value.(type) {
|
||||
case float32, float64:
|
||||
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return res
|
||||
result = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return result
|
||||
case int, int8, int16, int32, int64:
|
||||
res = strconv.FormatInt(v.Int(), 10)
|
||||
return res
|
||||
result = strconv.FormatInt(v.Int(), 10)
|
||||
return result
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = strconv.FormatUint(v.Uint(), 10)
|
||||
return res
|
||||
result = strconv.FormatUint(v.Uint(), 10)
|
||||
return result
|
||||
case string:
|
||||
res = v.String()
|
||||
return res
|
||||
result = v.String()
|
||||
return result
|
||||
case []byte:
|
||||
res = string(v.Bytes())
|
||||
return res
|
||||
result = string(v.Bytes())
|
||||
return result
|
||||
default:
|
||||
newValue, _ := json.Marshal(value)
|
||||
res = string(newValue)
|
||||
return res
|
||||
result = string(newValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// ToJson convert value to a valid json string
|
||||
func ToJson(value any) (string, error) {
|
||||
res, err := json.Marshal(value)
|
||||
result, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(res), nil
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
// ToFloat convert value to a float64, if input is not a float return 0.0 and error
|
||||
func ToFloat(value any) (float64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
res := 0.0
|
||||
result := 0.0
|
||||
err := fmt.Errorf("ToInt: unvalid interface type %T", value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
res = float64(v.Int())
|
||||
return res, nil
|
||||
result = float64(v.Int())
|
||||
return result, nil
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = float64(v.Uint())
|
||||
return res, nil
|
||||
result = float64(v.Uint())
|
||||
return result, nil
|
||||
case float32, float64:
|
||||
res = v.Float()
|
||||
return res, nil
|
||||
result = v.Float()
|
||||
return result, nil
|
||||
case string:
|
||||
res, err = strconv.ParseFloat(v.String(), 64)
|
||||
result, err = strconv.ParseFloat(v.String(), 64)
|
||||
if err != nil {
|
||||
res = 0.0
|
||||
result = 0.0
|
||||
}
|
||||
return res, err
|
||||
return result, err
|
||||
default:
|
||||
return res, err
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,29 +162,45 @@ func ToFloat(value any) (float64, error) {
|
||||
func ToInt(value any) (int64, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
var res int64
|
||||
var result int64
|
||||
err := fmt.Errorf("ToInt: invalid interface type %T", value)
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
res = v.Int()
|
||||
return res, nil
|
||||
result = v.Int()
|
||||
return result, nil
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = int64(v.Uint())
|
||||
return res, nil
|
||||
result = int64(v.Uint())
|
||||
return result, nil
|
||||
case float32, float64:
|
||||
res = int64(v.Float())
|
||||
return res, nil
|
||||
result = int64(v.Float())
|
||||
return result, nil
|
||||
case string:
|
||||
res, err = strconv.ParseInt(v.String(), 0, 64)
|
||||
result, err = strconv.ParseInt(v.String(), 0, 64)
|
||||
if err != nil {
|
||||
res = 0
|
||||
result = 0
|
||||
}
|
||||
return res, err
|
||||
return result, err
|
||||
default:
|
||||
return res, err
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
|
||||
// ToPointer returns a pointer to this value
|
||||
func ToPointer[T any](value T) *T {
|
||||
return &value
|
||||
}
|
||||
|
||||
// ToMap convert a slice or an array of structs to a map based on iteratee function
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
|
||||
result := make(map[K]V, len(array))
|
||||
for _, item := range array {
|
||||
k, v := iteratee(item)
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// StructToMap convert struct to map, only convert exported struct field
|
||||
// map key is specified same as struct field tag `json` value
|
||||
func StructToMap(value any) (map[string]any, error) {
|
||||
@@ -183,7 +214,7 @@ func StructToMap(value any) (map[string]any, error) {
|
||||
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
|
||||
}
|
||||
|
||||
res := make(map[string]any)
|
||||
result := make(map[string]any)
|
||||
|
||||
fieldNum := t.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
@@ -192,12 +223,23 @@ func StructToMap(value any) (map[string]any, error) {
|
||||
name := t.Field(i).Name
|
||||
tag := t.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
//res[name] = v.Field(i).Interface()
|
||||
res[tag] = v.Field(i).Interface()
|
||||
//result[name] = v.Field(i).Interface()
|
||||
result[tag] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// MapToSlice convert a map to a slice based on iteratee function
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T {
|
||||
result := make([]T, 0, len(aMap))
|
||||
|
||||
for k, v := range aMap {
|
||||
result = append(result, iteratee(k, v))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ColorHexToRGB convert hex color to rgb color
|
||||
@@ -229,3 +271,21 @@ func ColorRGBToHex(red, green, blue int) string {
|
||||
|
||||
return "#" + r + g + b
|
||||
}
|
||||
|
||||
// EncodeByte encode data to byte
|
||||
func EncodeByte(data any) ([]byte, error) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
encoder := gob.NewEncoder(buffer)
|
||||
err := encoder.Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// DecodeByte decode byte data to target object
|
||||
func DecodeByte(data []byte, target any) error {
|
||||
buffer := bytes.NewBuffer(data)
|
||||
decoder := gob.NewDecoder(buffer)
|
||||
return decoder.Decode(target)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package convertor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func TestToChar(t *testing.T) {
|
||||
@@ -21,6 +23,23 @@ func TestToChar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestToChannel(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToChannel")
|
||||
|
||||
ch := ToChannel([]int{1, 2, 3})
|
||||
val1, _ := <-ch
|
||||
assert.Equal(1, val1)
|
||||
|
||||
val2, _ := <-ch
|
||||
assert.Equal(2, val2)
|
||||
|
||||
val3, _ := <-ch
|
||||
assert.Equal(3, val3)
|
||||
|
||||
_, ok := <-ch
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToBool")
|
||||
|
||||
@@ -142,6 +161,25 @@ func TestToJson(t *testing.T) {
|
||||
assert.Equal("{\"Name\":\"TestStruct\"}", structJsonStr)
|
||||
}
|
||||
|
||||
func TestToMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToMap")
|
||||
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
expected := map[int]string{100: "Hello", 101: "Hi"}
|
||||
|
||||
assert.Equal(expected, result)
|
||||
}
|
||||
|
||||
func TestStructToMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToMap")
|
||||
|
||||
@@ -154,10 +192,25 @@ func TestStructToMap(t *testing.T) {
|
||||
100,
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
var expected = map[string]any{"name": "test"}
|
||||
|
||||
expected := map[string]any{"name": "test"}
|
||||
assert.Equal(expected, pm)
|
||||
}
|
||||
|
||||
func TestMapToSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMapToSlice")
|
||||
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
assert.Equal(3, len(result))
|
||||
assert.Equal(true, slice.Contain(result, "a:1"))
|
||||
assert.Equal(true, slice.Contain(result, "b:2"))
|
||||
assert.Equal(true, slice.Contain(result, "c:3"))
|
||||
}
|
||||
|
||||
func TestColorHexToRGB(t *testing.T) {
|
||||
colorHex := "#003366"
|
||||
r, g, b := ColorHexToRGB(colorHex)
|
||||
@@ -178,3 +231,28 @@ func TestColorRGBToHex(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestColorRGBToHex")
|
||||
assert.Equal(expected, colorHex)
|
||||
}
|
||||
|
||||
func TestToPointer(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToPointer")
|
||||
result := ToPointer(123)
|
||||
|
||||
assert.Equal(*result, 123)
|
||||
}
|
||||
|
||||
func TestEncodeByte(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEncodeByte")
|
||||
|
||||
byteData, _ := EncodeByte("abc")
|
||||
expected := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||
|
||||
assert.Equal(expected, byteData)
|
||||
}
|
||||
|
||||
func TestDecodeByte(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDecodeByte")
|
||||
|
||||
var obj string
|
||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||
DecodeByte(byteData, &obj)
|
||||
assert.Equal("abc", obj)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func AesEcbEncrypt(data, key []byte) []byte {
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
//
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
@@ -54,14 +54,18 @@ func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
data = pkcs7Padding(data, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
|
||||
|
||||
encrypted := make([]byte, len(data))
|
||||
blockMode.CryptBlocks(encrypted, data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
@@ -69,12 +73,14 @@ func AesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
blockMode.CryptBlocks(decrypted, encrypted)
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,16 @@ func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 8
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
data = pkcs7Padding(data, blockSize)
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, len(data))
|
||||
blockMode.CryptBlocks(encrypted, data)
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
@@ -69,13 +73,14 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
blockMode.CryptBlocks(decrypted, encrypted)
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
|
||||
175
datastructure/hashmap/hashmap.go
Normal file
175
datastructure/hashmap/hashmap.go
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
)
|
||||
|
||||
var defaultMapCapacity uint64 = 1 << 10
|
||||
|
||||
type mapNode struct {
|
||||
key any
|
||||
value any
|
||||
next *mapNode
|
||||
}
|
||||
|
||||
//HashMap implements a hash map
|
||||
type HashMap struct {
|
||||
capacity uint64
|
||||
size uint64
|
||||
table []*mapNode
|
||||
}
|
||||
|
||||
// NewHashMap return a HashMap instance
|
||||
func NewHashMap() *HashMap {
|
||||
return &HashMap{
|
||||
capacity: defaultMapCapacity,
|
||||
table: make([]*mapNode, defaultMapCapacity),
|
||||
}
|
||||
}
|
||||
|
||||
// NewHashMapWithCapacity return a HashMap instance with given size and capacity
|
||||
func NewHashMapWithCapacity(size, capacity uint64) *HashMap {
|
||||
return &HashMap{
|
||||
size: size,
|
||||
capacity: capacity,
|
||||
table: make([]*mapNode, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
// Get return the value of given key in hashmap
|
||||
func (hm *HashMap) Get(key any) any {
|
||||
hashValue := hm.hash(key)
|
||||
node := hm.table[hashValue]
|
||||
if node != nil {
|
||||
return node.value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Put new key value in hashmap
|
||||
func (hm *HashMap) Put(key any, value any) {
|
||||
hm.putValue(hm.hash(key), key, value)
|
||||
}
|
||||
|
||||
func (hm *HashMap) putValue(hash uint64, key, value any) {
|
||||
if hm.capacity == 0 {
|
||||
hm.capacity = defaultMapCapacity
|
||||
hm.table = make([]*mapNode, defaultMapCapacity)
|
||||
}
|
||||
|
||||
node := hm.table[hash]
|
||||
if node == nil {
|
||||
hm.table[hash] = newMapNode(key, value)
|
||||
} else if node.key == key {
|
||||
hm.table[hash] = newMapNodeWithNext(key, value, node)
|
||||
} else {
|
||||
hm.resize()
|
||||
hm.putValue(hash, value, value)
|
||||
}
|
||||
hm.size++
|
||||
}
|
||||
|
||||
// Delete item by given key in hashmap
|
||||
func (hm *HashMap) Delete(key any) {
|
||||
hash := hm.hash(key)
|
||||
node := hm.table[hash]
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hm.table = append(hm.table[:hash], hm.table[hash+1:]...)
|
||||
hm.size--
|
||||
}
|
||||
|
||||
// Contains checks if given key is in hashmap or not
|
||||
func (hm *HashMap) Contains(key any) bool {
|
||||
node := hm.table[hm.hash(key)]
|
||||
return node != nil
|
||||
}
|
||||
|
||||
// Iterate executes iteratee funcation for every key and value pair of hashmap (random order)
|
||||
func (hm *HashMap) Iterate(iteratee func(key, value any)) {
|
||||
if hm.size > 0 {
|
||||
for i := 0; i < len(hm.table); i++ {
|
||||
item := hm.table[i]
|
||||
if item != nil {
|
||||
iteratee(item.key, item.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keys returns a slice of the hashmap's keys (random order)
|
||||
func (hm *HashMap) Keys() []any {
|
||||
keys := make([]any, int(hm.size))
|
||||
index := 0
|
||||
if hm.size > 0 {
|
||||
hm.Iterate(func(key, value any) {
|
||||
keys[index] = key
|
||||
index++
|
||||
})
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
// Values returns a slice of the hashmap's keys (random order)
|
||||
func (hm *HashMap) Values() []any {
|
||||
values := make([]any, int(hm.size))
|
||||
index := 0
|
||||
if hm.size > 0 {
|
||||
hm.Iterate(func(key, value any) {
|
||||
values[index] = value
|
||||
index++
|
||||
})
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
func (hm *HashMap) resize() {
|
||||
hm.capacity <<= 1
|
||||
|
||||
tempTable := hm.table
|
||||
|
||||
hm.table = make([]*mapNode, hm.capacity)
|
||||
|
||||
for i := 0; i < len(tempTable); i++ {
|
||||
node := tempTable[i]
|
||||
if node == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
hm.table[hm.hash(node.key)] = node
|
||||
}
|
||||
}
|
||||
|
||||
func (hm *HashMap) hash(key any) uint64 {
|
||||
h := fnv.New64a()
|
||||
_, _ = h.Write([]byte(fmt.Sprintf("%v", key)))
|
||||
|
||||
hashValue := h.Sum64()
|
||||
|
||||
return (hm.capacity - 1) & (hashValue ^ (hashValue >> 16))
|
||||
}
|
||||
|
||||
func newMapNode(key, value any) *mapNode {
|
||||
return &mapNode{
|
||||
key: key,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
func newMapNodeWithNext(key, value any, next *mapNode) *mapNode {
|
||||
return &mapNode{
|
||||
key: key,
|
||||
value: value,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
71
datastructure/hashmap/hashmap_test.go
Normal file
71
datastructure/hashmap/hashmap_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestHashMap_PutAndGet(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHashMap_PutAndGet")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("abc", 3)
|
||||
assert.Equal(3, hm.Get("abc"))
|
||||
assert.IsNil(hm.Get("abcd"))
|
||||
|
||||
hm.Put("abc", 4)
|
||||
assert.Equal(4, hm.Get("abc"))
|
||||
}
|
||||
|
||||
func TestHashMap_Resize(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHashMap_Resize")
|
||||
|
||||
hm := NewHashMapWithCapacity(3, 3)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
hm.Put(i, 10)
|
||||
}
|
||||
|
||||
assert.Equal(10, hm.Get(5))
|
||||
}
|
||||
|
||||
func TestHashMap_Delete(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHashMap_Delete")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("abc", 3)
|
||||
assert.Equal(3, hm.Get("abc"))
|
||||
|
||||
hm.Delete("abc")
|
||||
assert.IsNil(hm.Get("abc"))
|
||||
}
|
||||
|
||||
func TestHashMap_Contains(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHashMap_Contains")
|
||||
|
||||
hm := NewHashMap()
|
||||
assert.Equal(false, hm.Contains("abc"))
|
||||
|
||||
hm.Put("abc", 3)
|
||||
assert.Equal(true, hm.Contains("abc"))
|
||||
}
|
||||
|
||||
func TestHashMap_KeysValues(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHashMap_KeysValues")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
keys := hm.Keys()
|
||||
values := hm.Values()
|
||||
t.Log(keys, values)
|
||||
|
||||
assert.Equal(3, len(values))
|
||||
assert.Equal(3, len(keys))
|
||||
}
|
||||
203
datastructure/heap/maxheap.go
Normal file
203
datastructure/heap/maxheap.go
Normal file
@@ -0,0 +1,203 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
// MaxHeap implements a binary max heap
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
|
||||
// NewMaxHeap returns a MaxHeap instance with the given comparator.
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
return &MaxHeap[T]{
|
||||
data: make([]T, 0),
|
||||
comparator: comparator,
|
||||
}
|
||||
}
|
||||
|
||||
// BuildMaxHeap builds a MaxHeap instance with data and given comparator.
|
||||
func BuildMaxHeap[T any](data []T, comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
heap := &MaxHeap[T]{
|
||||
data: make([]T, 0, len(data)),
|
||||
comparator: comparator,
|
||||
}
|
||||
|
||||
for _, v := range data {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
return heap
|
||||
}
|
||||
|
||||
// Push value into the heap
|
||||
func (h *MaxHeap[T]) Push(value T) {
|
||||
h.data = append(h.data, value)
|
||||
h.heapifyUp(len(h.data) - 1)
|
||||
}
|
||||
|
||||
// heapifyUp heapify the data from bottom to top
|
||||
func (h *MaxHeap[T]) heapifyUp(i int) {
|
||||
for h.comparator.Compare(h.data[parentIndex(i)], h.data[i]) < 0 {
|
||||
h.swap(parentIndex(i), i)
|
||||
i = parentIndex(i)
|
||||
}
|
||||
}
|
||||
|
||||
// Pop return the largest value, and remove it from the heap
|
||||
// if heap is empty, return zero value and fasle
|
||||
func (h *MaxHeap[T]) Pop() (T, bool) {
|
||||
var val T
|
||||
if h.Size() == 0 {
|
||||
return val, false
|
||||
}
|
||||
|
||||
val = h.data[0]
|
||||
l := len(h.data) - 1
|
||||
|
||||
h.data[0] = h.data[l]
|
||||
h.data = h.data[:l]
|
||||
h.heapifyDown(0)
|
||||
|
||||
return val, true
|
||||
}
|
||||
|
||||
// heapifyDown heapify the data from top to bottom
|
||||
func (h *MaxHeap[T]) heapifyDown(i int) {
|
||||
lastIndex := len(h.data) - 1
|
||||
l, r := leftChildIndex(i), rightChildIndex(i)
|
||||
childToCompare := 0
|
||||
|
||||
for l <= lastIndex {
|
||||
if l == lastIndex {
|
||||
childToCompare = l
|
||||
} else if h.comparator.Compare(h.data[l], h.data[r]) > 0 {
|
||||
childToCompare = l
|
||||
} else {
|
||||
childToCompare = r
|
||||
}
|
||||
|
||||
if h.comparator.Compare(h.data[i], h.data[childToCompare]) < 0 {
|
||||
h.swap(i, childToCompare)
|
||||
i = childToCompare
|
||||
l, r = leftChildIndex(i), rightChildIndex(i)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Peek returns the largest element from the heap without removing it.
|
||||
// if heap is empty, it returns zero value and false.
|
||||
func (h *MaxHeap[T]) Peek() (T, bool) {
|
||||
if h.Size() == 0 {
|
||||
var val T
|
||||
return val, false
|
||||
}
|
||||
|
||||
return h.data[0], true
|
||||
}
|
||||
|
||||
// Size return the number of elements in the heap
|
||||
func (h *MaxHeap[T]) Size() int {
|
||||
return len(h.data)
|
||||
}
|
||||
|
||||
// Data return data of the heap
|
||||
func (h *MaxHeap[T]) Data() []T {
|
||||
return h.data
|
||||
}
|
||||
|
||||
// PrintStructure print the structure of the heap
|
||||
func (h *MaxHeap[T]) PrintStructure() {
|
||||
level := 1
|
||||
data := h.data
|
||||
length := len(h.data)
|
||||
index := 0
|
||||
|
||||
list := [][]string{}
|
||||
temp := []string{}
|
||||
for index < length {
|
||||
start := powerTwo(level-1) - 1
|
||||
end := start + powerTwo(level-1) - 1
|
||||
|
||||
temp = append(temp, fmt.Sprintf("%v", data[index]))
|
||||
index++
|
||||
|
||||
if index > end || index >= length {
|
||||
list = append(list, temp)
|
||||
temp = []string{}
|
||||
|
||||
if index < length {
|
||||
level++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastNum := powerTwo(level - 1)
|
||||
lastLen := lastNum + (lastNum - 1)
|
||||
|
||||
heapTree := make([][]string, level, level)
|
||||
for i := 0; i < level; i++ {
|
||||
heapTree[i] = make([]string, lastLen, lastLen)
|
||||
for j := 0; j < lastLen; j++ {
|
||||
heapTree[i][j] = ""
|
||||
}
|
||||
}
|
||||
|
||||
for k := 0; k < len(list); k++ {
|
||||
vals := list[k]
|
||||
tempLevel := level - k
|
||||
st := powerTwo(tempLevel-1) - 1
|
||||
for _, v := range vals {
|
||||
heapTree[k][st] = v
|
||||
gap := powerTwo(tempLevel)
|
||||
st = st + gap
|
||||
}
|
||||
}
|
||||
|
||||
for m := 0; m < level; m++ {
|
||||
for n := 0; n < lastLen; n++ {
|
||||
val := heapTree[m][n]
|
||||
if val == "" {
|
||||
fmt.Printf(" ")
|
||||
} else {
|
||||
fmt.Printf(val)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
// parentIndex get parent index of the given index
|
||||
func parentIndex(i int) int {
|
||||
return (i - 1) / 2
|
||||
}
|
||||
|
||||
// leftChildIndex get left child index of the given index
|
||||
func leftChildIndex(i int) int {
|
||||
return 2*i + 1
|
||||
}
|
||||
|
||||
// rightChildIndex get right child index of the given index
|
||||
func rightChildIndex(i int) int {
|
||||
return 2*i + 2
|
||||
}
|
||||
|
||||
// swap two elements in the heap
|
||||
func (h *MaxHeap[T]) swap(i, j int) {
|
||||
h.data[i], h.data[j] = h.data[j], h.data[i]
|
||||
}
|
||||
|
||||
func powerTwo(n int) int {
|
||||
return 1 << n
|
||||
}
|
||||
92
datastructure/heap/maxheap_test.go
Normal file
92
datastructure/heap/maxheap_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
heap := BuildMaxHeap(values, &intComparator{})
|
||||
|
||||
expected := []int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
assert.Equal(expected, heap.data)
|
||||
|
||||
assert.Equal(12, heap.Size())
|
||||
|
||||
heap.PrintStructure()
|
||||
}
|
||||
|
||||
func TestMaxHeap_Push(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Push")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
expected := []int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
assert.Equal(expected, heap.data)
|
||||
|
||||
assert.Equal(12, heap.Size())
|
||||
|
||||
heap.PrintStructure()
|
||||
}
|
||||
|
||||
func TestMaxHeap_Pop(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
|
||||
_, ok := heap.Pop()
|
||||
assert.Equal(false, ok)
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
val, ok := heap.Pop()
|
||||
assert.Equal(12, val)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(11, heap.Size())
|
||||
}
|
||||
|
||||
func TestMaxHeap_Peek(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
|
||||
_, ok := heap.Peek()
|
||||
assert.Equal(false, ok)
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
for _, v := range values {
|
||||
heap.Push(v)
|
||||
}
|
||||
|
||||
val, ok := heap.Peek()
|
||||
assert.Equal(12, val)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
assert.Equal(12, heap.Size())
|
||||
}
|
||||
@@ -208,13 +208,13 @@ func (link *DoublyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all doubly linklist node value
|
||||
func (link *DoublyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
result := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
result = append(result, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Print all nodes info of a linked list
|
||||
|
||||
@@ -213,13 +213,13 @@ func (link *SinglyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all singly linklist node value
|
||||
func (link *SinglyLink[T]) Values() []T {
|
||||
res := []T{}
|
||||
result := []T{}
|
||||
current := link.Head
|
||||
for current != nil {
|
||||
res = append(res, current.Value)
|
||||
result = append(result, current.Value)
|
||||
current = current.Next
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// IsEmpty checks if link is empty or not
|
||||
|
||||
@@ -31,7 +31,7 @@ func (l *List[T]) ValueOf(index int) (*T, bool) {
|
||||
return &l.data[index], true
|
||||
}
|
||||
|
||||
// IndexOf reture the index of value. if not found return -1
|
||||
// IndexOf returns the index of value. if not found return -1
|
||||
func (l *List[T]) IndexOf(value T) int {
|
||||
index := -1
|
||||
data := l.data
|
||||
@@ -44,6 +44,48 @@ func (l *List[T]) IndexOf(value T) int {
|
||||
return index
|
||||
}
|
||||
|
||||
// LastIndexOf returns the index of the last occurrence of the value in this list.
|
||||
// if not found return -1
|
||||
func (l *List[T]) LastIndexOf(value T) int {
|
||||
index := -1
|
||||
data := l.data
|
||||
for i := len(data) - 1; i >= 0; i-- {
|
||||
if reflect.DeepEqual(data[i], value) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// IndexOfFunc returns the first index satisfying f(v)
|
||||
// if not found return -1
|
||||
func (l *List[T]) IndexOfFunc(f func(T) bool) int {
|
||||
index := -1
|
||||
data := l.data
|
||||
for i, v := range data {
|
||||
if f(v) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying f(data[i])
|
||||
// if not found return -1
|
||||
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int {
|
||||
index := -1
|
||||
data := l.data
|
||||
for i := len(data) - 1; i >= 0; i-- {
|
||||
if f(data[i]) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// Contain checks if the value in the list or not
|
||||
func (l *List[T]) Contain(value T) bool {
|
||||
data := l.data
|
||||
@@ -121,6 +163,31 @@ func (l *List[T]) DeleteAt(index int) {
|
||||
l.data = data
|
||||
}
|
||||
|
||||
// DeleteIf delete all satisfying f(data[i]), returns count of removed elements
|
||||
func (l *List[T]) DeleteIf(f func(T) bool) int {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
|
||||
var c int
|
||||
for index := 0; index < len(data); index++ {
|
||||
if !f(data[index]) {
|
||||
continue
|
||||
}
|
||||
if index == size-1 {
|
||||
data = append(data[:index])
|
||||
} else {
|
||||
data = append(data[:index], data[index+1:]...)
|
||||
index--
|
||||
}
|
||||
c++
|
||||
}
|
||||
|
||||
if c > 0 {
|
||||
l.data = data
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdateAt update value of list at index, index shoud between 0 and list size -1
|
||||
func (l *List[T]) UpdateAt(index int, value T) {
|
||||
data := l.data
|
||||
@@ -181,6 +248,11 @@ func (l *List[T]) Size() int {
|
||||
return len(l.data)
|
||||
}
|
||||
|
||||
// Cap return cap of the inner data
|
||||
func (l *List[T]) Cap() int {
|
||||
return cap(l.data)
|
||||
}
|
||||
|
||||
// Swap the value of index i and j in list
|
||||
func (l *List[T]) Swap(i, j int) {
|
||||
size := len(l.data)
|
||||
@@ -222,24 +294,32 @@ func (l *List[T]) Unique() {
|
||||
|
||||
// Union creates a new list contain all element in list l and other, remove duplicate element.
|
||||
func (l *List[T]) Union(other *List[T]) *List[T] {
|
||||
res := NewList([]T{})
|
||||
result := NewList([]T{})
|
||||
|
||||
res.data = append(res.data, l.data...)
|
||||
res.data = append(res.data, other.data...)
|
||||
res.Unique()
|
||||
result.data = append(result.data, l.data...)
|
||||
result.data = append(result.data, other.data...)
|
||||
result.Unique()
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// 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] {
|
||||
res := NewList(make([]T, 0, 0))
|
||||
result := NewList(make([]T, 0, 0))
|
||||
|
||||
for _, v := range l.data {
|
||||
if other.Contain(v) {
|
||||
res.data = append(res.data, v)
|
||||
result.data = append(result.data, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.
|
||||
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
|
||||
data := l.data[fromIndex:toIndex]
|
||||
subList := make([]T, len(data))
|
||||
copy(subList, data)
|
||||
return NewList(subList)
|
||||
}
|
||||
|
||||
@@ -36,6 +36,51 @@ func TestIndexOf(t *testing.T) {
|
||||
assert.Equal(-1, i)
|
||||
}
|
||||
|
||||
func TestIndexOfFunc(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
i := list.IndexOfFunc(func(a int) bool { return a == 1 })
|
||||
assert.Equal(0, i)
|
||||
|
||||
i = list.IndexOfFunc(func(a int) bool { return a == 4 })
|
||||
assert.Equal(-1, i)
|
||||
}
|
||||
|
||||
func TestLastIndexOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
||||
i := list.LastIndexOf(3)
|
||||
assert.Equal(5, i)
|
||||
|
||||
i = list.LastIndexOf(10)
|
||||
assert.Equal(-1, i)
|
||||
|
||||
i = list.LastIndexOf(4)
|
||||
assert.Equal(6, i)
|
||||
|
||||
i = list.LastIndexOf(1)
|
||||
assert.Equal(0, i)
|
||||
}
|
||||
|
||||
func TestLastIndexOfFunc(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
||||
i := list.LastIndexOfFunc(func(a int) bool { return a == 3 })
|
||||
assert.Equal(5, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 10 })
|
||||
assert.Equal(-1, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 4 })
|
||||
assert.Equal(6, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 1 })
|
||||
assert.Equal(0, i)
|
||||
}
|
||||
|
||||
func TestContain(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestContain")
|
||||
|
||||
@@ -216,6 +261,18 @@ func TestSize(t *testing.T) {
|
||||
assert.Equal(0, empty.Size())
|
||||
}
|
||||
|
||||
func TestCap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCap")
|
||||
|
||||
data := make([]int, 0, 100)
|
||||
list := NewList(data)
|
||||
assert.Equal(100, list.Cap())
|
||||
|
||||
data = make([]int, 0)
|
||||
list = NewList(data)
|
||||
assert.Equal(0, list.Cap())
|
||||
}
|
||||
|
||||
func TestSwap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSwap")
|
||||
|
||||
@@ -270,3 +327,33 @@ func TestIntersection(t *testing.T) {
|
||||
list3 := list1.Intersection(list2)
|
||||
assert.Equal(true, expected.Equal(list3))
|
||||
}
|
||||
|
||||
func TestSubSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSubSlice")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4, 5, 8})
|
||||
subList := list.SubList(2, 5)
|
||||
|
||||
assert.Equal([]int{3, 4, 5}, subList.Data())
|
||||
}
|
||||
|
||||
func BenchmarkSubSlice(b *testing.B) {
|
||||
list := NewList([]int{1, 2, 3, 4, 5, 8})
|
||||
for n := 0; n < b.N; n++ {
|
||||
list.SubList(2, 5)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteIf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDeleteIf")
|
||||
|
||||
list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
|
||||
|
||||
count := list.DeleteIf(func(a int) bool { return a == 1 })
|
||||
assert.Equal([]int{2, 3, 4}, list.Data())
|
||||
assert.Equal(12, count)
|
||||
|
||||
count = list.DeleteIf(func(a int) bool { return a == 5 })
|
||||
assert.Equal([]int{2, 3, 4}, list.Data())
|
||||
assert.Equal(0, count)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func (q *ArrayQueue[T]) Data() []T {
|
||||
return items
|
||||
}
|
||||
|
||||
// Size return length of queue data
|
||||
// Size return number of elements in queue
|
||||
func (q *ArrayQueue[T]) Size() int {
|
||||
return q.size
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
// CircularQueue implements circular queue with slice,
|
||||
// last index of CircularQueue don't contain value, so acturl capacity is capacity - 1
|
||||
type CircularQueue[T any] struct {
|
||||
data []T
|
||||
front int
|
||||
rear int
|
||||
capacity int
|
||||
data []T
|
||||
front int
|
||||
rear int
|
||||
capacity int
|
||||
}
|
||||
|
||||
// NewCircularQueue return a empty CircularQueue pointer
|
||||
|
||||
@@ -42,7 +42,6 @@ func (q *LinkedQueue[T]) IsEmpty() bool {
|
||||
return q.length == 0
|
||||
}
|
||||
|
||||
|
||||
// Enqueue put element into queue
|
||||
func (q *LinkedQueue[T]) Enqueue(value T) {
|
||||
newNode := datastructure.NewQueueNode(value)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package datastructure
|
||||
|
||||
// Set is a data container, like slice, but element of set is not duplicate
|
||||
type Set[T comparable] map[T]bool
|
||||
type Set[T comparable] map[T]struct{}
|
||||
|
||||
// NewSet return a instance of set
|
||||
func NewSet[T comparable](values ...T) Set[T] {
|
||||
@@ -13,7 +13,7 @@ func NewSet[T comparable](values ...T) Set[T] {
|
||||
// Add value to set
|
||||
func (s Set[T]) Add(values ...T) {
|
||||
for _, v := range values {
|
||||
s[v] = true
|
||||
s[v] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,20 +84,20 @@ func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool {
|
||||
|
||||
func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T],
|
||||
comparator lancetconstraints.Comparator) bool {
|
||||
res := false
|
||||
result := false
|
||||
|
||||
if superTreeRoot != nil && subTreeRoot != nil {
|
||||
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) == 0 {
|
||||
res = isSubTree(superTreeRoot, subTreeRoot, comparator)
|
||||
result = isSubTree(superTreeRoot, subTreeRoot, comparator)
|
||||
}
|
||||
if !res {
|
||||
res = hasSubTree(superTreeRoot.Left, subTreeRoot, comparator)
|
||||
if !result {
|
||||
result = hasSubTree(superTreeRoot.Left, subTreeRoot, comparator)
|
||||
}
|
||||
if !res {
|
||||
res = hasSubTree(superTreeRoot.Right, subTreeRoot, comparator)
|
||||
if !result {
|
||||
result = hasSubTree(superTreeRoot.Right, subTreeRoot, comparator)
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Print the bstree structure
|
||||
|
||||
@@ -226,8 +226,8 @@ func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], com
|
||||
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) != 0 {
|
||||
return false
|
||||
}
|
||||
res := isSubTree(superTreeRoot.Left, subTreeRoot.Left, comparator) && isSubTree(superTreeRoot.Right, subTreeRoot.Right, comparator)
|
||||
return res
|
||||
result := isSubTree(superTreeRoot.Left, subTreeRoot.Left, comparator) && isSubTree(superTreeRoot.Right, subTreeRoot.Right, comparator)
|
||||
return result
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
|
||||
@@ -4,24 +4,24 @@
|
||||
// Package datetime implements some functions to format date and time.
|
||||
// Note:
|
||||
// 1. `format` param in FormatTimeToStr function should be as flow:
|
||||
//"yyyy-mm-dd hh:mm:ss"
|
||||
//"yyyy-mm-dd hh:mm"
|
||||
//"yyyy-mm-dd hh"
|
||||
//"yyyy-mm-dd"
|
||||
//"yyyy-mm"
|
||||
//"mm-dd"
|
||||
//"dd-mm-yy hh:mm:ss"
|
||||
//"yyyy/mm/dd hh:mm:ss"
|
||||
//"yyyy/mm/dd hh:mm"
|
||||
//"yyyy/mm/dd hh"
|
||||
//"yyyy/mm/dd"
|
||||
//"yyyy/mm"
|
||||
//"mm/dd"
|
||||
//"dd/mm/yy hh:mm:ss"
|
||||
//"yyyy"
|
||||
//"mm"
|
||||
//"hh:mm:ss"
|
||||
//"mm:ss"
|
||||
// "yyyy-mm-dd hh:mm:ss"
|
||||
// "yyyy-mm-dd hh:mm"
|
||||
// "yyyy-mm-dd hh"
|
||||
// "yyyy-mm-dd"
|
||||
// "yyyy-mm"
|
||||
// "mm-dd"
|
||||
// "dd-mm-yy hh:mm:ss"
|
||||
// "yyyy/mm/dd hh:mm:ss"
|
||||
// "yyyy/mm/dd hh:mm"
|
||||
// "yyyy/mm/dd hh"
|
||||
// "yyyy/mm/dd"
|
||||
// "yyyy/mm"
|
||||
// "mm/dd"
|
||||
// "dd/mm/yy hh:mm:ss"
|
||||
// "yyyy"
|
||||
// "mm"
|
||||
// "hh:mm:ss"
|
||||
// "mm:ss"
|
||||
package datetime
|
||||
|
||||
import (
|
||||
@@ -147,16 +147,32 @@ func EndOfDay(t time.Time) time.Time {
|
||||
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
}
|
||||
|
||||
// BeginOfWeek return beginning week, week begin from Sunday
|
||||
func BeginOfWeek(t time.Time) time.Time {
|
||||
y, m, d := t.AddDate(0, 0, 0-int(BeginOfDay(t).Weekday())).Date()
|
||||
return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
// BeginOfWeek return beginning week, default week begin from Sunday
|
||||
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time {
|
||||
var beginFromWeekday = time.Sunday
|
||||
if len(beginFrom) > 0 {
|
||||
beginFromWeekday = beginFrom[0]
|
||||
}
|
||||
y, m, d := t.AddDate(0, 0, int(beginFromWeekday-t.Weekday())).Date()
|
||||
beginOfWeek := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
if beginOfWeek.After(t) {
|
||||
return beginOfWeek.AddDate(0, 0, -7)
|
||||
}
|
||||
return beginOfWeek
|
||||
}
|
||||
|
||||
// EndOfWeek return end week time, week end with Saturday
|
||||
func EndOfWeek(t time.Time) time.Time {
|
||||
y, m, d := BeginOfWeek(t).AddDate(0, 0, 7).Add(-time.Nanosecond).Date()
|
||||
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
// EndOfWeek return end week time, default week end with Saturday
|
||||
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time {
|
||||
var endWithWeekday = time.Saturday
|
||||
if len(endWith) > 0 {
|
||||
endWithWeekday = endWith[0]
|
||||
}
|
||||
y, m, d := t.AddDate(0, 0, int(endWithWeekday-t.Weekday())).Date()
|
||||
var endWithWeek = time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
|
||||
if endWithWeek.Before(t) {
|
||||
endWithWeek = endWithWeek.AddDate(0, 0, 7)
|
||||
}
|
||||
return endWithWeek
|
||||
}
|
||||
|
||||
// BeginOfMonth return beginning of month
|
||||
|
||||
@@ -5,7 +5,7 @@ Package algorithm implements some basic algorithm. eg. sort, search.
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
|
||||
|
||||
@@ -248,7 +248,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator)
|
||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -278,7 +278,7 @@ func main() {
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
algorithm.QuickSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
@@ -584,8 +584,8 @@ import (
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ algorithm算法包实现一些基本算法,sort,search,lrucache。
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
|
||||
|
||||
@@ -249,7 +249,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
|
||||
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -279,7 +279,7 @@ func main() {
|
||||
|
||||
intSlice := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
|
||||
algorithm.QuickSort(intSlice, comparator)
|
||||
|
||||
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
|
||||
}
|
||||
@@ -585,8 +585,8 @@ import (
|
||||
func main() {
|
||||
cache := algorithm.NewLRUCache[int, int](2)
|
||||
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
cache.Put(1, 1)
|
||||
cache.Put(2, 2)
|
||||
|
||||
_, ok := cache.Get(0) // ok -> false
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -133,7 +133,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -173,14 +173,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
|
||||
|
||||
for v := range intStream {
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -209,7 +209,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
fn := func() any {
|
||||
@@ -220,7 +220,7 @@ func main() {
|
||||
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
|
||||
|
||||
for v := range dataStream {
|
||||
fmt.Println(v) //a, a, a
|
||||
fmt.Println(v) //a, a, a
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -248,7 +248,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
c := make(chan interface{})
|
||||
go func() {
|
||||
defer close(c)
|
||||
@@ -296,7 +296,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -332,7 +332,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
numbers := make(chan any, 5)
|
||||
@@ -347,7 +347,7 @@ func main() {
|
||||
intStream := c.Take(ctx, numbers, 3)
|
||||
|
||||
for val := range intStream {
|
||||
fmt.Println(val) //1, 2, 3
|
||||
fmt.Println(val) //1, 2, 3
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -375,7 +375,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -383,8 +383,8 @@ func main() {
|
||||
|
||||
out1, out2 := c.Tee(ctx, inStream)
|
||||
for val := range out1 {
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -180,7 +180,7 @@ func main() {
|
||||
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
|
||||
|
||||
for v := range intStream {
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
fmt.Println(v) //1, 2, 1, 2, 1
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -220,7 +220,7 @@ func main() {
|
||||
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
|
||||
|
||||
for v := range dataStream {
|
||||
fmt.Println(v) //a, a, a
|
||||
fmt.Println(v) //a, a, a
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -248,7 +248,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
c := make(chan interface{})
|
||||
go func() {
|
||||
defer close(c)
|
||||
@@ -296,7 +296,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -332,7 +332,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
numbers := make(chan any, 5)
|
||||
@@ -347,7 +347,7 @@ func main() {
|
||||
intStream := c.Take(ctx, numbers, 3)
|
||||
|
||||
for val := range intStream {
|
||||
fmt.Println(val) //1, 2, 3
|
||||
fmt.Println(val) //1, 2, 3
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -375,7 +375,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
c := concurrency.NewChannel()
|
||||
@@ -383,8 +383,8 @@ func main() {
|
||||
|
||||
out1, out2 := c.Tee(ctx, inStream)
|
||||
for val := range out1 {
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
fmt.Println(val) //1
|
||||
fmt.Println(<-out2) //1
|
||||
}
|
||||
}
|
||||
```
|
||||
264
docs/condition.md
Normal file
264
docs/condition.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Condition
|
||||
Package condition contains some functions for conditional judgment. eg. And, Or, TernaryOperator... The implementation of this package refers to the implementation of carlmjohnson's truthy package, you may find more useful information in [truthy](https://github.com/carlmjohnson/truthy), thanks carlmjohnson.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/condition/condition.go](https://github.com/duke-git/lancet/blob/main/condition/condition.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [Bool](#Bool)
|
||||
- [And](#And)
|
||||
- [Or](#Or)
|
||||
- [Xor](#Generate)
|
||||
- [Nor](#Nor)
|
||||
- [Nand](#Nand)
|
||||
- [TernaryOperator](#TernaryOperator)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="Bool">Bool</span>
|
||||
<p>Returns the truthy value of anything.<br/>
|
||||
If the value's type has a Bool() bool method, the method is called and returned.<br/>
|
||||
If the type has an IsZero() bool method, the opposite value is returned.<br/>
|
||||
Slices and maps are truthy if they have a length greater than zero.<br/>
|
||||
All other types are truthy if they are not their zero value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Bool[T any](value T) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// bool
|
||||
fmt.Println(condition.Bool(false)) // false
|
||||
fmt.Println(condition.Bool(true)) // true
|
||||
|
||||
// integer
|
||||
fmt.Println(condition.Bool(0)) // false
|
||||
fmt.Println(condition.Bool(1)) // true
|
||||
|
||||
// float
|
||||
fmt.Println(condition.Bool(0.0)) // false
|
||||
fmt.Println(condition.Bool(0.1)) // true
|
||||
|
||||
// string
|
||||
fmt.Println(condition.Bool("")) // false
|
||||
fmt.Println(condition.Bool(" ")) // true
|
||||
fmt.Println(condition.Bool("0")) // true
|
||||
|
||||
// slice
|
||||
var nums [2]int
|
||||
fmt.Println(condition.Bool(nums)) // false
|
||||
nums = [2]int{0, 1}
|
||||
fmt.Println(condition.Bool(nums)) // true
|
||||
|
||||
// map
|
||||
fmt.Println(condition.Bool(map[string]string{})) // false
|
||||
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true
|
||||
|
||||
// struct
|
||||
fmt.Println(condition.Bool(struct{}{})) // false
|
||||
fmt.Println(condition.Bool(time.Now())) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="And">And</span>
|
||||
<p>Returns true if both a and b are truthy.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func And[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.And(0, 1)) // false
|
||||
fmt.Println(condition.And(0, "")) // false
|
||||
fmt.Println(condition.And(0, "0")) // false
|
||||
fmt.Println(condition.And(1, "0")) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Or">Or</span>
|
||||
<p>Returns false iff neither a nor b is truthy.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Or[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Or(0, "")) // false
|
||||
fmt.Println(condition.Or(0, 1)) // true
|
||||
fmt.Println(condition.Or(0, "0")) // true
|
||||
fmt.Println(condition.Or(1, "0")) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Xor">Xor</span>
|
||||
<p>Returns true iff a or b but not both is truthy.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Xor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Xor(0, 0)) // false
|
||||
fmt.Println(condition.Xor(0, 1)) // true
|
||||
fmt.Println(condition.Xor(1, 0)) // true
|
||||
fmt.Println(condition.Xor(1, 1)) // false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Nor">Nor</span>
|
||||
<p>Returns true iff neither a nor b is truthy.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Nor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Nor(0, 0)) // true
|
||||
fmt.Println(condition.Nor(0, 1)) // false
|
||||
fmt.Println(condition.Nor(1, 0)) // false
|
||||
fmt.Println(condition.Nor(1, 1)) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Nand">Nand</span>
|
||||
<p>Returns false iff both a and b are truthy</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Nand[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Nand(0, 0)) // true
|
||||
fmt.Println(condition.Nand(0, 1)) // true
|
||||
fmt.Println(condition.Nand(1, 0)) // true
|
||||
fmt.Println(condition.Nand(1, 1)) // false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="TernaryOperator">TernaryOperator</span>
|
||||
<p>Checks the value of param `isTrue`, if true return ifValue else return elseValue</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
trueValue := "1"
|
||||
falseValue := "0"
|
||||
|
||||
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
263
docs/condition_zh-CN.md
Normal file
263
docs/condition_zh-CN.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# Condition
|
||||
condition包含一些用于条件判断的函数。这个包的实现参考了carlmjohnson的truthy包的实现,更多有用的信息可以在[truthy](https://github.com/carlmjohnson/truthy)中找到,感谢carlmjohnson。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/condition/condition.go](https://github.com/duke-git/lancet/blob/main/condition/condition.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [Bool](#Bool)
|
||||
- [And](#And)
|
||||
- [Or](#Or)
|
||||
- [Xor](#Generate)
|
||||
- [Nor](#Nor)
|
||||
- [Nand](#Nand)
|
||||
- [TernaryOperator](#TernaryOperator)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
### <span id="Bool">Bool</span>
|
||||
<p>返回传入参数的bool值.<br/>
|
||||
如果出入类型参数含有Bool方法, 会调用该方法并返回<br/>
|
||||
如果传入类型参数有IsZero方法, 返回IsZero方法返回值的取反<br/>
|
||||
slices和map的length大于0时,返回true,否则返回false<br/>
|
||||
其他类型会判断是否是零值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Bool[T any](value T) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// bool
|
||||
fmt.Println(condition.Bool(false)) // false
|
||||
fmt.Println(condition.Bool(true)) // true
|
||||
|
||||
// integer
|
||||
fmt.Println(condition.Bool(0)) // false
|
||||
fmt.Println(condition.Bool(1)) // true
|
||||
|
||||
// float
|
||||
fmt.Println(condition.Bool(0.0)) // false
|
||||
fmt.Println(condition.Bool(0.1)) // true
|
||||
|
||||
// string
|
||||
fmt.Println(condition.Bool("")) // false
|
||||
fmt.Println(condition.Bool(" ")) // true
|
||||
fmt.Println(condition.Bool("0")) // true
|
||||
|
||||
// slice
|
||||
var nums [2]int
|
||||
fmt.Println(condition.Bool(nums)) // false
|
||||
nums = [2]int{0, 1}
|
||||
fmt.Println(condition.Bool(nums)) // true
|
||||
|
||||
// map
|
||||
fmt.Println(condition.Bool(map[string]string{})) // false
|
||||
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true
|
||||
|
||||
// struct
|
||||
fmt.Println(condition.Bool(struct{}{})) // false
|
||||
fmt.Println(condition.Bool(time.Now())) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="And">And</span>
|
||||
<p>逻辑且操作,当切仅当a和b都为true时返回true</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func And[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.And(0, 1)) // false
|
||||
fmt.Println(condition.And(0, "")) // false
|
||||
fmt.Println(condition.And(0, "0")) // false
|
||||
fmt.Println(condition.And(1, "0")) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Or">Or</span>
|
||||
<p>逻辑或操作,当切仅当a和b都为false时返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Or[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Or(0, "")) // false
|
||||
fmt.Println(condition.Or(0, 1)) // true
|
||||
fmt.Println(condition.Or(0, "0")) // true
|
||||
fmt.Println(condition.Or(1, "0")) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Xor">Xor</span>
|
||||
<p>逻辑异或操作,a和b相同返回false,a和b不相同返回true</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Xor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Xor(0, 0)) // false
|
||||
fmt.Println(condition.Xor(0, 1)) // true
|
||||
fmt.Println(condition.Xor(1, 0)) // true
|
||||
fmt.Println(condition.Xor(1, 1)) // false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Nor">Nor</span>
|
||||
<p>异或的取反操作</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Nor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Nor(0, 0)) // true
|
||||
fmt.Println(condition.Nor(0, 1)) // false
|
||||
fmt.Println(condition.Nor(1, 0)) // false
|
||||
fmt.Println(condition.Nor(1, 1)) // true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Nand">Nand</span>
|
||||
<p>如果a和b都为真,返回false,否则返回true</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Nand[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(condition.Nand(0, 0)) // true
|
||||
fmt.Println(condition.Nand(0, 1)) // true
|
||||
fmt.Println(condition.Nand(1, 0)) // true
|
||||
fmt.Println(condition.Nand(1, 1)) // false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="TernaryOperator">TernaryOperator</span>
|
||||
<p>三元运算符</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
trueValue := "1"
|
||||
falseValue := "0"
|
||||
|
||||
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,10 +24,18 @@ import (
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToChannel](#ToChannel)
|
||||
|
||||
- [ToFloat](#ToFloat)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToMap](#ToMap)
|
||||
- [ToPointer](#ToPointer)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
- [MapToSlice](#MapToSlice)
|
||||
- [EncodeByte](#EncodeByte)
|
||||
- [DecodeByte](#DecodeByte)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -191,6 +199,43 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="ToChannel">ToChannel</span>
|
||||
|
||||
<p>Convert a collection of elements to a read-only channels.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToChannel[T any](array []T) <-chan T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ch := convertor.ToChannel([]int{1, 2, 3})
|
||||
|
||||
val1, _ := <-ch
|
||||
fmt.Println(val1) //1
|
||||
|
||||
val2, _ := <-ch
|
||||
fmt.Println(val2) //2
|
||||
|
||||
val3, _ := <-ch
|
||||
fmt.Println(val3) //3
|
||||
|
||||
_, ok := <-ch
|
||||
fmt.Println(ok) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
@@ -286,14 +331,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
### <span id="ToMap">ToMap</span>
|
||||
|
||||
<p>Convert interface to string. </p>
|
||||
<p>Convert a slice or an array of structs to a map based on iteratee function. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToString(value any) string
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -306,9 +351,46 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("%q", convertor.ToString(1)) //"1"
|
||||
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1"
|
||||
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]"
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := convertor.ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
|
||||
fmt.Println(result) //{100: "Hello", 101: "Hi"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToPointer">ToPointer</span>
|
||||
|
||||
<p>Returns a pointer to passed value. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToPointer[T any](value T) *T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := convertor.ToPointer(123)
|
||||
fmt.Println(*result) //123
|
||||
}
|
||||
```
|
||||
|
||||
@@ -346,4 +428,90 @@ func main() {
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MapToSlice">MapToSlice</span>
|
||||
|
||||
<p>Convert a map to a slice based on iteratee function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
fmt.Println(result) //[]string{"a:1", "b:2", "c:3"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="EncodeByte">EncodeByte</span>
|
||||
|
||||
<p>Encode data to byte slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EncodeByte(data any) ([]byte, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
byteData, _ := convertor.EncodeByte("abc")
|
||||
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="DecodeByte">DecodeByte</span>
|
||||
|
||||
<p>Decode byte data to target object. target should be a pointer instance.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DecodeByte(data []byte, target any) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var result string
|
||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||
convertor.DecodeByte(byteData, &result)
|
||||
fmt.Println(result) //"abc"
|
||||
}
|
||||
```
|
||||
@@ -26,10 +26,18 @@ import (
|
||||
- [ToBool](#ToBool)
|
||||
- [ToBytes](#ToBytes)
|
||||
- [ToChar](#ToChar)
|
||||
- [ToChannel](#ToChannel)
|
||||
|
||||
- [ToFloat](#ToFloat)
|
||||
- [ToInt](#ToInt)
|
||||
- [ToJson](#ToJson)
|
||||
- [ToMap](#ToMap)
|
||||
- [ToPointer](#ToPointer)
|
||||
- [ToString](#ToString)
|
||||
- [StructToMap](#StructToMap)
|
||||
- [MapToSlice](#MapToSlice)
|
||||
- [EncodeByte](#EncodeByte)
|
||||
- [DecodeByte](#DecodeByte)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -194,6 +202,44 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToChannel">ToChannel</span>
|
||||
|
||||
<p>将切片转为只读channel</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToChannel[T any](array []T) <-chan T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ch := convertor.ToChannel([]int{1, 2, 3})
|
||||
|
||||
val1, _ := <-ch
|
||||
fmt.Println(val1) //1
|
||||
|
||||
val2, _ := <-ch
|
||||
fmt.Println(val2) //2
|
||||
|
||||
val3, _ := <-ch
|
||||
fmt.Println(val3) //3
|
||||
|
||||
_, ok := <-ch
|
||||
fmt.Println(ok) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToFloat">ToFloat</span>
|
||||
|
||||
<p>将interface转成float64类型,如果参数无法转换,会返回0和error</p>
|
||||
@@ -229,7 +275,7 @@ func main() {
|
||||
|
||||
### <span id="ToInt">ToInt</span>
|
||||
|
||||
<p>将interface转成intt64类型,如果参数无法转换,会返回0和error</p>
|
||||
<p>将interface转成int64类型,如果参数无法转换,会返回0和error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -288,6 +334,71 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ToMap">ToMap</span>
|
||||
|
||||
<p>将切片转为map</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Message struct {
|
||||
name string
|
||||
code int
|
||||
}
|
||||
messages := []Message{
|
||||
{name: "Hello", code: 100},
|
||||
{name: "Hi", code: 101},
|
||||
}
|
||||
result := convertor.ToMap(messages, func(msg Message) (int, string) {
|
||||
return msg.code, msg.name
|
||||
})
|
||||
|
||||
fmt.Println(result) //{100: "Hello", 101: "Hi"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToPointer">ToPointer</span>
|
||||
|
||||
<p>返回传入值的指针</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToPointer[T any](value T) *T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := convertor.ToPointer(123)
|
||||
fmt.Println(*result) //123
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToString">ToString</span>
|
||||
|
||||
<p>将interface转成字符串</p>
|
||||
@@ -348,4 +459,91 @@ func main() {
|
||||
|
||||
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="MapToSlice">MapToSlice</span>
|
||||
|
||||
<p>map中key和value执行函数iteratee后,转为切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result := MapToSlice(aMap, func(key string, value int) string {
|
||||
return key + ":" + strconv.Itoa(value)
|
||||
})
|
||||
|
||||
fmt.Println(result) //[]string{"a:1", "b:2", "c:3"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="EncodeByte">EncodeByte</span>
|
||||
|
||||
<p>将data编码成字节切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EncodeByte(data any) ([]byte, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
byteData, _ := convertor.EncodeByte("abc")
|
||||
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="DecodeByte">DecodeByte</span>
|
||||
|
||||
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例子</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DecodeByte(data []byte, target any) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var result string
|
||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||
convertor.DecodeByte(byteData, &result)
|
||||
fmt.Println(result) //"abc"
|
||||
}
|
||||
```
|
||||
@@ -85,7 +85,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -115,9 +115,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -145,7 +145,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -176,9 +176,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -207,7 +207,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -239,7 +239,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -271,7 +271,7 @@ func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -300,7 +300,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -330,9 +330,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -360,7 +360,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
fmt.Println(base64Str) //aGVsbG8gd29ybGQ=
|
||||
}
|
||||
```
|
||||
@@ -417,7 +417,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -448,9 +448,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -480,7 +480,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -511,7 +511,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -543,7 +543,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -575,7 +575,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -605,9 +605,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -636,7 +636,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -666,9 +666,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -725,8 +725,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -753,8 +753,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
}
|
||||
```
|
||||
|
||||
@@ -781,8 +781,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
|
||||
}
|
||||
```
|
||||
@@ -810,8 +810,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
```
|
||||
|
||||
@@ -838,8 +838,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -866,8 +866,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
}
|
||||
```
|
||||
|
||||
@@ -894,8 +894,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
}
|
||||
```
|
||||
|
||||
@@ -922,7 +922,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha512("hello world"))
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
}
|
||||
```
|
||||
@@ -950,10 +950,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -980,14 +980,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -1016,14 +1016,14 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -115,9 +115,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -145,7 +145,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -176,9 +176,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
@@ -208,7 +208,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -240,7 +240,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -270,9 +270,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -301,7 +301,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -331,9 +331,9 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
key := "abcdefghijklmnop"
|
||||
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
}
|
||||
```
|
||||
@@ -360,7 +360,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
base64Str := cryptor.Base64StdEncode("hello world")
|
||||
fmt.Println(base64Str) //aGVsbG8gd29ybGQ=
|
||||
}
|
||||
```
|
||||
@@ -388,7 +388,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=")
|
||||
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=")
|
||||
fmt.Println(str) //hello world
|
||||
}
|
||||
```
|
||||
@@ -417,7 +417,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -448,7 +448,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -480,7 +480,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
|
||||
|
||||
fmt.Println(string(encrypted))
|
||||
@@ -511,7 +511,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -543,7 +543,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
|
||||
|
||||
@@ -575,7 +575,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -605,7 +605,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -636,7 +636,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
fmt.Println(string(encrypted))
|
||||
}
|
||||
@@ -666,7 +666,7 @@ import (
|
||||
|
||||
func main() {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
key := "abcdefgh"
|
||||
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -696,8 +696,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacMd5("hello world", "12345"))
|
||||
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d
|
||||
s := cryptor.HmacMd5("hello world", "12345"))
|
||||
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d
|
||||
}
|
||||
```
|
||||
|
||||
@@ -724,8 +724,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
s := cryptor.HmacSha1("hello world", "12345"))
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -752,8 +752,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
}
|
||||
```
|
||||
|
||||
@@ -780,8 +780,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
|
||||
}
|
||||
```
|
||||
@@ -809,8 +809,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
```
|
||||
|
||||
@@ -837,8 +837,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
s := cryptor.Md5File("./main.go"))
|
||||
fmt.Println(s)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -865,8 +865,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
}
|
||||
```
|
||||
|
||||
@@ -893,8 +893,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
}
|
||||
```
|
||||
|
||||
@@ -921,8 +921,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
}
|
||||
```
|
||||
|
||||
@@ -949,10 +949,10 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -979,11 +979,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
@@ -1013,11 +1013,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
fmt.Println(string(decrypted)) //hello world
|
||||
|
||||
314
docs/datastructure/hashmap.md
Normal file
314
docs/datastructure/hashmap.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# HashMap
|
||||
|
||||
HashMap is a key value map data structure.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/hashmap/hashmap.go](https://github.com/duke-git/lancet/blob/main/datastructure/hashmap/hashmap.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import (
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## Index
|
||||
|
||||
- [NewHashMap](#NewHashMap)
|
||||
- [NewHashMapWithCapacity](#NewHashMapWithCapacity)
|
||||
- [Get](#Get)
|
||||
- [Put](#Put)
|
||||
- [Delete](#Delete)
|
||||
- [Contains](#Contains)
|
||||
- [Iterate](#Iterate)
|
||||
- [Keys](#Keys)
|
||||
- [Values](#Values)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="NewHashMap">NewHashMap</span>
|
||||
|
||||
<p>Make a HashMap instance with default capacity is 1 << 10.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewHashMap() *HashMap
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
fmt.Println(hm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NewHashMap">NewHashMap</span>
|
||||
|
||||
<p>Make a HashMap instance with given size and capacity.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewHashMapWithCapacity(size, capacity uint64) *HashMap
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMapWithCapacity(uint64(100), uint64(1000))
|
||||
fmt.Println(hm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Get">Get</span>
|
||||
|
||||
<p>Get the value of given key in hashmap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Get(key any) any
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
val := hm.Get("a")
|
||||
|
||||
fmt.Println(val) //nil
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Put">Put</span>
|
||||
|
||||
<p>Put new key value in hashmap, then return value</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Put(key any, value any) any
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
|
||||
val := hm.Get("a")
|
||||
fmt.Println(val) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delete">Delete</span>
|
||||
|
||||
<p>Delete key-value item by given key in hashmap.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Delete(key any)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
val := hm.Get("a")
|
||||
fmt.Println(val) //1
|
||||
|
||||
hm.Delete("a")
|
||||
val = hm.Get("a")
|
||||
fmt.Println(val) //nil
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contains">Contains</span>
|
||||
|
||||
<p>Checks if given key is in hashmap or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Contains(key any) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
|
||||
fmt.Println(hm.Contains("a")) //true
|
||||
fmt.Println(hm.Contains("b")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Iterate">Iterate</span>
|
||||
|
||||
<p>Executes iteratee funcation for every key and value pair of hashmap.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Iterate(iteratee func(key, value any))
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
hm.Iterate(func(key, value any) {
|
||||
fmt.Println(key)
|
||||
fmt.Println(value)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Keys">Keys</span>
|
||||
|
||||
<p>Return a slice of the hashmap's keys (random order).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Keys() []any
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
keys := hm.Keys()
|
||||
fmt.Println(keys) //[]interface{"a", "b", "c"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>Return a slice of the hashmap's values (random order).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Values() []any
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
values := hm.Values()
|
||||
fmt.Println(values) //[]interface{2, 1, 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
308
docs/datastructure/hashmap_zh-CN.md
Normal file
308
docs/datastructure/hashmap_zh-CN.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# HashMap
|
||||
|
||||
HashMap 数据结构实现
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/hashmap/hashmap.go](https://github.com/duke-git/lancet/blob/main/datastructure/hashmap/hashmap.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
|
||||
```go
|
||||
import (
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewHashMap](#NewHashMap)
|
||||
- [NewHashMapWithCapacity](#NewHashMapWithCapacity)
|
||||
- [Get](#Get)
|
||||
- [Put](#Put)
|
||||
- [Delete](#Delete)
|
||||
- [Contains](#Contains)
|
||||
- [Iterate](#Iterate)
|
||||
- [Keys](#Keys)
|
||||
- [Values](#Values)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API 文档
|
||||
|
||||
### <span id="NewHashMap">NewHashMap</span>
|
||||
|
||||
<p>新建默认容量(1 << 10)的HashMap指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewHashMap() *HashMap
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
fmt.Println(hm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NewHashMapWithCapacity">NewHashMapWithCapacity</span>
|
||||
|
||||
<p>新建指定容量和长度的HashMap指针实例.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewHashMapWithCapacity(size, capacity uint64) *HashMap
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMapWithCapacity(uint64(100), uint64(1000))
|
||||
fmt.Println(hm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Get">Get</span>
|
||||
|
||||
<p>在hashmap中根据key获取值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Get(key any) any
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
val := hm.Get("a")
|
||||
|
||||
fmt.Println(val) //nil
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Put">Put</span>
|
||||
|
||||
<p>将key-value放入hashmap中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Put(key any, value any) any
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
|
||||
val := hm.Get("a")
|
||||
fmt.Println(val) //1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Delete">Delete</span>
|
||||
|
||||
<p>将指定的key从hashmap中删除</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Delete(key any)
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
val := hm.Get("a")
|
||||
fmt.Println(val) //1
|
||||
|
||||
hm.Delete("a")
|
||||
val = hm.Get("a")
|
||||
fmt.Println(val) //nil
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Contains">Contains</span>
|
||||
|
||||
<p>判断hashmap中是否包含指定的key</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Contains(key any) bool
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
|
||||
fmt.Println(hm.Contains("a")) //true
|
||||
fmt.Println(hm.Contains("b")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Iterate">Iterate</span>
|
||||
|
||||
<p>迭代hashmap,对每个key和value执行iteratee函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Iterate(iteratee func(key, value any))
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
hm.Iterate(func(key, value any) {
|
||||
fmt.Println(key)
|
||||
fmt.Println(value)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Keys">Keys</span>
|
||||
|
||||
<p>返回hashmap所有key的切片 (随机顺序)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Keys() []any
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
keys := hm.Keys()
|
||||
fmt.Println(keys) //[]interface{"a", "b", "c"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>返回hashmap所有值的切片 (随机顺序).</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) Values() []any
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := heap.NewHashMap()
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
values := hm.Values()
|
||||
fmt.Println(values) //[]interface{2, 1, 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
364
docs/datastructure/heap.md
Normal file
364
docs/datastructure/heap.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Heap
|
||||
Heap is a binary heap tree implemented by slice.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go](https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [MaxHeap](#MaxHeap)
|
||||
- [Push](#Push)
|
||||
- [Pop](#Pop)
|
||||
- [Peek](#Peek)
|
||||
- [Data](#Data)
|
||||
- [Size](#Size)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### 1. MaxHeap
|
||||
MaxHeap is a binary heap tree implemented by slice, The key of the root node is both greater than or equal to the key value of the left subtree and greater than or equal to the key value of the right subtree.
|
||||
|
||||
### <span id="NewMaxHeap">NewMaxHeap</span>
|
||||
<p>Return a NewMaxHeap pointer instance.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
fmt.Println(maxHeap)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>Push value into the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Push(value T)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Pop">Pop</span>
|
||||
<p>Pop return the largest value, and remove it from the heap if heap is empty, return zero value and fasle</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Pop() (T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Pop()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Peek">Peek</span>
|
||||
<p>Return the largest element from the heap without removing it, if heap is empty, it returns zero value and false.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Peek() (T, bool)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Peek()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(maxHeap.Size()) //12
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>Return all element of the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Data() []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>Return the number of elements in the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Size() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="PrintStructure">PrintStructure</span>
|
||||
<p>Print the tree structure of the heap</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) PrintStructure()
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.PrintStructure())
|
||||
// 12
|
||||
// 9 11
|
||||
// 4 8 10 7
|
||||
// 1 3 5 6 2
|
||||
}
|
||||
```
|
||||
364
docs/datastructure/heap_zh-CN.md
Normal file
364
docs/datastructure/heap_zh-CN.md
Normal file
@@ -0,0 +1,364 @@
|
||||
# Heap
|
||||
堆,切片实现的二叉堆数据结构。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go](https://github.com/duke-git/lancet/blob/main/datastructure/heap/maxheap.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [MaxHeap](#MaxHeap)
|
||||
- [Push](#Push)
|
||||
- [Pop](#Pop)
|
||||
- [Peek](#Peek)
|
||||
- [Data](#Data)
|
||||
- [Size](#Size)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API文档
|
||||
|
||||
### 1. MaxHeap
|
||||
MaxHeap是通过slice实现的二叉堆树,根节点的key既大于等于左子树的key值且大于等于右子树的key值。
|
||||
|
||||
### <span id="NewMaxHeap">NewMaxHeap</span>
|
||||
<p>返回NewMaxHeap指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
fmt.Println(maxHeap)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>向堆中插入数据</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Push(value T)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Pop">Pop</span>
|
||||
<p>返回堆中最大值并将其从堆中删除,如果堆为空,返回零值并返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Pop() (T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Pop()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(ok) //true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Peek">Peek</span>
|
||||
<p>返回堆中最大值,如果堆为空,返回零值并返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Peek() (T, bool)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
val, ok := maxHeap.Peek()
|
||||
|
||||
fmt.Println(val) //12
|
||||
fmt.Println(maxHeap.Size()) //12
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Data">Data</span>
|
||||
<p>返回堆中全部元素的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Data() []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Data()) //[]int{12, 9, 11, 4, 8, 10, 7, 1, 3, 5, 6, 2}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
<p>返回堆中元素的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) Size() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.Size()) //3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="PrintStructure">PrintStructure</span>
|
||||
<p>打印堆的树形结构</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (h *MaxHeap[T]) PrintStructure()
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
)
|
||||
|
||||
type intComparator struct{}
|
||||
|
||||
func (c *intComparator) Compare(v1, v2 any) int {
|
||||
val1, _ := v1.(int)
|
||||
val2, _ := v2.(int)
|
||||
|
||||
if val1 < val2 {
|
||||
return -1
|
||||
} else if val1 > val2 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
maxHeap := heap.NewMaxHeap[int](&intComparator{})
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
|
||||
for _, v := range values {
|
||||
maxHeap.Push(v)
|
||||
}
|
||||
|
||||
fmt.Println(maxHeap.PrintStructure())
|
||||
// 12
|
||||
// 9 11
|
||||
// 4 8 10 7
|
||||
// 1 3 5 6 2
|
||||
}
|
||||
```
|
||||
@@ -26,6 +26,9 @@ import (
|
||||
- [Data](#Data)
|
||||
- [ValueOf](#ValueOf)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [IndexOfFunc](#IndexOfFunc)
|
||||
- [LastIndexOfFunc](#LastIndexOfFunc)
|
||||
- [Push](#Push)
|
||||
- [PopFirst](#PopFirst)
|
||||
- [PopLast](#PopLast)
|
||||
@@ -38,11 +41,14 @@ import (
|
||||
- [Clone](#Clone)
|
||||
- [Merge](#Merge)
|
||||
- [Size](#Size)
|
||||
- [Cap](#Cap)
|
||||
- [Swap](#Swap)
|
||||
- [Reverse](#Reverse)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
- [SubList](#SubList)
|
||||
- [DeleteIf](#DeleteIf)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -167,7 +173,7 @@ func main() {
|
||||
|
||||
|
||||
### <span id="IndexOf">IndexOf</span>
|
||||
<p>Reture the index of value in the list. if not found return -1</p>
|
||||
<p>Returns the index of value in the list. if not found return -1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -192,6 +198,84 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOf">LastIndexOf</span>
|
||||
<p> Returns the index of the last occurrence of the value in this list if not found return -1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) LastIndexOf(value T) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(li.LastIndexOf(1)) // 3
|
||||
fmt.Println(li.LastIndexOf(0)) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IndexOfFunc">IndexOfFunc</span>
|
||||
<p> IndexOfFunc returns the first index satisfying f(v). if not found return -1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.IndexOfFunc(func(a int) bool { return a == 1 })) //0
|
||||
fmt.Println(li.IndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOfFunc">LastIndexOfFunc</span>
|
||||
<p>LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying f(data[i]). if not found return -1</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(li.LastIndexOfFunc(func(a int) bool { return a == 1 })) // 3
|
||||
fmt.Println(li.LastIndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
@@ -568,6 +652,36 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Cap">Cap</span>
|
||||
<p>Cap return cap of the inner data</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Cap() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := make([]int, 0, 100)
|
||||
|
||||
li := list.NewList(data)
|
||||
|
||||
fmt.Println(li.Cap()) // 100
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Swap">Swap</span>
|
||||
<p>Swap the value at two index in list</p>
|
||||
|
||||
@@ -710,4 +824,61 @@ func main() {
|
||||
|
||||
fmt.Println(li3.Data()) //4
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="SubList">SubList</span>
|
||||
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewList([]int{1, 2, 3, 4, 5, 6})
|
||||
|
||||
fmt.Println(l.SubList(2, 5)) // []int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="DeleteIf">DeleteIf</span>
|
||||
<p>DeleteIf delete all satisfying f(data[i]), returns count of removed elements</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) DeleteIf(f func(T) bool) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
|
||||
|
||||
fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12
|
||||
fmt.Println(l.Data()) // []int{2, 3, 4}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -26,11 +26,15 @@ import (
|
||||
- [Data](#Data)
|
||||
- [ValueOf](#ValueOf)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [IndexOfFunc](#IndexOfFunc)
|
||||
- [LastIndexOfFunc](#LastIndexOfFunc)
|
||||
- [Push](#Push)
|
||||
- [PopFirst](#PopFirst)
|
||||
- [PopLast](#PopLast)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [InsertAt](#InsertAt)
|
||||
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Equal](#Equal)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
@@ -38,11 +42,14 @@ import (
|
||||
- [Clone](#Clone)
|
||||
- [Merge](#Merge)
|
||||
- [Size](#Size)
|
||||
- [Cap](#Cap)
|
||||
- [Swap](#Swap)
|
||||
- [Reverse](#Reverse)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
- [SubList](#SubList)
|
||||
- [DeleteIf](#DeleteIf)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -192,6 +199,85 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="LastIndexOf">LastIndexOf</span>
|
||||
<p>返回列表中最后一次出现的值的索引。如果未找到,则返回-1</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) LastIndexOf(value T) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(li.LastIndexOf(1)) // 3
|
||||
fmt.Println(li.LastIndexOf(0)) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IndexOfFunc">IndexOfFunc</span>
|
||||
<p>返回第一个符合函数条件的元素的索引。如果未找到,则返回-1</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) IndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(li.IndexOfFunc(func(a int) bool { return a == 1 })) //0
|
||||
fmt.Println(li.IndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOfFunc">LastIndexOfFunc</span>
|
||||
<p>返回最后一个符合函数条件的元素的索引。如果未找到,则返回-1</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
li := list.NewList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(li.LastIndexOfFunc(func(a int) bool { return a == 1 })) // 3
|
||||
fmt.Println(li.LastIndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Push">Push</span>
|
||||
<p>将值附加到列表末尾</p>
|
||||
@@ -566,6 +652,34 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Cap">Cap</span>
|
||||
<p>返回列表数据容量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) Cap() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := make([]int, 0, 100)
|
||||
|
||||
li := list.NewList(data)
|
||||
|
||||
fmt.Println(li.Cap()) // 100
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Swap">Swap</span>
|
||||
<p>交换列表中两个索引位置的值</p>
|
||||
@@ -709,4 +823,60 @@ func main() {
|
||||
|
||||
fmt.Println(li3.Data()) //4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SubList">SubList</span>
|
||||
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T]
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewList([]int{1, 2, 3, 4, 5, 6})
|
||||
|
||||
fmt.Println(l.SubList(2, 5)) // []int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="DeleteIf">DeleteIf</span>
|
||||
<p>删除列表中所有符合函数(调用函数返回true)的元素,返回删除元素的数量</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *List[T]) DeleteIf(f func(T) bool) int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
|
||||
|
||||
fmt.Println(l.DeleteIf(func(a int) bool { return a == 1 })) // 12
|
||||
fmt.Println(l.Data()) // []int{2, 3, 4}
|
||||
}
|
||||
```
|
||||
@@ -251,7 +251,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BeginOfWeek(t time.Time) time.Time
|
||||
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -414,7 +414,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EndOfWeek(t time.Time) time.Time
|
||||
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -712,7 +712,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
@@ -741,7 +741,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
@@ -771,7 +771,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
|
||||
@@ -243,12 +243,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="BeginOfWeek">BeginOfWeek</span>
|
||||
<p>返回指定时间的星期开始时间</p>
|
||||
<p>返回指定时间的每周开始时间,默认开始时间星期日</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfWeek(t time.Time) time.Time
|
||||
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -406,12 +406,12 @@ func main() {
|
||||
|
||||
|
||||
### <span id="EndOfWeek">EndOfWeek</span>
|
||||
<p>返回指定时间的星期结束时间</p>
|
||||
<p>返回指定时间的星期结束时间,默认结束时间星期六</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfWeek(t time.Time) time.Time
|
||||
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
@@ -680,7 +680,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnixNow() *theTime
|
||||
```
|
||||
@@ -708,7 +708,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
@@ -737,7 +737,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
@@ -767,7 +767,7 @@ func main() {
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
unix int64
|
||||
unix int64
|
||||
}
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
|
||||
@@ -21,18 +21,20 @@ import (
|
||||
## Index
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
|
||||
- [UnZip](#UnZip)
|
||||
- [UnZip](#UnZip)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -92,6 +94,32 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CreateDir">CreateDir</span>
|
||||
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CreateDir(absPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CreateDir("/a/")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>Copy src file to dest file. If dest file exist will overwrite it.</p>
|
||||
|
||||
@@ -112,9 +140,9 @@ import (
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -140,9 +168,9 @@ import (
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
@@ -310,8 +338,8 @@ import (
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -337,12 +365,12 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
@@ -370,13 +398,13 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
@@ -402,7 +430,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -431,7 +459,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
## 目录
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -92,6 +93,32 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="CreateDir">CreateDir</span>
|
||||
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CreateDir(absPath string) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CreateDir("/a/")
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
<p>拷贝文件,会覆盖原有的拷贝文件</p>
|
||||
|
||||
@@ -112,9 +139,9 @@ import (
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -140,9 +167,9 @@ import (
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
@@ -310,8 +337,8 @@ import (
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -337,12 +364,12 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
@@ -370,13 +397,13 @@ import (
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
@@ -402,7 +429,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -431,7 +458,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Pipeline](#Pipeline)
|
||||
- [Watcher](#Watcher)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -101,8 +102,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
@@ -120,7 +119,7 @@ func main() {
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
fmt.Println(res) // 0, 1, 2, 2, 2
|
||||
}
|
||||
```
|
||||
|
||||
@@ -302,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>
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Pipeline](#Pipeline)
|
||||
- [Watcher](#Watcher)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -101,8 +102,6 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
assert := internal.NewAssert(t, "TestBefore")
|
||||
|
||||
arr := []string{"a", "b", "c", "d", "e"}
|
||||
f := function.Before(3, func(i int) int {
|
||||
return i
|
||||
@@ -119,8 +118,7 @@ func main() {
|
||||
appendStr(i, arr[i], f)
|
||||
}
|
||||
|
||||
expected := []int64{0, 1, 2, 2, 2}
|
||||
assert.Equal(expected, res)
|
||||
fmt.Println(res) // 0, 1, 2, 2, 2
|
||||
}
|
||||
```
|
||||
|
||||
@@ -297,7 +295,45 @@ func main() {
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
fmt.Println(res) //[* * * * *]
|
||||
fmt.Println(res) //[* * * * *]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <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
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Package maputil includes some functions to manipulate map.
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
- [IsDisjoint](#IsDisjoint)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -301,4 +302,51 @@ func main() {
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsDisjoint">IsDisjoint</span>
|
||||
<p>Checks two maps are disjoint if they have no keys in common</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m2 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m3 := map[int]string{
|
||||
6: "a",
|
||||
}
|
||||
|
||||
ok := maputil.IsDisjoint(m2, m1)
|
||||
fmt.Println(ok) // false
|
||||
|
||||
ok = maputil.IsDisjoint(m2, m3)
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
@@ -5,7 +5,7 @@ maputil包包括一些操作map的函数。
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
- [IsDisjoint](#IsDisjoint)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -231,7 +232,6 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>返回一个map,其中的key存在于mapA,不存在于mapB.</p>
|
||||
|
||||
@@ -301,4 +301,52 @@ func main() {
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsDisjoint">IsDisjoint</span>
|
||||
<p>验证两个map是否具有不同的key</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m2 := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
m3 := map[int]string{
|
||||
6: "a",
|
||||
}
|
||||
|
||||
ok := maputil.IsDisjoint(m2, m1)
|
||||
fmt.Println(ok) // false
|
||||
|
||||
ok = maputil.IsDisjoint(m2, m3)
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
370
docs/netutil.md
370
docs/netutil.md
@@ -7,6 +7,8 @@ Package netutil contains functions to get net information and send http request.
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -22,17 +24,26 @@ import (
|
||||
|
||||
## Index
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [EncodeUrl](#EncodeUrl)
|
||||
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [GetRequestPublicIp](#GetRequestPublicIp)
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
- [IsInternalIP](#IsInternalIP)
|
||||
- [HttpRequest](#HttpRequest)
|
||||
- [HttpClient](#HttpClient)
|
||||
- [SendRequest](#SendRequest)
|
||||
- [DecodeResponse](#DecodeResponse)
|
||||
- [StructToUrlValues](#StructToUrlValues)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
||||
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
||||
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -72,6 +83,36 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="EncodeUrl">EncodeUrl</span>
|
||||
<p>Encode url query string values.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func EncodeUrl(urlStr string) (string, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := netutil.EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>Get internal ip information.</p>
|
||||
|
||||
@@ -199,8 +240,51 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
|
||||
<p>Get http request public ip.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetRequestPublicIp(req *http.Request) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request1 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp1 := netutil.GetRequestPublicIp(&request1)
|
||||
fmt.Println(publicIp1) //36.112.24.10
|
||||
|
||||
request2 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp2 := netutil.GetRequestPublicIp(&request2)
|
||||
fmt.Println(publicIp2) //36.112.24.10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>Checks if a ip is public or not.</p>
|
||||
<p>Checks if an ip is public or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -230,14 +314,268 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
### <span id="IsInternalIP">IsInternalIP</span>
|
||||
<p>Checks if an ip is intranet or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsInternalIP(IP net.IP) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("127.0.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsInternalIP(ip1)) //true
|
||||
fmt.Println(netutil.IsInternalIP(ip2)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="HttpRequest">HttpRequest</span>
|
||||
<p>HttpRequest is a struct used to abstract HTTP request entity.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type HttpRequest struct {
|
||||
RawURL string
|
||||
Method string
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
Body []byte
|
||||
}
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
header := http.Header{}
|
||||
header.Add("Content-Type", "multipart/form-data")
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "testItem")
|
||||
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "POST",
|
||||
Headers: header,
|
||||
FormData: postData,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="HttpClient">HttpClient</span>
|
||||
<p>HttpClient is a struct used to send HTTP request. It can be instanced with some configurations or none config.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type HttpClient struct {
|
||||
*http.Client
|
||||
TLS *tls.Config
|
||||
Request *http.Request
|
||||
Config HttpClientConfig
|
||||
}
|
||||
|
||||
type HttpClientConfig struct {
|
||||
SSLEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
Compressed bool
|
||||
HandshakeTimeout time.Duration
|
||||
ResponseTimeout time.Duration
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
func NewHttpClient() *HttpClient
|
||||
|
||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
|
||||
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
httpClientCfg := netutil.HttpClientConfig{
|
||||
SSLEnabled: true,
|
||||
HandshakeTimeout:10 * time.Second
|
||||
}
|
||||
httpClient := netutil.NewHttpClientWithConfig(&httpClientCfg)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SendRequest">SendRequest</span>
|
||||
<p>Use HttpClient to send HTTP request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := netutil.NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
httpClient.DecodeResponse(resp, &todo)
|
||||
|
||||
fmt.Println(todo.Id) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="DecodeResponse">DecodeResponse</span>
|
||||
<p>Decode http response into target object.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := netutil.NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
httpClient.DecodeResponse(resp, &todo)
|
||||
|
||||
fmt.Println(todo.Id) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="StructToUrlValues">StructToUrlValues</span>
|
||||
<p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func StructToUrlValues(targetStruct any) url.Values
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 2,
|
||||
}
|
||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
||||
|
||||
fmt.Println(todoValues.Get("id")) //1
|
||||
fmt.Println(todoValues.Get("userId")) //2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>Send http get request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
@@ -272,14 +610,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>Send http post request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
@@ -321,14 +659,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>Send http put request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
@@ -371,14 +709,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>Send http delete request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
@@ -410,14 +748,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>Send http patch request.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any,
|
||||
// params[1] is query param which type should be url.Values or map[string]string,
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
|
||||
@@ -6,6 +6,9 @@ netutil网络包支持获取ip地址,发送http请求。
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -21,17 +24,27 @@ import (
|
||||
|
||||
## 目录
|
||||
- [ConvertMapToQueryString](#ConvertMapToQueryString)
|
||||
- [EncodeUrl](#EncodeUrl)
|
||||
- [GetInternalIp](#GetInternalIp)
|
||||
- [GetIps](#GetIps)
|
||||
- [GetMacAddrs](#GetMacAddrs)
|
||||
- [GetPublicIpInfo](#GetPublicIpInfo)
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [HttpGet](#HttpGet)
|
||||
- [HttpDelete](#HttpDelete)
|
||||
- [HttpPost](#HttpPost)
|
||||
- [HttpPut](#HttpPut)
|
||||
- [GetRequestPublicIp](#GetRequestPublicIp)
|
||||
|
||||
- [IsPublicIP](#IsPublicIP)
|
||||
- [IsInternalIP](#IsInternalIP)
|
||||
- [HttpRequest](#HttpRequest)
|
||||
- [HttpClient](#HttpClient)
|
||||
- [SendRequest](#SendRequest)
|
||||
- [DecodeResponse](#DecodeResponse)
|
||||
- [StructToUrlValues](#StructToUrlValues)
|
||||
|
||||
- [HttpGet<sup>Deprecated</sup>](#HttpGet)
|
||||
- [HttpDelete<sup>Deprecated</sup>](#HttpDelete)
|
||||
- [HttpPost<sup>Deprecated</sup>](#HttpPost)
|
||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||
|
||||
- [HttpPatch](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -71,6 +84,37 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="EncodeUrl">EncodeUrl</span>
|
||||
<p>编码url query string的值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EncodeUrl(urlStr string) (string, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := netutil.EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetInternalIp">GetInternalIp</span>
|
||||
<p>获取内部ip</p>
|
||||
|
||||
@@ -197,6 +241,50 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
|
||||
<p>获取http请求ip</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetRequestPublicIp(req *http.Request) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request1 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp1 := netutil.GetRequestPublicIp(&request1)
|
||||
fmt.Println(publicIp1) //36.112.24.10
|
||||
|
||||
request2 := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp2 := netutil.GetRequestPublicIp(&request2)
|
||||
fmt.Println(publicIp2) //36.112.24.10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="IsPublicIP">IsPublicIP</span>
|
||||
<p>判断ip是否是公共ip</p>
|
||||
|
||||
@@ -227,15 +315,268 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="IsInternalIP">IsInternalIP</span>
|
||||
<p>判断ip是否是局域网ip.</p>
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsInternalIP(IP net.IP) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ip1 := net.ParseIP("127.0.0.1")
|
||||
ip2 := net.ParseIP("36.112.24.10")
|
||||
|
||||
fmt.Println(netutil.IsInternalIP(ip1)) //true
|
||||
fmt.Println(netutil.IsInternalIP(ip2)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="HttpRequest">HttpRequest</span>
|
||||
<p>HttpRequest用于抽象HTTP请求实体的结构</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type HttpRequest struct {
|
||||
RawURL string
|
||||
Method string
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
Body []byte
|
||||
}
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
header := http.Header{}
|
||||
header.Add("Content-Type", "multipart/form-data")
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "testItem")
|
||||
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "POST",
|
||||
Headers: header,
|
||||
FormData: postData,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="HttpClient">HttpClient</span>
|
||||
<p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type HttpClient struct {
|
||||
*http.Client
|
||||
TLS *tls.Config
|
||||
Request *http.Request
|
||||
Config HttpClientConfig
|
||||
}
|
||||
|
||||
type HttpClientConfig struct {
|
||||
SSLEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
Compressed bool
|
||||
HandshakeTimeout time.Duration
|
||||
ResponseTimeout time.Duration
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
func NewHttpClient() *HttpClient
|
||||
|
||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
|
||||
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
httpClientCfg := netutil.HttpClientConfig{
|
||||
SSLEnabled: true,
|
||||
HandshakeTimeout:10 * time.Second
|
||||
}
|
||||
httpClient := netutil.NewHttpClientWithConfig(&httpClientCfg)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="SendRequest">SendRequest</span>
|
||||
<p>HttpClient发送http请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := netutil.NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
httpClient.DecodeResponse(resp, &todo)
|
||||
|
||||
fmt.Println(todo.Id) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="DecodeResponse">DecodeResponse</span>
|
||||
<p>解析http响应体到目标结构体</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
request := &netutil.HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := netutil.NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
httpClient.DecodeResponse(resp, &todo)
|
||||
|
||||
fmt.Println(todo.Id) //1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="StructToUrlValues">StructToUrlValues</span>
|
||||
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StructToUrlValues(targetStruct any) url.Values
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 2,
|
||||
}
|
||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
||||
|
||||
fmt.Println(todoValues.Get("id")) //1
|
||||
fmt.Println(todoValues.Get("userId")) //2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>发送http get请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpGet(url string, params ...any) (*http.Response, error)
|
||||
@@ -270,14 +611,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>发送http post请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPost(url string, params ...any) (*http.Response, error)
|
||||
@@ -319,19 +660,19 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>发送http put请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPut(url string, params ...any) (*http.Response, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -369,14 +710,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>发送http delete请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpDelete(url string, params ...any) (*http.Response, error)
|
||||
@@ -408,14 +749,14 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
|
||||
<p>发送http patch请求</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// params[0] http请求header,类型必须是http.Header或者map[string]string
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]any
|
||||
// params[1] http查询字符串,类型必须是url.Values或者map[string]string
|
||||
// params[2] post请求体,类型必须是[]byte
|
||||
// params[3] http client,类型必须是http.Client
|
||||
func HttpPatch(url string, params ...any) (*http.Response, error)
|
||||
|
||||
138
docs/random.md
138
docs/random.md
@@ -1,16 +1,17 @@
|
||||
# Random
|
||||
|
||||
Package random implements some basic functions to generate random int and string.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 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>
|
||||
|
||||
## Usage:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
@@ -20,17 +21,23 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [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>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
### <span id="RandBytes">RandBytes</span>
|
||||
|
||||
<p>Generate random byte slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -38,6 +45,7 @@ import (
|
||||
```go
|
||||
func RandBytes(length int) []byte
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -54,8 +62,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandInt">RandInt</span>
|
||||
|
||||
<p>Generate random int between min and max, may contain min, not max.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -63,6 +71,7 @@ func main() {
|
||||
```go
|
||||
func RandInt(min, max int) int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -79,16 +88,16 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandString">RandString</span>
|
||||
|
||||
|
||||
### <span id="RandString">RandInt</span>
|
||||
<p>Generate random given length string.</p>
|
||||
<p>Generate random given length string. only contains letter (a-zA-Z)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandString(length int) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -101,14 +110,116 @@ import (
|
||||
|
||||
func main() {
|
||||
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>
|
||||
|
||||
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -116,6 +227,7 @@ func main() {
|
||||
```go
|
||||
func UUIdV4() (string, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
@@ -134,5 +246,3 @@ func main() {
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Random
|
||||
random随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
<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>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
@@ -20,18 +21,23 @@ import (
|
||||
<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>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
### <span id="RandBytes">RandBytes</span>
|
||||
|
||||
<p>生成随机字节切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -39,6 +45,7 @@ import (
|
||||
```go
|
||||
func RandBytes(length int) []byte
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -55,8 +62,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandInt">RandInt</span>
|
||||
|
||||
<p>生成随机int, 范围[min, max)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -64,6 +71,7 @@ func main() {
|
||||
```go
|
||||
func RandInt(min, max int) int
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -80,16 +88,16 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandString">RandString</span>
|
||||
|
||||
|
||||
### <span id="RandString">RandInt</span>
|
||||
<p>生成随机给定长度的随机字符串</p>
|
||||
<p>生成给定长度的随机字符串,只包含字母(a-zA-Z)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandString(length int) string
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -102,13 +110,116 @@ import (
|
||||
|
||||
func main() {
|
||||
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>
|
||||
|
||||
<p>生成UUID v4字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -116,6 +227,7 @@ func main() {
|
||||
```go
|
||||
func UUIdV4() (string, error)
|
||||
```
|
||||
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
@@ -134,5 +246,3 @@ func main() {
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -97,8 +97,8 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
@@ -139,6 +139,7 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
|
||||
@@ -99,8 +99,7 @@ import (
|
||||
|
||||
func main() {
|
||||
var number int
|
||||
var increaseNumber retry.RetryFunc
|
||||
increaseNumber = func() error {
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
|
||||
553
docs/slice.md
553
docs/slice.md
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ import (
|
||||
- [UpperFirst](#UpperFirst)
|
||||
- [PadEnd](#PadEnd)
|
||||
- [PadStart](#PadStart)
|
||||
- [ReverseStr](#ReverseStr)
|
||||
- [Reverse](#Reverse)
|
||||
- [SnakeCase](#SnakeCase)
|
||||
- [SplitEx](#SplitEx)
|
||||
- [Wrap](#Wrap)
|
||||
@@ -430,13 +430,13 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ReverseStr">ReverseStr</span>
|
||||
### <span id="Reverse">Reverse</span>
|
||||
<p>Return string whose char order is reversed to the given string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReverseStr(s string) string
|
||||
func Reverse(s string) string
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
- [UpperFirst](#UpperFirst)
|
||||
- [PadEnd](#PadEnd)
|
||||
- [PadStart](#PadStart)
|
||||
- [ReverseStr](#ReverseStr)
|
||||
- [Reverse](#Reverse)
|
||||
- [SnakeCase](#SnakeCase)
|
||||
- [SplitEx](#SplitEx)
|
||||
- [Wrap](#Wrap)
|
||||
@@ -431,13 +431,13 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="ReverseStr">ReverseStr</span>
|
||||
### <span id="Reverse">Reverse</span>
|
||||
<p>返回字符顺序与给定字符串相反的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReverseStr(s string) string
|
||||
func Reverse(s string) string
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -210,7 +211,7 @@ func main() {
|
||||
|
||||
|
||||
### <span id="ExecCommand">CompareOsEnv</span>
|
||||
<p>use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||
<p>Use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -236,7 +237,27 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@ import (
|
||||
- [GetOsEnv](#GetOsEnv)
|
||||
- [SetOsEnv](#SetOsEnv)
|
||||
- [RemoveOsEnv](#RemoveOsEnv)
|
||||
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -236,6 +238,30 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
<p>获取当前操作系统位数,返回32或64</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetOsBits() int
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
osBit := system.GetOsBits()
|
||||
fmt.Println(osBit)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import (
|
||||
- [IsStrongPassword](#IsStrongPassword)
|
||||
- [IsUrl](#IsUrl)
|
||||
- [IsWeakPassword](#IsWeakPassword)
|
||||
- [IsZeroValue](#IsZeroValue)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -765,7 +766,7 @@ func main() {
|
||||
|
||||
|
||||
### <span id="IsWeakPassword">IsWeakPassword</span>
|
||||
<p>Check if the string is weak password(only letter or only number or letter + number)
|
||||
<p>Checks if the string is weak password(only letter or only number or letter + number)
|
||||
.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
@@ -792,6 +793,36 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="IsZeroValue">IsZeroValue</span>
|
||||
<p>Checks if passed value is a zero value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsZeroValue(value any) bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsZeroValue(nil)) //true
|
||||
fmt.Println(validator.IsZeroValue(0)) //true
|
||||
fmt.Println(validator.IsZeroValue("")) //true
|
||||
fmt.Println(validator.IsZeroValue([]int)) //true
|
||||
fmt.Println(validator.IsZeroValue(interface{})) //true
|
||||
|
||||
fmt.Println(validator.IsZeroValue("0")) //false
|
||||
fmt.Println(validator.IsZeroValue("nil")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import (
|
||||
- [IsStrongPassword](#IsStrongPassword)
|
||||
- [IsUrl](#IsUrl)
|
||||
- [IsWeakPassword](#IsWeakPassword)
|
||||
- [IsZeroValue](#IsZeroValue)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -792,8 +793,31 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="IsZeroValue">IsZeroValue</span>
|
||||
<p>判断传入的参数值是否为零值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsZeroValue(value any) bool
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(validator.IsZeroValue(nil)) //true
|
||||
fmt.Println(validator.IsZeroValue(0)) //true
|
||||
fmt.Println(validator.IsZeroValue("")) //true
|
||||
fmt.Println(validator.IsZeroValue([]int)) //true
|
||||
fmt.Println(validator.IsZeroValue(interface{})) //true
|
||||
|
||||
fmt.Println(validator.IsZeroValue("0")) //false
|
||||
fmt.Println(validator.IsZeroValue("nil")) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := strconv.Atoi("4o2")
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
|
||||
|
||||
@@ -46,7 +46,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := strconv.Atoi("4o2")
|
||||
_, err := strconv.Atoi("4o2")
|
||||
defer func() {
|
||||
v := recover()
|
||||
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
|
||||
|
||||
@@ -8,11 +8,13 @@ import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
@@ -40,6 +42,11 @@ func CreateFile(path string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/
|
||||
func CreateDir(absPath string) error {
|
||||
return os.MkdirAll(path.Dir(absPath), os.ModePerm)
|
||||
}
|
||||
|
||||
// IsDir checks if the path is directory or not
|
||||
func IsDir(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
@@ -110,7 +117,7 @@ func ReadFileByLine(path string) ([]string, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
res := make([]string, 0)
|
||||
result := make([]string, 0)
|
||||
buf := bufio.NewReader(f)
|
||||
|
||||
for {
|
||||
@@ -122,10 +129,10 @@ func ReadFileByLine(path string) ([]string, error) {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
res = append(res, l)
|
||||
result = append(result, l)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ListFileNames return all file names in the path
|
||||
@@ -144,14 +151,14 @@ func ListFileNames(path string) ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
res := []string{}
|
||||
result := []string{}
|
||||
for i := 0; i < sz; i++ {
|
||||
if !fs[i].IsDir() {
|
||||
res = append(res, fs[i].Name())
|
||||
result = append(result, fs[i].Name())
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Zip create zip file, fpath could be a single file or a directory
|
||||
@@ -207,6 +214,7 @@ func Zip(fpath string, destPath string) error {
|
||||
|
||||
// UnZip unzip the file and save it to destPath
|
||||
func UnZip(zipFile string, destPath string) error {
|
||||
|
||||
zipReader, err := zip.OpenReader(zipFile)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -215,6 +223,13 @@ func UnZip(zipFile string, destPath string) error {
|
||||
|
||||
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() {
|
||||
os.MkdirAll(path, os.ModePerm)
|
||||
} else {
|
||||
@@ -243,6 +258,17 @@ func UnZip(zipFile string, destPath string) error {
|
||||
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
|
||||
func IsLink(path string) bool {
|
||||
fi, err := os.Lstat(path)
|
||||
|
||||
@@ -25,6 +25,7 @@ func TestCreateFile(t *testing.T) {
|
||||
f := "./text.txt"
|
||||
if CreateFile(f) {
|
||||
file, err := os.Open(f)
|
||||
defer file.Close()
|
||||
assert.IsNil(err)
|
||||
assert.Equal(f, file.Name())
|
||||
} else {
|
||||
@@ -33,6 +34,27 @@ func TestCreateFile(t *testing.T) {
|
||||
os.Remove(f)
|
||||
}
|
||||
|
||||
func TestCreateDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCreateDir")
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
dirPath := pwd + "/a/"
|
||||
err = CreateDir(dirPath)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(true, IsExist(dirPath))
|
||||
os.Remove(dirPath)
|
||||
assert.Equal(false, IsExist(dirPath))
|
||||
}
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsDir")
|
||||
|
||||
@@ -90,6 +112,7 @@ func TestReadFileToString(t *testing.T) {
|
||||
CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := ReadFileToString(path)
|
||||
@@ -197,6 +220,7 @@ func TestMiMeType(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMiMeType")
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
defer f.Close()
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
|
||||
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
|
||||
}
|
||||
|
||||
@@ -27,16 +27,16 @@ func After(n int, fn any) func(args ...any) []reflect.Value {
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value {
|
||||
// Catch programming error while constructing the closure
|
||||
mustBeFunction(fn)
|
||||
var res []reflect.Value
|
||||
var result []reflect.Value
|
||||
return func(args ...any) []reflect.Value {
|
||||
if n > 0 {
|
||||
res = unsafeInvokeFunc(fn, args...)
|
||||
result = unsafeInvokeFunc(fn, args...)
|
||||
}
|
||||
if n <= 0 {
|
||||
fn = nil
|
||||
}
|
||||
n--
|
||||
return res
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,3 +113,15 @@ func Schedule(d time.Duration, fn any, args ...any) chan bool {
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestDebounced(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSchedule(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSchedule")
|
||||
// assert := internal.NewAssert(t, "TestSchedule")
|
||||
|
||||
var res []string
|
||||
appendStr := func(s string) {
|
||||
@@ -127,6 +127,28 @@ func TestSchedule(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
close(stop)
|
||||
|
||||
expected := []string{"*", "*", "*", "*", "*"}
|
||||
assert.Equal(expected, res)
|
||||
t.Log(res)
|
||||
|
||||
// todo: in github action, for now, this test is not working sometimes
|
||||
// res maybe [* * * * *] or [* * * * * *]
|
||||
// expected := []string{"*", "*", "*", "*", "*"}
|
||||
// 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)
|
||||
}
|
||||
|
||||
func longRunningTask() {
|
||||
var slice []int64
|
||||
func longRunningTask() []int64 {
|
||||
var data []int64
|
||||
for i := 0; i < 10000000; i++ {
|
||||
slice = append(slice, int64(i))
|
||||
data = append(data, int64(i))
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ type Comparator interface {
|
||||
|
||||
// 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
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
|
||||
}
|
||||
|
||||
BIN
logo.png
BIN
logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 18 KiB |
@@ -8,10 +8,12 @@ import "reflect"
|
||||
|
||||
// Keys returns a slice of the map's keys
|
||||
func Keys[K comparable, V any](m map[K]V) []K {
|
||||
keys := make([]K, 0, len(m))
|
||||
keys := make([]K, len(m))
|
||||
|
||||
var i int
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
|
||||
return keys
|
||||
@@ -19,10 +21,12 @@ func Keys[K comparable, V any](m map[K]V) []K {
|
||||
|
||||
// Values returns a slice of the map's values
|
||||
func Values[K comparable, V any](m map[K]V) []V {
|
||||
values := make([]V, 0, len(m))
|
||||
values := make([]V, len(m))
|
||||
|
||||
var i int
|
||||
for _, v := range m {
|
||||
values = append(values, v)
|
||||
values[i] = v
|
||||
i++
|
||||
}
|
||||
|
||||
return values
|
||||
@@ -30,15 +34,15 @@ func Values[K comparable, V any](m map[K]V) []V {
|
||||
|
||||
// Merge maps, next key will overwrite previous key
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
res := make(map[K]V, 0)
|
||||
result := make(map[K]V, 0)
|
||||
|
||||
for _, m := range maps {
|
||||
for k, v := range m {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// ForEach executes iteratee funcation for every key and value pair in map
|
||||
@@ -50,14 +54,14 @@ func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
|
||||
|
||||
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
|
||||
res := make(map[K]V)
|
||||
result := make(map[K]V)
|
||||
|
||||
for k, v := range m {
|
||||
if predicate(k, v) {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
|
||||
@@ -69,7 +73,7 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
return maps[0]
|
||||
}
|
||||
|
||||
var res map[K]V
|
||||
var result map[K]V
|
||||
|
||||
reducer := func(m1, m2 map[K]V) map[K]V {
|
||||
m := make(map[K]V)
|
||||
@@ -82,25 +86,35 @@ func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
}
|
||||
|
||||
reduceMaps := make([]map[K]V, 2, 2)
|
||||
res = reducer(maps[0], maps[1])
|
||||
result = reducer(maps[0], maps[1])
|
||||
|
||||
for i := 2; i < len(maps); i++ {
|
||||
reduceMaps[0] = res
|
||||
reduceMaps[0] = result
|
||||
reduceMaps[1] = maps[i]
|
||||
res = reducer(reduceMaps[0], reduceMaps[1])
|
||||
result = reducer(reduceMaps[0], reduceMaps[1])
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Minus creates an map of whose key in mapA but not in mapB
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
|
||||
res := make(map[K]V)
|
||||
result := make(map[K]V)
|
||||
|
||||
for k, v := range mapA {
|
||||
if _, ok := mapB[k]; !ok {
|
||||
res[k] = v
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// IsDisjoint two map are disjoint if they have no keys in common
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool {
|
||||
for k := range mapA {
|
||||
if _, ok := mapB[k]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -148,3 +148,25 @@ func TestMinus(t *testing.T) {
|
||||
|
||||
assert.Equal(map[string]int{"c": 3}, Minus(m1, m2))
|
||||
}
|
||||
|
||||
func TestIsDisjoint(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMinus")
|
||||
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"d": 22,
|
||||
}
|
||||
|
||||
assert.Equal(true, IsDisjoint(m1, m2))
|
||||
|
||||
m3 := map[string]int{
|
||||
"a": 22,
|
||||
}
|
||||
|
||||
assert.Equal(false, IsDisjoint(m1, m3))
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ func Percent(val, total float64, n int) float64 {
|
||||
return float64(0)
|
||||
}
|
||||
tmp := val / total * 100
|
||||
res := RoundToFloat(tmp, n)
|
||||
result := RoundToFloat(tmp, n)
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// RoundToString round up to n decimal places
|
||||
@@ -67,8 +67,8 @@ func RoundToString(x float64, n int) string {
|
||||
tmp := math.Pow(10.0, float64(n))
|
||||
x *= tmp
|
||||
x = math.Round(x)
|
||||
res := strconv.FormatFloat(x/tmp, 'f', n, 64)
|
||||
return res
|
||||
result := strconv.FormatFloat(x/tmp, 'f', n, 64)
|
||||
return result
|
||||
}
|
||||
|
||||
// RoundToFloat round up to n decimal places
|
||||
@@ -89,8 +89,8 @@ func TruncRound(x float64, n int) float64 {
|
||||
} else {
|
||||
newFloat = temp[0] + "." + temp[1][:n]
|
||||
}
|
||||
res, _ := strconv.ParseFloat(newFloat, 64)
|
||||
return res
|
||||
result, _ := strconv.ParseFloat(newFloat, 64)
|
||||
return result
|
||||
}
|
||||
|
||||
// Max return max value of params
|
||||
|
||||
@@ -87,6 +87,9 @@ func TestMax(t *testing.T) {
|
||||
assert.Equal(Max(0, 0), 0)
|
||||
assert.Equal(Max(1, 2, 3), 3)
|
||||
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) {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
|
||||
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
|
||||
// params[0] is header which type should be http.Header or map[string]string,
|
||||
// params[1] is query param which type should be url.Values or map[string]any, when content-type header is
|
||||
// multipart/form-data or application/x-www-form-urlencoded, params[1] should be url.Values
|
||||
// params[1] is query string param which type should be url.Values or map[string]string, when content-type header is
|
||||
// multipart/form-data or application/x-www-form-urlencoded
|
||||
// params[2] is post body which type should be []byte.
|
||||
// params[3] is http client which type should be http.Client.
|
||||
package netutil
|
||||
|
||||
228
netutil/http_client.go
Normal file
228
netutil/http_client.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
// HttpRequest struct is a composed http request
|
||||
type HttpRequest struct {
|
||||
RawURL string
|
||||
Method string
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// HttpClientConfig contains some configurations for http client
|
||||
type HttpClientConfig struct {
|
||||
SSLEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
Compressed bool
|
||||
HandshakeTimeout time.Duration
|
||||
ResponseTimeout time.Duration
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// defaultHttpClientConfig defalut client config
|
||||
var defaultHttpClientConfig = &HttpClientConfig{
|
||||
Compressed: false,
|
||||
HandshakeTimeout: 20 * time.Second,
|
||||
ResponseTimeout: 40 * time.Second,
|
||||
}
|
||||
|
||||
// HttpClient is used for sending http request
|
||||
type HttpClient struct {
|
||||
*http.Client
|
||||
TLS *tls.Config
|
||||
Request *http.Request
|
||||
Config HttpClientConfig
|
||||
}
|
||||
|
||||
// NewHttpClient make a HttpClient instance
|
||||
func NewHttpClient() *HttpClient {
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
||||
DisableCompression: !defaultHttpClientConfig.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *defaultHttpClientConfig,
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
||||
if config == nil {
|
||||
config = defaultHttpClientConfig
|
||||
}
|
||||
|
||||
client := &HttpClient{
|
||||
Client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSHandshakeTimeout: config.HandshakeTimeout,
|
||||
ResponseHeaderTimeout: config.ResponseTimeout,
|
||||
DisableCompression: !config.Compressed,
|
||||
},
|
||||
},
|
||||
Config: *config,
|
||||
}
|
||||
|
||||
if config.SSLEnabled {
|
||||
client.TLS = config.TLSConfig
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// SendRequest send http request
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
|
||||
err := validateRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawUrl := request.RawURL
|
||||
|
||||
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.setTLS(rawUrl)
|
||||
client.setHeader(req, request.Headers)
|
||||
client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||
|
||||
if request.FormData != nil {
|
||||
client.setFormData(req, request.FormData)
|
||||
}
|
||||
|
||||
client.Request = req
|
||||
|
||||
resp, err := client.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// DecodeResponse decode response into target object
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
|
||||
if resp == nil {
|
||||
return errors.New("invalid target param")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return json.NewDecoder(resp.Body).Decode(target)
|
||||
}
|
||||
|
||||
// setTLS set http client transport TLSClientConfig
|
||||
func (client *HttpClient) setTLS(rawUrl string) {
|
||||
if strings.HasPrefix(rawUrl, "https") {
|
||||
if transport, ok := client.Client.Transport.(*http.Transport); ok {
|
||||
transport.TLSClientConfig = client.TLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setHeader set http rquest header
|
||||
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
||||
if headers == nil {
|
||||
headers = make(http.Header)
|
||||
}
|
||||
|
||||
if _, ok := headers["Accept"]; !ok {
|
||||
headers["Accept"] = []string{"*/*"}
|
||||
}
|
||||
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
|
||||
headers["Accept-Encoding"] = []string{"deflate, gzip"}
|
||||
}
|
||||
|
||||
req.Header = headers
|
||||
}
|
||||
|
||||
// setQueryParam set http request query string param
|
||||
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
|
||||
if queryParam != nil {
|
||||
if !strings.Contains(reqUrl, "?") {
|
||||
reqUrl = reqUrl + "?" + queryParam.Encode()
|
||||
} else {
|
||||
reqUrl = reqUrl + "&" + queryParam.Encode()
|
||||
}
|
||||
u, err := url.Parse(reqUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.URL = u
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||
formData := []byte(values.Encode())
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
}
|
||||
|
||||
// validateRequest check if a request has url, and valid method.
|
||||
func validateRequest(req *HttpRequest) error {
|
||||
if req.RawURL == "" {
|
||||
return errors.New("invalid request url")
|
||||
}
|
||||
|
||||
// common HTTP methods
|
||||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
|
||||
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
|
||||
|
||||
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
|
||||
return errors.New("invalid request method")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StructToUrlValues convert struct to url valuse,
|
||||
// only convert the field which is exported and has `json` tag
|
||||
func StructToUrlValues(targetStruct any) url.Values {
|
||||
rv := reflect.ValueOf(targetStruct)
|
||||
rt := reflect.TypeOf(targetStruct)
|
||||
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
if rt.Kind() != reflect.Struct {
|
||||
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
||||
}
|
||||
|
||||
result := url.Values{}
|
||||
|
||||
fieldNum := rt.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
for i := 0; i < fieldNum; i++ {
|
||||
name := rt.Field(i).Name
|
||||
tag := rt.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
95
netutil/http_client_test.go
Normal file
95
netutil/http_client_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestHttpClient_Get(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHttpClient_Get")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||
Method: "GET",
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Completed bool `json:"completed"`
|
||||
}
|
||||
|
||||
var todo Todo
|
||||
httpClient.DecodeResponse(resp, &todo)
|
||||
|
||||
assert.Equal(1, todo.Id)
|
||||
}
|
||||
|
||||
func TestHttpClent_Post(t *testing.T) {
|
||||
header := http.Header{}
|
||||
header.Add("Content-Type", "multipart/form-data")
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "testItem")
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "POST",
|
||||
Headers: header,
|
||||
FormData: postData,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
func TestStructToUrlValues(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
||||
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 1,
|
||||
}
|
||||
todoValues := StructToUrlValues(todoQuery)
|
||||
|
||||
assert.Equal("1", todoValues.Get("id"))
|
||||
assert.Equal("1", todoValues.Get("userId"))
|
||||
|
||||
request := &HttpRequest{
|
||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||
Method: "GET",
|
||||
QueryParams: todoValues,
|
||||
}
|
||||
|
||||
httpClient := NewHttpClient()
|
||||
resp, err := httpClient.SendRequest(request)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", string(body))
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -19,7 +18,6 @@ func TestHttpGet(t *testing.T) {
|
||||
resp, err := HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
@@ -41,7 +39,6 @@ func TestHttpPost(t *testing.T) {
|
||||
resp, err := HttpPost(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
@@ -57,14 +54,17 @@ func TestHttpPostFormData(t *testing.T) {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestAddToDo")
|
||||
// postData := url.Values{}
|
||||
// postData.Add("userId", "1")
|
||||
// postData.Add("title", "TestAddToDo")
|
||||
|
||||
postData := make(map[string]string)
|
||||
postData["userId"] = "1"
|
||||
postData["title"] = "title"
|
||||
|
||||
resp, err := HttpPost(apiUrl, header, postData, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
@@ -86,7 +86,6 @@ func TestHttpPut(t *testing.T) {
|
||||
resp, err := HttpPut(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
@@ -108,7 +107,6 @@ func TestHttpPatch(t *testing.T) {
|
||||
resp, err := HttpPatch(url, header, nil, bodyParams)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
@@ -119,7 +117,6 @@ func TestHttpDelete(t *testing.T) {
|
||||
resp, err := HttpDelete(url)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
@@ -145,7 +142,6 @@ func TestParseResponse(t *testing.T) {
|
||||
resp, err := HttpGet(url, header)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
@@ -159,7 +155,6 @@ func TestParseResponse(t *testing.T) {
|
||||
err = ParseHttpResponse(resp, toDoResp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
t.FailNow()
|
||||
}
|
||||
t.Log("response: ", toDoResp)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetInternalIp return internal ipv4
|
||||
@@ -24,6 +26,26 @@ func GetInternalIp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetRequestPublicIp return the requested public ip
|
||||
func GetRequestPublicIp(req *http.Request) string {
|
||||
var ip string
|
||||
for _, ip = range strings.Split(req.Header.Get("X-Forwarded-For"), ",") {
|
||||
if ip = strings.TrimSpace(ip); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
|
||||
if ip = strings.TrimSpace(req.Header.Get("X-Real-Ip")); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
|
||||
if ip, _, _ = net.SplitHostPort(req.RemoteAddr); !IsInternalIP(net.ParseIP(ip)) {
|
||||
return ip
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
// GetPublicIpInfo return public ip information
|
||||
// return the PublicIpInfo struct
|
||||
func GetPublicIpInfo() (*PublicIpInfo, error) {
|
||||
@@ -122,3 +144,29 @@ func IsPublicIP(IP net.IP) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsInternalIP verify an ip is intranet or not
|
||||
func IsInternalIP(IP net.IP) bool {
|
||||
if IP.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
if ip4 := IP.To4(); ip4 != nil {
|
||||
return ip4[0] == 10 ||
|
||||
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) ||
|
||||
(ip4[0] == 169 && ip4[1] == 254) ||
|
||||
(ip4[0] == 192 && ip4[1] == 168)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// EncodeUrl encode url
|
||||
func EncodeUrl(urlStr string) (string, error) {
|
||||
URL, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
URL.RawQuery = URL.Query().Encode()
|
||||
|
||||
return URL.String(), nil
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package netutil
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -81,9 +80,18 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if req.Header.Get("Content-Type") == "multipart/form-data" || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
|
||||
formData := queryParam.(url.Values)
|
||||
err = setBodyByte(req, []byte(formData.Encode()))
|
||||
if strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
|
||||
if formData, ok := queryParam.(url.Values); ok {
|
||||
err = setBodyByte(req, []byte(formData.Encode()))
|
||||
}
|
||||
if formData, ok := queryParam.(map[string]string); ok {
|
||||
postData := url.Values{}
|
||||
for k, v := range formData {
|
||||
postData.Set(k, v)
|
||||
}
|
||||
err = setBodyByte(req, []byte(postData.Encode()))
|
||||
}
|
||||
|
||||
} else {
|
||||
err = setBodyByte(req, body)
|
||||
}
|
||||
@@ -132,15 +140,15 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
|
||||
var values url.Values
|
||||
if queryParam != nil {
|
||||
switch v := queryParam.(type) {
|
||||
case map[string]any:
|
||||
case map[string]string:
|
||||
values = url.Values{}
|
||||
for k := range v {
|
||||
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||
values.Set(k, v[k])
|
||||
}
|
||||
case url.Values:
|
||||
values = v
|
||||
default:
|
||||
return errors.New("query params type should be url.Values or map[string]any")
|
||||
return errors.New("query string params type should be url.Values or map[string]string")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package netutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -15,6 +16,30 @@ func TestGetInternalIp(t *testing.T) {
|
||||
assert.IsNotNil(ip)
|
||||
}
|
||||
|
||||
func TestGetRequestPublicIp(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||
|
||||
ip := "36.112.24.10"
|
||||
|
||||
request := http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Forwarded-For": {ip},
|
||||
},
|
||||
}
|
||||
publicIp := GetRequestPublicIp(&request)
|
||||
assert.Equal(publicIp, ip)
|
||||
|
||||
request = http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"X-Real-Ip": {ip},
|
||||
},
|
||||
}
|
||||
publicIp = GetRequestPublicIp(&request)
|
||||
assert.Equal(publicIp, ip)
|
||||
}
|
||||
|
||||
func TestGetPublicIpInfo(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||
|
||||
@@ -43,6 +68,25 @@ func TestIsPublicIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsInternalIP(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsInternalIP")
|
||||
|
||||
ips := []net.IP{
|
||||
net.ParseIP("127.0.0.1"),
|
||||
net.ParseIP("192.168.0.1"),
|
||||
net.ParseIP("10.91.210.131"),
|
||||
net.ParseIP("172.20.16.1"),
|
||||
net.ParseIP("36.112.24.10"),
|
||||
}
|
||||
|
||||
expected := []bool{true, true, true, true, false}
|
||||
|
||||
for i := 0; i < len(ips); i++ {
|
||||
actual := IsInternalIP(ips[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIps(t *testing.T) {
|
||||
ips := GetIps()
|
||||
t.Log(ips)
|
||||
@@ -52,3 +96,16 @@ func TestGetMacAddrs(t *testing.T) {
|
||||
macAddrs := GetMacAddrs()
|
||||
t.Log(macAddrs)
|
||||
}
|
||||
|
||||
func TestEncodeUrl(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsInternalIP")
|
||||
|
||||
urlAddr := "http://www.lancet.com?a=1&b=[2]"
|
||||
encodedUrl, err := EncodeUrl(urlAddr)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
expected := "http://www.lancet.com?a=1&b=%5B2%5D"
|
||||
assert.Equal(expected, encodedUrl)
|
||||
}
|
||||
|
||||
@@ -12,18 +12,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// RandString generate random string
|
||||
// see https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
|
||||
func RandString(length int) string {
|
||||
const 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)
|
||||
}
|
||||
const (
|
||||
NUMERAL = "0123456789"
|
||||
LOWER_LETTERS = "abcdefghijklmnopqrstuvwxyz"
|
||||
UPPER_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
)
|
||||
|
||||
// RandInt generate random int between min and max, maybe min, not be max
|
||||
func RandInt(min, max int) int {
|
||||
@@ -50,6 +44,41 @@ func RandBytes(length int) []byte {
|
||||
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
|
||||
func UUIdV4() (string, error) {
|
||||
uuid := make([]byte, 16)
|
||||
|
||||
@@ -19,6 +19,51 @@ func TestRandString(t *testing.T) {
|
||||
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) {
|
||||
assert := internal.NewAssert(t, "TestRandInt")
|
||||
|
||||
|
||||
401
slice/slice.go
401
slice/slice.go
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights resulterved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package slice implements some functions to manipulate slice.
|
||||
@@ -13,18 +13,18 @@ import (
|
||||
)
|
||||
|
||||
// Contain check if the value is in the slice or not
|
||||
func Contain[T any](slice []T, value T) bool {
|
||||
func Contain[T comparable](slice []T, value T) bool {
|
||||
set := make(map[T]struct{}, len(slice))
|
||||
for _, v := range slice {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return true
|
||||
}
|
||||
set[v] = struct{}{}
|
||||
}
|
||||
|
||||
return false
|
||||
_, ok := set[value]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ContainSubSlice check if the slice contain subslice or not
|
||||
func ContainSubSlice[T any](slice, subslice []T) bool {
|
||||
func ContainSubSlice[T comparable](slice, subslice []T) bool {
|
||||
for _, v := range subslice {
|
||||
if !Contain(slice, v) {
|
||||
return false
|
||||
@@ -36,10 +36,10 @@ func ContainSubSlice[T any](slice, subslice []T) bool {
|
||||
|
||||
// Chunk creates an slice of elements split into groups the length of size.
|
||||
func Chunk[T any](slice []T, size int) [][]T {
|
||||
var res [][]T
|
||||
result := [][]T{}
|
||||
|
||||
if len(slice) == 0 || size <= 0 {
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
length := len(slice)
|
||||
@@ -47,9 +47,9 @@ func Chunk[T any](slice []T, size int) [][]T {
|
||||
for _, v := range slice {
|
||||
var tmp []T
|
||||
tmp = append(tmp, v)
|
||||
res = append(res, tmp)
|
||||
result = append(result, tmp)
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// divide slice equally
|
||||
@@ -57,74 +57,75 @@ func Chunk[T any](slice []T, size int) [][]T {
|
||||
for i := 0; i < divideNum; i++ {
|
||||
if i == divideNum-1 {
|
||||
if len(slice[i*size:]) > 0 {
|
||||
res = append(res, slice[i*size:])
|
||||
result = append(result, slice[i*size:])
|
||||
}
|
||||
} else {
|
||||
res = append(res, slice[i*size:(i+1)*size])
|
||||
result = append(result, slice[i*size:(i+1)*size])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey
|
||||
func Compact[T any](slice []T) []T {
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0)
|
||||
for _, v := range slice {
|
||||
if !reflect.DeepEqual(v, nil) &&
|
||||
!reflect.DeepEqual(v, false) &&
|
||||
!reflect.DeepEqual(v, "") &&
|
||||
!reflect.DeepEqual(v, 0) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Concat creates a new slice concatenating slice with any additional slices and/or values.
|
||||
func Concat[T any](slice []T, values ...[]T) []T {
|
||||
res := append([]T{}, slice...)
|
||||
result := append([]T{}, slice...)
|
||||
|
||||
for _, v := range values {
|
||||
res = append(res, v...)
|
||||
result = append(result, v...)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Difference creates an slice of whose element in slice but not in comparedSlice
|
||||
func Difference[T comparable](slice, comparedSlice []T) []T {
|
||||
var res []T
|
||||
result := []T{}
|
||||
|
||||
for _, v := range slice {
|
||||
if !Contain(comparedSlice, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// DifferenceBy it accepts iteratee which is invoked for each element of slice
|
||||
// and values to generate the criterion by which they're compared.
|
||||
// like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy,
|
||||
func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T {
|
||||
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T {
|
||||
orginSliceAfterMap := Map(slice, iteratee)
|
||||
comparedSliceAfterMap := Map(comparedSlice, iteratee)
|
||||
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0)
|
||||
for i, v := range orginSliceAfterMap {
|
||||
if !Contain(comparedSliceAfterMap, v) {
|
||||
res = append(res, slice[i])
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
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).
|
||||
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T {
|
||||
res := make([]T, 0, 0)
|
||||
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value1, value2 T) bool) []T {
|
||||
result := make([]T, 0)
|
||||
|
||||
getIndex := func(arr []T, item T, comparison func(v1, v2 T) bool) int {
|
||||
index := -1
|
||||
@@ -140,20 +141,48 @@ func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value,
|
||||
for i, v := range slice {
|
||||
index := getIndex(comparedSlice, v, comparator)
|
||||
if index == -1 {
|
||||
res = append(res, slice[i])
|
||||
result = append(result, slice[i])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Equal checks if two slices are equal: the same length and all elements' order and value are equal
|
||||
func Equal[T comparable](slice1, slice2 []T) bool {
|
||||
if len(slice1) != len(slice2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range slice1 {
|
||||
if slice1[i] != slice2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualWith checks if two slices are equal with comparator func
|
||||
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool {
|
||||
if len(slice1) != len(slice2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, v1 := range slice1 {
|
||||
v2 := slice2[i]
|
||||
if !comparator(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
var currentLength int
|
||||
|
||||
for i, v := range slice {
|
||||
if predicate(i, v) {
|
||||
currentLength++
|
||||
@@ -165,9 +194,6 @@ func Every[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||
|
||||
// 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 {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
var currentLength int
|
||||
for i, v := range slice {
|
||||
@@ -181,39 +207,30 @@ func None[T any](slice []T, predicate func(index int, item T) bool) bool {
|
||||
|
||||
// Some return true if any of the values in the list pass the predicate function.
|
||||
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 {
|
||||
if predicate(i, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
res := make([]T, 0, 0)
|
||||
result := make([]T, 0)
|
||||
for i, v := range slice {
|
||||
if predicate(i, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
return res
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Count iterates over elements of slice, returns a count of all matched elements
|
||||
func Count[T any](slice []T, predicate func(index int, item T) bool) int {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
if len(slice) == 0 {
|
||||
return 0
|
||||
}
|
||||
@@ -230,10 +247,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
|
||||
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 {
|
||||
return make([]T, 0), make([]T, 0)
|
||||
}
|
||||
@@ -253,32 +266,24 @@ func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
|
||||
return groupA, groupB
|
||||
}
|
||||
|
||||
// GroupWith return a map composed of keys generated from the results of running each element of slice thru iteratee.
|
||||
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
|
||||
res := make(map[U][]T)
|
||||
// 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(item T) U) map[U][]T {
|
||||
result := make(map[U][]T)
|
||||
|
||||
for _, v := range slice {
|
||||
key := iteratee(v)
|
||||
if _, ok := res[key]; !ok {
|
||||
res[key] = []T{}
|
||||
if _, ok := result[key]; !ok {
|
||||
result[key] = []T{}
|
||||
}
|
||||
res[key] = append(res[key], v)
|
||||
result[key] = append(result[key], v)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
}
|
||||
@@ -301,10 +306,6 @@ 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.
|
||||
// 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) {
|
||||
if predicate == nil {
|
||||
panic("predicate func is missing")
|
||||
}
|
||||
|
||||
if len(slice) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
@@ -324,13 +325,40 @@ func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, boo
|
||||
return &slice[index], true
|
||||
}
|
||||
|
||||
// Flatten flattens slice with one level
|
||||
func Flatten(slice any) any {
|
||||
sv := sliceValue(slice)
|
||||
|
||||
var result reflect.Value
|
||||
if sv.Type().Elem().Kind() == reflect.Interface {
|
||||
result = reflect.MakeSlice(reflect.TypeOf([]interface{}{}), 0, sv.Len())
|
||||
} else if sv.Type().Elem().Kind() == reflect.Slice {
|
||||
result = reflect.MakeSlice(sv.Type().Elem(), 0, sv.Len())
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
item := reflect.ValueOf(sv.Index(i).Interface())
|
||||
if item.Kind() == reflect.Slice {
|
||||
for j := 0; j < item.Len(); j++ {
|
||||
result = reflect.Append(result, item.Index(j))
|
||||
}
|
||||
} else {
|
||||
result = reflect.Append(result, item)
|
||||
}
|
||||
}
|
||||
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
// FlattenDeep flattens slice recursive
|
||||
func FlattenDeep(slice any) any {
|
||||
sv := sliceValue(slice)
|
||||
st := sliceElemType(sv.Type())
|
||||
tmp := reflect.MakeSlice(reflect.SliceOf(st), 0, 0)
|
||||
res := flattenRecursive(sv, tmp)
|
||||
return res.Interface()
|
||||
result := flattenRecursive(sv, tmp)
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
||||
@@ -350,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
|
||||
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 {
|
||||
iteratee(i, v)
|
||||
}
|
||||
@@ -361,38 +385,51 @@ 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.
|
||||
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
|
||||
res := make([]U, len(slice), cap(slice))
|
||||
result := make([]U, len(slice), cap(slice))
|
||||
for i, v := range slice {
|
||||
res[i] = iteratee(i, v)
|
||||
result[i] = iteratee(i, v)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if iteratee == nil {
|
||||
panic("iteratee func is missing")
|
||||
}
|
||||
|
||||
if len(slice) == 0 {
|
||||
return initial
|
||||
}
|
||||
|
||||
res := 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++ {
|
||||
tmp[0] = res
|
||||
tmp[0] = result
|
||||
tmp[1] = slice[i]
|
||||
res = iteratee(i, tmp[0], tmp[1])
|
||||
result = iteratee(i, tmp[0], tmp[1])
|
||||
}
|
||||
|
||||
return res
|
||||
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)
|
||||
}
|
||||
|
||||
// InterfaceSlice convert param to slice of interface.
|
||||
@@ -402,12 +439,12 @@ func InterfaceSlice(slice any) []any {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := make([]any, sv.Len())
|
||||
result := make([]any, sv.Len())
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
res[i] = sv.Index(i).Interface()
|
||||
result[i] = sv.Index(i).Interface()
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// StringSlice convert param to slice of string.
|
||||
@@ -464,7 +501,7 @@ func DeleteAt[T any](slice []T, start int, end ...int) []T {
|
||||
}
|
||||
|
||||
if start == size-1 {
|
||||
slice = append(slice[:start])
|
||||
slice = slice[:start]
|
||||
} else {
|
||||
slice = append(slice[:start], slice[start+1:]...)
|
||||
}
|
||||
@@ -499,13 +536,11 @@ func InsertAt[T any](slice []T, index int, value any) []T {
|
||||
return slice
|
||||
}
|
||||
|
||||
// value is T
|
||||
if v, ok := value.(T); ok {
|
||||
slice = append(slice[:index], append([]T{v}, slice[index:]...)...)
|
||||
return slice
|
||||
}
|
||||
|
||||
// value is []T
|
||||
if v, ok := value.([]T); ok {
|
||||
slice = append(slice[:index], append(v, slice[index:]...)...)
|
||||
return slice
|
||||
@@ -527,50 +562,75 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
|
||||
}
|
||||
|
||||
// Unique remove duplicate elements in slice.
|
||||
func Unique[T any](slice []T) []T {
|
||||
if len(slice) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
func Unique[T comparable](slice []T) []T {
|
||||
result := []T{}
|
||||
|
||||
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
|
||||
var res []T
|
||||
for i := 0; i < len(slice); i++ {
|
||||
v := slice[i]
|
||||
skip := true
|
||||
for j := range res {
|
||||
if reflect.DeepEqual(v, res[j]) {
|
||||
for j := range result {
|
||||
if v == result[j] {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
|
||||
func Union[T any](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
|
||||
result := []T{}
|
||||
|
||||
for _, v := range slice {
|
||||
val := iteratee(v)
|
||||
result = append(result, val)
|
||||
}
|
||||
|
||||
// append all slices, then unique it
|
||||
var allElements []T
|
||||
return Unique(result)
|
||||
}
|
||||
|
||||
// Union creates a slice of unique values, in order, from all given slices.
|
||||
func Union[T comparable](slices ...[]T) []T {
|
||||
result := []T{}
|
||||
contain := map[T]struct{}{}
|
||||
|
||||
for _, slice := range slices {
|
||||
for _, v := range slice {
|
||||
allElements = append(allElements, v)
|
||||
for _, item := range slice {
|
||||
if _, ok := contain[item]; !ok {
|
||||
contain[item] = struct{}{}
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Unique(allElements)
|
||||
return result
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Intersection creates a slice of unique values that included by all slices.
|
||||
func Intersection[T any](slices ...[]T) []T {
|
||||
func Intersection[T comparable](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -578,32 +638,36 @@ func Intersection[T any](slices ...[]T) []T {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
var res []T
|
||||
reducer := func(sliceA, sliceB []T) []T {
|
||||
hashMap := make(map[T]int)
|
||||
for _, val := range sliceA {
|
||||
hashMap[val] = 1
|
||||
}
|
||||
|
||||
reducer := func(s1, s2 []T) []T {
|
||||
s := make([]T, 0, 0)
|
||||
for _, v := range s1 {
|
||||
if Contain(s2, v) {
|
||||
s = append(s, v)
|
||||
out := make([]T, 0)
|
||||
for _, val := range sliceB {
|
||||
if v, ok := hashMap[val]; v == 1 && ok {
|
||||
out = append(out, val)
|
||||
hashMap[val]++
|
||||
}
|
||||
}
|
||||
return s
|
||||
return out
|
||||
}
|
||||
|
||||
res = 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++ {
|
||||
reduceSlice[0] = res
|
||||
reduceSlice[0] = result
|
||||
reduceSlice[1] = slices[i]
|
||||
res = reducer(reduceSlice[0], reduceSlice[1])
|
||||
result = reducer(reduceSlice[0], reduceSlice[1])
|
||||
}
|
||||
|
||||
return Unique(res)
|
||||
return result
|
||||
}
|
||||
|
||||
// SymmetricDifference oppoiste operation of intersection function
|
||||
func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
func SymmetricDifference[T comparable](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -611,7 +675,7 @@ func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
res := make([]T, 0)
|
||||
result := make([]T, 0)
|
||||
|
||||
intersectSlice := Intersection(slices...)
|
||||
|
||||
@@ -619,13 +683,13 @@ func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
slice := slices[i]
|
||||
for _, v := range slice {
|
||||
if !Contain(intersectSlice, v) {
|
||||
res = append(res, v)
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Unique(res)
|
||||
return Unique(result)
|
||||
}
|
||||
|
||||
// Reverse return slice of element order is reversed to the given slice
|
||||
@@ -637,13 +701,12 @@ func Reverse[T any](slice []T) {
|
||||
|
||||
// Shuffle creates an slice of shuffled values
|
||||
func Shuffle[T any](slice []T) []T {
|
||||
|
||||
res := make([]T, len(slice))
|
||||
result := make([]T, len(slice))
|
||||
for i, v := range rand.Perm(len(slice)) {
|
||||
res[i] = slice[v]
|
||||
result[i] = slice[v]
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// SortByField return sorted slice by field
|
||||
@@ -719,26 +782,26 @@ func SortByField(slice any, field string, sortType ...string) error {
|
||||
}
|
||||
|
||||
// Without creates a slice excluding all given values
|
||||
func Without[T any](slice []T, values ...T) []T {
|
||||
func Without[T comparable](slice []T, values ...T) []T {
|
||||
if len(values) == 0 || len(slice) == 0 {
|
||||
return slice
|
||||
}
|
||||
|
||||
out := make([]T, 0, len(slice))
|
||||
result := make([]T, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
if !Contain(values, 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
|
||||
// if the value cannot be found.
|
||||
func IndexOf[T any](slice []T, value T) int {
|
||||
func IndexOf[T comparable](slice []T, value T) int {
|
||||
for i, v := range slice {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
if v == value {
|
||||
return i
|
||||
}
|
||||
}
|
||||
@@ -748,12 +811,50 @@ func IndexOf[T any](slice []T, value T) int {
|
||||
|
||||
// LastIndexOf returns the index at which the last occurrence of a value is found in a slice or return -1
|
||||
// if the value cannot be found.
|
||||
func LastIndexOf[T any](slice []T, value T) int {
|
||||
func LastIndexOf[T comparable](slice []T, value T) int {
|
||||
for i := len(slice) - 1; i > 0; i-- {
|
||||
if reflect.DeepEqual(value, slice[i]) {
|
||||
if value == slice[i] {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
|
||||
func ToSlicePointer[T any](value ...T) []*T {
|
||||
result := make([]*T, len(value))
|
||||
for i := range value {
|
||||
result[i] = &value[i]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ToSlice returns a slices of a variable parameter transformation
|
||||
func ToSlice[T any](value ...T) []T {
|
||||
result := make([]T, len(value))
|
||||
copy(result, value)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// AppendIfAbsent only absent append the value
|
||||
func AppendIfAbsent[T comparable](slice []T, value T) []T {
|
||||
if !Contain(slice, value) {
|
||||
slice = append(slice, value)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -14,45 +14,6 @@ func sliceValue(slice any) reflect.Value {
|
||||
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
|
||||
func sliceElemType(reflectType reflect.Type) reflect.Type {
|
||||
for {
|
||||
|
||||
@@ -61,11 +61,39 @@ func TestCompact(t *testing.T) {
|
||||
func TestConcat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "Concat")
|
||||
|
||||
// assert.Equal([]int{0}, Concat([]int{}, 0))
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, 4, 5))
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4, 5}))
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, []int{5}))
|
||||
// assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, 5))
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{1, 2, 3}
|
||||
slice3 := []int{3, 2, 1}
|
||||
|
||||
assert.Equal(true, Equal(slice1, slice2))
|
||||
assert.Equal(false, Equal(slice1, slice3))
|
||||
}
|
||||
|
||||
// go test -fuzz=Fuzz -fuzztime=10s .
|
||||
func FuzzEqual(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, a, b []byte) {
|
||||
Equal(a, b)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEqualWith(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEqualWith")
|
||||
|
||||
slice1 := []int{1, 2, 3}
|
||||
slice2 := []int{2, 4, 6}
|
||||
|
||||
isDouble := func(a, b int) bool {
|
||||
return b == a*2
|
||||
}
|
||||
|
||||
assert.Equal(true, EqualWith(slice1, slice2, isDouble))
|
||||
}
|
||||
|
||||
func TestEvery(t *testing.T) {
|
||||
@@ -208,6 +236,14 @@ func TestFindFoundNothing(t *testing.T) {
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestFlatten(t *testing.T) {
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := [][]string{{"a", "b"}, {"c", "d"}}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFlattenDeep")
|
||||
assert.Equal(expected, Flatten(input))
|
||||
}
|
||||
|
||||
func TestFlattenDeep(t *testing.T) {
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := []string{"a", "b", "c", "d"}
|
||||
@@ -371,6 +407,15 @@ func TestUnique(t *testing.T) {
|
||||
assert.Equal([]string{"a", "b", "c"}, Unique([]string{"a", "a", "b", "c"}))
|
||||
}
|
||||
|
||||
func TestUniqueBy(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUniqueBy")
|
||||
|
||||
actual := UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
|
||||
return val % 4
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 0}, actual)
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUnion")
|
||||
|
||||
@@ -383,6 +428,17 @@ func TestUnion(t *testing.T) {
|
||||
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 TestIntersection(t *testing.T) {
|
||||
s1 := []int{1, 2, 2, 3}
|
||||
s2 := []int{1, 2, 3, 4}
|
||||
@@ -546,3 +602,66 @@ func TestLastIndexOf(t *testing.T) {
|
||||
assert.Equal(1, LastIndexOf(arr, "a"))
|
||||
assert.Equal(-1, LastIndexOf(arr, "d"))
|
||||
}
|
||||
|
||||
func TestToSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToSlice")
|
||||
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
assert.Equal([]string{"a"}, ToSlice(str1))
|
||||
assert.Equal([]string{"a", "b"}, ToSlice(str1, str2))
|
||||
}
|
||||
|
||||
func TestToSlicePointer(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToSlicePointer")
|
||||
|
||||
str1 := "a"
|
||||
str2 := "b"
|
||||
assert.Equal([]*string{&str1}, ToSlicePointer(str1))
|
||||
assert.Equal([]*string{&str1, &str2}, ToSlicePointer(str1, str2))
|
||||
}
|
||||
|
||||
func TestAppendIfAbsent(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAppendIfAbsent")
|
||||
|
||||
str1 := []string{"a", "b"}
|
||||
assert.Equal([]string{"a", "b"}, AppendIfAbsent(str1, "a"))
|
||||
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"})
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func CamelCase(s string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
res := ""
|
||||
result := ""
|
||||
blankSpace := " "
|
||||
regex, _ := regexp.Compile("[-_&]+")
|
||||
ss := regex.ReplaceAllString(s, blankSpace)
|
||||
@@ -26,13 +26,13 @@ func CamelCase(s string) string {
|
||||
if vv[i] >= 65 && vv[i] <= 96 {
|
||||
vv[0] += 32
|
||||
}
|
||||
res += string(vv)
|
||||
result += string(vv)
|
||||
} else {
|
||||
res += Capitalize(v)
|
||||
result += Capitalize(v)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
|
||||
@@ -126,15 +126,15 @@ func KebabCase(s string) string {
|
||||
match := regex.ReplaceAllString(s, blankSpace)
|
||||
rs := strings.Split(match, blankSpace)
|
||||
|
||||
var res []string
|
||||
var result []string
|
||||
for _, v := range rs {
|
||||
splitWords := splitWordsToLower(v)
|
||||
if len(splitWords) > 0 {
|
||||
res = append(res, splitWords...)
|
||||
result = append(result, splitWords...)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(res, "-")
|
||||
return strings.Join(result, "-")
|
||||
}
|
||||
|
||||
// SnakeCase covert string to snake_case
|
||||
@@ -148,15 +148,15 @@ func SnakeCase(s string) string {
|
||||
match := regex.ReplaceAllString(s, blankSpace)
|
||||
rs := strings.Split(match, blankSpace)
|
||||
|
||||
var res []string
|
||||
var result []string
|
||||
for _, v := range rs {
|
||||
splitWords := splitWordsToLower(v)
|
||||
if len(splitWords) > 0 {
|
||||
res = append(res, splitWords...)
|
||||
result = append(result, splitWords...)
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(res, "_")
|
||||
return strings.Join(result, "_")
|
||||
}
|
||||
|
||||
// Before create substring in source string before position when char first appear
|
||||
@@ -208,8 +208,8 @@ func IsString(v any) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// ReverseStr return string whose char order is reversed to the given string
|
||||
func ReverseStr(s string) string {
|
||||
// Reverse return string whose char order is reversed to the given string
|
||||
func Reverse(s string) string {
|
||||
r := []rune(s)
|
||||
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
|
||||
@@ -4,37 +4,37 @@ import "strings"
|
||||
|
||||
// splitWordsToLower split a string into worlds by uppercase char
|
||||
func splitWordsToLower(s string) []string {
|
||||
var res []string
|
||||
var result []string
|
||||
|
||||
upperIndexes := upperIndex(s)
|
||||
l := len(upperIndexes)
|
||||
if upperIndexes == nil || l == 0 {
|
||||
if s != "" {
|
||||
res = append(res, s)
|
||||
result = append(result, s)
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
if i < l-1 {
|
||||
res = append(res, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
|
||||
result = append(result, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
|
||||
} else {
|
||||
res = append(res, strings.ToLower(s[upperIndexes[i]:]))
|
||||
result = append(result, strings.ToLower(s[upperIndexes[i]:]))
|
||||
}
|
||||
}
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
// upperIndex get a int slice which elements are all the uppercase char index of a string
|
||||
func upperIndex(s string) []int {
|
||||
var res []int
|
||||
var result []int
|
||||
for i := 0; i < len(s); i++ {
|
||||
if 64 < s[i] && s[i] < 91 {
|
||||
res = append(res, i)
|
||||
result = append(result, i)
|
||||
}
|
||||
}
|
||||
if len(s) > 0 && res != nil && res[0] != 0 {
|
||||
res = append([]int{0}, res...)
|
||||
if len(s) > 0 && result != nil && result[0] != 0 {
|
||||
result = append([]int{0}, result...)
|
||||
}
|
||||
|
||||
return res
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -143,11 +143,11 @@ func TestIsString(t *testing.T) {
|
||||
assert.Equal(false, IsString([]string{}))
|
||||
}
|
||||
|
||||
func TestReverseStr(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReverseStr")
|
||||
func TestReverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReverse")
|
||||
|
||||
assert.Equal("cba", ReverseStr("abc"))
|
||||
assert.Equal("54321", ReverseStr("12345"))
|
||||
assert.Equal("cba", Reverse("abc"))
|
||||
assert.Equal("54321", Reverse("12345"))
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
|
||||
@@ -70,3 +70,9 @@ func ExecCommand(command string) (stdout, stderr string, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetOsBits get this system bits 32bit or 64bit
|
||||
// return bit int (32/64)
|
||||
func GetOsBits() int {
|
||||
return 32 << (^uint(0) >> 63)
|
||||
}
|
||||
|
||||
@@ -60,3 +60,13 @@ func TestExecCommand(t *testing.T) {
|
||||
assert.IsNotNil(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOsBits(t *testing.T) {
|
||||
osBits := GetOsBits()
|
||||
switch osBits {
|
||||
case 32, 64:
|
||||
t.Logf("os is %d", osBits)
|
||||
default:
|
||||
t.Error("os is not 32 or 64 bits")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -253,3 +254,32 @@ func IsWeakPassword(password string) bool {
|
||||
|
||||
return (num || letter) && !special
|
||||
}
|
||||
|
||||
// IsZeroValue checks if value is a zero value
|
||||
func IsZeroValue(value any) bool {
|
||||
if value == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(value)
|
||||
if !rv.IsValid() {
|
||||
return true
|
||||
}
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.String:
|
||||
return rv.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return rv.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return rv.Float() == 0
|
||||
case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Interface, reflect.Slice, reflect.Map:
|
||||
return rv.IsNil()
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(rv.Interface(), reflect.Zero(rv.Type()).Interface())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
@@ -279,3 +281,110 @@ func TestIsWeakPassword(t *testing.T) {
|
||||
assert.Equal(true, IsWeakPassword("abcABC123"))
|
||||
assert.Equal(false, IsWeakPassword("abc123@#$"))
|
||||
}
|
||||
|
||||
func TestIsZeroValue(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsZeroValue")
|
||||
|
||||
var (
|
||||
zeroPtr *string
|
||||
zeroSlice []int
|
||||
zeroFunc func() string
|
||||
zeroMap map[string]string
|
||||
nilIface interface{}
|
||||
zeroIface fmt.Formatter
|
||||
)
|
||||
zeroValues := []interface{}{
|
||||
nil,
|
||||
false,
|
||||
0,
|
||||
int8(0),
|
||||
int16(0),
|
||||
int32(0),
|
||||
int64(0),
|
||||
uint(0),
|
||||
uint8(0),
|
||||
uint16(0),
|
||||
uint32(0),
|
||||
uint64(0),
|
||||
|
||||
0.0,
|
||||
float32(0.0),
|
||||
float64(0.0),
|
||||
|
||||
"",
|
||||
|
||||
// func
|
||||
zeroFunc,
|
||||
|
||||
// array / slice
|
||||
[0]int{},
|
||||
zeroSlice,
|
||||
|
||||
// map
|
||||
zeroMap,
|
||||
|
||||
// interface
|
||||
nilIface,
|
||||
zeroIface,
|
||||
|
||||
// pointer
|
||||
zeroPtr,
|
||||
|
||||
// struct
|
||||
time.Time{},
|
||||
}
|
||||
|
||||
for _, value := range zeroValues {
|
||||
assert.Equal(true, IsZeroValue(value))
|
||||
}
|
||||
|
||||
var nonZeroIface fmt.Stringer = time.Now()
|
||||
|
||||
nonZeroValues := []interface{}{
|
||||
// bool
|
||||
true,
|
||||
|
||||
// int
|
||||
1,
|
||||
int8(1),
|
||||
int16(1),
|
||||
int32(1),
|
||||
int64(1),
|
||||
uint8(1),
|
||||
uint16(1),
|
||||
uint32(1),
|
||||
uint64(1),
|
||||
|
||||
// float
|
||||
1.0,
|
||||
float32(1.0),
|
||||
float64(1.0),
|
||||
|
||||
// string
|
||||
"test",
|
||||
|
||||
// func
|
||||
time.Now,
|
||||
|
||||
// array / slice
|
||||
[]int{},
|
||||
[]int{42},
|
||||
[1]int{42},
|
||||
|
||||
// map
|
||||
make(map[string]string, 1),
|
||||
|
||||
// interface
|
||||
nonZeroIface,
|
||||
|
||||
// pointer
|
||||
&nonZeroIface,
|
||||
|
||||
// struct
|
||||
time.Now(),
|
||||
}
|
||||
|
||||
for _, value := range nonZeroValues {
|
||||
assert.Equal(false, IsZeroValue(value))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user