1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

Compare commits

...

17 Commits

Author SHA1 Message Date
dudaodong 6307d624cb Merge branch 'rc' of github.com:duke-git/lancet into rc 2025-07-07 10:18:37 +08:00
dudaodong 2f9f8b3f3d release v2.3.7 2025-07-07 10:18:05 +08:00
jake db5d9407bb Update slice_concurrent.go (#316) 2025-06-25 15:33:07 +08:00
dudaodong 55ee000684 merge rc 2025-06-23 11:32:51 +08:00
dudaodong fc7f2509ca fix: fix issue #314 2025-06-23 11:31:54 +08:00
残念 a97d27c32e perf(retry): the error returned by the Retry function contains the last error (#315) 2025-06-23 11:04:54 +08:00
Grigoris Thanasoulas c176ba378e arrayqueue: Fix bug in Back() method (#313) 2025-06-20 23:05:14 +08:00
dudaodong a3a24fc381 doc: update doc styles 2025-06-06 14:33:54 +08:00
Axiss 9caf2ffb1c fix one typo in doc (#310) 2025-06-03 10:10:51 +08:00
残念 1a5c31fd02 perf(retry): remove the waiting time after the last retry (#309) 2025-06-03 09:57:29 +08:00
dudaodong c175b202de doc: update cryptordoc 2025-05-29 14:04:09 +08:00
dudaodong d818219672 doc: update cryptordoc 2025-05-29 14:01:12 +08:00
dudaodong 539078e6b8 doc: add play ground demo for v2.3.6 2025-05-29 11:50:17 +08:00
dudaodong cdefbde9f5 release v2.3.6 2025-05-29 10:07:19 +08:00
dudaodong 1e57a743af Merge branch 'rc' into v2 2025-05-29 10:05:13 +08:00
Yurun 7d4184a365 doc: fix typo (#308) 2025-05-29 10:01:38 +08:00
dudaodong 1b73483945 doc: update doc for v2.3.6 2025-05-28 11:30:12 +08:00
35 changed files with 818 additions and 287 deletions
+42 -7
View File
@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.3.5-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.3.7-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) [![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) [![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) [![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)
@@ -214,6 +214,30 @@ import "github.com/duke-git/lancet/v2/concurrency"
- **<big>Tee</big>** : split one chanel into two channels, until cancel the context. - **<big>Tee</big>** : split one chanel into two channels, until cancel the context.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Tee)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)] [[play](https://go.dev/play/p/3TQPKnCirrP)]
- **<big>NewKeyedLocker</big>** : KeyedLocker is a simple implementation of a keyed locker that allows for non-blocking lock acquisition.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#NewKeyedLocker)]
[[play](https://go.dev/play/p/GzeyC33T5rw)]
- **<big>Do</big>** :acquires a lock for the specified key and executes the provided function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Do)]
[[play](https://go.dev/play/p/GzeyC33T5rw)]
- **<big>NewRWKeyedLocker</big>** :RRWKeyedLocker is a read-write version of KeyedLocker.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#NewRWKeyedLocker)]
[[play](https://go.dev/play/p/ZrCr8sMo77T)]
- **<big>RLock</big>** : acquires a read lock for the specified key and executes the provided function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#RLock)]
[[play](https://go.dev/play/p/ZrCr8sMo77T)]
- **<big>Lock</big>** : acquires a write lock for the specified key and executes the provided function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Lock)]
[[play](https://go.dev/play/p/WgAcXbOPKGk)]
- **<big>NewTryKeyedLocker</big>** : TryKeyedLocker is a non-blocking version of KeyedLocker.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#NewTryKeyedLocker)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
- **<big>TryLock</big>** : TryLock tries to acquire a lock for the specified key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#TryLock)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
- **<big>Unlock</big>** : Unlock releases the lock for the specified key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Unlock)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
<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> <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>
@@ -331,7 +355,7 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>ToRawUrlBase64</big>** : converts a value to a string encoded in raw url Base64. - **<big>ToRawUrlBase64</big>** : converts a value to a string encoded in raw url Base64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToRawUrlBase64)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToRawUrlBase64)]
[[play](https://go.dev/play/p/HwdDPFcza1O)] [[play](https://go.dev/play/p/HwdDPFcza1O)]
- **<big>ToBigInt</big>** : converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int. - **<big>ToBigInt</big>** : converts an integer of any supported type (int, int64, uint64, etc.) to \*big.Int.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToBigInt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToBigInt)]
[[play](https://go.dev/play/p/X3itkCxwB_x)] [[play](https://go.dev/play/p/X3itkCxwB_x)]
@@ -694,7 +718,6 @@ import optional "github.com/duke-git/lancet/v2/datastructure/optional"
- **<big>Optional</big>** : Optional container. - **<big>Optional</big>** : Optional container.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datastructure/optional.md)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datastructure/optional.md)]
<h3 id="eventbus"> 9. EventBus is an event bus used for handling events within an application. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">Index</a></h3> <h3 id="eventbus"> 9. EventBus is an event bus used for handling events within an application. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">Index</a></h3>
```go ```go
@@ -778,6 +801,9 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>RemoveFile</big>** : remove file, param should be file path. - **<big>RemoveFile</big>** : remove file, param should be file path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#RemoveFile)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#RemoveFile)]
[[play](https://go.dev/play/p/P2y0XW8a1SH)] [[play](https://go.dev/play/p/P2y0XW8a1SH)]
- **<big>RemoveDir</big>** : delete directory.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#RemoveDir)]
[[play](https://go.dev/play/p/Oa6KnPek2uy)]
- **<big>ReadFileToString</big>** : return string of file content. - **<big>ReadFileToString</big>** : return string of file content.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ReadFileToString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ReadFileToString)]
[[play](https://go.dev/play/p/cmfwp_5SQTp)] [[play](https://go.dev/play/p/cmfwp_5SQTp)]
@@ -926,7 +952,6 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Watcher)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)] [[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</a></h3> <h3 id="maputil"> 12. Maputil package includes some functions to manipulate map.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go ```go
@@ -1097,7 +1122,9 @@ import "github.com/duke-git/lancet/v2/maputil"
- **<big>GetOrDefault</big>** : returns the value of the given key or a default value if the key is not present. - **<big>GetOrDefault</big>** : returns the value of the given key or a default value if the key is not present.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#GetOrDefault)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#GetOrDefault)]
[[play](https://go.dev/play/p/99QjSYSBdiM)] [[play](https://go.dev/play/p/99QjSYSBdiM)]
- **<big>FindValuesBy</big>** : returns a slice of values from the map that satisfy the given predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#FindValuesBy)]
[[play](https://go.dev/play/p/bvNwNBZDm6v)]
<h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3> <h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1282,6 +1309,12 @@ import "github.com/duke-git/lancet/v2/netutil"
- **<big>IsTelnetConnected</big>** : checks if can if can telnet the specified host or not. - **<big>IsTelnetConnected</big>** : checks if can if can telnet the specified host or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#IsTelnetConnected)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)] [[play](https://go.dev/play/p/yiLCGtQv_ZG)]
- **<big>BuildUrl</big>** : builds a URL from the given params.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#BuildUrl)]
[[play](https://go.dev/play/p/JLXl1hZK7l4)]
- **<big>AddQueryParams</big>** : adds query parameters to the given URL.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#AddQueryParams)]
[[play](https://go.dev/play/p/JLXl1hZK7l4)]
<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>
@@ -1408,7 +1441,6 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)]
[[play](https://go.dev/play/p/xp1avQmn16X)] [[play](https://go.dev/play/p/xp1avQmn16X)]
<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 ```go
@@ -2012,7 +2044,6 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetProcessInfo)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetProcessInfo)]
[[play](https://go.dev/play/p/NQDVywEYYx7)] [[play](https://go.dev/play/p/NQDVywEYYx7)]
<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 ```go
@@ -2195,6 +2226,9 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsNumberStr</big>** : check if the string can convert to a number. - **<big>IsNumberStr</big>** : check if the string can convert to a number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsNumberStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)] [[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsAlphaNumeric</big>** : check if the string is alphanumeric.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsAlphaNumeric)]
[[play](https://go.dev/play/p/RHeESLrLg9c)]
- **<big>IsJSON</big>** : check if the string is valid JSON. - **<big>IsJSON</big>** : check if the string is valid JSON.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsJSON)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsJSON)]
[[play](https://go.dev/play/p/8Kip1Itjiil)] [[play](https://go.dev/play/p/8Kip1Itjiil)]
@@ -2324,6 +2358,7 @@ import "github.com/duke-git/lancet/v2/xerror"
#### [Contribution Guide](./CONTRIBUTION.md) #### [Contribution Guide](./CONTRIBUTION.md)
## Contributors ## Contributors
Thank you to all the people who contributed to lancet! Thank you to all the people who contributed to lancet!
<a href="https://github.com/duke-git/lancet/graphs/contributors"> <a href="https://github.com/duke-git/lancet/graphs/contributors">
+55 -14
View File
@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.3.5-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.3.7-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) [![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) [![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) [![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)
@@ -101,7 +101,6 @@ func main() {
- [Validator](#user-content-validator) - [Validator](#user-content-validator)
- [Xerror](#user-content-xerror) - [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 ```go
@@ -214,6 +213,30 @@ import "github.com/duke-git/lancet/v2/concurrency"
- **<big>Tee</big>** : 将一个 channel 分成两个 channel,直到取消上下文。 - **<big>Tee</big>** : 将一个 channel 分成两个 channel,直到取消上下文。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Tee)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)] [[play](https://go.dev/play/p/3TQPKnCirrP)]
- **<big>NewKeyedLocker</big>** : NewKeyedLocker 创建一个新的 KeyedLocker,并为锁的过期设置指定的 TTL。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewKeyedLocker)]
[[play](https://go.dev/play/p/GzeyC33T5rw)]
- **<big>Do</big>** :为指定的键获取锁并执行提供的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Do)]
[[play](https://go.dev/play/p/GzeyC33T5rw)]
- **<big>NewRWKeyedLocker</big>** :RWKeyedLocker 是一个简单的键值读写锁实现,允许非阻塞的锁获取。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewRWKeyedLocker)]
[[play](https://go.dev/play/p/ZrCr8sMo77T)]
- **<big>RLock</big>** : 为指定的键获取读锁并执行提供的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#RLock)]
[[play](https://go.dev/play/p/ZrCr8sMo77T)]
- **<big>Lock</big>** : 为指定的键获取锁并执行提供的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Lock)]
[[play](https://go.dev/play/p/WgAcXbOPKGk)]
- **<big>NewTryKeyedLocker</big>** : 创建一个 TryKeyedLocker 实例,TryKeyedLocker 是 KeyedLocker 的非阻塞版本。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewTryKeyedLocker)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
- **<big>TryLock</big>** : TryLock 尝试获取指定键的锁。如果锁成功获取,则返回 true,否则返回 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#TryLock)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
- **<big>Unlock</big>** : 释放指定键的锁。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Unlock)]
[[play](https://go.dev/play/p/VG9qLvyetE2)]
<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>
@@ -331,7 +354,7 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>ToRawUrlBase64</big>** : 将值转换为 RawUrlBase64 编码的字符串。 - **<big>ToRawUrlBase64</big>** : 将值转换为 RawUrlBase64 编码的字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawUrlBase64)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawUrlBase64)]
[[play](https://go.dev/play/p/HwdDPFcza1O)] [[play](https://go.dev/play/p/HwdDPFcza1O)]
- **<big>ToBigInt</big>** : 将整数转为*big.Int。 - **<big>ToBigInt</big>** : 将整数转为\*big.Int。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToBigInt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToBigInt)]
[[play](https://go.dev/play/p/X3itkCxwB_x)] [[play](https://go.dev/play/p/X3itkCxwB_x)]
@@ -355,9 +378,15 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>AesCbcDecrypt</big>** : 使用 AES CBC 算法模式解密数据。 - **<big>AesCbcDecrypt</big>** : 使用 AES CBC 算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCbcDecrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCbcDecrypt)]
[[play](https://go.dev/play/p/IOq_g8_lKZD)] [[play](https://go.dev/play/p/IOq_g8_lKZD)]
- **<big>AesCtrCrypt</big>** : 使用 AES CTR 算法模式加密/解密数据。 - **<big>AesCtrCrypt<sup>deprecated</sup></big>** : 使用 AES CTR 算法模式加密/解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)]
[[play](https://go.dev/play/p/SpaZO0-5Nsp)] [[play](https://go.dev/play/p/SpaZO0-5Nsp)]
- **<big>AesCtrEncrypt</big>** : 使用 AES CTR 算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)]
[[play](https://go.dev/play/p/x6pjPAvThRz)]
- **<big>AesCtrDecrypt</big>** : 使用 AES CTR 算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)]
[[play](https://go.dev/play/p/x6pjPAvThRz)]
- **<big>AesCfbEncrypt</big>** : 使用 AES CFB 算法模式加密数据。 - **<big>AesCfbEncrypt</big>** : 使用 AES CFB 算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCfbEncrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCfbEncrypt)]
[[play](https://go.dev/play/p/tfkF10B13kH)] [[play](https://go.dev/play/p/tfkF10B13kH)]
@@ -394,9 +423,15 @@ import "github.com/duke-git/lancet/v2/cryptor"
- **<big>DesCbcDecrypt</big>** : 使用 DES CBC 算法模式解密数据。 - **<big>DesCbcDecrypt</big>** : 使用 DES CBC 算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCbcDecrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCbcDecrypt)]
[[play](https://go.dev/play/p/4cC4QvWfe3_1)] [[play](https://go.dev/play/p/4cC4QvWfe3_1)]
- **<big>DesCtrCrypt</big>** : 使用 DES CTR 算法模式加密/解密数据。 - **<big>DesCtrCrypt<sup>deprecated</sup></big>** : 使用 DES CTR 算法模式加密/解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCtrCrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCtrCrypt)]
[[play](https://go.dev/play/p/9-T6OjKpcdw)] [[play](https://go.dev/play/p/9-T6OjKpcdw)]
- **<big>DesCtrEncrypt</big>** : 使用 DES CTR 算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCtrEncrypt)]
[[play](https://go.dev/play/p/S6p_WHCgH1d)]
- **<big>DesCtrDecrypt</big>** : 使用 DES CTR 算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCtrDecrypt)]
[[play](https://go.dev/play/p/S6p_WHCgH1d)]
- **<big>DesCfbEncrypt</big>** : 使用 DES CFB 算法模式加密数据。 - **<big>DesCfbEncrypt</big>** : 使用 DES CFB 算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCfbEncrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCfbEncrypt)]
[[play](https://go.dev/play/p/y-eNxcFBlxL)] [[play](https://go.dev/play/p/y-eNxcFBlxL)]
@@ -658,7 +693,6 @@ import "github.com/duke-git/lancet/v2/datetime"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#MaxMin)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#MaxMin)]
[[play](https://go.dev/play/p/rbW51cDtM_2)] [[play](https://go.dev/play/p/rbW51cDtM_2)]
<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 ```go
@@ -777,6 +811,9 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>RemoveFile</big>** : 删除文件。 - **<big>RemoveFile</big>** : 删除文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#RemoveFile)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#RemoveFile)]
[[play](https://go.dev/play/p/P2y0XW8a1SH)] [[play](https://go.dev/play/p/P2y0XW8a1SH)]
- **<big>RemoveDir</big>** : 删除目录,支持传入删除前的回调函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#RemoveDir)]
[[play](https://go.dev/play/p/Oa6KnPek2uy)]
- **<big>ReadFileToString</big>** : 读取文件内容并返回字符串。 - **<big>ReadFileToString</big>** : 读取文件内容并返回字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadFileToString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadFileToString)]
[[play](https://go.dev/play/p/cmfwp_5SQTp)] [[play](https://go.dev/play/p/cmfwp_5SQTp)]
@@ -832,7 +869,6 @@ import "github.com/duke-git/lancet/v2/fileutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#GetExeOrDllVersion)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#GetExeOrDllVersion)]
[[play](https://go.dev/play/p/iLRrDBhE38E)] [[play](https://go.dev/play/p/iLRrDBhE38E)]
<h3 id="formatter"> 11. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="formatter"> 11. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go ```go
@@ -926,8 +962,6 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Watcher)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)] [[play](https://go.dev/play/p/l2yrOpCLd1I)]
<h3 id="maputil"> 13. maputil 包括一些操作 map 的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="maputil"> 13. maputil 包括一些操作 map 的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go ```go
@@ -1098,6 +1132,9 @@ import "github.com/duke-git/lancet/v2/maputil"
- **<big>GetOrDefault</big>** : 返回给定键的值,如果键不存在,则返回默认值。 - **<big>GetOrDefault</big>** : 返回给定键的值,如果键不存在,则返回默认值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrDefault)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrDefault)]
[[play](https://go.dev/play/p/99QjSYSBdiM)] [[play](https://go.dev/play/p/99QjSYSBdiM)]
- **<big>FindValuesBy</big>** : 返回一个切片,包含满足给定谓词判断函数的 map 中的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#FindValuesBy)]
[[play](https://go.dev/play/p/bvNwNBZDm6v)]
<h3 id="mathutil"> 14. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="mathutil"> 14. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1282,6 +1319,12 @@ import "github.com/duke-git/lancet/v2/netutil"
- **<big>IsTelnetConnected</big>** : 检查能否 telnet 到主机。 - **<big>IsTelnetConnected</big>** : 检查能否 telnet 到主机。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#IsTelnetConnected)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)] [[play](https://go.dev/play/p/yiLCGtQv_ZG)]
- **<big>BuildUrl</big>** : 创建 url 字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#BuildUrl)]
[[play](https://go.dev/play/p/JLXl1hZK7l4)]
- **<big>AddQueryParams</big>** : 向 url 添加查询参数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#AddQueryParams)]
[[play](https://go.dev/play/p/JLXl1hZK7l4)]
<h3 id="pointer"> 16. pointer 包支持一些指针类型的操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="pointer"> 16. pointer 包支持一些指针类型的操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1405,8 +1448,6 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)]
[[play](https://go.dev/play/p/xp1avQmn16X)] [[play](https://go.dev/play/p/xp1avQmn16X)]
<h3 id="slice"> 19. slice 包含操作切片的方法集合。&nbsp; &nbsp; &nbsp; &nbsp; <a href="#index">回到目录</a></h3> <h3 id="slice"> 19. slice 包含操作切片的方法集合。&nbsp; &nbsp; &nbsp; &nbsp; <a href="#index">回到目录</a></h3>
```go ```go
@@ -1964,7 +2005,6 @@ import "github.com/duke-git/lancet/v2/strutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#FindAllOccurrences)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#FindAllOccurrences)]
[[play](https://go.dev/play/p/uvyA6azGLB1)] [[play](https://go.dev/play/p/uvyA6azGLB1)]
<h3 id="system"> 23. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="system"> 23. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go ```go
@@ -2013,8 +2053,6 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)]
[[play](https://go.dev/play/p/NQDVywEYYx7)] [[play](https://go.dev/play/p/NQDVywEYYx7)]
<h3 id="tuple"> 24. Tuple 包实现一个元组数据类型。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3> <h3 id="tuple"> 24. Tuple 包实现一个元组数据类型。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go ```go
@@ -2197,6 +2235,9 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。 - **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsNumberStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)] [[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsAlphaNumeric</big>** : 验证字符串是字母或数字。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsAlphaNumeric)]
[[play](https://go.dev/play/p/RHeESLrLg9c)]
- **<big>IsJSON</big>** : 验证字符串是否是有效 json。 - **<big>IsJSON</big>** : 验证字符串是否是有效 json。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsJSON)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsJSON)]
[[play](https://go.dev/play/p/8Kip1Itjiil)] [[play](https://go.dev/play/p/8Kip1Itjiil)]
+8
View File
@@ -25,12 +25,14 @@ type lockEntry struct {
// NewKeyedLocker creates a new KeyedLocker with the specified TTL for lock expiration. // NewKeyedLocker creates a new KeyedLocker with the specified TTL for lock expiration.
// The TTL is used to automatically release locks that are no longer held. // The TTL is used to automatically release locks that are no longer held.
// Play: https://go.dev/play/p/GzeyC33T5rw
func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] { func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] {
return &KeyedLocker[K]{ttl: ttl} return &KeyedLocker[K]{ttl: ttl}
} }
// Do acquires a lock for the specified key and executes the provided function. // Do acquires a lock for the specified key and executes the provided function.
// It returns an error if the context is canceled before the function completes. // It returns an error if the context is canceled before the function completes.
// Play: https://go.dev/play/p/GzeyC33T5rw
func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error { func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error {
entry := l.acquire(key) entry := l.acquire(key)
defer l.release(key, entry, key) defer l.release(key, entry, key)
@@ -107,12 +109,14 @@ type rwLockEntry struct {
// NewRWKeyedLocker creates a new RWKeyedLocker with the specified TTL for lock expiration. // NewRWKeyedLocker creates a new RWKeyedLocker with the specified TTL for lock expiration.
// The TTL is used to automatically release locks that are no longer held. // The TTL is used to automatically release locks that are no longer held.
// Play: https://go.dev/play/p/CkaJWWwZm9
func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] { func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] {
return &RWKeyedLocker[K]{ttl: ttl} return &RWKeyedLocker[K]{ttl: ttl}
} }
// RLock acquires a read lock for the specified key and executes the provided function. // RLock acquires a read lock for the specified key and executes the provided function.
// It returns an error if the context is canceled before the function completes. // It returns an error if the context is canceled before the function completes.
// Play: https://go.dev/play/p/ZrCr8sMo77T
func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error { func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error {
entry := l.acquire(key) entry := l.acquire(key)
defer l.release(entry, key) defer l.release(entry, key)
@@ -141,6 +145,7 @@ func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error {
// Lock acquires a write lock for the specified key and executes the provided function. // Lock acquires a write lock for the specified key and executes the provided function.
// It returns an error if the context is canceled before the function completes. // It returns an error if the context is canceled before the function completes.
// Play: https://go.dev/play/p/WgAcXbOPKGk
func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error { func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error {
entry := l.acquire(key) entry := l.acquire(key)
defer l.release(entry, key) defer l.release(entry, key)
@@ -199,12 +204,14 @@ type TryKeyedLocker[K comparable] struct {
} }
// NewTryKeyedLocker creates a new TryKeyedLocker. // NewTryKeyedLocker creates a new TryKeyedLocker.
// Play: https://go.dev/play/p/VG9qLvyetE2
func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] { func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] {
return &TryKeyedLocker[K]{locks: make(map[K]*casMutex)} return &TryKeyedLocker[K]{locks: make(map[K]*casMutex)}
} }
// TryLock tries to acquire a lock for the specified key. // TryLock tries to acquire a lock for the specified key.
// It returns true if the lock was acquired, false otherwise. // It returns true if the lock was acquired, false otherwise.
// Play: https://go.dev/play/p/VG9qLvyetE2
func (l *TryKeyedLocker[K]) TryLock(key K) bool { func (l *TryKeyedLocker[K]) TryLock(key K) bool {
l.mu.Lock() l.mu.Lock()
@@ -219,6 +226,7 @@ func (l *TryKeyedLocker[K]) TryLock(key K) bool {
} }
// Unlock releases the lock for the specified key. // Unlock releases the lock for the specified key.
// Play: https://go.dev/play/p/VG9qLvyetE2
func (l *TryKeyedLocker[K]) Unlock(key K) { func (l *TryKeyedLocker[K]) Unlock(key K) {
l.mu.Lock() l.mu.Lock()
defer l.mu.Unlock() defer l.mu.Unlock()
+4 -4
View File
@@ -174,7 +174,7 @@ func AesCtrCrypt(data, key []byte) []byte {
// AesCtrEncrypt encrypt data with key use AES CTR algorithm // AesCtrEncrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: todo // Play: https://go.dev/play/p/x6pjPAvThRz
func AesCtrEncrypt(data, key []byte) []byte { func AesCtrEncrypt(data, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) { if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)") panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
@@ -199,7 +199,7 @@ func AesCtrEncrypt(data, key []byte) []byte {
// AesCtrDecrypt decrypt data with key use AES CTR algorithm // AesCtrDecrypt decrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: todo // Play: https://go.dev/play/p/x6pjPAvThRz
func AesCtrDecrypt(encrypted, key []byte) []byte { func AesCtrDecrypt(encrypted, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) { if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)") panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
@@ -507,7 +507,7 @@ func DesCtrCrypt(data, key []byte) []byte {
// DesCtrEncrypt encrypt data with key use DES CTR algorithm // DesCtrEncrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: todo // Play: https://go.dev/play/p/S6p_WHCgH1d
func DesCtrEncrypt(data, key []byte) []byte { func DesCtrEncrypt(data, key []byte) []byte {
if len(key) != 8 { if len(key) != 8 {
panic("des: key length must be 8 bytes") panic("des: key length must be 8 bytes")
@@ -534,7 +534,7 @@ func DesCtrEncrypt(data, key []byte) []byte {
// DesCtrDecrypt decrypt data with key use DES CTR algorithm // DesCtrDecrypt decrypt data with key use DES CTR algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: todo // Play: https://go.dev/play/p/S6p_WHCgH1d
func DesCtrDecrypt(encrypted, key []byte) []byte { func DesCtrDecrypt(encrypted, key []byte) []byte {
if len(key) != 8 { if len(key) != 8 {
panic("des: key length must be 8 bytes") panic("des: key length must be 8 bytes")
+39
View File
@@ -74,6 +74,32 @@ func ExampleAesCtrCrypt() {
// hello // hello
} }
func ExampleAesCtrEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
enCrypt := AesCtrEncrypt([]byte(data), []byte(key))
deCrypt := AesCtrDecrypt(enCrypt, []byte(key))
fmt.Println(string(deCrypt))
// Output:
// hello
}
func ExampleAesCtrDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
enCrypt := AesCtrEncrypt([]byte(data), []byte(key))
deCrypt := AesCtrDecrypt(enCrypt, []byte(key))
fmt.Println(string(deCrypt))
// Output:
// hello
}
func ExampleAesCfbEncrypt() { func ExampleAesCfbEncrypt() {
data := "hello" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -227,6 +253,19 @@ func ExampleDesCtrCrypt() {
// hello // hello
} }
func ExampleDesCtrDecrypt() {
data := "hello"
key := "abcdefgh"
enCrypt := DesCtrEncrypt([]byte(data), []byte(key))
deCrypt := DesCtrDecrypt(enCrypt, []byte(key))
fmt.Println(string(deCrypt))
// Output:
// hello
}
func ExampleDesCfbEncrypt() { func ExampleDesCfbEncrypt() {
data := "hello" data := "hello"
key := "abcdefgh" key := "abcdefgh"
+49 -49
View File
@@ -1,51 +1,51 @@
-----BEGIN rsa private key----- -----BEGIN rsa private key-----
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
-----END rsa private key----- -----END rsa private key-----
+12 -12
View File
@@ -1,14 +1,14 @@
-----BEGIN rsa public key----- -----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw6Q11wDtWHZiyQbv+Xzn MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw0anfgtraA2uaZwoLpLB
tJbEELkPQ3oVSVCVjTx+ls5I+yR6oq8LxyoUE6SHcBlludkzs02B0rDkkfj6vl0i vo1EkfYvDBgeXoMQ4WMKbcw6jU8k18E+f3WM52I2RssEk6g0X1vIiarHZU5qyxbv
PCzr3HP1XT1WwFiQJnXKtNNNiLvvewB/aynj/UIBCZZvMTYwK6nc76i4JWcajaiU 2iNoT7EfgizzlXYvx06pM69GNBQrV46+lNhiOv4eeLZcOHBnxAyizlIKyLuwO+C1
I4u84Fp7gOn0IgXMhvrwtGHk7HK1Zjr0afUJVbodc6pMZfe0QWpnDq7zaeYdkPwz cX/6BxuXjX3ogw+6IaBFZN/EOMmTWc6sPKrnNCEqgCNiTbPAXb+N8j5Iv8QPs0Aw
8klWAatLDZTeR5dYli2NiWOBepO1538ZvEK3S/QP2nWJzPJy2PbEHfDaFgr055w/ VTB3jC9LP0mRt2GGD0cu+QIZkoGEhyW9Dd+0tgeIK32uXCF8uDjNpUV1TxCdn5H+
wu0MzAQgkXGV8PubhYboJuQAkuXc63IPpmWVL/93WeCNRiL5fvNzUHsbPtT48A9N lvgddxfiaIJAdY5UaTx48XRIdULhQrVKXJNyTYWTXbezViYIf1nXOdDI2hsGgKTf
nnUn4QVuVGeXIxJ1skAFsoh7i+h+mK/p5rzjPtw56nE20gYXhxf7FzbHYtHn0ego NVCocDT1LcT5zebijFHVCWfAAKEPRLdzPZomkFIa3rQQgChgePzE8Oqsaxuwx8sU
BddUzlOY0yzvCgI5Yy1RdkNe/5vU1bpLsdU/WItjR2h6EfqLosQ4iKowPBYQXJOI 09NAo3giSq1OmBBwly7h60Lwtm8+XuwmWtEgZoSQy2Hm8UMAJ3guotfYuS8mPQBi
NbpkvIhkhCVbPpMvmhfi/lATiKdoXgtvuB04wth011c5W/yXA+A3Ob73Sr2+zyxF 55JZpdqVN0D5SdwuWXhHpO4xDodNYAoMMei1NNgrX2zN3FCS8PVi97wD6cQ8xsWM
870tOp3rNTWsYLvCOjf+JdjgM3AzNuFxE4NdMLvXDf7CIXSb3X9rj3qM769Lz6XX 62nByrzIjmPwTfoCb3qP/928FMJMg7b3bYBrUnOrpVWZfAIDs4H7DoP8VLL4rMgB
bRBVbO0HxGyqLTPPmSWV61jQuUTWNGnxkovoYLrpgyumIjjIcl0aY1hogmQeA6ZN 5PuWNQ13gtX7y5ZOyLhopiKLnar9XiN8GAMANBdKRI2anGEozrfJoelJ5POXZwSa
gJxaUw9r/p8vnThL5UXKlbcCAwEAAQ== tRjbL+nWO3YnBzEunCw1xmMCAwEAAQ==
-----END rsa public key----- -----END rsa public key-----
+1 -1
View File
@@ -60,7 +60,7 @@ func (q *ArrayQueue[T]) Front() T {
// Back return back value of queue // Back return back value of queue
func (q *ArrayQueue[T]) Back() T { func (q *ArrayQueue[T]) Back() T {
return q.data[q.size-1] return q.data[q.tail-1]
} }
// EnQueue put element into queue // EnQueue put element into queue
+1 -2
View File
@@ -6,7 +6,6 @@ outline: deep
<b>lancet(柳叶刀)是一个功能强大、全面、高效、可复用的 go 语言工具函数库。包含 25 个包,超过 600 个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。</b> <b>lancet(柳叶刀)是一个功能强大、全面、高效、可复用的 go 语言工具函数库。包含 25 个包,超过 600 个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。</b>
<style> <style>
.package-title { .package-title {
color: black; color: black;
@@ -27,7 +26,7 @@ outline: deep
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
line-height: 40px; line-height: 40px;
background: #10b981; background: #6cadf5;
border: 1px solid; border: 1px solid;
margin-right: 10px; margin-right: 10px;
margin-bottom: 10px; margin-bottom: 10px;
+1 -1
View File
@@ -8,7 +8,7 @@ algorithm 算法包实现一些基本算法,sortsearchlrucache。
- [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
+22 -19
View File
@@ -41,12 +41,11 @@ import (
- [NewKeyedLocker](#NewKeyedLocker) - [NewKeyedLocker](#NewKeyedLocker)
- [KeyedLocker_Do](#Do) - [KeyedLocker_Do](#Do)
- [NewRWKeyedLocker](#NewRWKeyedLocker) - [NewRWKeyedLocker](#NewRWKeyedLocker)
- [RWKeyedLocker_RLock](#RLock) - [RLock](#RLock)
- [RWKeyedLocker_Lock](#Lock) - [Lock](#Lock)
- [NewTryKeyedLocker](#NewTryKeyedLocker) - [NewTryKeyedLocker](#NewTryKeyedLocker)
- [TryKeyedLocker_TryLock](#TryLock) - [TryLock](#TryLock)
- [TryKeyedLocker_Unlock](#Unlock) - [Unlock](#Unlock)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -478,7 +477,7 @@ func main() {
func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K]
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GzeyC33T5rw)</span></b>
```go ```go
package main package main
@@ -525,7 +524,7 @@ func main() {
} }
``` ```
### <span id="Do">KeyedLocker_Do</span> ### <span id="Do">Do</span>
<p>为指定的键获取锁并执行提供的函数。</p> <p>为指定的键获取锁并执行提供的函数。</p>
@@ -535,7 +534,7 @@ func main() {
func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GzeyC33T5rw)</span></b>
```go ```go
package main package main
@@ -591,7 +590,8 @@ func main() {
```go ```go
func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K]
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CkaJWWwZm9)</span></b>
```go ```go
package main package main
@@ -630,7 +630,7 @@ func main() {
} }
``` ```
### <span id="RLock">RWKeyedLocker_RLock</span> ### <span id="RLock">RLock</span>
<p>RLock为指定的键获取读锁并执行提供的函数。</p> <p>RLock为指定的键获取读锁并执行提供的函数。</p>
@@ -639,7 +639,8 @@ func main() {
```go ```go
func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZrCr8sMo77T)</span></b>
```go ```go
package main package main
@@ -678,16 +679,17 @@ func main() {
} }
``` ```
### <span id="Lock">RWKeyedLocker_Lock</span> ### <span id="Lock">Lock</span>
<p>RLock为指定的键获取锁并执行提供的函数。</p> <p>Lock为指定的键获取锁并执行提供的函数。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WgAcXbOPKGk)</span></b>
```go ```go
package main package main
@@ -735,7 +737,8 @@ func main() {
```go ```go
func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K]
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
@@ -766,7 +769,7 @@ func main() {
} }
``` ```
### <span id="TryLock">TryKeyedLocker_TryLock</span> ### <span id="TryLock">TryLock</span>
<p>TryLock尝试获取指定键的锁。如果锁成功获取,则返回true,否则返回false。</p> <p>TryLock尝试获取指定键的锁。如果锁成功获取,则返回true,否则返回false。</p>
@@ -776,7 +779,7 @@ func main() {
func (l *TryKeyedLocker[K]) TryLock(key K) bool func (l *TryKeyedLocker[K]) TryLock(key K) bool
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
@@ -807,7 +810,7 @@ func main() {
} }
``` ```
### <span id="Unlock">TryKeyedLocker_Unlock</span> ### <span id="Unlock">Unlock</span>
<p>释放指定键的锁。</p> <p>释放指定键的锁。</p>
@@ -817,7 +820,7 @@ func main() {
func (l *TryKeyedLocker[K]) Unlock(key K) func (l *TryKeyedLocker[K]) Unlock(key K)
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
+144 -3
View File
@@ -27,7 +27,9 @@ import (
- [AesEcbDecrypt](#AesEcbDecrypt) - [AesEcbDecrypt](#AesEcbDecrypt)
- [AesCbcEncrypt](#AesCbcEncrypt) - [AesCbcEncrypt](#AesCbcEncrypt)
- [AesCbcDecrypt](#AesCbcDecrypt) - [AesCbcDecrypt](#AesCbcDecrypt)
- [AesCtrCrypt](#AesCtrCrypt) - [AesCtrCrypt<sup>deprecated</sup>](#AesCtrCrypt)
- [AesCtrEncrypt](#AesCtrEncrypt)
- [AesCtrDecrypt](#AesCtrDecrypt)
- [AesCfbEncrypt](#AesCfbEncrypt) - [AesCfbEncrypt](#AesCfbEncrypt)
- [AesCfbDecrypt](#AesCfbDecrypt) - [AesCfbDecrypt](#AesCfbDecrypt)
- [AesOfbEncrypt](#AesOfbEncrypt) - [AesOfbEncrypt](#AesOfbEncrypt)
@@ -40,7 +42,7 @@ import (
- [DesEcbDecrypt](#DesEcbDecrypt) - [DesEcbDecrypt](#DesEcbDecrypt)
- [DesCbcEncrypt](#DesCbcEncrypt) - [DesCbcEncrypt](#DesCbcEncrypt)
- [DesCbcDecrypt](#DesCbcDecrypt) - [DesCbcDecrypt](#DesCbcDecrypt)
- [DesCtrCrypt](#DesCtrCrypt) - [DesCtrCrypt<sup>deprecated</sup>](#DesCtrCrypt)
- [DesCfbEncrypt](#DesCfbEncrypt) - [DesCfbEncrypt](#DesCfbEncrypt)
- [DesCfbDecrypt](#DesCfbDecrypt) - [DesCfbDecrypt](#DesCfbDecrypt)
- [DesOfbEncrypt](#DesOfbEncrypt) - [DesOfbEncrypt](#DesOfbEncrypt)
@@ -73,7 +75,6 @@ import (
- [RsaSign](#RsaSign) - [RsaSign](#RsaSign)
- [RsaVerifySign](#RsaVerifySign) - [RsaVerifySign](#RsaVerifySign)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
@@ -218,6 +219,8 @@ func main() {
<p>使用AES CTR算法模式加密/解密数据,参数`key`的长度是16, 24 or 32。</p> <p>使用AES CTR算法模式加密/解密数据,参数`key`的长度是16, 24 or 32。</p>
> ⚠️ 本函数已弃用,使用`AesCtrEncrypt``AesCtrDecrypt`代替。
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
@@ -248,6 +251,74 @@ func main() {
} }
``` ```
### <span id="AesCtrEncrypt">AesCtrEncrypt</span>
<p>使用AES CTR算法模式加密数据,参数`key`的长度是16, 24 or 32。</p>
<b>函数签名:</b>
```go
func AesCtrEncrypt(data, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/x6pjPAvThRz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCtrDecrypt">AesCtrDecrypt</span>
<p>使用AES CTR算法模式解密数据,参数`key`的长度是16, 24 or 32。</p>
<b>函数签名:</b>
```go
func AesCtrDecrypt(encrypted, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/x6pjPAvThRz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCfbEncrypt">AesCfbEncrypt</span> ### <span id="AesCfbEncrypt">AesCfbEncrypt</span>
<p>使用AES CFB算法模式加密数据,参数`key`的长度是16, 24 or 32。</p> <p>使用AES CFB算法模式加密数据,参数`key`的长度是16, 24 or 32。</p>
@@ -648,10 +719,80 @@ func main() {
} }
``` ```
### <span id="DesCtrEncrypt">DesCtrEncrypt</span>
<p>使用DES CTR算法模式加密数据,参数`key`的长度是8</p>
<b>函数签名:</b>
```go
func DesCtrEncrypt(data, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/S6p_WHCgH1d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCtrDecrypt">DesCtrDecrypt</span>
<p>使用DES CTR算法模式加密数据,参数`key`的长度是8</p>
<b>函数签名:</b>
```go
func DesCtrDecrypt(encrypted, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/S6p_WHCgH1d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCtrCrypt">DesCtrCrypt</span> ### <span id="DesCtrCrypt">DesCtrCrypt</span>
<p>使用DES CTR算法模式加密/解密数据,参数`key`的长度是8</p> <p>使用DES CTR算法模式加密/解密数据,参数`key`的长度是8</p>
> ⚠️ 本函数已弃用,使用`DesCtrEncrypt``DesCtrDecrypt`代替。
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
+1 -1
View File
@@ -1092,7 +1092,7 @@ func main() {
### 4. PriorityQueue ### 4. PriorityQueue
切片实现的优先级队列。 切片实现的优先级队列。
### <span id="NewPriorityQueue">NewPriorityQueue</span> ### <span id="NewPriorityQueue">NewPriorityQueue</span>
<p>返回一个具有特定容量的PriorityQueue指针,参数 `comarator` 用于比较队列中T类型的值。</p> <p>返回一个具有特定容量的PriorityQueue指针,参数 `comarator` 用于比较队列中T类型的值。</p>
+2 -1
View File
@@ -427,7 +427,7 @@ func main() {
func RemoveDir(path string, onDelete ...func(path string)) error func RemoveDir(path string, onDelete ...func(path string)) error
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Oa6KnPek2uy)</span></b>
```go ```go
package main package main
@@ -1114,6 +1114,7 @@ func main() {
// 2 // 2
} }
``` ```
### <span id="GetExeOrDllVersion">GetExeOrDllVersion</span> ### <span id="GetExeOrDllVersion">GetExeOrDllVersion</span>
<p>返回exe,dll文件版本号(仅Window平台).</p> <p>返回exe,dll文件版本号(仅Window平台).</p>
+1 -3
View File
@@ -1259,7 +1259,6 @@ func main() {
} }
``` ```
### <span id="OrderedMap_Delete">OrderedMap_Delete</span> ### <span id="OrderedMap_Delete">OrderedMap_Delete</span>
<p>删除给定键的键值对。</p> <p>删除给定键的键值对。</p>
@@ -2192,7 +2191,6 @@ func main() {
} }
``` ```
### <span id="GetOrSet">GetOrSet</span> ### <span id="GetOrSet">GetOrSet</span>
<p>返回给定键的值,如果不存在则设置该值。</p> <p>返回给定键的值,如果不存在则设置该值。</p>
@@ -2319,7 +2317,7 @@ func main() {
func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bvNwNBZDm6v)</span></b>
```go ```go
package main package main
+2 -3
View File
@@ -48,7 +48,6 @@ import (
- [UploadFile](#UploadFile) - [UploadFile](#UploadFile)
- [IsPingConnected](#IsPingConnected) - [IsPingConnected](#IsPingConnected)
- [IsTelnetConnected](#IsTelnetConnected) - [IsTelnetConnected](#IsTelnetConnected)
- [IsTelnetConnected](#IsTelnetConnected)
- [BuildUrl](#BuildUrl) - [BuildUrl](#BuildUrl)
- [AddQueryParams](#AddQueryParams) - [AddQueryParams](#AddQueryParams)
@@ -1045,7 +1044,7 @@ func main() {
func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) func BuildUrl(scheme, host, path string, query map[string][]string) (string, error)
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JLXl1hZK7l4)</span></b>
```go ```go
package main package main
@@ -1085,7 +1084,7 @@ func main() {
func AddQueryParams(urlStr string, params map[string][]string) (string, error) func AddQueryParams(urlStr string, params map[string][]string) (string, error)
``` ```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JLXl1hZK7l4)</span></b>
```go ```go
package main package main
+37
View File
@@ -824,6 +824,43 @@ func main() {
} }
``` ```
### <span id="IsAlphaNumeric">IsAlphaNumeric</span>
<p>验证字符串是字母或数字。</p>
<b>函数签名:</b>
```go
func IsAlphaNumeric(s string) bool
```
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/RHeESLrLg9c)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
result1 := validator.IsAlphaNumeric("ABC")
result2 := validator.IsAlphaNumeric("123")
result3 := validator.IsAlphaNumeric("abc123")
result4 := validator.IsAlphaNumeric("abc123@#$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
```
### <span id="IsJSON">IsJSON</span> ### <span id="IsJSON">IsJSON</span>
<p>验证字符串是否是有效json。</p> <p>验证字符串是否是有效json。</p>
+2 -3
View File
@@ -6,7 +6,6 @@ outline: deep
<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> <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> <style>
.package-title { .package-title {
color: black; color: black;
@@ -27,7 +26,7 @@ outline: deep
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
line-height: 40px; line-height: 40px;
background: #059669; background: #6cadf5;
border: 1px solid; border: 1px solid;
margin-right: 10px; margin-right: 10px;
margin-bottom: 10px; margin-bottom: 10px;
@@ -47,6 +46,7 @@ outline: deep
<div class="package-cell">cryptor</div> <div class="package-cell">cryptor</div>
<div class="package-cell">datastructure</div> <div class="package-cell">datastructure</div>
<div class="package-cell">datetime</div> <div class="package-cell">datetime</div>
<div class="package-cell">eventbus</div>
<div class="package-cell">fileutil</div> <div class="package-cell">fileutil</div>
<div class="package-cell">formatter</div> <div class="package-cell">formatter</div>
<div class="package-cell">function</div> <div class="package-cell">function</div>
@@ -67,4 +67,3 @@ outline: deep
<div class="package-cell">xerror</div> <div class="package-cell">xerror</div>
</div> </div>
</div> </div>
+1 -1
View File
@@ -8,7 +8,7 @@ Package algorithm implements some basic algorithm. eg. sort, search.
- [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
+36 -18
View File
@@ -1,4 +1,5 @@
# Concurrency # Concurrency
Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel. Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ Package concurrency contain some functions to support concurrent programming. eg
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/concurrency" "github.com/duke-git/lancet/v2/concurrency"
@@ -37,20 +39,22 @@ import (
### KeyedLocker ### KeyedLocker
- [NewKeyedLocker](#NewKeyedLocker) - [NewKeyedLocker](#NewKeyedLocker)
- [KeyedLocker_Do](#Do) - [Do](#Do)
- [NewRWKeyedLocker](#NewRWKeyedLocker) - [NewRWKeyedLocker](#NewRWKeyedLocker)
- [RWKeyedLocker_RLock](#RLock) - [RLock](#RLock)
- [RWKeyedLocker_Lock](#Lock) - [Lock](#Lock)
- [NewTryKeyedLocker](#NewTryKeyedLocker) - [NewTryKeyedLocker](#NewTryKeyedLocker)
- [TryKeyedLocker_TryLock](#TryLock) - [TryLock](#TryLock)
- [TryKeyedLocker_Unlock](#Unlock) - [Unlock](#Unlock)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
## Channel ## Channel
### <span id="NewChannel">NewChannel</span> ### <span id="NewChannel">NewChannel</span>
<p>Create a Channel pointer instance.</p> <p>Create a Channel pointer instance.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -59,6 +63,7 @@ import (
type Channel[T any] struct type Channel[T any] struct
func NewChannel[T any]() *Channel[T] func NewChannel[T any]() *Channel[T]
``` ```
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b> <b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go ```go
@@ -83,6 +88,7 @@ func main() {
```go ```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/qmWSy1NVF-Y)</span></b> <b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
```go ```go
@@ -135,6 +141,7 @@ func main() {
```go ```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/2VYFMexEvTm)</span></b> <b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/2VYFMexEvTm)</span></b>
```go ```go
@@ -174,6 +181,7 @@ func main() {
```go ```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -213,6 +221,7 @@ func main() {
```go ```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
``` ```
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b> <b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go ```go
@@ -251,6 +260,7 @@ func main() {
```go ```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -293,6 +303,7 @@ func main() {
```go ```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -336,6 +347,7 @@ func main() {
```go ```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -374,6 +386,7 @@ func main() {
```go ```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -420,6 +433,7 @@ func main() {
```go ```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -465,7 +479,7 @@ func main() {
func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K]
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GzeyC33T5rw)</span></b>
```go ```go
package main package main
@@ -512,7 +526,7 @@ func main() {
} }
``` ```
### <span id="Do">KeyedLocker_Do</span> ### <span id="Do">Do</span>
<p>Acquires a lock for the specified key and executes the provided function.</p> <p>Acquires a lock for the specified key and executes the provided function.</p>
@@ -522,7 +536,7 @@ func main() {
func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GzeyC33T5rw)</span></b>
```go ```go
package main package main
@@ -578,7 +592,8 @@ func main() {
```go ```go
func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K]
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ZrCr8sMo77T)</span></b>
```go ```go
package main package main
@@ -617,7 +632,7 @@ func main() {
} }
``` ```
### <span id="RLock">RWKeyedLocker_RLock</span> ### <span id="RLock">RLock</span>
<p>Acquires a read lock for the specified key and executes the provided function.</p> <p>Acquires a read lock for the specified key and executes the provided function.</p>
@@ -626,7 +641,8 @@ func main() {
```go ```go
func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ZrCr8sMo77T)</span></b>
```go ```go
package main package main
@@ -665,7 +681,7 @@ func main() {
} }
``` ```
### <span id="Lock">RWKeyedLocker_Lock</span> ### <span id="Lock">Lock</span>
<p>Acquires a write lock for the specified key and executes the provided function.</p> <p>Acquires a write lock for the specified key and executes the provided function.</p>
@@ -674,7 +690,8 @@ func main() {
```go ```go
func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/WgAcXbOPKGk)</span></b>
```go ```go
package main package main
@@ -722,7 +739,8 @@ func main() {
```go ```go
func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K]
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
@@ -753,7 +771,7 @@ func main() {
} }
``` ```
### <span id="TryLock">TryKeyedLocker_TryLock</span> ### <span id="TryLock">TryLock</span>
<p>TryLock tries to acquire a lock for the specified key.</p> <p>TryLock tries to acquire a lock for the specified key.</p>
@@ -763,7 +781,7 @@ func main() {
func (l *TryKeyedLocker[K]) TryLock(key K) bool func (l *TryKeyedLocker[K]) TryLock(key K) bool
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
@@ -794,7 +812,7 @@ func main() {
} }
``` ```
### <span id="Unlock">TryKeyedLocker_Unlock</span> ### <span id="Unlock">Unlock</span>
<p>Unlock releases the lock for the specified key.</p> <p>Unlock releases the lock for the specified key.</p>
@@ -804,7 +822,7 @@ func main() {
func (l *TryKeyedLocker[K]) Unlock(key K) func (l *TryKeyedLocker[K]) Unlock(key K)
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/VG9qLvyetE2)</span></b>
```go ```go
package main package main
+146 -2
View File
@@ -27,7 +27,9 @@ import (
- [AesEcbDecrypt](#AesEcbDecrypt) - [AesEcbDecrypt](#AesEcbDecrypt)
- [AesCbcEncrypt](#AesCbcEncrypt) - [AesCbcEncrypt](#AesCbcEncrypt)
- [AesCbcDecrypt](#AesCbcDecrypt) - [AesCbcDecrypt](#AesCbcDecrypt)
- [AesCtrCrypt](#AesCtrCrypt) - [AesCtrCrypt<sup>deprecated</sup>](#AesCtrCrypt)
- [AesCtrEncrypt](#AesCtrEncrypt)
- [AesCtrDecrypt](#AesCtrDecrypt)
- [AesCfbEncrypt](#AesCfbEncrypt) - [AesCfbEncrypt](#AesCfbEncrypt)
- [AesCfbDecrypt](#AesCfbDecrypt) - [AesCfbDecrypt](#AesCfbDecrypt)
- [AesOfbEncrypt](#AesOfbEncrypt) - [AesOfbEncrypt](#AesOfbEncrypt)
@@ -40,7 +42,9 @@ import (
- [DesEcbDecrypt](#DesEcbDecrypt) - [DesEcbDecrypt](#DesEcbDecrypt)
- [DesCbcEncrypt](#DesCbcEncrypt) - [DesCbcEncrypt](#DesCbcEncrypt)
- [DesCbcDecrypt](#DesCbcDecrypt) - [DesCbcDecrypt](#DesCbcDecrypt)
- [DesCtrCrypt](#DesCtrCrypt) - [DesCtrCrypt<sup>deprecated</sup>](#DesCtrCrypt)
- [DesCfbEncrypt](#DesCfbEncrypt)
- [DesCfbDecrypt](#DesCfbDecrypt)
- [DesCfbEncrypt](#DesCfbEncrypt) - [DesCfbEncrypt](#DesCfbEncrypt)
- [DesCfbDecrypt](#DesCfbDecrypt) - [DesCfbDecrypt](#DesCfbDecrypt)
- [DesOfbEncrypt](#DesOfbEncrypt) - [DesOfbEncrypt](#DesOfbEncrypt)
@@ -217,6 +221,8 @@ func main() {
<p>Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.</p>
> ⚠️ This function is deprecated. use `AesCtrEncrypt` and `AesCtrDecrypt` instead.
<b>Signature:</b> <b>Signature:</b>
```go ```go
@@ -247,6 +253,74 @@ func main() {
} }
``` ```
### <span id="AesCtrEncrypt">AesCtrEncrypt</span>
<p>Encrypt data with key use AES CTR algorithm</p>
<b>Signature:</b>
```go
func AesCtrEncrypt(data, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/x6pjPAvThRz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCtrDecrypt">AesCtrDecrypt</span>
<p>Decrypt data with key use AES CTR algorithm</p>
<b>Signature:</b>
```go
func AesCtrDecrypt(encrypted, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/x6pjPAvThRz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="AesCfbEncrypt">AesCfbEncrypt</span> ### <span id="AesCfbEncrypt">AesCfbEncrypt</span>
<p>Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -651,6 +725,8 @@ func main() {
<p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p> <p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
> ⚠️ This function is deprecated. use `DesCtrEncrypt` and `DesCtrDecrypt` instead.
<b>Signature:</b> <b>Signature:</b>
```go ```go
@@ -681,6 +757,74 @@ func main() {
} }
``` ```
### <span id="DesCtrEncrypt">DesCtrCrypt</span>
<p>Encrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
<b>Signature:</b>
```go
func DesCtrEncrypt(data, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/S6p_WHCgH1d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCtrDecrypt">DesCtrDecrypt</span>
<p>Decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
<b>Signature:</b>
```go
func DesCtrDecrypt(encrypted, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/S6p_WHCgH1d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := "hello"
key := "abcdefgh"
encrypted := cryptor.DesCtrEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
```
### <span id="DesCfbEncrypt">DesCfbEncrypt</span> ### <span id="DesCfbEncrypt">DesCfbEncrypt</span>
<p>Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.</p> <p>Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.</p>
+1 -1
View File
@@ -427,7 +427,7 @@ func main() {
func RemoveDir(path string, onDelete ...func(path string)) error func RemoveDir(path string, onDelete ...func(path string)) error
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Oa6KnPek2uy)</span></b>
```go ```go
package main package main
+1 -3
View File
@@ -10,7 +10,6 @@ Package maputil includes some functions to manipulate map.
- [https://github.com/duke-git/lancet/blob/main/maputil/concurrentmap.go](https://github.com/duke-git/lancet/blob/main/maputil/concurrentmap.go) - [https://github.com/duke-git/lancet/blob/main/maputil/concurrentmap.go](https://github.com/duke-git/lancet/blob/main/maputil/concurrentmap.go)
- [https://github.com/duke-git/lancet/blob/main/maputil/orderedmap.go](https://github.com/duke-git/lancet/blob/main/maputil/orderedmap.go) - [https://github.com/duke-git/lancet/blob/main/maputil/orderedmap.go](https://github.com/duke-git/lancet/blob/main/maputil/orderedmap.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Example: ## Example:
@@ -1275,7 +1274,6 @@ func main() {
} }
``` ```
### <span id="OrderedMap_Delete">OrderedMap_Delete</span> ### <span id="OrderedMap_Delete">OrderedMap_Delete</span>
<p>Deletes the key-value pair for the given key.</p> <p>Deletes the key-value pair for the given key.</p>
@@ -2337,7 +2335,7 @@ func main() {
func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/bvNwNBZDm6v)</span></b>
```go ```go
package main package main
+2 -3
View File
@@ -51,7 +51,6 @@ import (
- [BuildUrl](#BuildUrl) - [BuildUrl](#BuildUrl)
- [AddQueryParams](#AddQueryParams) - [AddQueryParams](#AddQueryParams)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css"> <link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
@@ -1045,7 +1044,7 @@ func main() {
func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) func BuildUrl(scheme, host, path string, query map[string][]string) (string, error)
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/JLXl1hZK7l4)</span></b>
```go ```go
package main package main
@@ -1085,7 +1084,7 @@ func main() {
func AddQueryParams(urlStr string, params map[string][]string) (string, error) func AddQueryParams(urlStr string, params map[string][]string) (string, error)
``` ```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b> <b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/JLXl1hZK7l4)</span></b>
```go ```go
package main package main
+37
View File
@@ -826,6 +826,43 @@ func main() {
} }
``` ```
### <span id="IsAlphaNumeric">IsAlphaNumeric</span>
<p>Check if the string is alphanumeric.</p>
<b>Signature:</b>
```go
func IsAlphaNumeric(s string) bool
```
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/RHeESLrLg9c)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
result1 := validator.IsAlphaNumeric("ABC")
result2 := validator.IsAlphaNumeric("123")
result3 := validator.IsAlphaNumeric("abc123")
result4 := validator.IsAlphaNumeric("abc123@#$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
```
### <span id="IsJSON">IsJSON</span> ### <span id="IsJSON">IsJSON</span>
<p>Check if the string is valid JSON.</p> <p>Check if the string is valid JSON.</p>
+1 -1
View File
@@ -190,7 +190,7 @@ func RemoveFile(path string, onDelete ...func(path string)) error {
} }
// RemoveDir remove the path directory. // RemoveDir remove the path directory.
// Play: todo // Play: https://go.dev/play/p/Oa6KnPek2uy
func RemoveDir(path string, onDelete ...func(path string)) error { func RemoveDir(path string, onDelete ...func(path string)) error {
info, err := os.Stat(path) info, err := os.Stat(path)
if err != nil { if err != nil {
+1 -1
View File
@@ -668,7 +668,7 @@ func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V {
} }
// FindValuesBy returns a slice of values from the map that satisfy the given predicate function. // FindValuesBy returns a slice of values from the map that satisfy the given predicate function.
// Play: todo // Play: https://go.dev/play/p/bvNwNBZDm6v
func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V { func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V {
result := make([]V, 0) result := make([]V, 0)
+3 -3
View File
@@ -309,7 +309,7 @@ func IsTelnetConnected(host string, port string) bool {
} }
// BuildUrl builds a URL from the given params. // BuildUrl builds a URL from the given params.
// Play: todo // Play: https://go.dev/play/p/JLXl1hZK7l4
func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) { func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) {
if err := validateScheme(scheme); err != nil { if err := validateScheme(scheme); err != nil {
return "", err return "", err
@@ -365,13 +365,13 @@ func validateScheme(scheme string) error {
return nil return nil
} }
var hostRegex = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])(\.[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])*$`) var hostRegex = regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]?)(\.[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]?)+$`)
var pathRegex = regexp.MustCompile(`^\/([a-zA-Z0-9%_-]+(?:\/[a-zA-Z0-9%_-]+)*)$`) var pathRegex = regexp.MustCompile(`^\/([a-zA-Z0-9%_-]+(?:\/[a-zA-Z0-9%_-]+)*)$`)
var alphaNumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]+$`) var alphaNumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]+$`)
// AddQueryParams adds query parameters to the given URL. // AddQueryParams adds query parameters to the given URL.
// Play: todoå // Play: https://go.dev/play/p/JLXl1hZK7l4
func AddQueryParams(urlStr string, params map[string][]string) (string, error) { func AddQueryParams(urlStr string, params map[string][]string) (string, error) {
parsedUrl, err := url.Parse(urlStr) parsedUrl, err := url.Parse(urlStr)
if err != nil { if err != nil {
+8
View File
@@ -196,6 +196,14 @@ func TestBuildUrl(t *testing.T) {
want: "https://www.test.com/path%20with%20spaces", want: "https://www.test.com/path%20with%20spaces",
wantErr: false, wantErr: false,
}, },
{
scheme: "https",
host: "my.api.edu.cn",
path: "/api",
query: nil,
want: "https://my.api.edu.cn/api",
wantErr: false,
},
} }
for _, tt := range tests { for _, tt := range tests {
+8 -5
View File
@@ -128,16 +128,19 @@ func Retry(retryFunc RetryFunc, opts ...Option) error {
} }
var i uint var i uint
var lastErr error
for i < config.retryTimes { for i < config.retryTimes {
err := retryFunc() lastErr = retryFunc()
if err != nil { if lastErr == nil {
return nil
}
if i < config.retryTimes-1 { // Only wait if it's not the last retry
select { select {
case <-time.After(config.backoffStrategy.CalculateInterval()): case <-time.After(config.backoffStrategy.CalculateInterval()):
case <-config.context.Done(): case <-config.context.Done():
return errors.New("retry is cancelled") return errors.New("retry is cancelled")
} }
} else {
return nil
} }
i++ i++
} }
@@ -146,7 +149,7 @@ func Retry(retryFunc RetryFunc, opts ...Option) error {
lastSlash := strings.LastIndex(funcPath, "/") lastSlash := strings.LastIndex(funcPath, "/")
funcName := funcPath[lastSlash+1:] funcName := funcPath[lastSlash+1:]
return fmt.Errorf("function %s run failed after %d times retry", funcName, i) return fmt.Errorf("function %s run failed after %d times retry, last error: %w", funcName, i, lastErr)
} }
// BackoffStrategy is an interface that defines a method for calculating backoff intervals. // BackoffStrategy is an interface that defines a method for calculating backoff intervals.
+1 -1
View File
@@ -118,7 +118,7 @@ func ExampleRetryTimes() {
} }
// Output: // Output:
// function retry.ExampleRetryTimes.func1 run failed after 2 times retry // function retry.ExampleRetryTimes.func1 run failed after 2 times retry, last error: error occurs
} }
func ExampleRetry() { func ExampleRetry() {
+3 -1
View File
@@ -15,14 +15,16 @@ func TestRetryFailed(t *testing.T) {
assert := internal.NewAssert(t, "TestRetryFailed") assert := internal.NewAssert(t, "TestRetryFailed")
var number int var number int
customError := errors.New("error occurs")
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
return errors.New("error occurs") return customError
} }
err := Retry(increaseNumber, RetryWithLinearBackoff(time.Microsecond*50)) err := Retry(increaseNumber, RetryWithLinearBackoff(time.Microsecond*50))
assert.IsNotNil(err) assert.IsNotNil(err)
assert.Equal(errors.Is(err, customError), true)
assert.Equal(DefaultRetryTimes, number) assert.Equal(DefaultRetryTimes, number)
} }
+4
View File
@@ -125,6 +125,8 @@ func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T { func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T {
result := make([]T, 0) result := make([]T, 0)
var wg sync.WaitGroup var wg sync.WaitGroup
var mu sync.Mutex
workerChan := make(chan struct{}, numThreads) workerChan := make(chan struct{}, numThreads)
@@ -137,7 +139,9 @@ func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool,
defer wg.Done() defer wg.Done()
if predicate(i, v) { if predicate(i, v) {
mu.Lock()
result = append(result, v) result = append(result, v)
mu.Unlock()
} }
<-workerChan <-workerChan
+2 -2
View File
@@ -182,8 +182,8 @@ func IsJSON(str string) bool {
return json.Unmarshal([]byte(str), &js) == nil return json.Unmarshal([]byte(str), &js) == nil
} }
// IsAlphaNumericStr check if the string is alphanumeric. // IsAlphaNumeric check if the string is alphanumeric.
// Play: todo // Play: https://go.dev/play/p/RHeESLrLg9c
func IsAlphaNumeric(s string) bool { func IsAlphaNumeric(s string) bool {
return alphaNumericMatcher.MatchString(s) return alphaNumericMatcher.MatchString(s)
} }
+18
View File
@@ -665,3 +665,21 @@ func ExampleIsChinaUnionPay() {
// true // true
// false // false
} }
func ExampleIsAlphaNumeric() {
result1 := IsAlphaNumeric("ABC")
result2 := IsAlphaNumeric("123")
result3 := IsAlphaNumeric("abc123")
result4 := IsAlphaNumeric("abc123@#$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}