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

Compare commits

...

55 Commits

Author SHA1 Message Date
dudaodong
51f166d1d9 doc: update doc styles 2023-08-24 19:27:47 +08:00
dudaodong
fbeb031b40 doc: update doc 2023-08-24 19:07:24 +08:00
dudaodong
095cfc0aab doc: add new site for doc 2023-08-24 17:47:03 +08:00
ggymm
e66ab154bc fix: 覆盖写入字符串到文件问题 (#128) 2023-08-24 16:36:44 +08:00
dudaodong
91bc1a512c test: update TestZipFolder 2023-08-22 10:49:46 +08:00
dudaodong
8753255026 doc: update link in readme 2023-08-22 10:43:52 +08:00
dudaodong
9cf1f13fec doc: update link in readme 2023-08-22 10:39:37 +08:00
dudaodong
5d78bae4bb doc: update link in readme 2023-08-22 10:34:16 +08:00
dudaodong
27777eecc0 doc: update copyonwritelist doc 2023-08-22 10:26:39 +08:00
dudaodong
1a7e0e8792 doc: add copyonwritelist 2023-08-22 10:25:21 +08:00
dudaodong
02b7aa8f33 update version 2023-08-22 10:18:21 +08:00
dudaodong
f188d3d08f doc: add doc for InDelta 2023-08-21 11:05:11 +08:00
dudaodong
0c924b859e Merge branch 'main' into v2 2023-08-21 11:00:23 +08:00
warpmatrix
c5a5a07462 feat: InDelta (#127) 2023-08-15 09:53:16 +08:00
dudaodong
1ff5dd6df0 Merge branch 'main' into v2 2023-08-03 15:06:15 +08:00
Faucherwind
b5f86a488c feat: CopyOnWriteList adds more functions such as ForEach, Sort... (#126)
* feat: CopyOnWriteList adds more functions such as ForEach, Sort

* feat: CopyOnWriteList adds more functions such as ForEach, Sort
2023-08-03 15:05:30 +08:00
dudaodong
1390b7a964 fix: fix bug of Zip 2023-08-03 10:45:48 +08:00
dudaodong
c3e28a9fc0 fix: fix bug of Zip 2023-08-02 20:17:55 +08:00
dudaodong
e924429d6e fix: fix test case TestConcurrentMap_GetAndDelete 2023-08-02 11:33:27 +08:00
dudaodong
7079b1f704 format doc 2023-08-02 11:29:51 +08:00
Faucherwind
40cad365c0 feat: add CopyOnWriteList. A thread-safe list. (#125)
* fix: use loop to get value . On Get() and Contains()

* fix: Use reflect. DeepEqual() determines whether the keys are equal

* feat: add CopyOnWriteList. A thread-safe list.

* fix: fix failed unit test

* feat: add Equal() in CopyOnWriteList.

fix: update some function`s  names

* doc: add copyonwritelist.md and copyonwritelist_zh-CN.md
2023-08-02 11:10:10 +08:00
Faucherwind
6386ab908d fix: use loop to get value . On Get() and Contains() (#124)
* fix: use loop to get value . On Get() and Contains()

* fix: Use reflect. DeepEqual() determines whether the keys are equal
2023-08-01 11:14:45 +08:00
dudaodong
bb563724c7 doc: add go playground demo 2023-08-01 11:01:57 +08:00
dudaodong
72924d4486 release v2.2.4 2023-08-01 09:58:53 +08:00
dudaodong
231f8b04b4 doc: add new function doc for v2.2.4 2023-07-30 13:22:32 +08:00
dudaodong
daa932fee3 update: make IsWeekend deprecated 2023-07-30 12:47:00 +08:00
dudaodong
1b0691f1d5 Merge branch 'main' into v2 2023-07-30 12:41:03 +08:00
CyJaySong
0b6a00bd99 IsWeekend func Deprecated (#123)
* expand BeginOfWeek、EndOfWeek

* IsWeekend func Deprecated
2023-07-30 12:39:26 +08:00
dudaodong
4ab98664bb refactor: rename file name 2023-07-28 17:55:36 +08:00
dudaodong
31eb5f4d1f feat: add HmacMd5WithBase64 2023-07-28 17:53:46 +08:00
dudaodong
0ae5d17a06 doc: add doc for CurrentMap 2023-07-27 15:08:55 +08:00
dudaodong
4558d7a3c2 test: add test for currentmap 2023-07-27 11:54:52 +08:00
dudaodong
4715301240 doc: update doc for cryptor package 2023-07-27 11:20:06 +08:00
dudaodong
1c58ee23f1 feat: add Timestamp,TimestampMilli,TimestampMicro, TimestampNano 2023-07-26 17:28:15 +08:00
dudaodong
2a303d5e4b doc: update format 2023-07-26 15:28:20 +08:00
dudaodong
326e7881a6 feat: add NowDateOrTime 2023-07-26 15:03:59 +08:00
dudaodong
31e8b12674 feat: add timezone support for FormatTimeToStr and FormatStrToTime 2023-07-26 14:40:12 +08:00
dudaodong
a0431d9435 fix: fix TestConcurrentMap_Delete test failed 2023-07-25 10:21:11 +08:00
dudaodong
0456b65cc7 test: add example for cryptor package new functions 2023-07-25 10:18:54 +08:00
dudaodong
989b4dd791 test: add test for cryptor package new functions 2023-07-25 10:06:25 +08:00
dudaodong
a76b02fbba Merge branch 'main' into v2 2023-07-24 17:28:41 +08:00
hoslo
2d7747738a feat: add base cryptor method (#119)
Co-authored-by: shuai_yang <shuai_yang@intsig.net>
2023-07-24 17:24:17 +08:00
dudaodong
fe0cb04137 feat: add ConcurrentMap 2023-07-24 17:10:45 +08:00
dudaodong
fe0264f628 refactor: clean code 2023-07-24 15:42:36 +08:00
dudaodong
65396cee32 Merge branch 'main' into v2 2023-07-23 15:43:35 +08:00
Ta
544702b460 fix: remove unused message in pointer.md (#117) 2023-07-23 15:42:54 +08:00
dudaodong
d8936cdcb5 doc: add doc for pointer 2023-07-23 13:26:07 +08:00
dudaodong
d4b97d6b20 Merge branch 'main' into v2 2023-07-23 13:13:56 +08:00
Ta
5caa14c838 feat: add UnwarpOr and UnwarpOrDefault to pointer pkg (#116) 2023-07-23 13:09:50 +08:00
dudaodong
0d0848ac67 refactor: use for loop than for range 2023-07-10 10:56:53 +08:00
dudaodong
d5334f892f feat: add Join 2023-07-10 10:51:43 +08:00
dudaodong
36ef5b3bd3 doc: add doc for HasKey 2023-07-10 10:39:55 +08:00
dudaodong
6f48b00c88 feat: add HasKey 2023-07-10 10:33:04 +08:00
dudaodong
7b744c299e fix: fix bug of CreateDir 2023-07-10 10:13:23 +08:00
dudaodong
154ec56780 doc: add go playground demo 2023-07-04 16:31:13 +08:00
118 changed files with 7277 additions and 358 deletions

5
.gitignore vendored
View File

@@ -6,6 +6,9 @@ fileutil/*.txt
fileutil/*.zip
fileutil/*.link
fileutil/unzip/*
fileutil/tempdir/*
slice/testdata/*
cryptor/*.pem
test
test
docs/node_modules
docs/.vitepress/cache

236
README.md
View File

@@ -4,7 +4,7 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.2.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.2.5-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)
@@ -38,7 +38,7 @@ English | [简体中文](./README_zh-CN.md)
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. The latest of v1.x.x is v1.4.0. </b>
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.1. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
@@ -75,33 +75,34 @@ func main() {
### <span id="index">Index<span>
- [Algorithm](#Algorithm)
- [Compare](#Compare)
- [Concurrency](#Concurrency)
- [Condition](#Condition)
- [Convertor](#Convertor)
- [Cryptor](#Cryptor)
- [Datetime](#Datetime)
- [Datastructure](#Datastructure)
- [Fileutil](#Fileutil)
- [Formatter](#Formatter)
- [Function](#Function)
- [Maputil](#Maputil)
- [Mathutil](#Mathutil)
- [Netutil](#Netutil)
- [Pointer](#Pointer)
- [Random](#Random)
- [Retry](#Retry)
- [Slice](#Slice)
- [Stream](#Stream)
- [Structs](#Structs)
- [Strutil](#Strutil)
- [System](#System)
- [Tuple](#Tuple)
- [Validator](#Validator)
- [Xerror](#Xerror)
- [Algorithm](#user-content-algorithm)
- [Compare](#user-content-compare)
- [Concurrency](#user-content-concurrency)
- [Condition](#user-content-condition)
- [Convertor](#user-content-convertor)
- [Cryptor](#user-content-cryptor)
- [Datetime](#user-content-datetime)
- [Datastructure](#user-content-datastructure)
- [Fileutil](#user-content-fileutil)
- [Formatter](#user-content-formatter)
- [Function](#user-content-function)
- [Maputil](#user-content-maputil)
- [Mathutil](#user-content-mathutil)
- [Netutil](#user-content-netutil)
- [Pointer](#user-content-pointer)
- [Random](#user-content-random)
- [Retry](#user-content-retry)
- [Slice](#user-content-slice)
- [Stream](#user-content-stream)
- [Structs](#user-content-structs)
- [Strutil](#user-content-strutil)
- [System](#user-content-system)
- [Tuple](#user-content-tuple)
- [Validator](#user-content-validator)
- [Xerror](#user-content-xerror)
<h3 id="Algorithm"> 1. Algorithm package implements some basic algorithm. eg. sort, search. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
<h3 id="algorithm">1. Algorithm package implements some basic algorithm. eg. sort, search. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/algorithm"
@@ -146,7 +147,7 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
<h3 id="Compare"> 2. Compare package provides a lightweight comparison function on any type. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
<h3 id="compare"> 2. Compare package provides a lightweight comparison function on any type. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a> </h3>
```go
import "github.com/duke-git/lancet/v2/compare"
@@ -172,8 +173,10 @@ import "github.com/duke-git/lancet/v2/compare"
- **<big>GreaterOrEqual</big>** : Checks if value `left` less greater or equal than value `right`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
- **<big>InDelta</big>** : Checks if two values are equal or not within a delta.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#InDelta)]
<h3 id="Concurrency"> 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
<h3 id="concurrency"> 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a> </h3>
```go
import "github.com/duke-git/lancet/v2/concurrency"
@@ -212,7 +215,7 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)]
<h3 id="Condition"> 4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
<h3 id="condition"> 4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a> </h3>
```go
import "github.com/duke-git/lancet/v2/condition"
@@ -245,7 +248,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
<h3 id="Convertor"> 5. Convertor package contains some functions for data convertion. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
<h3 id="convertor"> 5. Convertor package contains some functions for data convertion. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a> </h3>
```go
import "github.com/duke-git/lancet/v2/convertor"
@@ -317,7 +320,7 @@ import "github.com/duke-git/lancet/v2/convertor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#GbkToUtf8)]
[[play](https://go.dev/play/p/OphmHCN_9u8)]
<h3 id="Cryptor"> 6. Cryptor package is for data encryption and decryption.</span> &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="cryptor"> 6. Cryptor package is for data encryption and decryption.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/cryptor"
@@ -388,29 +391,58 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>HmacMd5</big>** : return the md5 hmac hash of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>HmacMd5WithBase64</big>** : return the md5 hmac hash of base64 string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5WithBase64)]
- **<big>HmacSha1</big>** : return the hmac hash of string use sha1.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)]
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
- **<big>HmacSha1WithBase64</big>** : return the hmac hash of string use sha1 with base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1WithBase64)]
[[play](https://go.dev/play/p/47JmmGrnF7B)]
- **<big>HmacSha256</big>** : return the hmac hash of string use sha256.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)]
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
- **<big>HmacSha256WithBase64</big>** : return the hmac hash of string use sha256 with base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256WithBase64)]
[[play](https://go.dev/play/p/EKbkUvPTLwO)]
- **<big>HmacSha512</big>** : return the hmac hash of string use sha512.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)]
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
- **<big>HmacSha512WithBase64</big>** : return the hmac hash of string use sha512 with base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512WithBase64)]
[[play](https://go.dev/play/p/c6dSe3E2ydU)]
- **<big>Md5Byte</big>** : return the md5 string of byte slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5Byte)]
[[play](https://go.dev/play/p/suraalH8lyC)]
- **<big>Md5ByteWithBase64</big>** : return the md5 string of byte slice with base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5ByteWithBase64)]
[[play](https://go.dev/play/p/Tcb-Z7LN2ax)]
- **<big>Md5String</big>** : return the md5 value of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)]
[[play](https://go.dev/play/p/1bLcVetbTOI)]
- **<big>Md5StringWithBase64</big>** : return the md5 value of string with base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5StringWithBase64)]
[[play](https://go.dev/play/p/Lx4gH7Vdr5_y)]
- **<big>Md5File</big>** : return the md5 value of file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)]
- **<big>Sha1</big>** : return the sha1 value (SHA-1 hash algorithm) of string.
- **<big>Sha1</big>** : return the sha1 value (SHA-1 hash algorithm) of base64 string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)]
[[play](https://go.dev/play/p/_m_uoD1deMT)]
- **<big>Sha1WithBase64</big>** : return the sha1 value (SHA-1 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1WithBase64)]
[[play](https://go.dev/play/p/fSyx-Gl2l2-)]
- **<big>Sha256</big>** : return the sha256 value (SHA-256 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)]
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
- **<big>Sha256WithBase64</big>** : return the sha256 value (SHA256 hash algorithm) of base64 string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256WithBase64)]
[[play](https://go.dev/play/p/85IXJHIal1k)]
- **<big>Sha512</big>** : return the sha512 value (SHA-512 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)]
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
- **<big>Sha512WithBase64</big>** : return the sha512 value (SHA-512 hash algorithm) of base64 string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512WithBase64)]
[[play](https://go.dev/play/p/q_fY2rA-k5I)]
- **<big>GenerateRsaKey</big>** : create rsa private and public pemo file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)]
[[play](https://go.dev/play/p/zutRHrDqs0X)]
@@ -421,7 +453,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
<h3 id="Datetime"> 7. Datetime package supports date and time format and compare. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/datetime"
@@ -486,6 +518,12 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>GetNowDateTime</big>** : return format yyyy-mm-dd hh-mm-ss of current datetime.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)]
[[play](https://go.dev/play/p/pI4AqngD0al)]
- **<big>GetTodayStartTime</big>** : return the start time of today, format: yyyy-mm-dd 00:00:00.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetTodayStartTime)]
[[play](https://go.dev/play/p/84siyYF7t99)]
- **<big>GetTodayEndTime</big>** : return the end time of today, format: yyyy-mm-dd 23:59:59.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetTodayEndTime)]
[[play](https://go.dev/play/p/jjrLnfoqgn3)]
- **<big>GetZeroHourTimestamp</big>** : return timestamp of zero hour (timestamp of 00:00).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp)]
[[play](https://go.dev/play/p/QmL2oIaGE3q)]
@@ -534,11 +572,27 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>IsWeekend</big>** : checks if passed time is weekend or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
- **<big>NowDateOrTime</big>** : returns current datetime with specific format and timezone.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NowDateOrTime)]
[[play](https://go.dev/play/p/EZ-begEjtT0)]
- **<big>Timestamp</big>** : returns current second timestamp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#Timestamp)]
- **<big>TimestampMilli</big>** : returns current mill second timestamp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#TimestampMilli)]
[[play](https://go.dev/play/p/4gvEusOTu1T)]
- **<big>TimestampMicro</big>** : returns current micro second timestamp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#TimestampMicro)]
[[play](https://go.dev/play/p/2maANglKHQE)]
- **<big>TimestampNano</big>** : returns current nano second timestamp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#TimestampNano)]
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
<h3 id="Datastructure"> 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="datastructure"> 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import list "github.com/duke-git/lancet/v2/datastructure/list"
import copyonwritelist "github.com/duke-git/lancet/v2/datastructure/copyonwritelist"
import link "github.com/duke-git/lancet/v2/datastructure/link"
import stack "github.com/duke-git/lancet/v2/datastructure/stack"
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
@@ -552,6 +606,8 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>List</big>** : a linear table, implemented with slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md)]
- **<big>CopyOnWriteList</big>** : a thread-safe list implementation that uses go slicing as its base.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/copyonwritelist.md)]
- **<big>Link</big>** : link list structure, contains singly link and doubly link.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/link.md)]
- **<big>Stack</big>** : stack structure(fifo), contains array stack and link stack.
@@ -567,7 +623,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : hash map structure.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)]
<h3 id="Fileutil"> 9. Fileutil package implements some basic functions for file operations. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="fileutil"> 9. Fileutil package implements some basic functions for file operations. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/fileutil"
@@ -650,7 +706,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
<h3 id="Formatter"> 10. Formatter contains some functions for data formatting. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="formatter"> 10. Formatter contains some functions for data formatting. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/formatter"
@@ -680,7 +736,7 @@ import "github.com/duke-git/lancet/v2/formatter"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
<h3 id="Function"> 11. Function package can control the flow of function execution and support part of functional programming.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="function"> 11. Function package can control the flow of function execution and support part of functional programming.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/function"
@@ -716,7 +772,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
<h3 id="Maputil"> 12. Maputil package includes some functions to manipulate map.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="maputil"> 12. Maputil package includes some functions to manipulate map.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/maputil"
@@ -787,8 +843,36 @@ import "github.com/duke-git/lancet/v2/maputil"
- **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>HasKey</big>** : checks if map has key or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#HasKey)]
[[play](https://go.dev/play/p/isZZHOsDhFc)]
- **<big>NewConcurrentMap</big>** : creates a ConcurrentMap with specific shard count.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#NewConcurrentMap)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_Set</big>** : set the value for a key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_Set)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_Get</big>** : get the value stored in the map for a key, or nil if no.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_Get)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_GetOrSet</big>** : returns the existing value for the key if present.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_GetOrSet)]
[[play](https://go.dev/play/p/aDcDApOK01a)]
- **<big>ConcurrentMap_Delete</big>** : delete the value for a key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_Delete)]
[[play](https://go.dev/play/p/uTIJZYhpVMS)]
- **<big>ConcurrentMap_GetAndDelete</big>** :returns the existing value for the key if present and then delete the value for the key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_GetAndDelete)]
[[play](https://go.dev/play/p/ZyxeIXSZUiM)]
- **<big>ConcurrentMap_Has</big>** : checks if map has the value for a key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_Has)]
[[play](https://go.dev/play/p/C8L4ul9TVwf)]
- **<big>ConcurrentMap_Range</big>** : calls iterator sequentially for each key and value present in each of the shards in the map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ConcurrentMap_Range)]
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
<h3 id="Mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
<h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/mathutil"
@@ -869,7 +953,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sum)]
[[play](https://go.dev/play/p/1To2ImAMJA7)]
<h3 id="Netutil"> 14. Netutil package contains functions to get net information and send http request. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="netutil"> 14. Netutil package contains functions to get net information and send http request. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/netutil"
@@ -942,7 +1026,7 @@ import "github.com/duke-git/lancet/v2/netutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
<h3 id="Pointer"> 15. Pointer package contains some util functions to operate go pointer. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="pointer"> 15. Pointer package contains some util functions to operate go pointer. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/pointer"
@@ -959,8 +1043,14 @@ import "github.com/duke-git/lancet/v2/pointer"
- **<big>Unwrap</big>** : return the value from the pointer.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#Unwrap)]
[[play](https://go.dev/play/p/cgeu3g7cjWb)]
- **<big>UnwarpOr</big>** : UnwarpOr returns the value from the pointer or fallback if the pointer is nil.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#UnwrapOr)]
[[play](https://go.dev/play/p/mmNaLC38W8C)]
- **<big>UnwarpOrDefault</big>** : UnwarpOrDefault returns the value from the pointer or the default value if the pointer is nil.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#UnwrapOrDefault)]
[[play](https://go.dev/play/p/ZnGIHf8_o4E)]
<h3 id="Random"> 16. Random package implements some basic functions to generate random int and string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="random"> 16. Random package implements some basic functions to generate random int and string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/random"
@@ -996,7 +1086,7 @@ import "github.com/duke-git/lancet/v2/random"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUniqueIntSlice)]
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
<h3 id="Retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/retry"
@@ -1020,7 +1110,7 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
<h3 id="Slice"> 18. Slice contains some functions to manipulate slice. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="slice"> 18. Slice contains some functions to manipulate slice. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/slice"
@@ -1232,8 +1322,12 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>KeyBy</big>** : converts a slice to a map based on a callback function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
- **<big>Join</big>** : join the slice item with specify separator.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Join)]
[[play](https://go.dev/play/p/huKzqwNDD7V)]
<h3 id="Stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/stream"
@@ -1320,7 +1414,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
<h3 id="Structs"> 20. Structs package provides several high level functions to manipulate struct, tag, and field. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="structs"> 20. Structs package provides several high level functions to manipulate struct, tag, and field. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/structs"
@@ -1353,7 +1447,7 @@ import "github.com/duke-git/lancet/v2/structs"
- **<big>IsSlice</big>** : check if the field is a slice
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsSlice)]
<h3 id="Strutil"> 21. Strutil package contains some functions to manipulate string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="strutil"> 21. Strutil package contains some functions to manipulate string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/strutil"
@@ -1471,7 +1565,7 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>RemoveWhiteSpace</big>** : remove whitespace characters from a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveWhiteSpace)]
<h3 id="System"> 22. System package contain some functions about os, runtime, shell command. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="system"> 22. System package contain some functions about os, runtime, shell command. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/system"
@@ -1507,7 +1601,7 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
<h3 id="Tuple"> 23. Tuple package implements tuple data type and some operations on it. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/tuple"
@@ -1517,78 +1611,114 @@ import "github.com/duke-git/lancet/v2/tuple"
- **<big>Tuple2</big>** : represents a 2 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple2)]
[[play](https://go.dev/play/p/3sHVqBQpLYN)]
- **<big>Tuple2_Unbox</big>** : returns values in Tuple2.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple2_Unbox)]
[[play](https://go.dev/play/p/0fD1qfCVwjm)]
- **<big>Zip2</big>** : create a slice of Tuple2, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip2)]
[[play](https://go.dev/play/p/4ncWJJ77Xio)]
- **<big>Unzip2</big>** : create a group of slice from a slice of Tuple2.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip2)]
[[play](https://go.dev/play/p/KBecr60feXb)]
- **<big>Tuple3</big>** : represents a 3 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple3)]
[[play](https://go.dev/play/p/FtH2sdCLlCf)]
- **<big>Tuple3_Unbox</big>** : returns values in Tuple3.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple3_Unbox)]
[[play](https://go.dev/play/p/YojLy-id1BS)]
- **<big>Zip3</big>** : create a slice of Tuple3, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip3)]
[[play](https://go.dev/play/p/97NgmsTILfu)]
- **<big>Unzip3</big>** : create a group of slice from a slice of Tuple3.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip3)]
[[play](https://go.dev/play/p/bba4cpAa7KO)]
- **<big>Tuple4</big>** : represents a 4 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple4)]
[[play](https://go.dev/play/p/D2EqDz096tk)]
- **<big>Tuple4_Unbox</big>** : returns values in Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple4_Unbox)]
[[play](https://go.dev/play/p/ACj9YuACGgW)]
- **<big>Zip4</big>** : create a slice of Tuple4, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip4)]
[[play](https://go.dev/play/p/PEmTYVK5hL4)]
- **<big>Unzip4</big>** : create a group of slice from a slice of Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip4)]
[[play](https://go.dev/play/p/rb8z4gyYSRN)]
- **<big>Tuple5</big>** : represents a 5 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple5)]
[[play](https://go.dev/play/p/2WndmVxPg-r)]
- **<big>Tuple5_Unbox</big>** : returns values in Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple5_Unbox)]
[[play](https://go.dev/play/p/GyIyZHjCvoS)]
- **<big>Zip5</big>** : create a slice of Tuple5, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip5)]
[[play](https://go.dev/play/p/fCAAJLMfBIP)]
- **<big>Unzip5</big>** : create a group of slice from a slice of Tuple5.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip5)]
[[play](https://go.dev/play/p/gyl6vKfhqPb)]
- **<big>Tuple6</big>** : represents a 6 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple6)]
[[play](https://go.dev/play/p/VjqcCwEJZbs)]
- **<big>Tuple6_Unbox</big>** : returns values in Tuple6.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple6_Unbox)]
[[play](https://go.dev/play/p/FjIHV7lpxmW)]
- **<big>Zip6</big>** : create a slice of Tuple6, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip6)]
[[play](https://go.dev/play/p/oWPrnUYuFHo)]
- **<big>Unzip6</big>** : create a group of slice from a slice of Tuple6.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip6)]
[[play](https://go.dev/play/p/l41XFqCyh5E)]
- **<big>Tuple7</big>** : represents a 7 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple7)]
[[play](https://go.dev/play/p/dzAgv_Ezub9)]
- **<big>Tuple7_Unbox</big>** : returns values in Tuple7.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple7_Unbox)]
[[play](https://go.dev/play/p/R9I8qeDk0zs)]
- **<big>Zip7</big>** : create a slice of Tuple7, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip7)]
[[play](https://go.dev/play/p/WUJuo897Egf)]
- **<big>Unzip7</big>** : create a group of slice from a slice of Tuple7.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip7)]
[[play](https://go.dev/play/p/hws_P1Fr2j3)]
- **<big>Tuple8</big>** : represents a 8 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple8)]
[[play](https://go.dev/play/p/YA9S0rz3dRz)]
- **<big>Tuple8_Unbox</big>** : returns values in Tuple8.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple8_Unbox)]
[[play](https://go.dev/play/p/PRxLBBb4SMl)]
- **<big>Zip8</big>** : create a slice of Tuple8, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip8)]
[[play](https://go.dev/play/p/8V9jWkuJfaQ)]
- **<big>Unzip8</big>** : create a group of slice from a slice of Tuple8.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip8)]
[[play](https://go.dev/play/p/1SndOwGsZB4)]
- **<big>Tuple9</big>** : represents a 9 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple9)]
[[play](https://go.dev/play/p/yS2NGGtZpQr)]
- **<big>Tuple9_Unbox</big>** : returns values in Tuple9.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple9_Unbox)]
[[play](https://go.dev/play/p/oFJFGTAuOa8)]
- **<big>Zip9</big>** : create a slice of Tuple9, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip9)]
[[play](https://go.dev/play/p/cgsL15QYnfz)]
- **<big>Unzip9</big>** : create a group of slice from a slice of Tuple9.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip9)]
[[play](https://go.dev/play/p/91-BU_KURSA)]
- **<big>Tuple10</big>** : represents a 10 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple10)]
[[play](https://go.dev/play/p/799qqZg0hUv)]
- **<big>Tuple10_Unbox</big>** : returns values in Tuple10.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple10_Unbox)]
[[play](https://go.dev/play/p/qfyx3x_X0Cu)]
- **<big>Zip10</big>** : create a slice of Tuple10, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip10)]
[[play](https://go.dev/play/p/YSR-2cXnrY4)]
- **<big>Unzip10</big>** : create a group of slice from a slice of Tuple10.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip10)]
[[play](https://go.dev/play/p/-taQB6Wfre_z)]
<h3 id="Validator"> 24. Validator package contains some functions for data validation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="validator"> 24. Validator package contains some functions for data validation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/validator"
@@ -1696,7 +1826,7 @@ import "github.com/duke-git/lancet/v2/validator"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
<h3 id="Xerror"> 25. Xerror package implements helpers for errors. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
<h3 id="xerror"> 25. Xerror package implements helpers for errors. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/xerror"

View File

@@ -4,7 +4,7 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.2.3-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.2.5-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)
@@ -37,7 +37,7 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.0。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.1。</b>
```go
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
@@ -74,33 +74,33 @@ func main() {
### <span id="index">目录<span>
- [Algorithm](#Algorithm)
- [Compare](#Compare)
- [Concurrency](#Concurrency)
- [Condition](#Condition)
- [Convertor](#Convertor)
- [Cryptor](#Cryptor)
- [Datetime](#Datetime)
- [Datastructure](#Datastructure)
- [Fileutil](#Fileutil)
- [Formatter](#Formatter)
- [Function](#Function)
- [Maputil](#Maputil)
- [Mathutil](#Mathutil)
- [Netutil](#Netutil)
- [Pointer](#Pointer)
- [Random](#Random)
- [Retry](#Retry)
- [Slice](#Slice)
- [Stream](#Stream)
- [Structs](#Structs)
- [Strutil](#Strutil)
- [System](#System)
- [Tuple](#Tuple)
- [Validator](#Validator)
- [Xerror](#Xerror)
- [Algorithm](#user-content-algorithm)
- [Compare](#user-content-compare)
- [Concurrency](#user-content-concurrency)
- [Condition](#user-content-condition)
- [Convertor](#user-content-convertor)
- [Cryptor](#user-content-cryptor)
- [Datetime](#user-content-datetime)
- [Datastructure](#user-content-datastructure)
- [Fileutil](#user-content-fileutil)
- [Formatter](#user-content-formatter)
- [Function](#user-content-function)
- [Maputil](#user-content-maputil)
- [Mathutil](#user-content-mathutil)
- [Netutil](#user-content-netutil)
- [Pointer](#user-content-pointer)
- [Random](#user-content-random)
- [Retry](#user-content-retry)
- [Slice](#user-content-slice)
- [Stream](#user-content-stream)
- [Structs](#user-content-structs)
- [Strutil](#user-content-strutil)
- [System](#user-content-system)
- [Tuple](#user-content-tuple)
- [Validator](#user-content-validator)
- [Xerror](#user-content-xerror)
<h3 id="Algorithm"> 1. algorithm 包实现一些基本查找和排序算法。 &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="algorithm"> 1. algorithm 包实现一些基本查找和排序算法。 &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/algorithm"
@@ -145,7 +145,7 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
<h3 id="Compare"> 2. compare 包提供几个轻量级的类型比较函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="compare"> 2. compare 包提供几个轻量级的类型比较函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/compare"
@@ -171,8 +171,10 @@ import "github.com/duke-git/lancet/v2/compare"
- **<big>GreaterOrEqual</big>** : 验证参数`left`的值是否大于或等于参数`right`的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
- **<big>InDelta</big>** : 检查增量内两个值是否相等。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#InDelta)]
<h3 id="Concurrency"> 3. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="concurrency"> 3. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/concurrency"
@@ -211,7 +213,7 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)]
<h3 id="Condition"> 4. condition 包含一些用于条件判断的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="condition"> 4. condition 包含一些用于条件判断的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/condition"
@@ -244,7 +246,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
<h3 id="Convertor"> 5. convertor 转换器包支持一些常见的数据类型转换。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="convertor"> 5. convertor 转换器包支持一些常见的数据类型转换。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/convertor"
@@ -316,7 +318,7 @@ import "github.com/duke-git/lancet/v2/convertor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#GbkToUtf8)]
[[play](https://go.dev/play/p/OphmHCN_9u8)]
<h3 id="Cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/cryptor"
@@ -387,29 +389,59 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>HmacMd5</big>** : 返回字符串 md5 hmac 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>HmacMd5WithBase64</big>** : 获取字符串 md5 hmac base64 字符串值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5WithBase64)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5WithBase64)]
- **<big>HmacSha1</big>** : 返回字符串 sha1 hmac 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)]
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
- **<big>HmacSha1WithBase64</big>** : 获取字符串的 sha1 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1WithBase64)]
[[play](https://go.dev/play/p/47JmmGrnF7B)]
- **<big>HmacSha256</big>** : 返回字符串 sha256 hmac 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)]
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
- **<big>HmacSha256WithBase64</big>** : 获取字符串 sha256 hmac base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256WithBase64)]
[[play](https://go.dev/play/p/EKbkUvPTLwO)]
- **<big>HmacSha512</big>** : 返回字符串 sha256 hmac 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)]
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
- **<big>HmacSha512WithBase64</big>** : 获取字符串 sha512 hmac base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512WithBase64)]
[[play](https://go.dev/play/p/c6dSe3E2ydU)]
- **<big>Md5Byte</big>** : 返回 byte slice 的 md5 值.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5Byte)]
[[play](https://go.dev/play/p/suraalH8lyC)]
- **<big>Md5ByteWithBase64</big>** : 获取 byte slice 的 md5 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5ByteWithBase64)]
[[play](https://go.dev/play/p/Tcb-Z7LN2ax)]
- **<big>Md5String</big>** : 返回字符串 md5 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)]
[[play](https://go.dev/play/p/1bLcVetbTOI)]
- **<big>Md5StringWithBase64</big>** : 获取字符串 md5 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5StringWithBase64)]
[[play](https://go.dev/play/p/Lx4gH7Vdr5_y)]
- **<big>Md5File</big>** : 返回文件 md5 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)]
- **<big>Sha1</big>** : 返回字符串 sha1 哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)]
[[play](https://go.dev/play/p/_m_uoD1deMT)]
- **<big>Sha1WithBase64</big>** : 获取字符串 sha1 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1WithBase64)]
[[play](https://go.dev/play/p/fSyx-Gl2l2-)]
- **<big>Sha256</big>** :返回字符串 sha256 哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)]
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
- **<big>Sha256WithBase64</big>** : 获取字符串 sha256 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256WithBase64)]
[[play](https://go.dev/play/p/85IXJHIal1k)]
- **<big>Sha512</big>** : 返回字符串 sha512 哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)]
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
- **<big>Sha512WithBase64</big>** : 获取字符串 sha512 base64 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512WithBase64)]
[[play](https://go.dev/play/p/q_fY2rA-k5I)]
- **<big>GenerateRsaKey</big>** : 在当前目录下创建 rsa 私钥文件和公钥文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)]
[[play](https://go.dev/play/p/zutRHrDqs0X)]
@@ -420,7 +452,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
<h3 id="Datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/datetime"
@@ -485,6 +517,12 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>GetNowDateTime</big>** : 获取当时日期和时间返回格式yyyy-mm-dd hh:mm:ss。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)]
[[play](https://go.dev/play/p/pI4AqngD0al)]
- **<big>GetTodayStartTime</big>** : 返回当天开始时间, 格式: yyyy-mm-dd 00:00:00。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetTodayStartTime)]
[[play](https://go.dev/play/p/84siyYF7t99)]
- **<big>GetTodayEndTime</big>** : 返回当天结束时间,格式: yyyy-mm-dd 23:59:59。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetTodayEndTime)]
[[play](https://go.dev/play/p/jjrLnfoqgn3)]
- **<big>GetZeroHourTimestamp</big>** : 获取零时时间戳(timestamp of 00:00)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp)]
[[play](https://go.dev/play/p/QmL2oIaGE3q)]
@@ -536,11 +574,27 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>IsWeekend</big>** : 判断日期是否是周末。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
- **<big>NowDateOrTime</big>** : 根据指定的格式和时区返回当前时间字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NowDateOrTime)]
[[play](https://go.dev/play/p/EZ-begEjtT0)]
- **<big>Timestamp</big>** : 返回当前秒级时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#Timestamp)]
[[play](https://go.dev/play/p/iU5b7Vvjx6x)]
- **<big>TimestampMilli</big>** : 返回当前毫秒级时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#TimestampMilli)]
[[play](https://go.dev/play/p/4gvEusOTu1T)]
- **<big>TimestampMicro</big>** : 返回当前微秒级时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#TimestampMicro)]
[[play](https://go.dev/play/p/2maANglKHQE)]
- **<big>TimestampNano</big>** : 返回当前纳秒级时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#TimestampNano)]
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
<h3 id="Datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import list "github.com/duke-git/lancet/v2/datastructure/list"
import copyonwritelist "github.com/duke-git/lancet/v2/datastructure/copyonwritelist"
import link "github.com/duke-git/lancet/v2/datastructure/link"
import stack "github.com/duke-git/lancet/v2/datastructure/stack"
import queue "github.com/duke-git/lancet/v2/datastructure/queue"
@@ -554,6 +608,8 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>List</big>** : 线性表结构, 用切片实现。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)]
- **<big>CopyOnWriteList</big>** : 是一个线程安全的 List 实现,底层使用 go 切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/copyonwritelist_zh-CN.md)]
- **<big>Link</big>** : 链表解构, 包括单链表和双向链表。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/link_zh-CN.md)]
- **<big>Stack</big>** : 栈结构(fifo), 包括数组栈和链表栈。
@@ -569,7 +625,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : 哈希映射。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
<h3 id="Fileutil"> 9. fileutil 包含文件基本操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="fileutil"> 9. fileutil 包含文件基本操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/fileutil"
@@ -652,7 +708,7 @@ import "github.com/duke-git/lancet/v2/fileutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
<h3 id="Formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/formatter"
@@ -682,7 +738,7 @@ import "github.com/duke-git/lancet/v2/formatter"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
<h3 id="Function"> 11. function 函数包控制函数执行流程,包含部分函数式编程。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="function"> 11. function 函数包控制函数执行流程,包含部分函数式编程。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/function"
@@ -718,7 +774,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
<h3 id="Maputil"> 12. maputil 包括一些操作 map 的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="maputil"> 12. maputil 包括一些操作 map 的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/maputil"
@@ -769,28 +825,55 @@ import "github.com/duke-git/lancet/v2/maputil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)]
[[play](https://go.dev/play/p/CBKdUc5FTW6)]
- **<big>ValuesBy</big>** : 创建一个切片,其元素是每个 map 的 value 调用 mapper 函数的结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#ValuesBy)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ValuesBy)]
[[play](https://go.dev/play/p/sg9-oRidh8f)]
- **<big>MapKeys</big>** : 操作 map 的每个 key然后转为新的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapKeys)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#MapKeys)]
[[play](https://go.dev/play/p/8scDxWeBDKd)]
- **<big>MapValues</big>** : 操作 map 的每个 value然后转为新的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapValues)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#MapValues)]
[[play](https://go.dev/play/p/g92aY3fc7Iw)]
- **<big>Entries</big>** : 将 map 转换为键/值对切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Entries)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Entries)]
[[play](https://go.dev/play/p/Ltb11LNcElY)]
- **<big>FromEntries</big>** : 基于键/值对的切片创建 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FromEntries)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#FromEntries)]
[[play](https://go.dev/play/p/fTdu4sCNjQO)]
- **<big>Transform</big>** : 将 map 转换为其他类型的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Transform)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Transform)]
[[play](https://go.dev/play/p/P6ovfToM3zj)]
- **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>HasKey</big>** : 检查 map 是否包含某个 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#HasKey)]
[[play](https://go.dev/play/p/isZZHOsDhFc)]
- **<big>NewConcurrentMap</big>** : ConcurrentMap 协程安全的 map 结构。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#NewConcurrentMap)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_Set</big>** : 在 map 中设置 key 和 value。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_Set)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_Get</big>** : 根据 key 获取 value, 如果不存在 key,返回零值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_Get)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
- **<big>ConcurrentMap_GetOrSet</big>** : 返回键的现有值(如果存在),否则,设置 key 并返回给定值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_GetOrSet)]
[[play](https://go.dev/play/p/aDcDApOK01a)]
- **<big>ConcurrentMap_Delete</big>** : 删除 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_Delete)]
[[play](https://go.dev/play/p/uTIJZYhpVMS)]
- **<big>ConcurrentMap_GetAndDelete</big>** :获取 key然后删除。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_GetAndDelete)]
[[play](https://go.dev/play/p/ZyxeIXSZUiM)]
- **<big>ConcurrentMap_Has</big>** : 验证是否包含 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_Has)]
[[play](https://go.dev/play/p/C8L4ul9TVwf)]
- **<big>ConcurrentMap_Range</big>** : 为 map 中每个键和值顺序调用迭代器。 如果 iterator 返回 false则停止迭代。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ConcurrentMap_Range)]
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
<h3 id="Mathutil"> 13. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="mathutil"> 13. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/mathutil"
@@ -871,7 +954,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sum)]
[[play](https://go.dev/play/p/1To2ImAMJA7)]
<h3 id="Netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/netutil"
@@ -944,7 +1027,7 @@ import "github.com/duke-git/lancet/v2/netutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
<h3 id="Pointer"> 15. pointer 包支持一些指针类型的操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="pointer"> 15. pointer 包支持一些指针类型的操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/pointer"
@@ -960,9 +1043,15 @@ import "github.com/duke-git/lancet/v2/pointer"
[[play](https://go.dev/play/p/HFd70x4DrMj)]
- **<big>Unwrap</big>** : 返回传入指针指向的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/cgeu3g7cjWb)]
[[play](https://go.dev/play/p/cgeu3g7cjWb)
- **<big>UnwarpOr</big>** : 返回指针的值,如果指针为零值,则返回 fallback。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#UnwrapOr)]
[[play](https://go.dev/play/p/mmNaLC38W8C)]
- **<big>UnwarpOrDefault</big>** : 返回指针的值,如果指针为零值,则返回相应零值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#UnwrapOrDefault)]
[[play](https://go.dev/play/p/ZnGIHf8_o4E)]
<h3 id="Random"> 16. random 随机数生成器包,可以生成随机[]bytes, int, string。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="random"> 16. random 随机数生成器包,可以生成随机[]bytes, int, string。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/random"
@@ -998,7 +1087,7 @@ import "github.com/duke-git/lancet/v2/random"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUniqueIntSlice)]
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
<h3 id="Retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/retry"
@@ -1022,7 +1111,7 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
<h3 id="Slice"> 18. slice 包含操作切片的方法集合。</span>&nbsp; &nbsp; &nbsp; &nbsp; [回到目录](#index)
<h3 id="slice"> 18. slice 包含操作切片的方法集合。&nbsp; &nbsp; &nbsp; &nbsp; [回到目录](#index)
```go
import "github.com/duke-git/lancet/v2/slice"
@@ -1234,8 +1323,11 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>KeyBy</big>** :将切片每个元素调用函数后转为 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
- **<big>Join</big>** : 用指定的分隔符链接切片元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Join)]
[[play](https://go.dev/play/p/huKzqwNDD7V)]
<h3 id="Stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/stream"
@@ -1322,7 +1414,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
<h3 id="Structs"> 20. structs 提供操作 struct, tag, field 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="structs"> 20. structs 提供操作 struct, tag, field 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/structs"
@@ -1357,7 +1449,7 @@ import "github.com/duke-git/lancet/v2/structs"
- **<big>IsSlice</big>** : 判断属性是否是切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsSlice)]
<h3 id="Strutil"> 21. strutil 包含字符串处理的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="strutil"> 21. strutil 包含字符串处理的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/strutil"
@@ -1476,7 +1568,7 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>RemoveWhiteSpace</big>** : 删除字符串中的空格。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveWhiteSpace)]
<h3 id="System"> 22. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="system"> 22. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/system"
@@ -1512,7 +1604,7 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
<h3 id="Tuple"> 23. Tuple 包实现一个元组数据类型。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="tuple"> 23. Tuple 包实现一个元组数据类型。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/tuple"
@@ -1522,78 +1614,114 @@ import "github.com/duke-git/lancet/v2/tuple"
- **<big>Tuple2</big>** : 2 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple2)]
[[play](https://go.dev/play/p/3sHVqBQpLYN)]
- **<big>Tuple2_Unbox</big>** : 返回 2 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple2_Unbox)]
[[play](https://go.dev/play/p/0fD1qfCVwjm)]
- **<big>Zip2</big>** : 创建一个 Tuple2 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip2)]
- **<big>Unzip2</big>** : 根据传入的Tuple2切片创建一组和Tuple2元素相对应的切片。
[[play](https://go.dev/play/p/4ncWJJ77Xio)]
- **<big>Unzip2</big>** : 根据传入的 Tuple2 切片,创建一组和 Tuple2 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip2)]
[[play](https://go.dev/play/p/KBecr60feXb)]
- **<big>Tuple3</big>** : 3 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple3)]
[[play](https://go.dev/play/p/FtH2sdCLlCf)]
- **<big>Tuple3_Unbox</big>** : 返回 3 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple3_Unbox)]
[[play](https://go.dev/play/p/YojLy-id1BS)]
- **<big>Zip3</big>** : 创建一个 Tuple3 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip3)]
- **<big>Unzip3</big>** : 根据传入的Tuple3切片创建一组和Tuple3元素相对应的切片。
[[play](https://go.dev/play/p/97NgmsTILfu)]
- **<big>Unzip3</big>** : 根据传入的 Tuple3 切片,创建一组和 Tuple3 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip3)]
[[play](https://go.dev/play/p/bba4cpAa7KO)]
- **<big>Tuple4</big>** : 4 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple4)]
[[play](https://go.dev/play/p/D2EqDz096tk)]
- **<big>Tuple4_Unbox</big>** : 返回 4 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple4_Unbox)]
[[play](https://go.dev/play/p/ACj9YuACGgW)]
- **<big>Zip4</big>** : 创建一个 Tuple4 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip4)]
- **<big>Unzip4</big>** : 根据传入的Tuple4切片创建一组和Tuple4元素相对应的切片。
[[play](https://go.dev/play/p/PEmTYVK5hL4)]
- **<big>Unzip4</big>** : 根据传入的 Tuple4 切片,创建一组和 Tuple4 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip4)]
[[play](https://go.dev/play/p/rb8z4gyYSRN)]
- **<big>Tuple5</big>** : 5 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple5)]
[[play](https://go.dev/play/p/2WndmVxPg-r)]
- **<big>Tuple5_Unbox</big>** : 返回 5 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple5_Unbox)]
[[play](https://go.dev/play/p/GyIyZHjCvoS)]
- **<big>Zip5</big>** : 创建一个 Tuple5 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip5)]
- **<big>Unzip5</big>** : 根据传入的Tuple5切片创建一组和Tuple5元素相对应的切片。
[[play](https://go.dev/play/p/fCAAJLMfBIP)]
- **<big>Unzip5</big>** : 根据传入的 Tuple5 切片,创建一组和 Tuple5 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip5)]
[[play](https://go.dev/play/p/gyl6vKfhqPb)]
- **<big>Tuple6</big>** : 6 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple6)]
[[play](https://go.dev/play/p/VjqcCwEJZbs)]
- **<big>Tuple6_Unbox</big>** : 返回 6 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple6_Unbox)]
[[play](https://go.dev/play/p/FjIHV7lpxmW)]
- **<big>Zip6</big>** : 创建一个 Tuple6 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip6)]
- **<big>Unzip6</big>** : 根据传入的Tuple6切片创建一组和Tuple6元素相对应的切片。
[[play](https://go.dev/play/p/oWPrnUYuFHo)]
- **<big>Unzip6</big>** : 根据传入的 Tuple6 切片,创建一组和 Tuple6 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip6)]
[[play](https://go.dev/play/p/l41XFqCyh5E)]
- **<big>Tuple7</big>** : 7 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple7)]
[[play](https://go.dev/play/p/dzAgv_Ezub9)]
- **<big>Tuple7_Unbox</big>** : 返回 7 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple7_Unbox)]
[[play](https://go.dev/play/p/R9I8qeDk0zs)]
- **<big>Zip7</big>** : 创建一个 Tuple7 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip7)]
- **<big>Unzip7</big>** : 根据传入的Tuple7切片创建一组和Tuple7元素相对应的切片。
[[play](https://go.dev/play/p/WUJuo897Egf)]
- **<big>Unzip7</big>** : 根据传入的 Tuple7 切片,创建一组和 Tuple7 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip7)]
[[play](https://go.dev/play/p/hws_P1Fr2j3)]
- **<big>Tuple8</big>** : 8 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple8)]
[[play](https://go.dev/play/p/YA9S0rz3dRz)]
- **<big>Tuple8_Unbox</big>** : 返回 8 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple8_Unbox)]
[[play](https://go.dev/play/p/PRxLBBb4SMl)]
- **<big>Zip8</big>** : 创建一个 Tuple8 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip8)]
- **<big>Unzip8</big>** : 根据传入的Tuple8切片创建一组和Tuple8元素相对应的切片。
[[play](https://go.dev/play/p/8V9jWkuJfaQ)]
- **<big>Unzip8</big>** : 根据传入的 Tuple8 切片,创建一组和 Tuple8 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip8)]
[[play](https://go.dev/play/p/1SndOwGsZB4)]
- **<big>Tuple9</big>** : 9 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple9)]
[[play](https://go.dev/play/p/yS2NGGtZpQr)]
- **<big>Tuple9_Unbox</big>** : 返回 9 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple9_Unbox)]
[[play](https://go.dev/play/p/oFJFGTAuOa8)]
- **<big>Zip9</big>** : 创建一个 Tuple9 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip9)]
- **<big>Unzip9</big>** : 根据传入的Tuple9切片创建一组和Tuple9元素相对应的切片。
[[play](https://go.dev/play/p/cgsL15QYnfz)]
- **<big>Unzip9</big>** : 根据传入的 Tuple9 切片,创建一组和 Tuple9 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip9)]
[[play](https://go.dev/play/p/91-BU_KURSA)]
- **<big>Tuple10</big>** : 10 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple10)]
[[play](https://go.dev/play/p/799qqZg0hUv)]
- **<big>Tuple10_Unbox</big>** : 返回 10 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple10_Unbox)]
[[play](https://go.dev/play/p/qfyx3x_X0Cu)]
- **<big>Zip10</big>** : 创建一个 Tuple10 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip10)]
- **<big>Unzip10</big>** : 根据传入的Tuple10切片创建一组和Tuple10元素相对应的切片。
[[play](https://go.dev/play/p/YSR-2cXnrY4)]
- **<big>Unzip10</big>** : 根据传入的 Tuple10 切片,创建一组和 Tuple10 元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip10)]
[[play](https://go.dev/play/p/-taQB6Wfre_z)]
<h3 id="Validator"> 24. validator 验证器包,包含常用字符串格式验证函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="validator"> 24. validator 验证器包,包含常用字符串格式验证函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/validator"
@@ -1701,7 +1829,7 @@ import "github.com/duke-git/lancet/v2/validator"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
<h3 id="Xerror"> 25. xerror 包实现一些错误处理函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
<h3 id="xerror"> 25. xerror 包实现一些错误处理函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/xerror"

View File

@@ -10,6 +10,8 @@ import (
"time"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/mathutil"
"golang.org/x/exp/constraints"
)
// operator type
@@ -62,3 +64,8 @@ func LessOrEqual(left, right any) bool {
func GreaterOrEqual(left, right any) bool {
return compareValue(greaterOrEqual, left, right)
}
// InDelta checks if two values are equal or not within a delta.
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool {
return float64(mathutil.Abs(left-right)) <= delta
}

View File

@@ -168,3 +168,29 @@ func ExampleGreaterOrEqual() {
// false
// false
}
func ExampleInDelta() {
result1 := InDelta(1, 1, 0)
result2 := InDelta(1, 2, 0)
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
result4 := InDelta(2.0/3.0, 0.0, 0.001)
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// false
// true
// false
// false
// true
}

View File

@@ -138,3 +138,19 @@ func TestGreaterOrEqual(t *testing.T) {
assert.Equal(false, GreaterOrEqual(int64(2), 1))
assert.Equal(false, GreaterOrEqual("b", "c"))
}
func TestInDelta(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInDelta")
assert.Equal(true, InDelta(1, 1, 0))
assert.Equal(false, InDelta(1, 2, 0))
assert.Equal(true, InDelta(2.0/3.0, 0.66667, 0.001))
assert.Equal(false, InDelta(2.0/3.0, 0.0, 0.001))
assert.Equal(false, InDelta(float64(74.96)-float64(20.48), 54.48, 0))
assert.Equal(true, InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14))
assert.Equal(false, InDelta(float64(float32(80.45)), float64(80.45), 0))
assert.Equal(true, InDelta(float64(float32(80.45)), float64(80.45), 1e-5))
}

View File

@@ -40,14 +40,30 @@ func Md5String(s string) string {
return hex.EncodeToString(h.Sum(nil))
}
// Md5String return the md5 string of byte slice.
// Play: todo
// Md5StringWithBase64 return the md5 value of string with base64.
// Play: https://go.dev/play/p/Lx4gH7Vdr5_y
func Md5StringWithBase64(s string) string {
h := md5.New()
h.Write([]byte(s))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// Md5Byte return the md5 string of byte slice.
// Play: https://go.dev/play/p/suraalH8lyC
func Md5Byte(data []byte) string {
h := md5.New()
h.Write(data)
return hex.EncodeToString(h.Sum(nil))
}
// Md5ByteWithBase64 return the md5 string of byte slice with base64.
// Play: https://go.dev/play/p/Tcb-Z7LN2ax
func Md5ByteWithBase64(data []byte) string {
h := md5.New()
h.Write(data)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// Md5File return the md5 value of file.
func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil {
@@ -82,56 +98,112 @@ func Md5File(filename string) (string, error) {
// HmacMd5 return the hmac hash of string use md5.
// Play: https://go.dev/play/p/uef0q1fz53I
func HmacMd5(data, key string) string {
func HmacMd5(str, key string) string {
h := hmac.New(md5.New, []byte(key))
h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacMd5WithBase64 return the hmac hash of string use md5 with base64.
// todo
func HmacMd5WithBase64(data, key string) string {
h := hmac.New(md5.New, []byte(key))
h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte("")))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// HmacSha1 return the hmac hash of string use sha1.
// Play: https://go.dev/play/p/1UI4oQ4WXKM
func HmacSha1(data, key string) string {
func HmacSha1(str, key string) string {
h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(data))
h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha1WithBase64 return the hmac hash of string use sha1 with base64.
// Play: https://go.dev/play/p/47JmmGrnF7B
func HmacSha1WithBase64(str, key string) string {
h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// HmacSha256 return the hmac hash of string use sha256.
// Play: https://go.dev/play/p/HhpwXxFhhC0
func HmacSha256(data, key string) string {
func HmacSha256(str, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data))
h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha256WithBase64 return the hmac hash of string use sha256 with base64.
// Play: https://go.dev/play/p/EKbkUvPTLwO
func HmacSha256WithBase64(str, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// HmacSha512 return the hmac hash of string use sha512.
// Play: https://go.dev/play/p/59Od6m4A0Ud
func HmacSha512(data, key string) string {
func HmacSha512(str, key string) string {
h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(data))
h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacSha512WithBase64 return the hmac hash of string use sha512 with base64.
// Play: https://go.dev/play/p/c6dSe3E2ydU
func HmacSha512WithBase64(str, key string) string {
h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
// Play: https://go.dev/play/p/_m_uoD1deMT
func Sha1(data string) string {
func Sha1(str string) string {
sha1 := sha1.New()
sha1.Write([]byte(data))
sha1.Write([]byte(str))
return hex.EncodeToString(sha1.Sum([]byte("")))
}
// Sha1WithBase64 return the sha1 value (SHA-1 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/fSyx-Gl2l2-
func Sha1WithBase64(str string) string {
sha1 := sha1.New()
sha1.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha1.Sum([]byte("")))
}
// Sha256 return the sha256 value (SHA256 hash algorithm) of string.
// Play: https://go.dev/play/p/tU9tfBMIAr1
func Sha256(data string) string {
func Sha256(str string) string {
sha256 := sha256.New()
sha256.Write([]byte(data))
sha256.Write([]byte(str))
return hex.EncodeToString(sha256.Sum([]byte("")))
}
// Sha256WithBase64 return the sha256 value (SHA256 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/85IXJHIal1k
func Sha256WithBase64(str string) string {
sha256 := sha256.New()
sha256.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha256.Sum([]byte("")))
}
// Sha512 return the sha512 value (SHA512 hash algorithm) of string.
// Play: https://go.dev/play/p/3WsvLYZxsHa
func Sha512(data string) string {
func Sha512(str string) string {
sha512 := sha512.New()
sha512.Write([]byte(data))
sha512.Write([]byte(str))
return hex.EncodeToString(sha512.Sum([]byte("")))
}
// Sha512WithBase64 return the sha512 value (SHA512 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/q_fY2rA-k5I
func Sha512WithBase64(str string) string {
sha512 := sha512.New()
sha512.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha512.Sum([]byte("")))
}

View File

@@ -27,6 +27,13 @@ func TestMd5String(t *testing.T) {
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
}
func TestMd5StringWithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5StringWithBase64")
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5StringWithBase64("hello"))
}
func TestMd5Byte(t *testing.T) {
t.Parallel()
@@ -35,6 +42,13 @@ func TestMd5Byte(t *testing.T) {
assert.Equal("0cc175b9c0f1b6a831c399e269772661", Md5Byte(data))
}
func TestMd5ByteWithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5ByteWithBase64")
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5ByteWithBase64([]byte("hello")))
}
func TestMd5File(t *testing.T) {
t.Parallel()
@@ -51,6 +65,13 @@ func TestHmacMd5(t *testing.T) {
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
}
func TestHmacMd5WithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHmacMd5WithBase64")
assert.Equal("6DQwbquJLYclJdSRinpjmg==", HmacMd5WithBase64("hello", "12345"))
}
func TestHmacSha1(t *testing.T) {
t.Parallel()
@@ -63,18 +84,42 @@ func TestHmacSha1(t *testing.T) {
assert.Equal(expected, hmacSha1)
}
func TestHmacSha1WithBase64(t *testing.T) {
t.Parallel()
s := "hello"
key := "12345"
hmacSha1 := HmacSha1WithBase64(s, key)
expected := "XGqdsMzLkuNu0DI/0Jt/k23prOA="
assert := internal.NewAssert(t, "TestHmacSha1")
assert.Equal(expected, hmacSha1)
}
func TestHmacSha256(t *testing.T) {
t.Parallel()
s := "hello world"
str := "hello world"
key := "12345"
hmacSha256 := HmacSha256(s, key)
hmacSha256 := HmacSha256(str, key)
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
assert := internal.NewAssert(t, "TestHmacSha256")
assert.Equal(expected, hmacSha256)
}
func TestHmacSha256WithBase64(t *testing.T) {
t.Parallel()
str := "hello"
key := "12345"
hms := HmacSha256WithBase64(str, key)
expected := "MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU="
assert := internal.NewAssert(t, "TestHmacSha256WithBase64")
assert.Equal(expected, hms)
}
func TestHmacSha512(t *testing.T) {
t.Parallel()
@@ -87,6 +132,18 @@ func TestHmacSha512(t *testing.T) {
assert.Equal(expected, hmacSha512)
}
func TestHmacSha512WithBase64(t *testing.T) {
t.Parallel()
str := "hello"
key := "12345"
hms := HmacSha512WithBase64(str, key)
expected := "3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A=="
assert := internal.NewAssert(t, "TestHmacSha512WithBase64")
assert.Equal(expected, hms)
}
func TestSha1(t *testing.T) {
t.Parallel()
@@ -98,6 +155,16 @@ func TestSha1(t *testing.T) {
assert.Equal(expected, sha1)
}
func TestSha1WithBase64(t *testing.T) {
t.Parallel()
str := Sha1WithBase64("hello")
expected := "qvTGHdzF6KLavt4PO0gs2a6pQ00="
assert := internal.NewAssert(t, "TestSha1WithBase64")
assert.Equal(expected, str)
}
func TestSha256(t *testing.T) {
t.Parallel()
@@ -109,6 +176,16 @@ func TestSha256(t *testing.T) {
assert.Equal(expected, sha256)
}
func TestSha256WithBase64(t *testing.T) {
t.Parallel()
str := Sha256WithBase64("hello")
expected := "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
assert := internal.NewAssert(t, "TestSha256WithBase64")
assert.Equal(expected, str)
}
func TestSha512(t *testing.T) {
t.Parallel()
@@ -119,3 +196,13 @@ func TestSha512(t *testing.T) {
assert := internal.NewAssert(t, "TestSha512")
assert.Equal(expected, sha512)
}
func TestSha512WithBase64(t *testing.T) {
t.Parallel()
str := Sha512WithBase64("hello")
expected := "m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=="
assert := internal.NewAssert(t, "TestSha512WithBase64")
assert.Equal(expected, str)
}

View File

@@ -322,49 +322,89 @@ func ExampleHmacMd5() {
key := "12345"
hms := HmacMd5(str, key)
fmt.Println(hms)
// Output:
// e834306eab892d872525d4918a7a639a
}
func ExampleHmacMd5WithBase64() {
str := "hello"
key := "12345"
hms := HmacMd5WithBase64(str, key)
fmt.Println(hms)
// Output:
// 6DQwbquJLYclJdSRinpjmg==
}
func ExampleHmacSha1() {
str := "hello"
key := "12345"
hms := HmacSha1(str, key)
fmt.Println(hms)
// Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
func ExampleHmacSha1WithBase64() {
str := "hello"
key := "12345"
hms := HmacSha1WithBase64(str, key)
fmt.Println(hms)
// Output:
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
}
func ExampleHmacSha256() {
str := "hello"
key := "12345"
hms := HmacSha256(str, key)
fmt.Println(hms)
// Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
}
func ExampleHmacSha256WithBase64() {
str := "hello"
key := "12345"
hms := HmacSha256WithBase64(str, key)
fmt.Println(hms)
// Output:
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
}
func ExampleHmacSha512() {
str := "hello"
key := "12345"
hms := HmacSha512(str, key)
fmt.Println(hms)
// Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
}
func ExampleHmacSha512WithBase64() {
str := "hello"
key := "12345"
hms := HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
func ExampleMd5String() {
md5Str := Md5String("hello")
fmt.Println(md5Str)
@@ -373,6 +413,14 @@ func ExampleMd5String() {
// 5d41402abc4b2a76b9719d911017c592
}
func ExampleMd5StringWithBase64() {
md5Str := Md5StringWithBase64("hello")
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
func ExampleMd5Byte() {
md5Str := Md5Byte([]byte{'a'})
fmt.Println(md5Str)
@@ -380,6 +428,15 @@ func ExampleMd5Byte() {
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
func ExampleMd5ByteWithBase64() {
md5Str := Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
func ExampleSha1() {
result := Sha1("hello")
fmt.Println(result)
@@ -388,6 +445,14 @@ func ExampleSha1() {
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
}
func ExampleSha1WithBase64() {
result := Sha1WithBase64("hello")
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
func ExampleSha256() {
result := Sha256("hello")
fmt.Println(result)
@@ -396,6 +461,14 @@ func ExampleSha256() {
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
}
func ExampleSha256WithBase64() {
result := Sha256WithBase64("hello")
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
func ExampleSha512() {
result := Sha512("hello")
fmt.Println(result)
@@ -403,3 +476,11 @@ func ExampleSha512() {
// Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
}
func ExampleSha512WithBase64() {
result := Sha512WithBase64("hello")
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}

View File

@@ -7,6 +7,7 @@ package datastructure
import (
"fmt"
"hash/fnv"
"reflect"
)
var defaultMapCapacity uint64 = 1 << 10
@@ -45,13 +46,24 @@ func NewHashMapWithCapacity(size, capacity uint64) *HashMap {
func (hm *HashMap) Get(key any) any {
hashValue := hm.hash(key)
node := hm.table[hashValue]
if node != nil {
return node.value
for node != nil {
if reflect.DeepEqual(node.key, key) {
return node.value
}
node = node.next
}
return nil
}
// GetOrDefault return the value of given key in hashmap, if not found return default value
func (hm *HashMap) GetOrDefault(key any, defaultValue any) any {
value := hm.Get(key)
if value == nil {
return defaultValue
}
return value
}
// Put new key value in hashmap
func (hm *HashMap) Put(key any, value any) {
hm.putValue(hm.hash(key), key, value)
@@ -90,7 +102,13 @@ func (hm *HashMap) Delete(key any) {
// Contains checks if given key is in hashmap or not
func (hm *HashMap) Contains(key any) bool {
node := hm.table[hm.hash(key)]
return node != nil
for node != nil {
if reflect.DeepEqual(node.key, key) {
return true
}
node = node.next
}
return false
}
// Iterate executes iteratee funcation for every key and value pair of hashmap (random order)

View File

@@ -74,3 +74,34 @@ func TestHashMap_KeysValues(t *testing.T) {
assert.Equal(3, len(values))
assert.Equal(3, len(keys))
}
func TestHashMap_Keys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Keys")
hm := NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
keys := hm.Keys()
assert.Equal(3, len(keys))
}
func TestHashMap_GetOrDefault(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_GetOrDefault")
hm := NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
assert.Equal(1, hm.GetOrDefault("a", 5))
assert.Equal(5, hm.GetOrDefault("d", 5))
}

View File

@@ -0,0 +1,350 @@
package datastructure
import (
"reflect"
"sort"
"sync"
)
type CopyOnWriteList[T any] struct {
data []T
lock sync.Locker
}
// NewCopyOnWriteList Creates an empty list.
func NewCopyOnWriteList[T any](data []T) *CopyOnWriteList[T] {
return &CopyOnWriteList[T]{data: data, lock: &sync.RWMutex{}}
}
func (c *CopyOnWriteList[T]) getList() []T {
return c.data
}
func (c *CopyOnWriteList[T]) setList(data []T) {
c.data = data
}
// Size returns the number of elements in this list.
func (c *CopyOnWriteList[T]) Size() int {
return len(c.getList())
}
// IsEmpty returns true if this list contains no elements.
func (c *CopyOnWriteList[T]) IsEmpty() bool {
return c.Size() == 0
}
// Contain returns true if this list contains the specified element.
func (c *CopyOnWriteList[T]) Contain(e T) bool {
list := c.getList()
return indexOf(e, list, 0, c.Size()) >= 0
}
// ValueOf returns the index of the first occurrence of the specified element in this list, or null if this list does not contain the element.
func (c *CopyOnWriteList[T]) ValueOf(index int) (*T, bool) {
list := c.getList()
if index < 0 || index >= len(c.data) {
return nil, false
}
return get(list, index), true
}
// IndexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
func (c *CopyOnWriteList[T]) IndexOf(e T) int {
list := c.getList()
return indexOf(e, list, 0, c.Size())
}
// indexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
// start the start position of the search (inclusive)
// end the end position of the search (exclusive)
func indexOf[T any](o T, e []T, start int, end int) int {
if start >= end {
return -1
}
for i := start; i < end; i++ {
if reflect.DeepEqual(e[i], o) {
return i
}
}
return -1
}
// LastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int {
list := c.getList()
return lastIndexOf(e, list, 0, c.Size())
}
// lastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
// start the start position of the search (inclusive)
// end the end position of the search (exclusive)
func lastIndexOf[T any](o T, e []T, start int, end int) int {
if start >= end {
return -1
}
for i := end - 1; i >= start; i-- {
if reflect.DeepEqual(e[i], o) {
return i
}
}
return -1
}
// get returns the element at the specified position in this list.
func get[T any](o []T, index int) *T {
return &o[index]
}
// Get returns the element at the specified position in this list.
func (c *CopyOnWriteList[T]) Get(index int) *T {
list := c.getList()
if index < 0 || index >= len(list) {
return nil
}
return get(list, index)
}
func (c *CopyOnWriteList[T]) set(index int, e T) (oldValue *T) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
oldValue = get(list, index)
if reflect.DeepEqual(oldValue, e) {
c.setList(list)
} else {
newList := make([]T, len(list))
copy(newList, list)
newList[index] = e
c.setList(newList)
}
return
}
// Set replaces the element at the specified position in this list with the specified element.
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool) {
list := c.getList()
if index < 0 || index >= len(list) {
return oldValue, false
}
return c.set(index, e), true
}
// Add appends the specified element to the end of this list.
func (c *CopyOnWriteList[T]) Add(e T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
newList := make([]T, len(list)+1)
copy(newList, list)
newList[len(list)] = e
c.setList(newList)
return true
}
// AddAll appends all the elements in the specified collection to the end of this list
func (c *CopyOnWriteList[T]) AddAll(e []T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
newList := make([]T, len(list)+len(e))
copy(newList, list)
copy(newList[len(list):], e)
c.setList(newList)
return true
}
// AddByIndex inserts the specified element at the specified position in this list.
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
if index < 0 || index > length {
return false
}
var newList []T
var numMove = length - index
if numMove == 0 {
newList = make([]T, length+1)
copy(newList, list)
} else {
newList = make([]T, length+1)
copy(newList, list[:index])
copy(newList[index+1:], list[index:])
}
newList[index] = e
c.setList(newList)
return true
}
// delete removes the element at the specified position in this list.
func (c *CopyOnWriteList[T]) delete(index int) *T {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
oldValue := get(list, index)
numMove := length - index - 1
var newList []T
if numMove == 0 {
newList = make([]T, length-1)
copy(newList, list[:index])
} else {
newList = make([]T, length-1)
copy(newList, list[:index])
copy(newList[index:], list[index+1:])
}
c.setList(newList)
return oldValue
}
// DeleteAt removes the element at the specified position in this list.
func (c *CopyOnWriteList[T]) DeleteAt(index int) (*T, bool) {
list := c.getList()
if index < 0 || index >= len(list) {
return nil, false
}
return c.delete(index), true
}
// DeleteBy removes the first occurrence of the specified element from this list, if it is present.
func (c *CopyOnWriteList[T]) DeleteBy(o T) (*T, bool) {
list := c.getList()
index := indexOf(o, list, 0, len(list))
if index == -1 {
return nil, false
}
return c.delete(index), true
}
// DeleteRange removes from this list all the elements whose index is between fromIndex, inclusive, and toIndex, exclusive.
// left close and right open
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
if start < 0 || end > length || start > end {
return
}
var newList []T
numMove := length - end
if numMove == 0 {
newList = make([]T, length-(end-start))
copy(newList, list[:start])
} else {
newList = make([]T, length-(end-start))
copy(newList, list[:start])
copy(newList[start:], list[end:])
}
c.setList(newList)
}
// DeleteIf removes all the elements of this collection that satisfy the given predicate.
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
var newList []T
for i := 0; i < length; i++ {
if !f(list[i]) {
newList = append(newList, list[i])
}
}
c.setList(newList)
}
// Equal returns true if the specified object is equal to this list.
func (c *CopyOnWriteList[T]) Equal(other *[]T) bool {
if other == nil {
return false
}
if c.Size() != len(*other) {
return false
}
list := c.getList()
otherList := NewCopyOnWriteList(*other).getList()
for i := 0; i < len(list); i++ {
if !reflect.DeepEqual(list[i], otherList[i]) {
return false
}
}
return true
}
// Clear removes all the elements from this list.
func (c *CopyOnWriteList[T]) Clear() {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
list = make([]T, 0)
c.setList(list)
}
// Merge a tow list to one, change the list
func (c *CopyOnWriteList[T]) Merge(other []T) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
list = append(list, other...)
c.setList(list)
}
// ForEach performs the given action for each element of the Iterable until all elements have been processed
// or the action throws an exception.
func (c *CopyOnWriteList[T]) ForEach(f func(T)) {
list := c.getList()
for i := 0; i < len(list); i++ {
f(list[i])
}
}
// Sort sorts this list according to the order induced by the specified Comparator.
func (c *CopyOnWriteList[T]) Sort(compare func(o1 T, o2 T) bool) {
lock := c.lock
lock.Lock()
list := c.getList()
sort.Slice(list, func(i, j int) bool {
return compare(list[i], list[j])
})
c.setList(list)
}
func (c *CopyOnWriteList[T]) SubList(start int, end int) (newList []T) {
lock := c.lock
lock.Lock()
list := c.getList()
length := len(list)
defer lock.Unlock()
if start < 0 || end > length || start > end {
return []T{}
}
newList = make([]T, end-start)
copy(newList, list[start:end])
c.setList(newList)
return
}

View File

@@ -0,0 +1,235 @@
package datastructure
import (
"github.com/duke-git/lancet/v2/internal"
"testing"
)
func TestCopyOnWriteList_ValueOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
of, ok := list.ValueOf(3)
assert.Equal(4, *of)
assert.Equal(true, ok)
_, ok = list.ValueOf(6)
assert.Equal(false, ok)
}
func TestCopyOnWriteList_Contain(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Contains")
assert.Equal(true, list.Contain(3))
}
func TestCopyOnWriteList_IsEmpty(t *testing.T) {
list := NewCopyOnWriteList([]int{})
assert := internal.NewAssert(t, "CopyOnWriteList_IsEmpty")
assert.Equal(true, list.IsEmpty())
}
func TestCopyOnWriteList_Size(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_size")
assert.Equal(5, list.Size())
}
func TestCopyOnWriteList_GetList(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_GetList")
assert.Equal([]int{1, 2, 3, 4, 5}, list.getList())
}
func TestCopyOnWriteList_Get(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Get")
i := list.Get(2)
assert.Equal(3, *i)
}
func TestCopyOnWriteList_Set(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Set")
list.Set(2, 6)
assert.Equal(6, list.getList()[2])
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.Set(0, 6)
assert.Equal(6, list.getList()[0])
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.Set(0, 1)
assert.Equal(1, list.getList()[0])
}
func TestCopyOnWriteList_Add(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Add")
list.Add(6)
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
}
func TestCopyOnWriteList_AddAll(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_AddAll")
list.AddAll([]int{6, 7, 8})
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8}, list.getList())
}
func TestCopyOnWriteList_AddByIndex(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_AddByIndex")
list.AddByIndex(2, 6)
assert.Equal([]int{1, 2, 6, 3, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.AddByIndex(0, 6)
assert.Equal([]int{6, 1, 2, 3, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.AddByIndex(5, 6)
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
}
func TestCopyOnWriteList_DeleteAt2(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByIndex")
list.DeleteAt(2)
assert.Equal([]int{1, 2, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.DeleteAt(4)
assert.Equal([]int{1, 2, 3, 4}, list.getList())
}
func TestCopyOnWriteList_RemoveByValue(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByValue")
list.DeleteBy(3)
assert.Equal([]int{1, 2, 4, 5}, list.getList())
}
func TestCopyOnWriteList_DeleteRange(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveRange")
list.DeleteRange(1, 3)
assert.Equal([]int{1, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.DeleteRange(0, 5)
assert.Equal([]int{}, list.getList())
}
func TestCopyOnWriteList_LastIndexOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_LastIndexOf")
assert.Equal(5, list.LastIndexOf(3))
}
func TestCopyOnWriteList_DeleteAt(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteAt")
list.DeleteAt(2)
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
}
func TestCopyOnWriteList_DeleteBy(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteBy")
list.DeleteBy(3)
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
}
func TestCopyOnWriteList_DeleteIf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteIf")
list.DeleteIf(func(i int) bool {
return i%2 == 0
})
assert.Equal([]int{1, 3, 5, 3}, list.getList())
}
func TestCopyOnWriteList_Equal(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_Equal")
assert.Equal(true, list.Equal(&[]int{1, 2, 3, 4, 5, 3, 6}))
}
func TestCopyOnWriteList_ForEach(t *testing.T) {
testList := make([]int, 0)
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_ForEach")
list.ForEach(func(i int) {
testList = append(testList, i)
})
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6}, testList)
list.ForEach(func(i int) {
list.Add(i)
})
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6, 1, 2, 3, 4, 5, 3, 6}, list.getList())
}
func TestCopyOnWriteList_Clear(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_Clear")
list.Clear()
assert.Equal([]int{}, list.getList())
}
func TestCopyOnWriteList_Merge(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9})
assert := internal.NewAssert(t, "CopyOnWriteList_Merge")
list.Merge([]int{2, 4, 6, 8, 10})
assert.Equal([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}, list.getList())
}
func TestCopyOnWriteList_Sort(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_Sort")
list.Sort(func(i, j int) bool {
return i < j
})
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, list.getList())
}
func TestCopyOnWriteList_IndexOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
assert.Equal(0, list.IndexOf(1))
assert.Equal(9, list.IndexOf(10))
assert.Equal(-1, list.IndexOf(11))
}
func TestCopyOnWriteList_SubList(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_SubList")
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList := list.SubList(1, 3)
assert.Equal([]int{3, 5}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList = list.SubList(1, 1)
assert.Equal([]int{}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert.Equal(10, list.Size())
subList = list.SubList(1, 10)
assert.Equal([]int{3, 5, 7, 9, 2, 4, 6, 8, 10}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList = list.SubList(11, 1)
assert.Equal([]int{}, subList)
}

View File

@@ -271,7 +271,7 @@ func (l *List[T]) Reverse() {
}
}
// Unique remove duplicate items in list.
// Unique delete duplicate items in list.
func (l *List[T]) Unique() {
data := l.data
size := len(data)
@@ -294,7 +294,7 @@ func (l *List[T]) Unique() {
l.data = uniqueData
}
// Union creates a new list contain all element in list l and other, remove duplicate element.
// Union creates a new list contain all element in list l and other, delete duplicate element.
func (l *List[T]) Union(other *List[T]) *List[T] {
result := NewList([]T{})

View File

@@ -3,7 +3,7 @@
// Package datetime implements some functions to format date and time.
// Note:
// 1. `format` param in FormatTimeToStr function should be as flow:
// 1. `format` param in FormatTimeToStr function should be as flow (case no sensitive):
// "yyyy-mm-dd hh:mm:ss"
// "yyyy-mm-dd hh:mm"
// "yyyy-mm-dd hh"
@@ -18,14 +18,19 @@
// "yyyy/mm"
// "mm/dd"
// "dd/mm/yy hh:mm:ss"
// "yyyymmdd"
// "mmddyy"
// "yyyy"
// "yy"
// "mm"
// "hh:mm:ss"
// "hh:mm"
// "mm:ss"
package datetime
import (
"fmt"
"strings"
"time"
)
@@ -47,9 +52,13 @@ func init() {
"yyyy/mm": "2006/01",
"mm/dd": "01/02",
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
"yyyymmdd": "20060102",
"mmddyy": "010206",
"yyyy": "2006",
"yy": "06",
"mm": "01",
"hh:mm:ss": "15:04:05",
"hh:mm": "15:04",
"mm:ss": "04:05",
}
}
@@ -97,13 +106,13 @@ func GetNowDateTime() string {
}
// GetTodayStartTime return the start time of today, format: yyyy-mm-dd 00:00:00.
// Play: todo
// Play: https://go.dev/play/p/84siyYF7t99
func GetTodayStartTime() string {
return time.Now().Format("2006-01-02") + " 00:00:00"
}
// GetTodayEndTime return the end time of today, format: yyyy-mm-dd 23:59:59.
// Play: todo
// Play: https://go.dev/play/p/jjrLnfoqgn3
func GetTodayEndTime() string {
return time.Now().Format("2006-01-02") + " 23:59:59"
}
@@ -124,19 +133,40 @@ func GetNightTimestamp() int64 {
// FormatTimeToStr convert time to string.
// Play: https://go.dev/play/p/_Ia7M8H_OvE
func FormatTimeToStr(t time.Time, format string) string {
return t.Format(timeFormat[format])
func FormatTimeToStr(t time.Time, format string, timezone ...string) string {
tf, ok := timeFormat[strings.ToLower(format)]
if !ok {
return ""
}
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return ""
}
return t.In(loc).Format(tf)
}
return t.Format(tf)
}
// FormatStrToTime convert string to time.
// Play: https://go.dev/play/p/1h9FwdU8ql4
func FormatStrToTime(str, format string) (time.Time, error) {
v, ok := timeFormat[format]
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error) {
tf, ok := timeFormat[strings.ToLower(format)]
if !ok {
return time.Time{}, fmt.Errorf("format %s not found", format)
return time.Time{}, fmt.Errorf("format %s not support", format)
}
return time.Parse(v, str)
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return time.Time{}, err
}
return time.ParseInLocation(tf, str, loc)
}
return time.Parse(tf, str)
}
// BeginOfMinute return beginning minute time of day.
@@ -262,6 +292,92 @@ func DayOfYear(t time.Time) int {
// IsWeekend checks if passed time is weekend or not.
// Play: https://go.dev/play/p/cupRM5aZOIY
// Deprecated Use '== Weekday' instead
func IsWeekend(t time.Time) bool {
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
}
// NowDateOrTime return current datetime with specific format and timezone.
// Play: https://go.dev/play/p/EZ-begEjtT0
func NowDateOrTime(format string, timezone ...string) string {
tf, ok := timeFormat[strings.ToLower(format)]
if !ok {
return ""
}
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return ""
}
return time.Now().In(loc).Format(tf)
}
return time.Now().Format(tf)
}
// Timestamp return current second timestamp.
// Play: https://go.dev/play/p/iU5b7Vvjx6x
func Timestamp(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return t.Unix()
}
// TimestampMilli return current mill second timestamp.
// Play: https://go.dev/play/p/4gvEusOTu1T
func TimestampMilli(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Millisecond)
}
// TimestampMicro return current micro second timestamp.
// Play: https://go.dev/play/p/2maANglKHQE
func TimestampMicro(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Microsecond)
}
// TimestampNano return current nano second timestamp.
// Play: https://go.dev/play/p/A9Oq_COrcCF
func TimestampNano(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return t.UnixNano()
}

View File

@@ -147,6 +147,9 @@ func TestFormatTimeToStr(t *testing.T) {
actual := FormatTimeToStr(datetime, cases[i])
assert.Equal(expected[i], actual)
}
ds := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss", "EST")
t.Log(ds)
}
func TestFormatStrToTime(t *testing.T) {
@@ -163,19 +166,23 @@ func TestFormatStrToTime(t *testing.T) {
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
"yyyy/mm"}
datetimeStr := []string{
expected := []string{
"2021-01-02 16:04:08", "2021-01-02",
"02-01-21 16:04:08", "2021/01/02 16:04:08",
"2021/01"}
for i := 0; i < len(cases); i++ {
actual, err := FormatStrToTime(datetimeStr[i], cases[i])
actual, err := FormatStrToTime(expected[i], cases[i])
if err != nil {
t.Fatal(err)
}
expected, _ := time.Parse(formats[i], datetimeStr[i])
expected, _ := time.Parse(formats[i], expected[i])
assert.Equal(expected, actual)
}
estTime, err := FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss", "EST")
t.Log(estTime)
assert.IsNil(err)
}
func TestBeginOfMinute(t *testing.T) {
@@ -368,3 +375,38 @@ func TestIsWeekend(t *testing.T) {
result2 := IsWeekend(date2)
assert.Equal(false, result2)
}
func TestNowDateOrTime(t *testing.T) {
t.Parallel()
formats := []string{
"yyyy-mm-dd hh:mm:ss",
"yyyy-mm-dd",
"dd-mm-yy hh:mm:ss",
"yyyy/mm/dd hh:mm:ss",
"hh:mm:ss",
"yyyy/mm",
"yyyy-mm-dd hh",
}
for i := 0; i < len(formats); i++ {
result := NowDateOrTime(formats[i], "UTC")
t.Log(result)
}
}
func TestTimestamp(t *testing.T) {
t.Parallel()
ts1 := Timestamp()
t.Log(ts1)
ts2 := TimestampMilli()
t.Log(ts2)
ts3 := TimestampMicro()
t.Log(ts3)
ts4 := TimestampNano()
t.Log(ts4)
}

89
docs/.vitepress/common.ts Normal file
View File

@@ -0,0 +1,89 @@
import { defineConfig, HeadConfig } from 'vitepress'
export const META_IMAGE = '/lancet_logo.png'
export const isProduction = process.env.NETLIFY && process.env.CONTEXT === 'production'
if (process.env.NETLIFY) {
console.log('Netlify build', process.env.CONTEXT)
}
const productionHead: HeadConfig[] = [
[
'script',
{
src: 'https://unpkg.com/thesemetrics@latest',
async: '',
type: 'text/javascript',
},
],
]
const rControl = /[\u0000-\u001f]/g
const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g
const rCombining = /[\u0300-\u036F]/g
/**
* Default slugification function
*/
export const slugify = (str: string): string =>
str
.normalize('NFKD')
// Remove accents
.replace(rCombining, '')
// Remove control characters
.replace(rControl, '')
// Replace special characters
.replace(rSpecial, '-')
// ensure it doesn't start with a number
.replace(/^(\d)/, '_$1')
export const commonConfig = defineConfig({
title: 'Lancet',
appearance: 'dark',
markdown: {
theme: {
dark: 'dracula-soft',
light: 'vitesse-light',
},
attrs: {
leftDelimiter: '%{',
rightDelimiter: '}%',
},
anchor: {
slugify,
},
},
head: [
// ['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
['link', { rel: 'icon', type: 'image/png', href: '/lancet_logo_mini.png' }],
['meta', { name: 'theme-color', content: '#5f67ee' }],
['meta', { name: 'og:type', content: 'website' }],
['meta', { name: 'og:locale', content: 'zh' }],
...(isProduction ? productionHead : []),
],
themeConfig: {
logo: { src: '/lancet_logo_mini.png', width: 24, height: 24 },
outline: [2, 3],
search: {
provider: 'local',
},
socialLinks: [
{
icon: 'github',
link: 'https://github.com/duke-git/lancet',
},
],
footer: {
copyright: 'Copyright © 2023-present Duke Du',
message: 'Released under the MIT License.',
},
},
})

View File

@@ -0,0 +1,14 @@
import { defineConfig } from 'vitepress'
import { commonConfig } from './common'
import { zhConfig } from './zh'
import { enConfig } from './en'
// https://vitepress.dev/reference/site-config
export default defineConfig({
...commonConfig,
locales: {
root: { label: '简体中文', lang: 'zh-CN', link: '/', ...zhConfig },
en: { label: 'English', lang: 'en-US', link: '/en/', ...enConfig },
},
})

75
docs/.vitepress/en.ts Normal file
View File

@@ -0,0 +1,75 @@
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
export const META_URL = 'https://lancet.go.dev'
export const META_TITLE = 'Lancet'
export const META_DESCRIPTION = 'A powerful util function library of Go'
export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
description: META_DESCRIPTION,
head: [
['meta', { property: 'og:url', content: META_URL }],
['meta', { property: 'og:description', content: META_DESCRIPTION }],
['meta', { property: 'twitter:url', content: META_URL }],
['meta', { property: 'twitter:title', content: META_TITLE }],
['meta', { property: 'twitter:description', content: META_DESCRIPTION }],
],
themeConfig: {
nav: [
{
text: 'Home',
link: '/en/',
activeMatch: '^/en/',
},
{
text: 'Guide',
link: '/en/guide/introduction',
activeMatch: '^/en/guide/',
},
{ text: 'API', link: '/en/api/overview', activeMatch: '^/en/api/' },
{
text: 'Links',
items: [
{
text: 'Releaselog',
link: 'https://github.com/duke-git/lancet/releases',
},
],
},
],
sidebar: {
'/en/': [
{
text: 'Introduction',
items: [
{
text: 'What is Lancet',
link: '/en/guide/introduction',
},
{
text: 'getting started',
link: '/en/guide/getting_started',
},
],
},
],
'/en/api/': [
{
text: 'overview',
items: [{ text: 'overview of API', link: '/en/api/overview' }],
},
{
text: 'packages',
items: [
{ text: 'algorithm', link: '/en/api/packages/algorithm' },
{ text: 'compare', link: '/en/api/packages/compare' },
{ text: 'concurrency', link: '/en/api/packages/concurrency' },
{ text: 'condition', link: '/en/api/packages/condition' },
],
},
],
},
},
}

85
docs/.vitepress/zh.ts Normal file
View File

@@ -0,0 +1,85 @@
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
export const META_URL = 'https://lancet.go.dev'
export const META_TITLE = 'Lancet'
export const META_DESCRIPTION = '一个强大的Go语言工具函数库'
export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
description: META_DESCRIPTION,
head: [
['meta', { property: 'og:url', content: META_URL }],
['meta', { property: 'og:description', content: META_DESCRIPTION }],
['meta', { property: 'twitter:url', content: META_URL }],
['meta', { property: 'twitter:title', content: META_TITLE }],
['meta', { property: 'twitter:description', content: META_DESCRIPTION }],
],
themeConfig: {
outline: {
label: '本页内容',
},
docFooter: {
prev: '上一页',
next: '下一页',
},
nav: [
{
text: '首页',
link: '/',
activeMatch: '^/',
},
{
text: '指南',
link: '/guide/introduction',
activeMatch: '^/guide/',
},
{ text: 'API', link: '/api/overview', activeMatch: '^/api/' },
{
text: '相关链接',
items: [
{
text: '更新日志',
link: 'https://github.com/duke-git/lancet/releases',
},
],
},
],
sidebar: {
'/': [
{
text: '介绍',
items: [
{
text: 'Lancet是什么',
link: '/guide/introduction',
},
{
text: '开始',
link: '/guide/getting_started',
},
],
},
],
'/api/': [
{
text: '概览',
items: [{ text: 'API概述', link: '/api/overview' }],
},
{
text: 'API文档',
items: [
{ text: '算法', link: '/api/packages/algorithm' },
{ text: '比较器', link: '/api/packages/compare' },
{ text: '并发处理', link: '/api/packages/concurrency' },
{ text: '条件判断', link: '/api/packages/condition' },
],
},
],
},
},
}

69
docs/api/overview.md Normal file
View File

@@ -0,0 +1,69 @@
---
outline: deep
---
# API概述
<b>lancet柳叶刀是一个强大、全面、高效、可复用的go语言工具函数库。包含25个包超过600个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。</b>
<style>
.package-title {
color: black;
font-size: 18px;
text-align: center;
font-weight: bold;
}
.package-container {
font-size: 16px;
border: 1px dashed;
padding: 10px;
text-align: center;
}
.package-cell {
height: 40px;
width: 140px;
display: inline-block;
vertical-align: middle;
line-height: 40px;
background: #ecefff;
border: 1px solid;
margin-right: 10px;
margin-bottom: 10px;
border-radius: 6px;
font-weight: bold;
}
</style>
<div>
<p class="package-title">lancet功能模块</p>
<div class="package-container">
<div class="package-cell">algorithm</div>
<div class="package-cell">compare</div>
<div class="package-cell">concurrency</div>
<div class="package-cell">condition</div>
<div class="package-cell">convertor</div>
<div class="package-cell">cryptor</div>
<div class="package-cell">datastructure</div>
<div class="package-cell">datetime</div>
<div class="package-cell">fileutil</div>
<div class="package-cell">formatter</div>
<div class="package-cell">function</div>
<div class="package-cell">iterator</div>
<div class="package-cell">maputil</div>
<div class="package-cell">mathutil</div>
<div class="package-cell">netutil</div>
<div class="package-cell">pointer</div>
<div class="package-cell">random</div>
<div class="package-cell">retry</div>
<div class="package-cell">slice</div>
<div class="package-cell">stream</div>
<div class="package-cell">structs</div>
<div class="package-cell">strutil</div>
<div class="package-cell">system</div>
<div class="package-cell">tuple</div>
<div class="package-cell">validator</div>
<div class="package-cell">xerror</div>
</div>
</div>

View File

@@ -39,6 +39,8 @@ import (
<div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## 文档
### <span id="BubbleSort">BubbleSort</span>
@@ -51,7 +53,7 @@ import (
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
```go
package main
@@ -99,7 +101,7 @@ func main() {
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
```go
package main
@@ -162,7 +164,7 @@ func main() {
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/oXovbkekayS)</span></b>
```go
package main
@@ -210,7 +212,7 @@ func main() {
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/3ibkszpJEu3)</span></b>
```go
package main
@@ -258,7 +260,7 @@ func main() {
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
```go
package main
@@ -306,7 +308,7 @@ func main() {
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
```go
package main
@@ -354,7 +356,7 @@ func main() {
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ydinn9YzUJn)</span></b>
```go
package main
@@ -402,7 +404,7 @@ func main() {
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
```go
package main
@@ -451,7 +453,7 @@ func main() {
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/t6MeGiUSN47)</span></b>
```go
package main
@@ -502,7 +504,7 @@ func main() {
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
```go
package main
@@ -553,7 +555,7 @@ func main() {
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
```go
package main
@@ -596,7 +598,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/-EZjgOURufP)</span></b>
```go
package main

View File

@@ -30,10 +30,14 @@ import (
- [GreaterThan](#GreaterThan)
- [LessOrEqual](#LessOrEqual)
- [GreaterOrEqual](#GreaterOrEqual)
- [InDelta](#InDelta)
<div STYLE="page-break-after: always;"></div>
## Documentation
<link rel="stylesheet" type="text/css" href="../../styles/api_doc.css">
## 文档
### <span id="Equal">Equal</span>
@@ -45,7 +49,7 @@ import (
func Equal(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/wmVxR-to4lz)</span></b>
```go
package main
@@ -94,7 +98,7 @@ func main() {
func EqualValue(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/fxnna_LLD9u)</span></b>
```go
package main
@@ -133,7 +137,7 @@ func main() {
func LessThan(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/cYh7FQQj0ne)</span></b>
```go
package main
@@ -182,7 +186,7 @@ func main() {
func GreaterThan(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/9-NYDFZmIMp)</span></b>
```go
package main
@@ -234,7 +238,7 @@ func main() {
func LessOrEqual(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/e4T_scwoQzp)</span></b>
```go
package main
@@ -283,7 +287,7 @@ func main() {
func GreaterOrEqual(left, right any) bool
```
<b>示例:</b>
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/vx8mP0U8DFk)</span></b>
```go
package main
@@ -324,3 +328,50 @@ func main() {
// false
}
```
### <span id="InDelta">InDelta</span>
<p>检查增量内两个值是否相等。</p>
<b>函数签名:</b>
```go
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool
```
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/TuDdcNtMkjo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := InDelta(1, 1, 0)
result2 := InDelta(1, 2, 0)
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
result4 := InDelta(2.0/3.0, 0.0, 0.001)
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// false
// true
// false
// false
// true
}
```

View File

@@ -33,11 +33,15 @@ import (
<div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## 文档
### Channel
### <span id="NewChannel">NewChannel</span>
<p>返回一个Channel指针实例</p>
<b>函数签名:</b>
@@ -46,7 +50,7 @@ import (
type Channel[T any] struct
func NewChannel[T any]() *Channel[T]
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go
package main
@@ -70,7 +74,7 @@ func main() {
```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
```go
package main
@@ -122,7 +126,7 @@ func main() {
```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/2VYFMexEvTm)</span></b>
```go
package main
@@ -161,7 +165,7 @@ func main() {
```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go
package main
@@ -199,7 +203,7 @@ func main() {
```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
```go
package main
@@ -238,7 +242,7 @@ func main() {
```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/4J1zAWttP85)</span></b>
```go
package main
@@ -279,7 +283,7 @@ func main() {
```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/Wqz9rwioPww)</span></b>
```go
package main
@@ -322,7 +326,7 @@ func main() {
```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
```go
package main
@@ -360,7 +364,7 @@ func main() {
```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
```go
package main
@@ -406,7 +410,7 @@ func main() {
```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/3TQPKnCirrP)</span></b>
```go
package main

View File

@@ -18,7 +18,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
## 目录
- [Bool](#Bool)
- [And](#And)
@@ -31,7 +31,9 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## 文档
### <span id="Bool">Bool</span>
<p>返回传入参数的bool值.<br/>
@@ -45,7 +47,7 @@ slices和map的length大于0时返回true否则返回false<br/>
```go
func Bool[T any](value T) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
```go
package main
@@ -109,7 +111,7 @@ func main() {
```go
func And[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
```go
package main
@@ -135,7 +137,7 @@ func main() {
```go
func Or[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
```go
package main
@@ -161,7 +163,7 @@ func main() {
```go
func Xor[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
```go
package main
@@ -187,7 +189,7 @@ func main() {
```go
func Nor[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
```go
package main
@@ -213,7 +215,7 @@ func main() {
```go
func Xnor[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
```go
package main
@@ -239,7 +241,7 @@ func main() {
```go
func Nand[T, U any](a T, b U) bool
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
```go
package main
@@ -265,7 +267,7 @@ func main() {
```go
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
```
<b>示例:</b>
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
```go
package main

70
docs/en/api/overview.md Normal file
View File

@@ -0,0 +1,70 @@
---
outline: deep
---
# API Overview
<b>Lancet (Lancet) is a powerful, comprehensive, efficient and reusable go language tool function library. Contains 25 packages, more than 600 utility functions. Functions cover string processing, slice processing, network, concurrency, encryption and decryption, file processing, time/date, stream processing, iterators, and more.</b>
<style>
.package-title {
color: black;
font-size: 18px;
text-align: center;
font-weight: bold;
}
.package-container {
font-size: 16px;
border: 1px dashed;
padding: 10px;
text-align: center;
}
.package-cell {
height: 40px;
width: 140px;
display: inline-block;
vertical-align: middle;
line-height: 40px;
background: #ecefff;
border: 1px solid;
margin-right: 10px;
margin-bottom: 10px;
border-radius: 6px;
font-weight: bold;
}
</style>
<div>
<p class="package-title">lancet function module</p>
<div class="package-container">
<div class="package-cell">algorithm</div>
<div class="package-cell">compare</div>
<div class="package-cell">concurrency</div>
<div class="package-cell">condition</div>
<div class="package-cell">convertor</div>
<div class="package-cell">cryptor</div>
<div class="package-cell">datastructure</div>
<div class="package-cell">datetime</div>
<div class="package-cell">fileutil</div>
<div class="package-cell">formatter</div>
<div class="package-cell">function</div>
<div class="package-cell">iterator</div>
<div class="package-cell">maputil</div>
<div class="package-cell">mathutil</div>
<div class="package-cell">netutil</div>
<div class="package-cell">pointer</div>
<div class="package-cell">random</div>
<div class="package-cell">retry</div>
<div class="package-cell">slice</div>
<div class="package-cell">stream</div>
<div class="package-cell">structs</div>
<div class="package-cell">strutil</div>
<div class="package-cell">system</div>
<div class="package-cell">tuple</div>
<div class="package-cell">validator</div>
<div class="package-cell">xerror</div>
</div>
</div>

View File

@@ -12,6 +12,8 @@ Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## Usage
```go
@@ -51,7 +53,7 @@ import (
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
```go
package main
@@ -99,7 +101,7 @@ func main() {
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
```go
package main
@@ -162,7 +164,7 @@ func main() {
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/oXovbkekayS)</span></b>
```go
package main
@@ -210,7 +212,7 @@ func main() {
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/3ibkszpJEu3)</span></b>
```go
package main
@@ -258,7 +260,7 @@ func main() {
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example:<span class="run-container">[Run](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
```go
package main
@@ -306,7 +308,7 @@ func main() {
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
```go
package main
@@ -354,7 +356,7 @@ func main() {
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/ydinn9YzUJn)</span></b>
```go
package main
@@ -402,7 +404,7 @@ func main() {
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
```go
package main
@@ -451,7 +453,7 @@ func main() {
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/t6MeGiUSN47)</span></b>
```go
package main
@@ -502,7 +504,7 @@ func main() {
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
```go
package main
@@ -553,7 +555,7 @@ func main() {
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
```go
package main
@@ -596,7 +598,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
```go
package main

View File

@@ -30,16 +30,19 @@ import (
- [GreaterThan](#GreaterThan)
- [LessOrEqual](#LessOrEqual)
- [GreaterOrEqual](#GreaterOrEqual)
- [InDelta](#InDelta)
<div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## Documentation
### <span id="Equal">Equal</span>
<p>Checks if two values are equal or not. (check both type and value)</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/wmVxR-to4lz)</span></b>
```go
func Equal(left, right any) bool
@@ -88,7 +91,7 @@ func main() {
<p>Checks if two values are equal or not. (check value only)</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/fxnna_LLD9u)</span></b>
```go
func EqualValue(left, right any) bool
@@ -127,7 +130,7 @@ func main() {
<p>Checks if value `left` less than value `right`.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/cYh7FQQj0ne)</span></b>
```go
func LessThan(left, right any) bool
@@ -182,7 +185,7 @@ func main() {
func GreaterThan(left, right any) bool
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/9-NYDFZmIMp)</span></b>
```go
package main
@@ -234,7 +237,7 @@ func main() {
func LessOrEqual(left, right any) bool
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/e4T_scwoQzp)</span></b>
```go
package main
@@ -277,7 +280,7 @@ func main() {
<p>Checks if value `left` less greater or equal than value `right`.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/vx8mP0U8DFk)</span></b>
```go
func GreaterOrEqual(left, right any) bool
@@ -324,3 +327,50 @@ func main() {
// false
}
```
### <span id="InDelta">InDelta</span>
<p>Checks if two values are equal or not within a delta.</p>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/TuDdcNtMkjo)</span></b>
```go
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := InDelta(1, 1, 0)
result2 := InDelta(1, 2, 0)
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
result4 := InDelta(2.0/3.0, 0.0, 0.001)
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// false
// true
// false
// false
// true
}
```

View File

@@ -33,8 +33,9 @@ import (
<div STYLE="page-break-after: always;"></div>
## Documentation
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## Documentation
## Channel
### <span id="NewChannel">NewChannel</span>
@@ -46,7 +47,7 @@ import (
type Channel[T any] struct
func NewChannel[T any]() *Channel[T]
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go
package main
@@ -70,7 +71,7 @@ func main() {
```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
```go
package main
@@ -122,7 +123,7 @@ func main() {
```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/2VYFMexEvTm)</span></b>
```go
package main
@@ -156,7 +157,7 @@ func main() {
<p>Create channel, put values into the channel repeatly until cancel the context.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
@@ -200,7 +201,7 @@ func main() {
```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
```
<b>Example:</b>
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go
package main
@@ -233,7 +234,7 @@ func main() {
<p>Create a channel, excutes fn repeatly, and put the result into the channel, until close context.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/4J1zAWttP85)</span></b>
```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
@@ -275,7 +276,7 @@ func main() {
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/Wqz9rwioPww)</span></b>
```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
@@ -318,7 +319,7 @@ func main() {
<p>Read a channel into another channel, will close until cancel context.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
@@ -356,7 +357,7 @@ func main() {
<p>Create a channel whose values are taken from another channel with limit number.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
@@ -402,7 +403,7 @@ func main() {
<p>Split one chanel into two channels, until cancel the context.</p>
<b>Signature:</b>
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/3TQPKnCirrP)</span></b>
```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)

View File

@@ -31,6 +31,8 @@ import (
<div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
## Documentation
@@ -46,7 +48,7 @@ All other types are truthy if they are not their zero value.</p>
```go
func Bool[T any](value T) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
```go
package main
@@ -111,7 +113,7 @@ func main() {
```go
func And[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
```go
package main
@@ -139,7 +141,7 @@ func main() {
```go
func Or[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
```go
package main
@@ -167,7 +169,7 @@ func main() {
```go
func Xor[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
```go
package main
@@ -195,7 +197,7 @@ func main() {
```go
func Nor[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
```go
package main
@@ -222,7 +224,7 @@ func main() {
```go
func Xnor[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
```go
package main
@@ -249,7 +251,7 @@ func main() {
```go
func Nand[T, U any](a T, b U) bool
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
```go
package main
@@ -277,7 +279,7 @@ func main() {
```go
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
```
<b>Example:</b>
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
```go
package main

View File

@@ -0,0 +1,50 @@
---
outline: deep
---
# Installation
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause in v2.x.x all functions was rewriten with generics of go1.18.</b>
```go
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.1. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
```
## Usage
Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions, just import the strutil package like below:
```go
import "github.com/duke-git/lancet/v2/strutil"
```
## Example
Here takes the string function `Reverse` (reverse order string) as an example, and the strutil package needs to be imported.
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s := "hello"
rs := strutil.Reverse(s)
fmt.Println(rs) //olleh
}
```
## More
Check out the [APIs]([API](https://lancet.go.dev/api/overview.html)) for details.

View File

@@ -0,0 +1,18 @@
---
outline: deep
---
# What is lancet?
<b>Lancet is a powerful, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js. </b>
## Why lancet?
Lancet makes Go dev easier by taking the hassle out of working with concurrency, net, math, slice, string, etc.
Lancet's utility methods are great for:
- Iterating slice and array.
- Manipulating strings.
- Work with net and http.
- Other tools, eg. random, crypto, stream, retry, etc.

43
docs/en/index.md Normal file
View File

@@ -0,0 +1,43 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: "Lancet"
text: "A powerful util function library of Go"
tagline: Simple, powerful, and efficient.
actions:
- theme: brand
text: Get Started
link: /en/guide/getting_started
- theme: alt
text: View on GitHub
link: https://github.com/duke-git/lancet
# - theme: alt
# text: API Examples
# link: /api-examples
image:
src: /lancet_logo.png
alt: lancet
features:
- title: Powerful
icon: 💪
details: support 600+ go util functions. eg. string, slice, datetime, net, crypto, concurrency...
- title: Modular by design
icon: 🏗
details: Each module is designed as a package with no coupling between modules.
- title: Pure
icon: 💅
details: Only depends on two kinds of libraries, go standard library and golang.org/x.
- title: Simple
icon: 👏
details: Well structure, test for every exported function.
---
<p style="position:relative; top: -316px;left: 560px;">
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
</p>

View File

@@ -0,0 +1,48 @@
---
outline: deep
---
# 安装
1. <b>使用 go1.18 及以上版本的用户,建议安装 v2.x.x。 因为 v2.x.x 应用 go1.18 的泛型重写了大部分函数。</b>
```go
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.1。</b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
```
## 用法
lancet 是以包的结构组织代码的,使用时需要导入相应的包名。例如:如果使用字符串相关函数,需要导入 strutil 包:
```go
import "github.com/duke-git/lancet/v2/strutil"
```
## 示例
此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包:
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s := "hello"
rs := strutil.Reverse(s)
fmt.Println(rs) //olleh
}
```
## More
其他特性请参考[API](https://lancet.go.dev/api/overview.html).

View File

@@ -0,0 +1,18 @@
---
outline: deep
---
# lancet是什么?
<b>lancet柳叶刀是一个强大、全面、高效、可复用的go语言工具函数库。lancet受到了java apache common包和lodash.js的启发。 </b>
## 为什么选择lancet?
Lancet 消除了处理并发、网络、数学、切片、字符串等的麻烦,使 Go 开发变得更容易。
Lancet 的实用方法非常适合:
- 迭代切片和数组。
- 操作字符串。
- 处理网络和http请求。
- 其他工具,例如。 随机、加密、流、重试等。

45
docs/index.md Normal file
View File

@@ -0,0 +1,45 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: 'Lancet'
text: '一个强大的Go语言工具函数库'
tagline: '简洁, 强大, 高效'
actions:
- theme: brand
text: 开始使用
link: /guide/getting_started
- theme: alt
text: 在GitHub中查看
link: https://github.com/duke-git/lancet
image:
src: /lancet_logo.png
alt: lancet
features:
- title: 全面
icon: 💪
details: 特性丰富支持600+ go util函数。字符串、切片、日期时间、网络、加密、并发...
- title: 模块化设计
icon: 🏗
details: 每个模块设计成一个包,模块之间无耦合。
- title: 纯净
icon: 💅
details: 只依赖go标准库和golang.org/x。
- title: 简洁
icon: 👏
details: 结构良好,测试每个导出的函数。
---
<p style="position:relative; top: -316px;left: 540px;">
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
<!-- [![](https://img.shields.io/github/stars/duke-git/lancet?style=social)](https://github.com/duke-git/lancet)
[![](https://img.shields.io/github/forks/duke-git/lancet?style=social)](https://github.com/duke-git/lancet) -->
</p>

BIN
docs/lancet_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/lancet_logo_mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -6,7 +6,7 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Source:
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
@@ -44,15 +44,24 @@ import (
- [DesOfbEncrypt](#DesOfbEncrypt)
- [DesOfbDecrypt](#DesOfbDecrypt)
- [HmacMd5](#HmacMd5)
- [HmacMd5WithBase64](#HmacMd5WithBase64)
- [HmacSha1](#HmacSha1)
- [HmacSha1WithBase64](#HmacSha1WithBase64)
- [HmacSha256](#HmacSha256)
- [HmacSha256WithBase64](#HmacSha256WithBase64)
- [HmacSha512](#HmacSha512)
- [HmacSha512WithBase64](#HmacSha512WithBase64)
- [Md5String](#Md5String)
- [Md5StringWithBase64](#Md5StringWithBase64)
- [Md5Byte](#Md5Byte)
- [Md5ByteWithBase64](#Md5ByteWithBase64)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha1WithBase64](#Sha1WithBase64)
- [Sha256](#Sha256)
- [Sha256WithBase64](#Sha256WithBase64)
- [Sha512](#Sha512)
- [Sha512WithBase64](#Sha512WithBase64)
- [GenerateRsaKey](#GenerateRsaKey)
- [RsaEncrypt](#RsaEncrypt)
- [RsaDecrypt](#RsaDecrypt)
@@ -730,7 +739,7 @@ func main() {
<b>Signature:</b>
```go
func HmacMd5(data, key string) string
func HmacMd5(str, key string) string
```
<b>Example:</b>
@@ -744,7 +753,7 @@ import (
)
func main() {
str := "hello"
str := "hello"
key := "12345"
hms := cryptor.HmacMd5(str, key)
@@ -754,6 +763,39 @@ func main() {
// e834306eab892d872525d4918a7a639a
}
```
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
<p>Get the md5 hmac hash of base64 string.</p>
<b>Signature:</b>
```go
func HmacMd5WithBase64(str, key string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacMd5WithBase64(str, key)
fmt.Println(hms)
// Output:
// 6DQwbquJLYclJdSRinpjmg==
}
```
### <span id="HmacSha1">HmacSha1</span>
<p>Get the sha1 hmac hash of string.</p>
@@ -761,7 +803,7 @@ func main() {
<b>Signature:</b>
```go
func HmacSha1(data, key string) string
func HmacSha1(str, key string) string
```
<b>Example:</b>
@@ -785,6 +827,39 @@ func main() {
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
```
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
<p>Return the hmac hash of string use sha1 with base64.</p>
<b>Signature:</b>
```go
func HmacSha1WithBase64(str, key string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha1WithBase64(str, key)
fmt.Println(hms)
// Output:
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
}
```
### <span id="HmacSha256">HmacSha256</span>
<p>Get the sha256 hmac hash of string</p>
@@ -792,7 +867,7 @@ func main() {
<b>Signature:</b>
```go
func HmacSha256(data, key string) string
func HmacSha256(str, key string) string
```
<b>Example:</b>
@@ -817,6 +892,38 @@ func main() {
}
```
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
<p>Return the hmac hash of string use sha256 with base64.</p>
<b>Signature:</b>
```go
func HmacSha256WithBase64(str, key string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha256WithBase64(str, key)
fmt.Println(hms)
// Output:
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
}
```
### <span id="HmacSha512">HmacSha512</span>
<p>Get the sha512 hmac hash of string.</p>
@@ -824,7 +931,7 @@ func main() {
<b>Signature:</b>
```go
func HmacSha512(data, key string) string
func HmacSha512(str, key string) string
```
<b>Example:</b>
@@ -849,6 +956,38 @@ func main() {
}
```
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
<p>Return the hmac hash of string use sha512 with base64.</p>
<b>Signature:</b>
```go
func HmacSha512WithBase64(str, key string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
```
### <span id="Md5String">Md5String</span>
@@ -881,6 +1020,35 @@ func main() {
}
```
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
<p>Return the md5 value of string with base64.</p>
<b>Signature:</b>
```go
func Md5StringWithBase64(s string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5StringWithBase64("hello")
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5Byte">Md5Byte</span>
<p>Return the md5 string of byte slice.</p>
@@ -910,6 +1078,35 @@ func main() {
}
```
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
<p>Return the md5 string of byte slice with base64.</p>
<b>Signature:</b>
```go
func Md5ByteWithBase64(data []byte) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5File">Md5File</span>
<p>Get the md5 value of file.</p>
@@ -943,7 +1140,7 @@ func main() {
<b>Signature:</b>
```go
func Sha1(data string) string
func Sha1(str string) string
```
<b>Example:</b>
@@ -967,6 +1164,35 @@ func main() {
}
```
### <span id="Sha1WithBase64">Sha1WithBase64</span>
<p>Return the sha1 value (SHA-1 hash algorithm) of base64 string.</p>
<b>Signature:</b>
```go
func Sha1WithBase64(str string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha1WithBase64("hello")
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
```
### <span id="Sha256">Sha256</span>
<p>Get the sha256 value of string.</p>
@@ -974,7 +1200,7 @@ func main() {
<b>Signature:</b>
```go
func Sha256(data string) string
func Sha256(str string) string
```
<b>Example:</b>
@@ -998,6 +1224,35 @@ func main() {
}
```
### <span id="Sha256WithBase64">Sha256WithBase64</span>
<p>Return the sha256 value (SHA256 hash algorithm) of base64 string.</p>
<b>Signature:</b>
```go
func Sha256WithBase64(str string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha256WithBase64("hello")
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
```
### <span id="Sha512">Sha512</span>
<p>Get the sha512 value of string.</p>
@@ -1005,7 +1260,7 @@ func main() {
<b>Signature:</b>
```go
func Sha512(data string) string
func Sha512(str string) string
```
<b>Example:</b>
@@ -1029,6 +1284,35 @@ func main() {
}
```
### <span id="Sha512WithBase64">Sha512WithBase64</span>
<p>Get the sha512 value of string with base64.</p>
<b>Signature:</b>
```go
func Sha512WithBase64(str string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha512WithBase64("hello")
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}
```
### <span id="GenerateRsaKey">GenerateRsaKey</span>
<p>Create the rsa public and private key file in current directory.</p>

View File

@@ -6,7 +6,7 @@ cryptor加密包支持数据加密和解密获取md5hash值。支持base64
## 源码:
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
<div STYLE="page-break-after: always;"></div>
@@ -41,15 +41,24 @@ import (
- [DesOfbEncrypt](#DesOfbEncrypt)
- [DesOfbDecrypt](#DesOfbDecrypt)
- [HmacMd5](#HmacMd5)
- [HmacMd5WithBase64](#HmacMd5WithBase64)
- [HmacSha1](#HmacSha1)
- [HmacSha1WithBase64](#HmacSha1WithBase64)
- [HmacSha256](#HmacSha256)
- [HmacSha256WithBase64](#HmacSha256WithBase64)
- [HmacSha512](#HmacSha512)
- [HmacSha512WithBase64](#HmacSha512WithBase64)
- [Md5String](#Md5String)
- [Md5StringWithBase64](#Md5StringWithBase64)
- [Md5Byte](#Md5Byte)
- [Md5ByteWithBase64](#Md5ByteWithBase64)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha1WithBase64](#Sha1WithBase64)
- [Sha256](#Sha256)
- [Sha256WithBase64](#Sha256WithBase64)
- [Sha512](#Sha512)
- [Sha512WithBase64](#Sha512WithBase64)
- [GenerateRsaKey](#GenerateRsaKey)
- [RsaEncrypt](#RsaEncrypt)
- [RsaDecrypt](#RsaDecrypt)
@@ -729,7 +738,7 @@ func main() {
<b>函数签名:</b>
```go
func HmacMd5(data, key string) string
func HmacMd5(str, key string) string
```
<b>示例:</b>
@@ -743,7 +752,7 @@ import (
)
func main() {
str := "hello"
str := "hello"
key := "12345"
hms := cryptor.HmacMd5(str, key)
@@ -753,14 +762,46 @@ func main() {
// e834306eab892d872525d4918a7a639a
}
```
### <span id="HmacSha1">HmacSha1</span>
<p>获取字符串sha1 hmac值。</p>
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
<p>获取字符串md5 hmac base64字符串值。</p>
<b>函数签名:</b>
```go
func HmacSha1(data, key string) string
func HmacMd5WithBase64(str, key string) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacMd5WithBase64(str, key)
fmt.Println(hms)
// Output:
// 6DQwbquJLYclJdSRinpjmg==
}
```
### <span id="HmacSha1">HmacSha1</span>
<p>获取字符串的sha1 hmac值。</p>
<b>函数签名:</b>
```go
func HmacSha1(str, key string) string
```
<b>示例:</b>
@@ -784,6 +825,40 @@ func main() {
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
```
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
<p>获取字符串的sha1 base64值。</p>
<b>函数签名:</b>
```go
func HmacSha1WithBase64(str, key string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha1WithBase64(str, key)
fmt.Println(hms)
// Output:
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
}
```
### <span id="HmacSha256">HmacSha256</span>
<p>获取字符串sha256 hmac值。</p>
@@ -791,7 +866,7 @@ func main() {
<b>函数签名:</b>
```go
func HmacSha256(data, key string) string
func HmacSha256(str, key string) string
```
<b>示例:</b>
@@ -816,6 +891,38 @@ func main() {
}
```
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
<p>获取字符串sha256 hmac base64值。</p>
<b>函数签名:</b>
```go
func HmacSha256WithBase64(str, key string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha256WithBase64(str, key)
fmt.Println(hms)
// Output:
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
}
```
### <span id="HmacSha512">HmacSha512</span>
<p>获取字符串sha512 hmac值。</p>
@@ -823,7 +930,7 @@ func main() {
<b>函数签名:</b>
```go
func HmacSha512(data, key string) string
func HmacSha512(str, key string) string
```
<b>示例:</b>
@@ -848,6 +955,38 @@ func main() {
}
```
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
<p>获取字符串sha512 hmac base64值。</p>
<b>函数签名:</b>
```go
func HmacSha512WithBase64(str, key string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
```
### <span id="Md5String">Md5String</span>
@@ -856,7 +995,7 @@ func main() {
<b>函数签名:</b>
```go
func Md5String(s string) string
func Md5String(str string) string
```
<b>示例:</b>
@@ -880,9 +1019,38 @@ func main() {
}
```
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
<p>获取字符串md5 base64值。</p>
<b>函数签名:</b>
```go
func Md5StringWithBase64(s string) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5StringWithBase64("hello")
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5Byte">Md5Byte</span>
<p>获取byte slice的md5。</p>
<p>获取byte slice的md5。</p>
<b>函数签名:</b>
@@ -909,6 +1077,35 @@ func main() {
}
```
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
<p>获取byte slice的md5 base64值。</p>
<b>函数签名:</b>
```go
func Md5ByteWithBase64(data []byte) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5File">Md5File</span>
<p>获取文件md5值。</p>
@@ -942,7 +1139,7 @@ func main() {
<b>函数签名:</b>
```go
func Sha1(data string) string
func Sha1(str string) string
```
<b>示例:</b>
@@ -966,6 +1163,35 @@ func main() {
}
```
### <span id="Sha1WithBase64">Sha1WithBase64</span>
<p>获取字符串sha1 base64值。</p>
<b>函数签名:</b>
```go
func Sha1WithBase64(str string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha1WithBase64("hello")
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
```
### <span id="Sha256">Sha256</span>
<p>获取字符串sha256值。</p>
@@ -973,7 +1199,7 @@ func main() {
<b>函数签名:</b>
```go
func Sha256(data string) string
func Sha256(str string) string
```
<b>示例:</b>
@@ -997,6 +1223,35 @@ func main() {
}
```
### <span id="Sha256WithBase64">Sha256WithBase64</span>
<p>获取字符串sha256 base64值。</p>
<b>函数签名:</b>
```go
func Sha256WithBase64(str string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha256WithBase64("hello")
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
```
### <span id="Sha512">Sha512</span>
<p>获取字符串sha512值。</p>
@@ -1004,7 +1259,7 @@ func main() {
<b>函数签名:</b>
```go
func Sha512(data string) string
func Sha512(str string) string
```
<b>示例:</b>
@@ -1028,6 +1283,35 @@ func main() {
}
```
### <span id="Sha512WithBase64">Sha512WithBase64</span>
<p>获取字符串sha512 base64值。</p>
<b>函数签名:</b>
```go
func Sha512WithBase64(str string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha512WithBase64("hello")
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}
```
### <span id="GenerateRsaKey">GenerateRsaKey</span>
<p>在当前目录下创建rsa私钥文件和公钥文件。</p>

View File

@@ -0,0 +1,470 @@
# CopyOnWriteList
CopyOnWriteList is a thread-safe list implementation that uses go slicing as its base. When writing, a new slice is copied and assigned to the original slice when writing is complete. When reading, the original slice is read directly.
## 源码
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go](https://github.com/duke-git/lancet/blob/main /datastructure/list/copyonwritelist.go)
## 用法
```go
import (
"github.com/duke-git/lancet/datastructure/list"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [NewCopyOnWriteList](#NewCopyOnWriteList)
- [Size](#Size)
- [Get](#Get)
- [Set](#Set)
- [Remove](#Remove)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [IsEmpty](#IsEmpty)
- [Contain](#Contain)
- [ValueOf](#ValueOf)
- [Add](#Add)
- [AddAll](#AddAll)
- [AddByIndex](#AddByIndex)
- [DeleteAt](#DeleteAt)
- [DeleteIf](#DeleteIf)
- [DeleteBy](#DeleteBy)
- [DeleteRange](#DeleteRange)
- [Equal](#Equal)
## Documentation
### NewCopyOnWriteList
Returns a CopyOnWriteList with empty slices.
```go
type CopyOnWriteList[T any] struct {
data []T
lock sync.
}
func NewCopyOnWriteList() *CopyOnWriteList
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l)
}
```
### Size
Returns the length of the CopyOnWriteList.
```go
func (l *CopyOnWriteList[T]) Size() int
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Size())
}
```
### Get
Returns the element at the specified position in the list
```go
func (c *CopyOnWriteList[T]) Get(index int) *T
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Get(2))
}
```
### Set
Replaces the element at the specified position in this list with the specified element.
```go
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool)
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Set(2, 4))
}
```
### Remove
### IndexOf
Returns the index of the value in the list, or -1 if not found.
```go
func (c *CopyOnWriteList[T]) IndexOf(e T) int
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.IndexOf(1))
}
```
### LastIndexOf
Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain that element.
```go
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,1})
fmt.Println(l.LastIndexOf(1))
}
```
### IsEmpty
Returns true if this list does not contain any elements.
```go
func (c *CopyOnWriteList[T]) IsEmpty() bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{})
fmt.Println(l.IsEmpty())
}
```
### Contain
Determines if a CopyOnWriteList contains an element.
```go
func (c *CopyOnWriteList[T]) Contain(e T) bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Contain(1))
}
```
### ValueOf
Returns a pointer to the value at the index in the list
```go
func (c *CopyOnWriteList[T]) ValueOf(index int) []T
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.ValueOf(2))
}
```
### Add
Appends the specified element to the end of the list.
```go
func (c *CopyOnWriteList[T]) Add(e T) bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.Add(4)
fmt.Println(l.getList())
}
```
### AddAll
Appends all the elements of the specified collection to the end of this list
```go
func (c *CopyOnWriteList[T]) AddAll(e []T) bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.AddAll([]int{4,5,6})
fmt.Println(l.getList())
}
```
### AddByIndex
Inserts the specified element into the list at the specified position.
```go
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.AddByIndex(2, 6)
fmt.Println(l.getList())
}
```
### DeleteAt
Removes the element at the specified position in this list.
```go
func (c *CopyOnWriteList[T]) DeleteAt(index int) (oldValue *T, ok bool)
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteAt(2)
fmt.Println(l.getList())
}
```
### DeleteIf
Removes the first occurrence of the specified element from this list (if it exists).
```go
func (c *CopyOnWriteList[T]) DeleteIf(func(T) bool) (oldValue *T, ok bool)
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteIf(func(i int) bool {
return i == 2
})
fmt.Println(l.getList())
}
```
### DeleteBy
Deletes the first occurrence of the specified element from this list (if it exists).
```go
func (c *CopyOnWriteList[T]) DeleteBy(e T) (*T bool)
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteBy(2)
fmt.Println(l.getList())
}
```
### DeleteRange
Deletes all elements from this list with indexes between fromIndex (included) and toIndex (not included).
(leftCloseRightOpen)
```go
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int)
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
list.DeleteRange(2, 5)
fmt.Println(l.getList())
}
```
### Equal
Returns true if the specified object is equal to this list
```go
func (c *CopyOnWriteList[T]) Equal(e []T) bool
```
#### Example
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
fmt.Println(l.Equal([]int{1,2,3,4,5,6,7,8,9}))
}
```

View File

@@ -0,0 +1,471 @@
# CopyOnWriteList
CopyOnWriteList 是一个线程安全的 List 实现,底层使用 go 切片。写入时,会复制一份新的切片,写入完成后,再将新的切片赋值给原来的切片。读取时,直接读取原来的切片。
## 源码
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go](https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go)
## 用法
```go
import (
"github.com/duke-git/lancet/datastructure/list"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [NewCopyOnWriteList](#NewCopyOnWriteList)
- [Size](#Size)
- [Get](#Get)
- [Set](#Set)
- [Remove](#Remove)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [IsEmpty](#IsEmpty)
- [Contain](#Contain)
- [ValueOf](#ValueOf)
- [Add](#Add)
- [AddAll](#AddAll)
- [AddByIndex](#AddByIndex)
- [DeleteAt](#DeleteAt)
- [DeleteIf](#DeleteIf)
- [DeleteBy](#DeleteBy)
- [DeleteRange](#DeleteRange)
- [Equal](#Equal)
## 文档
### NewCopyOnWriteList
返回一个具有空切片的 CopyOnWriteList。
```go
type CopyOnWriteList[T any] struct {
data []T
lock sync.Locker
}
func NewCopyOnWriteList() *CopyOnWriteList
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l)
}
```
### Size
返回 CopyOnWriteList 的长度。
```go
func (l *CopyOnWriteList[T]) Size() int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Size())
}
```
### Get
返回列表中指定位置的元素
```go
func (c *CopyOnWriteList[T]) Get(index int) *T
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Get(2))
}
```
### Set
将此列表中指定位置的元素替换为指定元素。
```go
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Set(2, 4))
}
```
### Remove
### IndexOf
返回列表中值的索引,如果没有找到返回-1。
```go
func (c *CopyOnWriteList[T]) IndexOf(e T) int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.IndexOf(1))
}
```
### LastIndexOf
返回指定元素在此列表中最后出现的索引,如果此列表不包含该元素,则返回-1。
```go
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,1})
fmt.Println(l.LastIndexOf(1))
}
```
### IsEmpty
如果此列表不包含任何元素,则返回 true。
```go
func (c *CopyOnWriteList[T]) IsEmpty() bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{})
fmt.Println(l.IsEmpty())
}
```
### Contain
判断 CopyOnWriteList 是否包含某个元素
```go
func (c *CopyOnWriteList[T]) Contain(e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Contain(1))
}
```
### ValueOf
返回列表中索引处的值指针
```go
func (c *CopyOnWriteList[T]) ValueOf(index int) []T
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.ValueOf(2))
}
```
### Add
将指定的元素追加到此列表的末尾。
```go
func (c *CopyOnWriteList[T]) Add(e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.Add(4)
fmt.Println(l.getList())
}
```
### AddAll
将指定集合中的所有元素追加到此列表的末尾
```go
func (c *CopyOnWriteList[T]) AddAll(e []T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.AddAll([]int{4,5,6})
fmt.Println(l.getList())
}
```
### AddByIndex
将指定元素插入此列表中的指定位置。
```go
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.AddByIndex(2, 6)
fmt.Println(l.getList())
}
```
### DeleteAt
移除此列表中指定位置的元素。
```go
func (c *CopyOnWriteList[T]) DeleteAt(index int) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteAt(2)
fmt.Println(l.getList())
}
```
### DeleteIf
从此列表中删除第一个出现的指定元素(如果该元素存在)。
```go
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteIf(func(i int) bool {
return i == 2
})
fmt.Println(l.getList())
}
```
### DeleteBy
从此列表中删除第一个出现的指定元素(如果该元素存在)。
```go
func (c *CopyOnWriteList[T]) DeleteBy(e T) (*T bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteBy(2)
fmt.Println(l.getList())
}
```
### DeleteRange
从该列表中删除索引介于 fromIndex(包含)和 toIndex(不包含)之间的所有元素。
(左闭右开)。
```go
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
list.DeleteRange(2, 5)
fmt.Println(l.getList())
}
```
### Equal
如果指定的对象等于此列表,则返回 true。
```go
func (c *CopyOnWriteList[T]) Equal(e []T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
fmt.Println(l.Equal([]int{1,2,3,4,5,6,7,8,9}))
}
```

View File

@@ -59,7 +59,12 @@ import (
- [IsLeapYear](#IsLeapYear)
- [BetweenSeconds](#BetweenSeconds)
- [DayOfYear](#DayOfYear)
- [IsWeekend](#IsWeekend)
- [IsWeekend<sup>deprecated</sup>](#IsWeekend)
- [NowDateOrTime](#NowDateOrTime)
- [Timestamp](#Timestamp)
- [TimestampMilli](#TimestampMilli)
- [TimestampMicro](#TimestampMicro)
- [TimestampNano](#TimestampNano)
<div STYLE="page-break-after: always;"></div>
@@ -67,7 +72,7 @@ import (
## Note:
1. 'format' string param in func FormatTimeToStr and FormatStrToTime function should be one of flows:
1. In below functions, the `format` string param should be one of flows value (case no sensitive):
- yyyy-mm-dd hh:mm:ss
- yyyy-mm-dd hh:mm
@@ -78,14 +83,18 @@ import (
- dd-mm-yy hh:mm:ss
- yyyy/mm/dd hh:mm:ss
- yyyy/mm/dd hh:mm
- yyyy-mm-dd hh
- yyyy/mm/dd hh
- yyyy/mm/dd
- yyyy/mm
- mm/dd
- dd/mm/yy hh:mm:ss
- yyyymmdd
- mmddyy
- yyyy
- yy
- mm
- hh:mm:ss
- hh:mm
- mm:ss
### <span id="AddDay">AddDay</span>
@@ -838,7 +847,7 @@ func main() {
<b>Signature:</b>
```go
func FormatTimeToStr(t time.Time, format string) string
func FormatTimeToStr(t time.Time, format string, timezone ...string) string
```
<b>Example:</b>
@@ -877,7 +886,7 @@ func main() {
<b>Signature:</b>
```go
func FormatStrToTime(str, format string) (time.Time, error)
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error)
```
<b>Example:</b>
@@ -1185,7 +1194,6 @@ func main() {
}
```
### <span id="BetweenSeconds">BetweenSeconds</span>
<p>Return the number of seconds between two times.</p>
@@ -1223,7 +1231,6 @@ func main() {
}
```
### <span id="DayOfYear">DayOfYear</span>
<p>Returns which day of the year the parameter date `t` is.</p>
@@ -1265,8 +1272,7 @@ func main() {
}
```
### <span id="IsWeekend">IsWeekend</span>
### <span id="IsWeekend">IsWeekend(Deprecated, Use '== Weekday' instead)</span>
<p>Checks if passed time is weekend or not.</p>
@@ -1305,3 +1311,158 @@ func main() {
// false
}
```
### <span id="NowDateOrTime">NowDateOrTime</span>
<p>Return current datetime with specific format and timezone.</p>
<b>Signature:</b>
```go
func NowDateOrTime(format string, timezone ...string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2023-07-26 15:01:30
// 2023-07-26 02:01:30
}
```
### <span id="Timestamp">Timestamp</span>
<p>Return current second timestamp.</p>
<b>Signature:</b>
```go
func Timestamp(timezone ...string) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.Timestamp()
fmt.Println(ts)
// Output:
// 1690363051
}
```
### <span id="TimestampMilli">TimestampMilli</span>
<p>Return current mill second timestamp.</p>
<b>Signature:</b>
```go
func TimestampMilli(timezone ...string) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMilli()
fmt.Println(ts)
// Output:
// 1690363051331
}
```
### <span id="TimestampMicro">TimestampMicro</span>
<p>Return current micro second timestamp.</p>
<b>Signature:</b>
```go
func TimestampMicro(timezone ...string) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMicro()
fmt.Println(ts)
// Output:
// 1690363051331784
}
```
### <span id="TimestampNano">TimestampNano</span>
<p>Return current nano second timestamp.</p>
<b>Signature:</b>
```go
func TimestampNano(timezone ...string) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampNano()
fmt.Println(ts)
// Output:
// 1690363051331788000
}
```

View File

@@ -58,8 +58,12 @@ import (
- [IsLeapYear](#IsLeapYear)
- [BetweenSeconds](#BetweenSeconds)
- [DayOfYear](#DayOfYear)
- [IsWeekend](#IsWeekend)
- [IsWeekend<sup>deprecated</sup>](#IsWeekend)
- [NowDateOrTime](#NowDateOrTime)
- [Timestamp](#Timestamp)
- [TimestampMilli](#TimestampMilli)
- [TimestampMicro](#TimestampMicro)
- [TimestampNano](#TimestampNano)
<div STYLE="page-break-after: always;"></div>
@@ -67,7 +71,7 @@ import (
## 注:
1. 方法 FormatTimeToStr 和 FormatStrToTime 中的 format 参数值需要传以下类型之一:
1. 函数中`format`参数值需要传以下值之一 (忽略大小写):
- yyyy-mm-dd hh:mm:ss
- yyyy-mm-dd hh:mm
@@ -78,14 +82,18 @@ import (
- dd-mm-yy hh:mm:ss
- yyyy/mm/dd hh:mm:ss
- yyyy/mm/dd hh:mm
- yyyy-mm-dd hh
- yyyy/mm/dd hh
- yyyy/mm/dd
- yyyy/mm
- mm/dd
- dd/mm/yy hh:mm:ss
- yyyymmdd
- mmddyy
- yyyy
- yy
- mm
- hh:mm:ss
- hh:mm
- mm:ss
### <span id="AddDay">AddDay</span>
@@ -717,7 +725,7 @@ func main() {
### <span id="GetTodayStartTime">GetTodayStartTime</span>
<p>返回当天开始时间, 格式: yyyy-mm-dd 00:00:00.</p>
<p>返回当天开始时间, 格式: yyyy-mm-dd 00:00:00</p>
<b>函数签名:</b>
@@ -746,7 +754,7 @@ func main() {
### <span id="GetTodayEndTime">GetTodayEndTime</span>
<p>返回当天结束时间,格式: yyyy-mm-dd 23:59:59.</p>
<p>返回当天结束时间,格式: yyyy-mm-dd 23:59:59</p>
<b>函数签名:</b>
@@ -838,7 +846,7 @@ func main() {
<b>函数签名:</b>
```go
func FormatTimeToStr(t time.Time, format string) string
func FormatTimeToStr(t time.Time, format string, timezone ...string) string
```
<b>示例:</b>
@@ -877,7 +885,7 @@ func main() {
<b>函数签名:</b>
```go
func FormatStrToTime(str, format string) (time.Time, error)
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error)
```
<b>示例:</b>
@@ -1263,7 +1271,7 @@ func main() {
}
```
### <span id="IsWeekend">IsWeekend</span>
### <span id="IsWeekend">IsWeekend(已废弃, 使用 '== Weekday'</span>
<p>判断日期是否是周末。</p>
@@ -1302,3 +1310,158 @@ func main() {
// false
}
```
### <span id="NowDateOrTime">NowDateOrTime</span>
<p>根据指定的格式和时区返回当前时间字符串。</p>
<b>函数签名:</b>
```go
func NowDateOrTime(format string, timezone ...string) string
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2023-07-26 15:01:30
// 2023-07-26 02:01:30
}
```
### <span id="Timestamp">Timestamp</span>
<p>返回当前秒级时间戳。</p>
<b>函数签名:</b>
```go
func Timestamp(timezone ...string) int64
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.Timestamp()
fmt.Println(ts)
// Output:
// 1690363051
}
```
### <span id="TimestampMilli">TimestampMilli</span>
<p>返回当前毫秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampMilli(timezone ...string) int64
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMilli()
fmt.Println(ts)
// Output:
// 1690363051331
}
```
### <span id="TimestampMicro">TimestampMicro</span>
<p>返回当前微秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampMicro(timezone ...string) int64
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMicro()
fmt.Println(ts)
// Output:
// 1690363051331784
}
```
### <span id="TimestampNano">TimestampNano</span>
<p>返回当前纳秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampNano(timezone ...string) int64
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampNano()
fmt.Println(ts)
// Output:
// 1690363051331788000
}
```

View File

@@ -108,7 +108,7 @@ func main() {
### <span id="CreateDir">CreateDir</span>
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
<p>Create directory in absolute path. param `absPath` like /a, /a/b.</p>
<b>Signature:</b>
@@ -127,7 +127,7 @@ import (
)
func main() {
err := fileutil.CreateDir("/a/")
err := fileutil.CreateDir("/a/b") // will create folder /a/b
fmt.Println(err)
}
```

View File

@@ -108,7 +108,7 @@ func main() {
### <span id="CreateDir">CreateDir</span>
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b</p>
<b>函数签名:</b>
@@ -127,7 +127,7 @@ import (
)
func main() {
err := fileutil.CreateDir("/a/")
err := fileutil.CreateDir("/a/b") // will create folder /a/b
fmt.Println(err)
}
```

View File

@@ -43,12 +43,20 @@ import (
- [Merge](#Merge)
- [Minus](#Minus)
- [IsDisjoint](#IsDisjoint)
- [HasKey](#HasKey)
- [NewConcurrentMap](#NewConcurrentMap)
- [ConcurrentMap_Get](#ConcurrentMap_Get)
- [ConcurrentMap_Set](#ConcurrentMap_Set)
- [ConcurrentMap_GetOrSet](#ConcurrentMap_GetOrSet)
- [ConcurrentMap_Delete](#ConcurrentMap_Delete)
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
- [ConcurrentMap_Has](#ConcurrentMap_Has)
- [ConcurrentMap_Range](#ConcurrentMap_Range)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="MapTo">MapTo</span>
<p>Rry to map any interface to struct or base type.</p>
@@ -893,7 +901,7 @@ func main() {
### <span id="IsDisjoint">IsDisjoint</span>
<p>Checks two maps are disjoint if they have no keys in common</p>
<p>Checks two maps are disjoint if they have no keys in common.</p>
<b>Signature:</b>
@@ -937,3 +945,421 @@ func main() {
// false
}
```
### <span id="HasKey">HasKey</span>
<p>Checks if map has key or not. This function is used to replace the following boilerplate code:</p>
```go
_, haskey := amap["baz"];
if haskey {
fmt.Println("map has key baz")
}
```
<b>Signature:</b>
```go
func HasKey[K comparable, V any](m map[K]V, key K) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
}
result1 := maputil.HasKey(m, "a")
result2 := maputil.HasKey(m, "c")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="NewConcurrentMap">NewConcurrentMap</span>
<p>ConcurrentMap is like map, but is safe for concurrent use by multiple goroutines.</p>
<b>Signature:</b>
```go
// NewConcurrentMap create a ConcurrentMap with specific shard count.
func NewConcurrentMap[K comparable, V any](shardCount int) *ConcurrentMap[K, V]
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
// create a ConcurrentMap whose key type is string, value type is int
cm := maputil.NewConcurrentMap[string, int](100)
}
```
### <span id="ConcurrentMap_Set">ConcurrentMap_Set</span>
<p>Set the value for a key.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) Set(key K, value V)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_Get">ConcurrentMap_Get</span>
<p>Get the value stored in the map for a key, or nil if no.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) Get(key K) (V, bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_GetOrSet">ConcurrentMap_GetOrSet</span>
<p>Returns the existing value for the key if present. Otherwise, it sets and returns the given value.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) GetOrSet(key K, value V) (actual V, ok bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
val, ok := cm.GetOrSet(fmt.Sprintf("%d", n), n)
fmt.Println(val, ok)
wg.Done()
}(i)
}
wg.Wait()
// output: (order may change)
// 1 false
// 3 false
// 2 false
// 0 false
// 4 false
}
```
### <span id="ConcurrentMap_Delete">ConcurrentMap_Delete</span>
<p>Delete the value for a key.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) Delete(key K)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
cm.Delete(fmt.Sprintf("%d", n))
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_GetAndDelete">ConcurrentMap_GetAndDelete</span>
<p>Returns the existing value for the key if present and then delete the value for the key. Otherwise, do nothing, just return false.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) GetAndDelete(key K) (actual V, ok bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //n, true
_, ok = cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //false
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Has">ConcurrentMap_Has</span>
<p>Checks if map has the value for a key.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) Has(key K) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
ok := cm.Has(fmt.Sprintf("%d", n))
fmt.Println(ok) // true
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Range">ConcurrentMap_Range</span>
<p>Calls iterator sequentially for each key and value present in each of the shards in the map. If iterator returns false, range stops the iteration.</p>
<b>Signature:</b>
```go
func (cm *ConcurrentMap[K, V]) Range(iterator func(key K, value V) bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
cm.Range(func(key string, value int) bool {
fmt.Println(value)
return true
})
}
```

View File

@@ -43,6 +43,16 @@ import (
- [Merge](#Merge)
- [Minus](#Minus)
- [IsDisjoint](#IsDisjoint)
- [HasKey](#HasKey)
- [NewConcurrentMap](#NewConcurrentMap)
- [ConcurrentMap_Get](#ConcurrentMap_Get)
- [ConcurrentMap_Set](#ConcurrentMap_Set)
- [ConcurrentMap_GetOrSet](#ConcurrentMap_GetOrSet)
- [ConcurrentMap_Delete](#ConcurrentMap_Delete)
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
- [ConcurrentMap_Has](#ConcurrentMap_Has)
- [ConcurrentMap_Range](#ConcurrentMap_Range)
<div STYLE="page-break-after: always;"></div>
@@ -932,3 +942,419 @@ func main() {
// false
}
```
### <span id="HasKey">HasKey</span>
<p>检查map是否包含某个key。用于代替以下样板代码:</p>
```go
_, haskey := amap["baz"];
if haskey {
fmt.Println("map has key baz")
}
```
<b>函数签名:</b>
```go
func HasKey[K comparable, V any](m map[K]V, key K) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
}
result1 := maputil.HasKey(m, "a")
result2 := maputil.HasKey(m, "c")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="NewConcurrentMap">NewConcurrentMap</span>
<p>ConcurrentMap协程安全的map结构。</p>
<b>函数签名:</b>
```go
// NewConcurrentMap create a ConcurrentMap with specific shard count.
func NewConcurrentMap[K comparable, V any](shardCount int) *ConcurrentMap[K, V]
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
// create a ConcurrentMap whose key type is string, value type is int
cm := maputil.NewConcurrentMap[string, int](100)
}
```
### <span id="ConcurrentMap_Set">ConcurrentMap_Set</span>
<p>在map中设置key和value。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Set(key K, value V)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_Get">ConcurrentMap_Get</span>
<p>根据key获取value, 如果不存在key,返回零值。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Get(key K) (V, bool)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_GetOrSet">ConcurrentMap_GetOrSet</span>
<p>返回键的现有值如果存在否则设置key并返回给定值。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) GetOrSet(key K, value V) (actual V, ok bool)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
val, ok := cm.GetOrSet(fmt.Sprintf("%d", n), n)
fmt.Println(val, ok)
wg.Done()
}(i)
}
wg.Wait()
// output: (order may change)
// 1 false
// 3 false
// 2 false
// 0 false
// 4 false
}
```
### <span id="ConcurrentMap_Delete">ConcurrentMap_Delete</span>
<p>删除key。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Delete(key K)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
cm.Delete(fmt.Sprintf("%d", n))
wg2.Done()
}(i)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_GetAndDelete">ConcurrentMap_GetAndDelete</span>
<p>获取key然后删除。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) GetAndDelete(key K) (actual V, ok bool)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //n, true
_, ok = cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //false
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Has">ConcurrentMap_Has</span>
<p>验证是否包含key。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Has(key K) bool
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
ok := cm.Has(fmt.Sprintf("%d", n))
fmt.Println(ok) // true
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Range">ConcurrentMap_Range</span>
<p>为map中每个键和值顺序调用迭代器。 如果iterator返回false则停止迭代。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Range(iterator func(key K, value V) bool)
```
<b>实例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
cm.Range(func(key string, value int) bool {
fmt.Println(value)
return true
})
}
```

View File

@@ -24,6 +24,8 @@ import (
- [Of](#Of)
- [Unwrap](#Unwrap)
- [UnwarpOr](#UnwarpOr)
- [UnwarpOrDefault](#UnwarpOrDefault)
- [ExtractPointer](#ExtractPointer)
<div STYLE="page-break-after: always;"></div>
@@ -100,6 +102,97 @@ func main() {
}
```
### <span id="UnwarpOr">UnwarpOr</span>
<p>Returns the value from the pointer or fallback if the pointer is nil.</p>
<b>Signature:</b>
```go
UnwarpOr[T any](p *T, fallback T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOr(&a, 456)
result2 := pointer.UnwarpOr(&b, "abc")
result3 := pointer.UnwarpOr(c, 456)
result4 := pointer.UnwarpOr(d, "def")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 456
// def
}
```
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
<p>Returns the value from the pointer or the default value if the pointer is nil.</p>
<b>Signature:</b>
```go
UnwarpOrDefault[T any](p *T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOrDefault(&a)
result2 := pointer.UnwarpOrDefault(&b)
result3 := pointer.UnwarpOrDefault(c)
result4 := pointer.UnwarpOrDefault(d)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 0
//
}
```
### <span id="ExtractPointer">ExtractPointer</span>
<p>Returns the underlying value by the given interface type</p>

View File

@@ -1,6 +1,6 @@
# Pointer
pointer包支持一些指针类型的操作。
pointer 包支持一些指针类型的操作。
<div STYLE="page-break-after: always;"></div>
@@ -25,6 +25,8 @@ import (
- [Of](#Of)
- [Unwrap](#Unwrap)
- [ExtractPointer](#ExtractPointer)
- [UnwarpOr](#UnwarpOr)
- [UnwarpOrDefault](#UnwarpOrDefault)
<div STYLE="page-break-after: always;"></div>
@@ -63,7 +65,6 @@ func main() {
}
```
### <span id="Unwrap">Unwrap</span>
<p>返回传入指针指向的值。</p>
@@ -133,4 +134,94 @@ func main() {
// Output:
// 1
}
```
```
### <span id="UnwarpOr">UnwarpOr</span>
<p>返回指针的值如果指针为零值则返回fallback。</p>
<b>函数签名:</b>
```go
UnwarpOr[T any](p *T, fallback T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOr(&a, 456)
result2 := pointer.UnwarpOr(&b, "abc")
result3 := pointer.UnwarpOr(c, 456)
result4 := pointer.UnwarpOr(d, "def")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 456
// def
}
```
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
<p>返回指针的值,如果指针为零值,则返回相应零值。</p>
<b>函数签名:</b>
```go
UnwarpOrDefault[T any](p *T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOrDefault(&a)
result2 := pointer.UnwarpOrDefault(&b)
result3 := pointer.UnwarpOrDefault(c)
result4 := pointer.UnwarpOrDefault(d)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 0
//
}
```

View File

@@ -90,6 +90,7 @@ import (
- [UpdateAt](#UpdateAt)
- [Without](#Without)
- [KeyBy](#KeyBy)
- [Join](#Join)
<div STYLE="page-break-after: always;"></div>
@@ -2417,3 +2418,36 @@ func main() {
// map[1:a 2:ab 3:abc]
}
```
### <span id="Join">Join</span>
<p>Join the slice item with specify separator.</p>
<b>Signature:</b>
```go
func Join[T any](s []T, separator string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
result1 := slice.Join(nums, ",")
result2 := slice.Join(nums, "-")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1,2,3,4,5
// 1-2-3-4-5
}
```

View File

@@ -90,6 +90,7 @@ import (
- [UpdateAt](#UpdateAt)
- [Without](#Without)
- [KeyBy](#KeyBy)
- [Join](#Join)
<div STYLE="page-break-after: always;"></div>
@@ -2390,7 +2391,7 @@ func main() {
### <span id="KeyBy">KeyBy</span>
<p>将切片每个元素调用函数后转为map</p>
<p>将切片每个元素调用函数后转为map</p>
<b>函数签名:</b>
@@ -2417,3 +2418,36 @@ func main() {
// map[1:a 2:ab 3:abc]
}
```
### <span id="Join">Join</span>
<p>用指定的分隔符链接切片元素。</p>
<b>函数签名:</b>
```go
func Join[T any](s []T, separator string) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
result1 := slice.Join(nums, ",")
result2 := slice.Join(nums, "-")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1,2,3,4,5
// 1-2-3-4-5
}
```

View File

@@ -237,9 +237,9 @@ import (
)
func main() {
t := tuple.NewTuple2(1, 0.1, "a")
t := tuple.NewTuple3(1, 0.1, "a")
v1, v2, v3 := t.Unbox()
fmt.Printf("%v %v %v", t.FieldA, t.FieldB, t.FieldC)
fmt.Printf("%v %v %v", v1, v2, v3)
// Output: 1 0.1 a
}
@@ -1134,8 +1134,6 @@ func main() {
fmt.Printf("%v %v %v %v %v %v %v %v %v %v", v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)
// Output: 1 0.1 a true 2 2.2 b c map[a:1] {a}
// Output: 1 0.1 a true 2 2.2 b c map[a:1]
}
```

View File

@@ -239,7 +239,7 @@ import (
func main() {
t := tuple.NewTuple2(1, 0.1, "a")
v1, v2, v3 := t.Unbox()
fmt.Printf("%v %v %v", t.FieldA, t.FieldB, t.FieldC)
fmt.Printf("%v %v %v", v1, v2, v3)
// Output: 1 0.1 a
}
@@ -1134,8 +1134,6 @@ func main() {
fmt.Printf("%v %v %v %v %v %v %v %v %v %v", v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)
// Output: 1 0.1 a true 2 2.2 b c map[a:1] {a}
// Output: 1 0.1 a true 2 2.2 b c map[a:1]
}
```

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