1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-05 05:12:26 +08:00

Compare commits

..

57 Commits

Author SHA1 Message Date
dudaodong
2b17329094 release v2.1.10 2022-11-17 16:11:48 +08:00
dudaodong
f869a0a670 fix: issue#62: fix ZipSlip bug 2022-11-16 16:04:38 +08:00
dudaodong
be000a4bd6 fix: issue#62: fix ZipSlip bug 2022-11-16 15:08:42 +08:00
DuDaoDong
81efa800ea Create SECURITY.md 2022-11-16 11:31:50 +08:00
dudaodong
a783de57a8 release v2.1.9 2022-11-08 15:22:37 +08:00
dudaodong
a622959a78 docs: add new functions readme 2022-11-08 15:21:31 +08:00
dudaodong
f709dd53ce docs: update doc for random package 2022-11-08 14:48:02 +08:00
dudaodong
ee9e9625e2 docs: add doc for UnionBy and KeyBy 2022-11-08 14:21:17 +08:00
dudaodong
84da7d4f27 feat: add RandUpper, RandLower, RandNumeral, and RandNumeralOrLetter 2022-11-06 20:04:52 +08:00
dudaodong
089fd4e13c feat: add UnionBy for slice 2022-11-05 19:45:34 +08:00
dudaodong
6c40e02324 refactor: clean code 2022-11-05 19:33:56 +08:00
dudaodong
a270b1b634 feat: make code clear 2022-11-05 17:09:56 +08:00
dudaodong
260fb795d3 feat: add KeyBy for slice 2022-11-05 16:52:31 +08:00
dudaodong
8c036f830c refactor: remove unuseful code 2022-11-05 16:39:42 +08:00
dudaodong
bf332b9f1c release v2.1.8 2022-10-21 16:22:52 +08:00
dudaodong
6b6cd66f9f Merge branch 'main' into v2 2022-10-19 17:31:51 +08:00
燕归来
5399c2290e feat: support type alias for Number constraint (#60) 2022-10-19 17:21:53 +08:00
dudaodong
6248293c49 doc: add docment for Replace and ReplaceAll 2022-10-17 10:40:35 +08:00
dudaodong
eced25b76d test: add unit test for Replace and ReplaceAll 2022-10-17 10:26:54 +08:00
dudaodong
96a4327aa7 fix: fix some static check issues 2022-10-15 15:03:24 +08:00
dudaodong
fcfbdea597 feat: add Replace and ReplaceAll for slice 2022-10-15 14:49:49 +08:00
dudaodong
87896f917a doc: add document for pipeline 2022-10-15 12:36:11 +08:00
dudaodong
b8563ed646 feat: add Pipeline function 2022-10-15 12:29:47 +08:00
dudaodong
1ccf0af2b3 doc: update document for datetime package 2022-10-14 10:20:38 +08:00
dudaodong
6314889c6a release v2.1.7 2022-10-14 10:08:43 +08:00
dudaodong
294bd5a5ed doc: update document for hashmap 2022-10-11 15:41:09 +08:00
dudaodong
ca44815fd5 Merge branch 'main' into v2 2022-10-11 15:02:28 +08:00
dudaodong
bcd1cabf80 feat: add Keys and Values function for hashmap 2022-10-10 16:34:05 +08:00
CyJaySong
4edefcca67 expand BeginOfWeek、EndOfWeek (#59) 2022-10-10 15:44:22 +08:00
dudaodong
fab24c8d12 feat: add Iterate for hashmap datastructure 2022-10-10 15:25:30 +08:00
dudaodong
604acd9b07 doc:add lancet api doc website 2022-09-29 18:41:22 +08:00
dudaodong
531cb19fd1 release v2.1.6 2022-08-31 17:07:32 +08:00
dudaodong
4f0161ca53 doc: add source code link for http_client 2022-08-31 15:56:41 +08:00
dudaodong
73362b7f69 doc: update readme file 2022-08-31 11:40:24 +08:00
dudaodong
b289f2975b doc: add document for functions in netutil/http_client.go 2022-08-31 11:20:22 +08:00
dudaodong
90ce2705ca test: add unit test for http client 2022-08-30 17:33:58 +08:00
dudaodong
35e1d09ce3 feat: add http client for sending http request 2022-08-30 17:22:17 +08:00
dudaodong
d67d8fad3a doc: fix missing word in file condition.md 2022-08-29 14:02:30 +08:00
dudaodong
c5e6d01a31 update readme file: add new package and function 2022-08-29 11:50:37 +08:00
dudaodong
6d6c3f692f refactor: change TernaryOperator signature 2022-08-29 11:27:51 +08:00
dudaodong
c695837b16 doc: add document for package condition 2022-08-29 11:23:02 +08:00
dudaodong
ef28b52963 fix: fix regex isChineseMobileRegexMatcher not work 2022-08-28 20:58:34 +08:00
dudaodong
18b2b6ff7c feat: add functons: And, Or, Xor, Nor, Xnor, Nand 2022-08-28 20:57:28 +08:00
dudaodong
6a05a123f4 feat: add Bool function to check if a value is truthy or falsy 2022-08-28 20:38:19 +08:00
dudaodong
f7c33f258d Merge branch 'main' into v2 2022-08-27 19:25:24 +08:00
dudaodong
04058dd7da refactor: change common package to condition package 2022-08-27 19:19:34 +08:00
郑一诺她爸
72e1d92fa1 TernaryOperator Reduce if else operations (#56)
* feat:(slice add AppendIfAbsent function)

* feat:(slice add TernaryOperator function)

Co-authored-by: george.zheng <george.zheng@ambergroup.io>
2022-08-27 19:12:03 +08:00
dudaodong
063df0f0d1 doc: add docment for IsZeroValue function 2022-08-27 19:04:57 +08:00
dudaodong
fc10689b25 feat: add IsZeroValue function 2022-08-27 18:57:45 +08:00
dudaodong
9239bcfdc3 doc: fmt code example 2022-08-26 16:34:20 +08:00
dudaodong
c984815dea doc: fmt code example 2022-08-26 16:29:55 +08:00
dudaodong
301cb5db87 doc: add hashmap 2022-08-26 16:26:16 +08:00
dudaodong
cc1bacff74 doc: add document for EncodeByte and DecodeByte 2022-08-26 10:54:51 +08:00
dudaodong
f49f75b371 test: add unit test for EncodeByte and DecodeByte 2022-08-26 10:47:25 +08:00
dudaodong
b30f4a7bab feat: add DecodeByte 2022-08-26 10:35:54 +08:00
dudaodong
982cb8932b feat: add EncodeByte 2022-08-26 10:34:42 +08:00
dudaodong
9107eb4b32 fix: fix resize bug in HashMap 2022-08-25 14:04:26 +08:00
45 changed files with 4071 additions and 1168 deletions

663
README.md
View File

@@ -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/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.5-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.1.10-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](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.3.1. </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.3.1 // 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
@@ -69,147 +73,170 @@ func main() {
## 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)
- [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)
### 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"
@@ -219,18 +246,21 @@ 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)
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.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"
@@ -238,226 +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)
- [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)
- [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)
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)
### 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)
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.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_zh-CN.md#IsInternalIP)
- [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:
- [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)
- [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)
- [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)
- [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)
### 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)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
### 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"
@@ -465,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

View File

@@ -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/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.5-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.1.10-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](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.3.1。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.4。</b>
```go
go get github.com/duke-git/lancet@v1.3.1 // 使用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"
## 例子
此处以字符串工具函数Reverse逆序字符串为例需要导入strutil包:
此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包:
```go
package main
@@ -67,146 +70,172 @@ func main() {
}
```
## 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)
- [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)
### 4. cryptor加密包支持数据加密和解密获取md5hash值。支持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 加密包支持数据加密和解密,获取 md5hash 值。支持 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"
@@ -216,18 +245,21 @@ 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)
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.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"
@@ -235,183 +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)
- [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)
- [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)
- [IsDisjoint](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)
### 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)
- [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)
- [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"
```
#### 函数列表:
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)
- [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)
- [Flatten](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
- [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SymmetricDifference)
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlicePointer)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)
- [Compact](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Compact)
- [Concat](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Concat)
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
- [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"
@@ -419,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)
- [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)
- [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)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsBits)
### 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)
### 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
View 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.

