From 539078e6b8b0036473ba054fd95e97a6f75752c3 Mon Sep 17 00:00:00 2001 From: dudaodong Date: Thu, 29 May 2025 11:50:17 +0800 Subject: [PATCH 01/11] doc: add play ground demo for v2.3.6 --- README.md | 26 ++--- README_zh-CN.md | 42 +++++--- concurrency/keyed_locker.go | 8 ++ cryptor/crypto.go | 8 +- cryptor/crypto_example_test.go | 39 ++++++++ cryptor/rsa_private_example.pem | 98 +++++++++--------- cryptor/rsa_public_example.pem | 24 ++--- docs/api/packages/concurrency.md | 16 +-- docs/api/packages/cryptor.md | 143 ++++++++++++++++++++++++++- docs/api/packages/fileutil.md | 15 +-- docs/api/packages/maputil.md | 10 +- docs/api/packages/netutil.md | 4 +- docs/api/packages/validator.md | 2 +- docs/en/api/packages/concurrency.md | 16 +-- docs/en/api/packages/cryptor.md | 148 +++++++++++++++++++++++++++- docs/en/api/packages/fileutil.md | 12 +-- docs/en/api/packages/maputil.md | 12 +-- docs/en/api/packages/netutil.md | 7 +- docs/en/api/packages/validator.md | 2 +- fileutil/file.go | 2 +- maputil/map.go | 2 +- netutil/net.go | 4 +- validator/validator.go | 2 +- 23 files changed, 489 insertions(+), 153 deletions(-) diff --git a/README.md b/README.md index fe6717ab..239eedc6 100644 --- a/README.md +++ b/README.md @@ -216,28 +216,28 @@ import "github.com/duke-git/lancet/v2/concurrency" [[play](https://go.dev/play/p/3TQPKnCirrP)] - **NewKeyedLocker** : 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/todo)] + [[play](https://go.dev/play/p/GzeyC33T5rw)] - **Do** :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/todo)] + [[play](https://go.dev/play/p/GzeyC33T5rw)] - **NewRWKeyedLocker** :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/todo)] + [[play](https://go.dev/play/p/ZrCr8sMo77T)] - **RLock** : 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/todo)] + [[play](https://go.dev/play/p/ZrCr8sMo77T)] - **Lock** : 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/todo)] + [[play](https://go.dev/play/p/WgAcXbOPKGk)] - **NewTryKeyedLocker** : 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/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)] - **TryLock** : 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/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)] - **Unlock** : 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/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)]

4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...       index

@@ -803,7 +803,7 @@ import "github.com/duke-git/lancet/v2/fileutil" [[play](https://go.dev/play/p/P2y0XW8a1SH)] - **RemoveDir** : delete directory. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#RemoveDir)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/Oa6KnPek2uy)] - **ReadFileToString** : return string of file content. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ReadFileToString)] [[play](https://go.dev/play/p/cmfwp_5SQTp)] @@ -1124,7 +1124,7 @@ import "github.com/duke-git/lancet/v2/maputil" [[play](https://go.dev/play/p/99QjSYSBdiM)] - **FindValuesBy** : 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/todo)] + [[play](https://go.dev/play/p/bvNwNBZDm6v)]

13. Mathutil package implements some functions for math calculation.        index

@@ -1311,10 +1311,10 @@ import "github.com/duke-git/lancet/v2/netutil" [[play](https://go.dev/play/p/yiLCGtQv_ZG)] - **BuildUrl** : 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/todo)] + [[play](https://go.dev/play/p/JLXl1hZK7l4)] - **AddQueryParams** : 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/todo)] + [[play](https://go.dev/play/p/JLXl1hZK7l4)]

15. Pointer package contains some util functions to operate go pointer.        index

@@ -2228,7 +2228,7 @@ import "github.com/duke-git/lancet/v2/validator" [[play](https://go.dev/play/p/LzaKocSV79u)] - **IsAlphaNumeric** : 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/todo)] + [[play](https://go.dev/play/p/RHeESLrLg9c)] - **IsJSON** : check if the string is valid JSON. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsJSON)] [[play](https://go.dev/play/p/8Kip1Itjiil)] diff --git a/README_zh-CN.md b/README_zh-CN.md index 48f72236..7a602111 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -215,28 +215,28 @@ import "github.com/duke-git/lancet/v2/concurrency" [[play](https://go.dev/play/p/3TQPKnCirrP)] - **NewKeyedLocker** : NewKeyedLocker 创建一个新的 KeyedLocker,并为锁的过期设置指定的 TTL。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewKeyedLocker)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/GzeyC33T5rw)] - **Do** :为指定的键获取锁并执行提供的函数。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Do)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/GzeyC33T5rw)] - **NewRWKeyedLocker** :RWKeyedLocker 是一个简单的键值读写锁实现,允许非阻塞的锁获取。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewRWKeyedLocker)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/ZrCr8sMo77T)] - **RLock** : 为指定的键获取读锁并执行提供的函数。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#RLock)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/ZrCr8sMo77T)] - **Lock** : 为指定的键获取锁并执行提供的函数。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Lock)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/WgAcXbOPKGk)] - **NewTryKeyedLocker** : 创建一个 TryKeyedLocker 实例,TryKeyedLocker 是 KeyedLocker 的非阻塞版本。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#NewTryKeyedLocker)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)] - **TryLock** : TryLock 尝试获取指定键的锁。如果锁成功获取,则返回 true,否则返回 false。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#TryLock)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)] - **Unlock** : 释放指定键的锁。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/concurrency.md#Unlock)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/VG9qLvyetE2)]

4. condition 包含一些用于条件判断的函数。       回到目录

@@ -378,9 +378,15 @@ import "github.com/duke-git/lancet/v2/cryptor" - **AesCbcDecrypt** : 使用 AES CBC 算法模式解密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCbcDecrypt)] [[play](https://go.dev/play/p/IOq_g8_lKZD)] -- **AesCtrCrypt** : 使用 AES CTR 算法模式加密/解密数据。 +- **AesCtrCryptdeprecated** : 使用 AES CTR 算法模式加密/解密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)] [[play](https://go.dev/play/p/SpaZO0-5Nsp)] +- **AesCtrEncrypt** : 使用 AES CTR 算法模式加密数据。 + [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)] + [[play](https://go.dev/play/p/x6pjPAvThRz)] +- **AesCtrDecrypt** : 使用 AES CTR 算法模式解密数据。 + [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCtrCrypt)] + [[play](https://go.dev/play/p/x6pjPAvThRz)] - **AesCfbEncrypt** : 使用 AES CFB 算法模式加密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesCfbEncrypt)] [[play](https://go.dev/play/p/tfkF10B13kH)] @@ -417,9 +423,15 @@ import "github.com/duke-git/lancet/v2/cryptor" - **DesCbcDecrypt** : 使用 DES CBC 算法模式解密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCbcDecrypt)] [[play](https://go.dev/play/p/4cC4QvWfe3_1)] -- **DesCtrCrypt** : 使用 DES CTR 算法模式加密/解密数据。 +- **DesCtrCryptdeprecated** : 使用 DES CTR 算法模式加密/解密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCtrCrypt)] [[play](https://go.dev/play/p/9-T6OjKpcdw)] +- **DesCtrEncrypt** : 使用 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)] +- **DesCtrDecrypt** : 使用 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)] - **DesCfbEncrypt** : 使用 DES CFB 算法模式加密数据。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#DesCfbEncrypt)] [[play](https://go.dev/play/p/y-eNxcFBlxL)] @@ -801,7 +813,7 @@ import "github.com/duke-git/lancet/v2/fileutil" [[play](https://go.dev/play/p/P2y0XW8a1SH)] - **RemoveDir** : 删除目录,支持传入删除前的回调函数。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#RemoveDir)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/Oa6KnPek2uy)] - **ReadFileToString** : 读取文件内容并返回字符串。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadFileToString)] [[play](https://go.dev/play/p/cmfwp_5SQTp)] @@ -1122,7 +1134,7 @@ import "github.com/duke-git/lancet/v2/maputil" [[play](https://go.dev/play/p/99QjSYSBdiM)] - **FindValuesBy** : 返回一个切片,包含满足给定谓词判断函数的 map 中的值。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#FindValuesBy)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/bvNwNBZDm6v)]

14. mathutil 包实现了一些数学计算的函数。       回到目录

@@ -1309,10 +1321,10 @@ import "github.com/duke-git/lancet/v2/netutil" [[play](https://go.dev/play/p/yiLCGtQv_ZG)] - **BuildUrl** : 创建 url 字符串。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#BuildUrl)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/JLXl1hZK7l4)] - **AddQueryParams** : 向 url 添加查询参数。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#AddQueryParams)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/JLXl1hZK7l4)]

16. pointer 包支持一些指针类型的操作。       回到目录

@@ -2225,7 +2237,7 @@ import "github.com/duke-git/lancet/v2/validator" [[play](https://go.dev/play/p/LzaKocSV79u)] - **IsAlphaNumeric** : 验证字符串是字母或数字。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsAlphaNumeric)] - [[play](https://go.dev/play/p/todo)] + [[play](https://go.dev/play/p/RHeESLrLg9c)] - **IsJSON** : 验证字符串是否是有效 json。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsJSON)] [[play](https://go.dev/play/p/8Kip1Itjiil)] diff --git a/concurrency/keyed_locker.go b/concurrency/keyed_locker.go index 651619dd..c222d706 100644 --- a/concurrency/keyed_locker.go +++ b/concurrency/keyed_locker.go @@ -25,12 +25,14 @@ type lockEntry struct { // 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. +// Play: https://go.dev/play/p/GzeyC33T5rw func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] { return &KeyedLocker[K]{ttl: ttl} } // 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. +// Play: https://go.dev/play/p/GzeyC33T5rw func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error { entry := l.acquire(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. // 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] { return &RWKeyedLocker[K]{ttl: ttl} } // 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. +// Play: https://go.dev/play/p/ZrCr8sMo77T func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error { entry := l.acquire(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. // 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 { entry := l.acquire(key) defer l.release(entry, key) @@ -199,12 +204,14 @@ type TryKeyedLocker[K comparable] struct { } // NewTryKeyedLocker creates a new TryKeyedLocker. +// Play: https://go.dev/play/p/VG9qLvyetE2 func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] { return &TryKeyedLocker[K]{locks: make(map[K]*casMutex)} } // TryLock tries to acquire a lock for the specified key. // 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 { l.mu.Lock() @@ -219,6 +226,7 @@ func (l *TryKeyedLocker[K]) TryLock(key K) bool { } // Unlock releases the lock for the specified key. +// Play: https://go.dev/play/p/VG9qLvyetE2 func (l *TryKeyedLocker[K]) Unlock(key K) { l.mu.Lock() defer l.mu.Unlock() diff --git a/cryptor/crypto.go b/cryptor/crypto.go index 1fbf3f88..8e4fbf84 100644 --- a/cryptor/crypto.go +++ b/cryptor/crypto.go @@ -174,7 +174,7 @@ func AesCtrCrypt(data, key []byte) []byte { // AesCtrEncrypt encrypt data with key use AES CTR algorithm // len(key) should be 16, 24 or 32. -// Play: todo +// Play: https://go.dev/play/p/x6pjPAvThRz func AesCtrEncrypt(data, key []byte) []byte { if !isAesKeyLengthValid(len(key)) { 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 // len(key) should be 16, 24 or 32. -// Play: todo +// Play: https://go.dev/play/p/x6pjPAvThRz func AesCtrDecrypt(encrypted, key []byte) []byte { if !isAesKeyLengthValid(len(key)) { 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 // len(key) should be 8. -// Play: todo +// Play: https://go.dev/play/p/S6p_WHCgH1d func DesCtrEncrypt(data, key []byte) []byte { if len(key) != 8 { 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 // len(key) should be 8. -// Play: todo +// Play: https://go.dev/play/p/S6p_WHCgH1d func DesCtrDecrypt(encrypted, key []byte) []byte { if len(key) != 8 { panic("des: key length must be 8 bytes") diff --git a/cryptor/crypto_example_test.go b/cryptor/crypto_example_test.go index aa7fcf3c..e87e47db 100644 --- a/cryptor/crypto_example_test.go +++ b/cryptor/crypto_example_test.go @@ -74,6 +74,32 @@ func ExampleAesCtrCrypt() { // 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() { data := "hello" key := "abcdefghijklmnop" @@ -227,6 +253,19 @@ func ExampleDesCtrCrypt() { // 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() { data := "hello" key := "abcdefgh" diff --git a/cryptor/rsa_private_example.pem b/cryptor/rsa_private_example.pem index b95da9ae..408169ab 100644 --- a/cryptor/rsa_private_example.pem +++ b/cryptor/rsa_private_example.pem @@ -1,51 +1,51 @@ -----BEGIN rsa private key----- -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 -----END rsa private key----- diff --git a/cryptor/rsa_public_example.pem b/cryptor/rsa_public_example.pem index 714ab109..a0994612 100644 --- a/cryptor/rsa_public_example.pem +++ b/cryptor/rsa_public_example.pem @@ -1,14 +1,14 @@ -----BEGIN rsa public key----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw6Q11wDtWHZiyQbv+Xzn -tJbEELkPQ3oVSVCVjTx+ls5I+yR6oq8LxyoUE6SHcBlludkzs02B0rDkkfj6vl0i -PCzr3HP1XT1WwFiQJnXKtNNNiLvvewB/aynj/UIBCZZvMTYwK6nc76i4JWcajaiU -I4u84Fp7gOn0IgXMhvrwtGHk7HK1Zjr0afUJVbodc6pMZfe0QWpnDq7zaeYdkPwz -8klWAatLDZTeR5dYli2NiWOBepO1538ZvEK3S/QP2nWJzPJy2PbEHfDaFgr055w/ -wu0MzAQgkXGV8PubhYboJuQAkuXc63IPpmWVL/93WeCNRiL5fvNzUHsbPtT48A9N -nnUn4QVuVGeXIxJ1skAFsoh7i+h+mK/p5rzjPtw56nE20gYXhxf7FzbHYtHn0ego -BddUzlOY0yzvCgI5Yy1RdkNe/5vU1bpLsdU/WItjR2h6EfqLosQ4iKowPBYQXJOI -NbpkvIhkhCVbPpMvmhfi/lATiKdoXgtvuB04wth011c5W/yXA+A3Ob73Sr2+zyxF -870tOp3rNTWsYLvCOjf+JdjgM3AzNuFxE4NdMLvXDf7CIXSb3X9rj3qM769Lz6XX -bRBVbO0HxGyqLTPPmSWV61jQuUTWNGnxkovoYLrpgyumIjjIcl0aY1hogmQeA6ZN -gJxaUw9r/p8vnThL5UXKlbcCAwEAAQ== +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw0anfgtraA2uaZwoLpLB +vo1EkfYvDBgeXoMQ4WMKbcw6jU8k18E+f3WM52I2RssEk6g0X1vIiarHZU5qyxbv +2iNoT7EfgizzlXYvx06pM69GNBQrV46+lNhiOv4eeLZcOHBnxAyizlIKyLuwO+C1 +cX/6BxuXjX3ogw+6IaBFZN/EOMmTWc6sPKrnNCEqgCNiTbPAXb+N8j5Iv8QPs0Aw +VTB3jC9LP0mRt2GGD0cu+QIZkoGEhyW9Dd+0tgeIK32uXCF8uDjNpUV1TxCdn5H+ +lvgddxfiaIJAdY5UaTx48XRIdULhQrVKXJNyTYWTXbezViYIf1nXOdDI2hsGgKTf +NVCocDT1LcT5zebijFHVCWfAAKEPRLdzPZomkFIa3rQQgChgePzE8Oqsaxuwx8sU +09NAo3giSq1OmBBwly7h60Lwtm8+XuwmWtEgZoSQy2Hm8UMAJ3guotfYuS8mPQBi +55JZpdqVN0D5SdwuWXhHpO4xDodNYAoMMei1NNgrX2zN3FCS8PVi97wD6cQ8xsWM +62nByrzIjmPwTfoCb3qP/928FMJMg7b3bYBrUnOrpVWZfAIDs4H7DoP8VLL4rMgB +5PuWNQ13gtX7y5ZOyLhopiKLnar9XiN8GAMANBdKRI2anGEozrfJoelJ5POXZwSa +tRjbL+nWO3YnBzEunCw1xmMCAwEAAQ== -----END rsa public key----- diff --git a/docs/api/packages/concurrency.md b/docs/api/packages/concurrency.md index 7706d114..a6946426 100644 --- a/docs/api/packages/concurrency.md +++ b/docs/api/packages/concurrency.md @@ -477,7 +477,7 @@ func main() { func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/GzeyC33T5rw) ```go package main @@ -534,7 +534,7 @@ func main() { func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/GzeyC33T5rw) ```go package main @@ -591,7 +591,7 @@ func main() { func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/CkaJWWwZm9) ```go package main @@ -640,7 +640,7 @@ func main() { func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/ZrCr8sMo77T) ```go package main @@ -689,7 +689,7 @@ func main() { func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/WgAcXbOPKGk) ```go package main @@ -738,7 +738,7 @@ func main() { func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/VG9qLvyetE2) ```go package main @@ -779,7 +779,7 @@ func main() { func (l *TryKeyedLocker[K]) TryLock(key K) bool ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/VG9qLvyetE2) ```go package main @@ -820,7 +820,7 @@ func main() { func (l *TryKeyedLocker[K]) Unlock(key K) ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/VG9qLvyetE2) ```go package main diff --git a/docs/api/packages/cryptor.md b/docs/api/packages/cryptor.md index fa812629..f2d1c397 100644 --- a/docs/api/packages/cryptor.md +++ b/docs/api/packages/cryptor.md @@ -27,7 +27,9 @@ import ( - [AesEcbDecrypt](#AesEcbDecrypt) - [AesCbcEncrypt](#AesCbcEncrypt) - [AesCbcDecrypt](#AesCbcDecrypt) -- [AesCtrCrypt](#AesCtrCrypt) +- [AesCtrCryptdeprecated](#AesCtrCrypt) +- [AesCtrEncrypt](#AesCtrEncrypt) +- [AesCtrDecrypt](#AesCtrDecrypt) - [AesCfbEncrypt](#AesCfbEncrypt) - [AesCfbDecrypt](#AesCfbDecrypt) - [AesOfbEncrypt](#AesOfbEncrypt) @@ -40,7 +42,7 @@ import ( - [DesEcbDecrypt](#DesEcbDecrypt) - [DesCbcEncrypt](#DesCbcEncrypt) - [DesCbcDecrypt](#DesCbcDecrypt) -- [DesCtrCrypt](#DesCtrCrypt) +- [DesCtrCryptdeprecated](#DesCtrCrypt) - [DesCfbEncrypt](#DesCfbEncrypt) - [DesCfbDecrypt](#DesCfbDecrypt) - [DesOfbEncrypt](#DesOfbEncrypt) @@ -73,7 +75,6 @@ import ( - [RsaSign](#RsaSign) - [RsaVerifySign](#RsaVerifySign) -
## 文档 @@ -248,6 +249,74 @@ func main() { } ``` +### AesCtrEncrypt + +

使用AES CTR算法模式加密数据,参数`key`的长度是16, 24 or 32。

+ +函数签名: + +```go +func AesCtrEncrypt(data, key []byte) []byte +``` + +示例:[运行](https://go.dev/play/p/x6pjPAvThRz) + +```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 +} +``` + +### AesCtrDecrypt + +

使用AES CTR算法模式解密数据,参数`key`的长度是16, 24 or 32。

+ +函数签名: + +```go +func AesCtrDecrypt(encrypted, key []byte) []byte +``` + +示例:[运行](https://go.dev/play/p/x6pjPAvThRz) + +```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 +} +``` + ### AesCfbEncrypt

使用AES CFB算法模式加密数据,参数`key`的长度是16, 24 or 32。

@@ -648,6 +717,74 @@ func main() { } ``` +### DesCtrCrypt + +

使用DES CTR算法模式加密数据,参数`key`的长度是8

+ +函数签名: + +```go +func DesCtrEncrypt(data, key []byte) []byte +``` + +示例:[运行](https://go.dev/play/p/S6p_WHCgH1d) + +```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 +} +``` + +### DesCtrDecrypt + +

使用DES CTR算法模式加密数据,参数`key`的长度是8

+ +函数签名: + +```go +func DesCtrDecrypt(encrypted, key []byte) []byte +``` + +示例:[运行](https://go.dev/play/p/S6p_WHCgH1d) + +```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 +} +``` + ### DesCtrCrypt

使用DES CTR算法模式加密/解密数据,参数`key`的长度是8

diff --git a/docs/api/packages/fileutil.md b/docs/api/packages/fileutil.md index ed7fcfb5..8cee0bec 100644 --- a/docs/api/packages/fileutil.md +++ b/docs/api/packages/fileutil.md @@ -427,7 +427,7 @@ func main() { func RemoveDir(path string, onDelete ...func(path string)) error ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/Oa6KnPek2uy) ```go package main @@ -970,7 +970,7 @@ func main() { 函数签名: ```go -func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) +func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) ``` 示例:[运行](https://go.dev/play/p/uNep3Tr8fqF) @@ -994,9 +994,9 @@ func main() { if err != nil { return } - + fmt.Println(string(dat)) - + // Output: // User-agent: * // Disallow: /deny @@ -1025,7 +1025,7 @@ import ( func main() { const mb = 1024 * 1024 - const defaultChunkSizeMB = 100 + const defaultChunkSizeMB = 100 // test1.csv file content: // Lili,22,female @@ -1089,7 +1089,7 @@ func main() { numParsers := runtime.NumCPU() linesCh := make(chan []string, numParsers) - + // test1.csv file content: // Lili,22,female // Jim,21,male @@ -1114,6 +1114,7 @@ func main() { // 2 } ``` + ### GetExeOrDllVersion

返回exe,dll文件版本号(仅Window平台).

@@ -1143,4 +1144,4 @@ func main() { // Output: // 3.9.10.19 } -``` \ No newline at end of file +``` diff --git a/docs/api/packages/maputil.md b/docs/api/packages/maputil.md index 2f32e1d0..daa8b1a5 100644 --- a/docs/api/packages/maputil.md +++ b/docs/api/packages/maputil.md @@ -1095,7 +1095,7 @@ func main() { 函数签名: ```go -func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) +func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) ``` 示例:[运行](https://go.dev/play/p/0nlPo6YLdt3) @@ -1259,7 +1259,6 @@ func main() { } ``` - ### OrderedMap_Delete

删除给定键的键值对。

@@ -2192,7 +2191,6 @@ func main() { } ``` - ### GetOrSet

返回给定键的值,如果不存在则设置该值。

@@ -2276,7 +2274,7 @@ func main() { 函数签名: ```go -func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V +func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V ``` 示例:[运行](https://go.dev/play/p/99QjSYSBdiM) @@ -2319,7 +2317,7 @@ func main() { func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/bvNwNBZDm6v) ```go package main @@ -2346,4 +2344,4 @@ func main() { // Output: // [b d] } -``` \ No newline at end of file +``` diff --git a/docs/api/packages/netutil.md b/docs/api/packages/netutil.md index 0818d90d..7be8c18b 100644 --- a/docs/api/packages/netutil.md +++ b/docs/api/packages/netutil.md @@ -1044,7 +1044,7 @@ func main() { func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/JLXl1hZK7l4) ```go package main @@ -1084,7 +1084,7 @@ func main() { func AddQueryParams(urlStr string, params map[string][]string) (string, error) ``` -示例:[运行](todo) +示例:[运行](https://go.dev/play/p/JLXl1hZK7l4) ```go package main diff --git a/docs/api/packages/validator.md b/docs/api/packages/validator.md index 46b6a7c6..b354ce05 100644 --- a/docs/api/packages/validator.md +++ b/docs/api/packages/validator.md @@ -834,7 +834,7 @@ func main() { func IsAlphaNumeric(s string) bool ``` -示例:[运行](https://go.dev/play/p/todo) +示例:[运行](https://go.dev/play/p/RHeESLrLg9c) ```go import ( diff --git a/docs/en/api/packages/concurrency.md b/docs/en/api/packages/concurrency.md index 0ba938aa..fce2598f 100644 --- a/docs/en/api/packages/concurrency.md +++ b/docs/en/api/packages/concurrency.md @@ -479,7 +479,7 @@ func main() { func NewKeyedLocker[K comparable](ttl time.Duration) *KeyedLocker[K] ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/GzeyC33T5rw) ```go package main @@ -536,7 +536,7 @@ func main() { func (l *KeyedLocker[K]) Do(ctx context.Context, key K, fn func()) error ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/GzeyC33T5rw) ```go package main @@ -593,7 +593,7 @@ func main() { func NewRWKeyedLocker[K comparable](ttl time.Duration) *RWKeyedLocker[K] ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/ZrCr8sMo77T) ```go package main @@ -642,7 +642,7 @@ func main() { func (l *RWKeyedLocker[K]) RLock(ctx context.Context, key K, fn func()) error ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/ZrCr8sMo77T) ```go package main @@ -691,7 +691,7 @@ func main() { func (l *RWKeyedLocker[K]) Lock(ctx context.Context, key K, fn func()) error ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/WgAcXbOPKGk) ```go package main @@ -740,7 +740,7 @@ func main() { func NewTryKeyedLocker[K comparable]() *TryKeyedLocker[K] ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/VG9qLvyetE2) ```go package main @@ -781,7 +781,7 @@ func main() { func (l *TryKeyedLocker[K]) TryLock(key K) bool ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/VG9qLvyetE2) ```go package main @@ -822,7 +822,7 @@ func main() { func (l *TryKeyedLocker[K]) Unlock(key K) ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/VG9qLvyetE2) ```go package main diff --git a/docs/en/api/packages/cryptor.md b/docs/en/api/packages/cryptor.md index 9f1de9df..cb05faf1 100644 --- a/docs/en/api/packages/cryptor.md +++ b/docs/en/api/packages/cryptor.md @@ -27,7 +27,9 @@ import ( - [AesEcbDecrypt](#AesEcbDecrypt) - [AesCbcEncrypt](#AesCbcEncrypt) - [AesCbcDecrypt](#AesCbcDecrypt) -- [AesCtrCrypt](#AesCtrCrypt) +- [AesCtrCryptdeprecated](#AesCtrCrypt) +- [AesCtrEncrypt](#AesCtrEncrypt) +- [AesCtrDecrypt](#AesCtrDecrypt) - [AesCfbEncrypt](#AesCfbEncrypt) - [AesCfbDecrypt](#AesCfbDecrypt) - [AesOfbEncrypt](#AesOfbEncrypt) @@ -40,7 +42,9 @@ import ( - [DesEcbDecrypt](#DesEcbDecrypt) - [DesCbcEncrypt](#DesCbcEncrypt) - [DesCbcDecrypt](#DesCbcDecrypt) -- [DesCtrCrypt](#DesCtrCrypt) +- [DesCtrCryptdeprecated](#DesCtrCrypt) +- [DesCfbEncrypt](#DesCfbEncrypt) +- [DesCfbDecrypt](#DesCfbDecrypt) - [DesCfbEncrypt](#DesCfbEncrypt) - [DesCfbDecrypt](#DesCfbDecrypt) - [DesOfbEncrypt](#DesOfbEncrypt) @@ -217,6 +221,8 @@ func main() {

Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.

+> ⚠️ This function is deprecated. use `AesCtrEncrypt` and `AesCtrDecrypt` instead. + Signature: ```go @@ -247,6 +253,74 @@ func main() { } ``` +### AesCtrEncrypt + +

Encrypt data with key use AES CTR algorithm

+ +Signature: + +```go +func AesCtrEncrypt(data, key []byte) []byte +``` + +Example:[Run](https://go.dev/play/p/x6pjPAvThRz) + +```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 +} +``` + +### AesCtrDecrypt + +

Decrypt data with key use AES CTR algorithm

+ +Signature: + +```go +func AesCtrDecrypt(encrypted, key []byte) []byte +``` + +Example:[Run](https://go.dev/play/p/x6pjPAvThRz) + +```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 +} +``` + ### AesCfbEncrypt

Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.

@@ -651,6 +725,8 @@ func main() {

Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.

+> ⚠️ This function is deprecated. use `DesCtrEncrypt` and `DesCtrDecrypt` instead. + Signature: ```go @@ -681,6 +757,74 @@ func main() { } ``` +### DesCtrCrypt + +

Encrypt data with key use DES CTR algorithm. Length of `key` param should be 8.

+ +Signature: + +```go +func DesCtrEncrypt(data, key []byte) []byte +``` + +Example:[Run](https://go.dev/play/p/S6p_WHCgH1d) + +```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 +} +``` + +### DesCtrDecrypt + +

Decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.

+ +Signature: + +```go +func DesCtrDecrypt(encrypted, key []byte) []byte +``` + +Example:[Run](https://go.dev/play/p/S6p_WHCgH1d) + +```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 +} +``` + ### DesCfbEncrypt

Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.

diff --git a/docs/en/api/packages/fileutil.md b/docs/en/api/packages/fileutil.md index f1879289..a236846a 100644 --- a/docs/en/api/packages/fileutil.md +++ b/docs/en/api/packages/fileutil.md @@ -427,7 +427,7 @@ func main() { func RemoveDir(path string, onDelete ...func(path string)) error ``` -Example:[Run](todo) +Example:[Run](https://go.dev/play/p/Oa6KnPek2uy) ```go package main @@ -970,7 +970,7 @@ func main() { Signature: ```go -func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) +func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) ``` Example:[Run](https://go.dev/play/p/uNep3Tr8fqF) @@ -1023,7 +1023,7 @@ import ( func main() { const mb = 1024 * 1024 - const defaultChunkSizeMB = 100 + const defaultChunkSizeMB = 100 // test1.csv file content: // Lili,22,female @@ -1087,7 +1087,7 @@ func main() { numParsers := runtime.NumCPU() linesCh := make(chan []string, numParsers) - + // test1.csv file content: // Lili,22,female // Jim,21,male @@ -1140,8 +1140,8 @@ func main() { } fmt.Println(v) - + // Output: // 3.9.10.19 } -``` \ No newline at end of file +``` diff --git a/docs/en/api/packages/maputil.md b/docs/en/api/packages/maputil.md index 31d69838..9288c49d 100644 --- a/docs/en/api/packages/maputil.md +++ b/docs/en/api/packages/maputil.md @@ -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/orderedmap.go](https://github.com/duke-git/lancet/blob/main/maputil/orderedmap.go) -
## Example: @@ -1111,7 +1110,7 @@ Translate the key and value of the map into two slices that are sorted according Signature: ```go -func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) +func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) ``` Example:[Run](https://go.dev/play/p/0nlPo6YLdt3) @@ -1275,7 +1274,6 @@ func main() { } ``` - ### OrderedMap_Delete

Deletes the key-value pair for the given key.

@@ -1838,7 +1836,7 @@ func main() { fmt.Println(om.Elements()) // Output: - // [{a 1} {b 2} {c 3}] + // [{a 1} {b 2} {c 3}] } ``` @@ -2294,7 +2292,7 @@ func main() { Signature: ```go -func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V +func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V ``` Example:[Run](https://go.dev/play/p/99QjSYSBdiM) @@ -2337,7 +2335,7 @@ func main() { func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) []V ``` -Example:[Run](todo) +Example:[Run](https://go.dev/play/p/bvNwNBZDm6v) ```go package main @@ -2364,4 +2362,4 @@ func main() { // Output: // [b d] } -``` \ No newline at end of file +``` diff --git a/docs/en/api/packages/netutil.md b/docs/en/api/packages/netutil.md index f653dd5e..6b4cf236 100644 --- a/docs/en/api/packages/netutil.md +++ b/docs/en/api/packages/netutil.md @@ -51,7 +51,6 @@ import ( - [BuildUrl](#BuildUrl) - [AddQueryParams](#AddQueryParams) -
@@ -1045,7 +1044,7 @@ func main() { func BuildUrl(scheme, host, path string, query map[string][]string) (string, error) ``` -Example:[Run](todo) +Example:[Run](https://go.dev/play/p/JLXl1hZK7l4) ```go package main @@ -1085,7 +1084,7 @@ func main() { func AddQueryParams(urlStr string, params map[string][]string) (string, error) ``` -Example:[Run](todo) +Example:[Run](https://go.dev/play/p/JLXl1hZK7l4) ```go package main @@ -1113,4 +1112,4 @@ func main() { // https://example.com/query?a=foo&a=bar&b=baz // } -``` \ No newline at end of file +``` diff --git a/docs/en/api/packages/validator.md b/docs/en/api/packages/validator.md index 093893bd..2ab510dc 100644 --- a/docs/en/api/packages/validator.md +++ b/docs/en/api/packages/validator.md @@ -836,7 +836,7 @@ func main() { func IsAlphaNumeric(s string) bool ``` -Example:[Run](https://go.dev/play/p/todo) +Example:[Run](https://go.dev/play/p/RHeESLrLg9c) ```go import ( diff --git a/fileutil/file.go b/fileutil/file.go index 36cd1a20..a050fa72 100644 --- a/fileutil/file.go +++ b/fileutil/file.go @@ -190,7 +190,7 @@ func RemoveFile(path string, onDelete ...func(path string)) error { } // RemoveDir remove the path directory. -// Play: todo +// Play: https://go.dev/play/p/Oa6KnPek2uy func RemoveDir(path string, onDelete ...func(path string)) error { info, err := os.Stat(path) if err != nil { diff --git a/maputil/map.go b/maputil/map.go index 05629aa1..a033cf0d 100644 --- a/maputil/map.go +++ b/maputil/map.go @@ -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. -// 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 { result := make([]V, 0) diff --git a/netutil/net.go b/netutil/net.go index 33847df6..23af993c 100644 --- a/netutil/net.go +++ b/netutil/net.go @@ -309,7 +309,7 @@ func IsTelnetConnected(host string, port string) bool { } // 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) { if err := validateScheme(scheme); err != nil { return "", err @@ -371,7 +371,7 @@ var pathRegex = regexp.MustCompile(`^\/([a-zA-Z0-9%_-]+(?:\/[a-zA-Z0-9%_-]+)*)$` var alphaNumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]+$`) // 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) { parsedUrl, err := url.Parse(urlStr) if err != nil { diff --git a/validator/validator.go b/validator/validator.go index bbc25669..1362eb81 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -183,7 +183,7 @@ func IsJSON(str string) bool { } // IsAlphaNumeric check if the string is alphanumeric. -// Play: todo +// Play: https://go.dev/play/p/RHeESLrLg9c func IsAlphaNumeric(s string) bool { return alphaNumericMatcher.MatchString(s) } From d818219672ac3bf900d4f74dac8ef2e62f245898 Mon Sep 17 00:00:00 2001 From: dudaodong Date: Thu, 29 May 2025 14:01:12 +0800 Subject: [PATCH 02/11] doc: update cryptordoc --- docs/api/packages/cryptor.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/packages/cryptor.md b/docs/api/packages/cryptor.md index f2d1c397..9d2f126f 100644 --- a/docs/api/packages/cryptor.md +++ b/docs/api/packages/cryptor.md @@ -219,6 +219,8 @@ func main() {

使用AES CTR算法模式加密/解密数据,参数`key`的长度是16, 24 or 32。

+> ⚠️ 本函数已弃用,使用`AesCtrEncrypt`和`AesCtrDecrypt`代替。 + 函数签名: ```go @@ -789,6 +791,8 @@ func main() {

使用DES CTR算法模式加密/解密数据,参数`key`的长度是8

+> ⚠️ 本函数已弃用,使用`DesCtrEncrypt`和`DesCtrDecrypt`代替。 + 函数签名: ```go From c175b202de8c29ffa811d2db90ba1be99651fbfa Mon Sep 17 00:00:00 2001 From: dudaodong Date: Thu, 29 May 2025 14:04:09 +0800 Subject: [PATCH 03/11] doc: update cryptordoc --- docs/api/packages/cryptor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/packages/cryptor.md b/docs/api/packages/cryptor.md index 9d2f126f..2264c2ca 100644 --- a/docs/api/packages/cryptor.md +++ b/docs/api/packages/cryptor.md @@ -719,7 +719,7 @@ func main() { } ``` -### DesCtrCrypt +### DesCtrEncrypt

使用DES CTR算法模式加密数据,参数`key`的长度是8

From 1a5c31fd02755e3c4f5aff3251c6b21b32344b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AE=8B=E5=BF=B5?= Date: Tue, 3 Jun 2025 09:57:29 +0800 Subject: [PATCH 04/11] perf(retry): remove the waiting time after the last retry (#309) --- retry/retry.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/retry/retry.go b/retry/retry.go index 820f71ee..a30e6a11 100644 --- a/retry/retry.go +++ b/retry/retry.go @@ -130,14 +130,16 @@ func Retry(retryFunc RetryFunc, opts ...Option) error { var i uint for i < config.retryTimes { err := retryFunc() - if err != nil { + if err == nil { + return nil + } + + if i < config.retryTimes-1 { // Only wait if it's not the last retry select { case <-time.After(config.backoffStrategy.CalculateInterval()): case <-config.context.Done(): return errors.New("retry is cancelled") } - } else { - return nil } i++ } From 9caf2ffb1c02f1516c27e87936d40d68ce1fa4b3 Mon Sep 17 00:00:00 2001 From: Axiss <32772120+FanLu1994@users.noreply.github.com> Date: Tue, 3 Jun 2025 10:10:51 +0800 Subject: [PATCH 05/11] fix one typo in doc (#310) --- docs/api/packages/algorithm.md | 2 +- docs/en/api/packages/algorithm.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/packages/algorithm.md b/docs/api/packages/algorithm.md index 865ecba8..c48a7367 100644 --- a/docs/api/packages/algorithm.md +++ b/docs/api/packages/algorithm.md @@ -8,7 +8,7 @@ algorithm 算法包实现一些基本算法,sort,search,lrucache。 - [https://github.com/duke-git/lancet/blob/main/algorithm/sort.go](https://github.com/duke-git/lancet/blob/main/algorithm/sort.go) - [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go) -- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go) +- [https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lrucache.go)
diff --git a/docs/en/api/packages/algorithm.md b/docs/en/api/packages/algorithm.md index c2d3045b..a3260817 100644 --- a/docs/en/api/packages/algorithm.md +++ b/docs/en/api/packages/algorithm.md @@ -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/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)
From a3a24fc381119629d551bfacbbab5fb86cc7203a Mon Sep 17 00:00:00 2001 From: dudaodong Date: Fri, 6 Jun 2025 14:33:54 +0800 Subject: [PATCH 06/11] doc: update doc styles --- docs/api/overview.md | 9 ++++----- docs/en/api/overview.md | 5 ++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/api/overview.md b/docs/api/overview.md index 38a19c59..b004174d 100644 --- a/docs/api/overview.md +++ b/docs/api/overview.md @@ -2,10 +2,9 @@ outline: deep --- -# API概述 - -lancet(柳叶刀)是一个功能强大、全面、高效、可复用的go语言工具函数库。包含25个包,超过600个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。 +# API 概述 +lancet(柳叶刀)是一个功能强大、全面、高效、可复用的 go 语言工具函数库。包含 25 个包,超过 600 个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。