77
condition/condition.go Normal file
View 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
View 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))
}

View File

@@ -7,6 +7,7 @@ package convertor
import (
"bytes"
"encoding/binary"
"encoding/gob"
"encoding/json"
"fmt"
"math"
@@ -270,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)
}

View File

@@ -238,3 +238,21 @@ func TestToPointer(t *testing.T) {
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)
}

View File

@@ -93,11 +93,53 @@ func (hm *HashMap) Contains(key any) bool {
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 {

View File

@@ -19,6 +19,18 @@ func TestHashMap_PutAndGet(t *testing.T) {
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")
@@ -40,3 +52,20 @@ func TestHashMap_Contains(t *testing.T) {
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))
}

View File

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

264
docs/condition.md Normal file
View 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
View 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相同返回falsea和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"
}
```

View File

@@ -34,6 +34,8 @@ import (
- [ToString](#ToString)
- [StructToMap](#StructToMap)
- [MapToSlice](#MapToSlice)
- [EncodeByte](#EncodeByte)
- [DecodeByte](#DecodeByte)
<div STYLE="page-break-after: always;"></div>
@@ -457,4 +459,59 @@ func main() {
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"
}
```

View File

@@ -36,6 +36,8 @@ import (
- [ToString](#ToString)
- [StructToMap](#StructToMap)
- [MapToSlice](#MapToSlice)
- [EncodeByte](#EncodeByte)
- [DecodeByte](#DecodeByte)
<div STYLE="page-break-after: always;"></div>
@@ -489,3 +491,59 @@ func main() {
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"
}
```

View File

@@ -20,6 +20,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [NewHashMap](#NewHashMap)
@@ -28,6 +29,9 @@ import (
- [Put](#Put)
- [Delete](#Delete)
- [Contains](#Contains)
- [Iterate](#Iterate)
- [Keys](#Keys)
- [Values](#Values)
<div STYLE="page-break-after: always;"></div>
@@ -106,8 +110,8 @@ import (
)
func main() {
hm := heap.NewHashMap()
val := hm.Get("a")
hm := heap.NewHashMap()
val := hm.Get("a")
fmt.Println(val) //nil
}
@@ -134,10 +138,10 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
val := hm.Get("a")
fmt.Println(val) //1
}
```
@@ -165,13 +169,13 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
fmt.Println(val) //1
hm.Delete("a")
val = hm.Get("a")
hm.Delete("a")
val = hm.Get("a")
fmt.Println(val) //nil
}
```
@@ -199,10 +203,112 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
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}
}
```

View File

@@ -22,17 +22,15 @@ import (
## 目录
- [HashMap](#hashmap)
- [源码](#源码)
- [用法](#用法)
- [目录](#目录)
- [API 文档](#api-文档)
- [<span id="NewHashMap">NewHashMap</span>](#newhashmap)
- [<span id="NewHashMapWithCapacity">NewHashMapWithCapacity</span>](#newhashmapwithcapacity)
- [<span id="Get">Get</span>](#get)
- [<span id="Put">Put</span>](#put)
- [<span id="Delete">Delete</span>](#delete)
- [<span id="Contains">Contains</span>](#contains)
- [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>
@@ -111,8 +109,8 @@ import (
)
func main() {
hm := heap.NewHashMap()
val := hm.Get("a")
hm := heap.NewHashMap()
val := hm.Get("a")
fmt.Println(val) //nil
}
@@ -139,10 +137,10 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
val := hm.Get("a")
fmt.Println(val) //1
}
```
@@ -168,13 +166,13 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
hm := heap.NewHashMap()
hm.Put("a", 1)
val := hm.Get("a")
fmt.Println(val) //1
hm.Delete("a")
val = hm.Get("a")
hm.Delete("a")
val = hm.Get("a")
fmt.Println(val) //nil
}
```
@@ -200,10 +198,111 @@ import (
)
func main() {
hm := heap.NewHashMap()
hm.Put("a", 1)
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}
}
```

View File

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

View File

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

View File

@@ -26,6 +26,7 @@ import (
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
- [Pipeline](#Pipeline)
- [Watcher](#Watcher)
<div STYLE="page-break-after: always;"></div>
@@ -300,6 +301,43 @@ func main() {
```
### <span id="Pipeline">Pipeline</span>
<p>Pipeline takes a list of functions and returns a function whose param will be passed into
the functions one by one.</p>
<b>Signature:</b>
```go
func Pipeline[T any](funcs ...func(T) T) func(T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
addOne := func(x int) int {
return x + 1
}
double := func(x int) int {
return 2 * x
}
square := func(x int) int {
return x * x
}
f := Pipeline(addOne, double, square)
fmt.Println(f(2)) //36
}
```
### <span id="Watcher">Watcher</span>

View File

@@ -26,6 +26,7 @@ import (
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
- [Pipeline](#Pipeline)
- [Watcher](#Watcher)
<div STYLE="page-break-after: always;"></div>
@@ -300,6 +301,44 @@ func main() {
### <span id="Pipeline">Pipeline</span>
<p>执行函数pipeline.</p>
<b>函数签名:</b>
```go
func Pipeline[T any](funcs ...func(T) T) func(T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
addOne := func(x int) int {
return x + 1
}
double := func(x int) int {
return 2 * x
}
square := func(x int) int {
return x * x
}
f := Pipeline(addOne, double, square)
fmt.Println(f(2)) //36
}
```
### <span id="Watcher">Watcher</span>
<p>Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。 </p>

View File

@@ -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>
@@ -31,11 +33,17 @@ import (
- [GetRequestPublicIp](#GetRequestPublicIp)
- [IsPublicIP](#IsPublicIP)
- [IsInternalIP](#IsInternalIP)
- [HttpGet](#HttpGet)
- [HttpDelete](#HttpDelete)
- [HttpPost](#HttpPost)
- [HttpPut](#HttpPut)
- [HttpPatch](#HttpPatch)
- [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)
- [ParseHttpResponse](#ParseHttpResponse)
<div STYLE="page-break-after: always;"></div>
@@ -335,8 +343,232 @@ func main() {
```
### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest is a struct used to abstract HTTP request entity.</p>
### <span id="HttpGet">HttpGet</span>
<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>
@@ -378,7 +610,7 @@ 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>
@@ -427,7 +659,7 @@ 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>
@@ -477,7 +709,7 @@ 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>
@@ -516,7 +748,7 @@ 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>

View File

@@ -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>
@@ -30,11 +33,18 @@ import (
- [IsPublicIP](#IsPublicIP)
- [IsInternalIP](#IsInternalIP)
- [HttpGet](#HttpGet)
- [HttpDelete](#HttpDelete)
- [HttpPost](#HttpPost)
- [HttpPut](#HttpPut)
- [HttpPatch](#HttpPatch)
- [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)
- [ParseHttpResponse](#ParseHttpResponse)
<div STYLE="page-break-after: always;"></div>
@@ -334,8 +344,232 @@ func main() {
```
### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest用于抽象HTTP请求实体的结构</p>
### <span id="HttpGet">HttpGet</span>
<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>
@@ -377,7 +611,7 @@ func main() {
### <span id="HttpPost">HttpPost</span>
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>发送http post请求</p>
<b>函数签名:</b>
@@ -426,7 +660,7 @@ func main() {
### <span id="HttpPut">HttpPut</span>
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>发送http put请求</p>
<b>函数签名:</b>
@@ -438,7 +672,7 @@ func main() {
// params[3] http client类型必须是http.Client
func HttpPut(url string, params ...any) (*http.Response, error)
```
<b>Example:</b>
<b>例子:</b>
```go
package main
@@ -476,7 +710,7 @@ func main() {
### <span id="HttpDelete">HttpDelete</span>
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>发送http delete请求</p>
<b>函数签名:</b>
@@ -515,7 +749,7 @@ func main() {
### <span id="HttpPatch">HttpPatch</span>
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>发送http patch请求</p>
<b>函数签名:</b>

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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 passwordonly letter or only number or letter + number
<p>Checks if the string is weak passwordonly 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
}
```

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,7 @@ import (
"archive/zip"
"bufio"
"errors"
"fmt"
"io"
"io/fs"
"io/ioutil"
@@ -213,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
@@ -221,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 {
@@ -249,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)

View File

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

View File

@@ -134,3 +134,21 @@ func TestSchedule(t *testing.T) {
// 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))
}

View File

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

View File

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

View File

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

228
netutil/http_client.go Normal file
View 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
}

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

View File

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

View File

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

View File

@@ -36,7 +36,7 @@ func ContainSubSlice[T comparable](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 result [][]T
result := [][]T{}
if len(slice) == 0 || size <= 0 {
return result
@@ -69,7 +69,7 @@ func Chunk[T any](slice []T, size int) [][]T {
// Compact creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey
func Compact[T any](slice []T) []T {
result := make([]T, 0, 0)
result := make([]T, 0)
for _, v := range slice {
if !reflect.DeepEqual(v, nil) &&
!reflect.DeepEqual(v, false) &&
@@ -95,7 +95,8 @@ func Concat[T any](slice []T, values ...[]T) []T {
// Difference creates an slice of whose element in slice but not in comparedSlice
func Difference[T comparable](slice, comparedSlice []T) []T {
var result []T
result := []T{}
for _, v := range slice {
if !Contain(comparedSlice, v) {
result = append(result, v)
@@ -112,7 +113,7 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
orginSliceAfterMap := Map(slice, iteratee)
comparedSliceAfterMap := Map(comparedSlice, iteratee)
result := make([]T, 0, 0)
result := make([]T, 0)
for i, v := range orginSliceAfterMap {
if !Contain(comparedSliceAfterMap, v) {
result = append(result, slice[i])
@@ -123,8 +124,8 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
}
//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 {
result := 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
@@ -180,11 +181,8 @@ func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) boo
// Every return true if all of the values in the slice pass the predicate function.
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++
@@ -196,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 {
@@ -212,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")
}
result := make([]T, 0, 0)
result := make([]T, 0)
for i, v := range slice {
if predicate(i, v) {
result = append(result, v)
}
}
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
}
@@ -261,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)
}
@@ -285,11 +267,7 @@ func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
}
// GroupWith return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
if iteratee == nil {
panic("iteratee func is missing")
}
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 {
@@ -306,10 +284,6 @@ func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T {
// Find iterates over elements of slice, returning the first one that passes a truth test on predicate function.
// 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
}
@@ -332,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
}
@@ -408,10 +378,6 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
// ForEach iterates over elements of slice and invokes function for each element
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)
}
@@ -419,10 +385,6 @@ 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")
}
result := make([]U, len(slice), cap(slice))
for i, v := range slice {
result[i] = iteratee(i, v)
@@ -433,9 +395,6 @@ func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U {
// Reduce creates an slice of values by running each element of slice thru iteratee function.
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
@@ -443,7 +402,7 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
result := iteratee(0, initial, slice[0])
tmp := make([]T, 2, 2)
tmp := make([]T, 2)
for i := 1; i < len(slice); i++ {
tmp[0] = result
tmp[1] = slice[i]
@@ -453,6 +412,26 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
return result
}
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new
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.
func InterfaceSlice(slice any) []any {
sv := sliceValue(slice)
@@ -522,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:]...)
}
@@ -584,12 +563,8 @@ func UpdateAt[T any](slice []T, index int, value T) []T {
// Unique remove duplicate elements in slice.
func Unique[T comparable](slice []T) []T {
if len(slice) == 0 {
return []T{}
}
result := []T{}
// here no use map filter. if use it, the result slice element order is random, not same as origin slice
var result []T
for i := 0; i < len(slice); i++ {
v := slice[i]
skip := true
@@ -609,11 +584,8 @@ func Unique[T comparable](slice []T) []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 {
if len(slice) == 0 {
return []T{}
}
result := []T{}
var result []T
for _, v := range slice {
val := iteratee(v)
result = append(result, val)
@@ -622,22 +594,39 @@ func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T {
return Unique(result)
}
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
// Union creates a slice of unique values, in order, from all given slices.
func Union[T comparable](slices ...[]T) []T {
if len(slices) == 0 {
return []T{}
}
// append all slices, then unique it
var allElements []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.
@@ -649,8 +638,6 @@ func Intersection[T comparable](slices ...[]T) []T {
return Unique(slices[0])
}
var result []T
reducer := func(sliceA, sliceB []T) []T {
hashMap := make(map[T]int)
for _, val := range sliceA {
@@ -667,9 +654,9 @@ func Intersection[T comparable](slices ...[]T) []T {
return out
}
result = reducer(slices[0], slices[1])
result := reducer(slices[0], slices[1])
reduceSlice := make([][]T, 2, 2)
reduceSlice := make([][]T, 2)
for i := 2; i < len(slices); i++ {
reduceSlice[0] = result
reduceSlice[1] = slices[i]
@@ -800,14 +787,14 @@ func Without[T comparable](slice []T, values ...T) []T {
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
@@ -836,20 +823,20 @@ func LastIndexOf[T comparable](slice []T, value T) int {
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
func ToSlicePointer[T any](value ...T) []*T {
out := make([]*T, len(value))
result := make([]*T, len(value))
for i := range value {
out[i] = &value[i]
result[i] = &value[i]
}
return out
return result
}
// ToSlice returns a slices of a variable parameter transformation
func ToSlice[T any](value ...T) []T {
out := make([]T, len(value))
for i := range value {
out[i] = value[i]
}
return out
result := make([]T, len(value))
copy(result, value)
return result
}
// AppendIfAbsent only absent append the value
@@ -859,3 +846,15 @@ func AppendIfAbsent[T comparable](slice []T, value T) []T {
}
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
}

View File

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

View File

@@ -428,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}
@@ -617,3 +628,40 @@ func TestAppendIfAbsent(t *testing.T) {
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"})
}

View File

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

View File

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