mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 21:02:27 +08:00
Compare commits
237 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d6ab72059 | ||
|
|
30eb2c72b0 | ||
|
|
adf18a2e47 | ||
|
|
f99a8ef3cf | ||
|
|
fcdf1d5839 | ||
|
|
ee0afed963 | ||
|
|
1d94896c9b | ||
|
|
69cf9bbcf0 | ||
|
|
2bbcb85286 | ||
|
|
e58c9b797b | ||
|
|
3e1ac5e0b5 | ||
|
|
8869e0440d | ||
|
|
69f9c74bcb | ||
|
|
84ebc7ce71 | ||
|
|
c745097749 | ||
|
|
ba75e58e5f | ||
|
|
7e85a0ed7d | ||
|
|
2268a0312f | ||
|
|
da84d95aa3 | ||
|
|
48244d6711 | ||
|
|
5e3337a52e | ||
|
|
c3372e18b1 | ||
|
|
90e5a0bfb2 | ||
|
|
93be25920f | ||
|
|
f9e5ec9096 | ||
|
|
601df5dc12 | ||
|
|
63216d9b1c | ||
|
|
c32a19868d | ||
|
|
71e914019b | ||
|
|
9824db0056 | ||
|
|
ba9188a29a | ||
|
|
8625fbd8d3 | ||
|
|
81b29baf30 | ||
|
|
5a38e34063 | ||
|
|
159168dd7b | ||
|
|
ec092a009a | ||
|
|
ca40b5d6c6 | ||
|
|
a6d39a3bba | ||
|
|
38148978cf | ||
|
|
3e8c3bd396 | ||
|
|
30971c1aab | ||
|
|
bc260277bc | ||
|
|
c0b200f846 | ||
|
|
305847993c | ||
|
|
f5d70728c3 | ||
|
|
c2a5335bc6 | ||
|
|
7b4e060f85 | ||
|
|
a360372aa9 | ||
|
|
7f78a6b11e | ||
|
|
5c53cb5867 | ||
|
|
f7e9d5dc47 | ||
|
|
5c580ed013 | ||
|
|
0f9764f41e | ||
|
|
0bc5f82554 | ||
|
|
e91965b013 | ||
|
|
483a286d8e | ||
|
|
3f8e306ced | ||
|
|
0b29f0520d | ||
|
|
8611ec0c10 | ||
|
|
286e10d189 | ||
|
|
3e7f94b03e | ||
|
|
356351896d | ||
|
|
9be124211e | ||
|
|
f467658481 | ||
|
|
5c9d0e396e | ||
|
|
8f74460c1b | ||
|
|
d5752499bf | ||
|
|
eb7cf76eae | ||
|
|
4af074d181 | ||
|
|
73fb8fefd2 | ||
|
|
9cf535055d | ||
|
|
8be7b3e396 | ||
|
|
dac706d700 | ||
|
|
2097277a7d | ||
|
|
95b516e278 | ||
|
|
ca373b00a7 | ||
|
|
a220220f09 | ||
|
|
aeef0418a4 | ||
|
|
9b7d8d7abf | ||
|
|
4d21e81263 | ||
|
|
ce2397422e | ||
|
|
4b3a62b36a | ||
|
|
e054680d20 | ||
|
|
5381842eec | ||
|
|
6e0498514c | ||
|
|
967e6a3493 | ||
|
|
5b24801e49 | ||
|
|
974ba525a6 | ||
|
|
f0235c40b6 | ||
|
|
712a215ea6 | ||
|
|
7893f828d3 | ||
|
|
53fa210f09 | ||
|
|
de9ee08be4 | ||
|
|
5381450bea | ||
|
|
6853d627f4 | ||
|
|
e461acdb72 | ||
|
|
2a796adf85 | ||
|
|
5e6e8d82a8 | ||
|
|
e9280b8c25 | ||
|
|
bb6f10a1fb | ||
|
|
33b4cffe60 | ||
|
|
2b765b49e0 | ||
|
|
004dbdc32e | ||
|
|
ab50e8120a | ||
|
|
73c97af7d8 | ||
|
|
5e8a065eaa | ||
|
|
aa74400607 | ||
|
|
a6eaaef563 | ||
|
|
1b31014f81 | ||
|
|
036847577d | ||
|
|
d21edd1cde | ||
|
|
c58c50327c | ||
|
|
9bfdc686f8 | ||
|
|
5ca8f6ef6f | ||
|
|
a54d4c79a0 | ||
|
|
f7b54986aa | ||
|
|
92fae4273b | ||
|
|
0d29f5437a | ||
|
|
e95d7c82cd | ||
|
|
e138043289 | ||
|
|
aabfcb7bde | ||
|
|
0b5e884371 | ||
|
|
3d1bd08434 | ||
|
|
a62ad71791 | ||
|
|
c02c4f813b | ||
|
|
235d2f2486 | ||
|
|
e9380a3d9f | ||
|
|
81d13c2f1a | ||
|
|
7290296849 | ||
|
|
8a8460a592 | ||
|
|
7a98c431d3 | ||
|
|
606d887230 | ||
|
|
473f9c9f3e | ||
|
|
9ff3d0e79c | ||
|
|
5db1d07d6d | ||
|
|
6c6d14828a | ||
|
|
0e1593c67b | ||
|
|
6c7f38d8b3 | ||
|
|
069812e0ee | ||
|
|
4a539a23c8 | ||
|
|
0b1dab0399 | ||
|
|
805e2543d0 | ||
|
|
a3d518da76 | ||
|
|
e3e2d8394c | ||
|
|
0eeaa06055 | ||
|
|
a43bc554ee | ||
|
|
aebab7c944 | ||
|
|
665bad4ca3 | ||
|
|
e4901e99e9 | ||
|
|
4277e8eca5 | ||
|
|
fdc93c8cc7 | ||
|
|
860a499f98 | ||
|
|
2e1c2276a5 | ||
|
|
d367397dab | ||
|
|
66fd8cf651 | ||
|
|
a6be1828b9 | ||
|
|
8f5d297572 | ||
|
|
a1a4fdc598 | ||
|
|
1610076d22 | ||
|
|
cacbf97223 | ||
|
|
cd156dba5f | ||
|
|
3a71a8697d | ||
|
|
c88fd3db86 | ||
|
|
27d19d1717 | ||
|
|
da24bae6b4 | ||
|
|
3cd9d6b68c | ||
|
|
874d09f331 | ||
|
|
fdf251ac98 | ||
|
|
7ec2533b7a | ||
|
|
9fd0603f4a | ||
|
|
9f7b416a8d | ||
|
|
bf4b2b5fd6 | ||
|
|
22af59565e | ||
|
|
f9e047f190 | ||
|
|
fa298b740d | ||
|
|
6d4fc981b6 | ||
|
|
4c21fe700c | ||
|
|
b7370e8ef8 | ||
|
|
38920e3be6 | ||
|
|
a630a7cda9 | ||
|
|
66dfd9c4fd | ||
|
|
be62aaac9b | ||
|
|
e0c9ccbce3 | ||
|
|
d2d1e5a055 | ||
|
|
bbc58c7e46 | ||
|
|
ac2ecceaec | ||
|
|
a06bb8ee6a | ||
|
|
27b5702fd3 | ||
|
|
b2c3fa0ab8 | ||
|
|
4afc838937 | ||
|
|
3482f80d1c | ||
|
|
565f2893b9 | ||
|
|
1b1b10d0ee | ||
|
|
c5c3888ffc | ||
|
|
11214986cc | ||
|
|
0bc7b83e59 | ||
|
|
6225418074 | ||
|
|
ddd265de78 | ||
|
|
80e48f06ca | ||
|
|
0b976e9a4c | ||
|
|
96320069f4 | ||
|
|
c5297ec329 | ||
|
|
aa4b61ff85 | ||
|
|
7dbd7002a3 | ||
|
|
a995db445a | ||
|
|
6e5b67bee7 | ||
|
|
52b8ea8166 | ||
|
|
6fe8a9efe7 | ||
|
|
dcef06e9da | ||
|
|
8f410bf9cb | ||
|
|
9cd6eb4ddf | ||
|
|
bf581162ee | ||
|
|
bd984fa378 | ||
|
|
d7f23e2dee | ||
|
|
3802c715c3 | ||
|
|
4b12173f24 | ||
|
|
31c618c187 | ||
|
|
6497b321b0 | ||
|
|
bda78201f5 | ||
|
|
0753ea2801 | ||
|
|
e25b53712b | ||
|
|
56c9327a86 | ||
|
|
11eb559998 | ||
|
|
61a612a06a | ||
|
|
2351ab4714 | ||
|
|
88eec858b4 | ||
|
|
14c37b5a5f | ||
|
|
ad8b1d424c | ||
|
|
a9f01d8a69 | ||
|
|
781b89d51a | ||
|
|
073c77e751 | ||
|
|
91a0d3077d | ||
|
|
17b34f8f19 | ||
|
|
8ff37f0eff | ||
|
|
f445ecbaf8 | ||
|
|
b698fec50f | ||
|
|
b38bb66b34 |
8
.github/workflows/codecov.yml
vendored
8
.github/workflows/codecov.yml
vendored
@@ -3,11 +3,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# - v2
|
||||
- rc
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# - v2
|
||||
- rc
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -17,8 +17,10 @@ jobs:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: "1.18"
|
||||
go-version: "1.20"
|
||||
- name: Run coverage
|
||||
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
- name: Run govet
|
||||
run: go vet -v ./...
|
||||
- name: Upload coverage to Codecov
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Lancet Contributing Guide
|
||||
# Lancet Contribution Guide
|
||||
|
||||
Hi! Thank you for choosing Lancet.
|
||||
|
||||
@@ -30,7 +30,7 @@ We are excited that you are interested in contributing to lancet. Before submitt
|
||||
|
||||
- Before submitting a PR, please execute the unit test command: `go test -v ./...` to ensure that all unit test tasks should pass.
|
||||
|
||||
- Make sure PRs are created to `v2` branch instead of `master` branch.
|
||||
- Make sure PRs are created to `rc` branch instead of other branch.
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
@@ -30,7 +30,7 @@ Lancet 的成长离不开大家的支持,如果你愿意为 Lancet 贡献代
|
||||
|
||||
- 提交 PR 前请执行单元测试命令:go test -v ./...,确保所有单元测试任务通过。
|
||||
|
||||
- 确保 PR 是提交到 `v2` 分支,而不是 `main` 分支。
|
||||
- 确保 PR 是提交到 `rc` 分支,而不是其他分支。
|
||||
|
||||
- 如果是修复 bug,请在 PR 中给出描述信息。
|
||||
|
||||
456
README.md
456
README.md
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
## <a href="https://www.golancet.cn/en/" target="_blank"> Website</a> | [简体中文](./README_zh-CN.md)
|
||||
|
||||
## Feature
|
||||
## Features
|
||||
|
||||
- 👏 Comprehensive, efficient and reusable.
|
||||
- 💪 600+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💪 700+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💅 Only depends on two kinds of libraries: go standard library and golang.org/x.
|
||||
- 🌍 Unit test for every exported function.
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
|
||||
### Note:
|
||||
|
||||
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause in v2.x.x all functions was rewriten with generics of go1.18.</b>
|
||||
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause in v2.x.x all functions were rewritten with generics of go1.18.</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||
```
|
||||
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.1. </b>
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.4. </b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||
@@ -201,10 +201,10 @@ import "github.com/duke-git/lancet/v2/concurrency"
|
||||
- **<big>OrDone</big>** : read a channel into another channel, will close until cancel context.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#OrDone)]
|
||||
[[play](https://go.dev/play/p/lm_GoS6aDjo)]
|
||||
- **<big>Repeat</big>** : create channel, put values into the channel repeatly until cancel the context.
|
||||
- **<big>Repeat</big>** : create channel, put values into the channel repeatedly until cancel the context.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#Repeat)]
|
||||
[[play](https://go.dev/play/p/k5N_ALVmYjE)]
|
||||
- **<big>RepeatFn</big>** : create a channel, excutes fn repeatly, and put the result into the channel, until close context.
|
||||
- **<big>RepeatFn</big>** : create a channel, executes fn repeatedly, and put the result into the channel, until close context.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/concurrency.md#RepeatFn)]
|
||||
[[play](https://go.dev/play/p/4J1zAWttP85)]
|
||||
- **<big>Take</big>** : create a channel whose values are taken from another channel with limit number.
|
||||
@@ -247,7 +247,7 @@ import "github.com/duke-git/lancet/v2/condition"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/condition.md#TernaryOperator)]
|
||||
[[play](https://go.dev/play/p/ElllPZY0guT)]
|
||||
|
||||
<h3 id="convertor"> 5. Convertor package contains some functions for data convertion. <a href="#index">index</a> </h3>
|
||||
<h3 id="convertor"> 5. Convertor package contains some functions for data conversion. <a href="#index">index</a> </h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/convertor"
|
||||
@@ -318,6 +318,14 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
- **<big>GbkToUtf8</big>** : converts GBK encoding data to utf8 encoding data.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#GbkToUtf8)]
|
||||
[[play](https://go.dev/play/p/OphmHCN_9u8)]
|
||||
- **<big>ToStdBase64</big>** : converts a value to a string encoded in standard Base64.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToStdBase64)]
|
||||
- **<big>ToUrlBase64</big>** : converts a value to a string encoded in url Base64.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToUrlBase64)]
|
||||
- **<big>ToRawStdBase64</big>** : converts a value to a string encoded in raw standard Base64.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToRawStdBase64)]
|
||||
- **<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)]
|
||||
|
||||
<h3 id="cryptor"> 6. Cryptor package is for data encryption and decryption. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -354,6 +362,12 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<big>AesOfbDecrypt</big>** : decrypt byte slice data with key use AES OFB algorithm.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#AesOfbDecrypt)]
|
||||
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
||||
- **<big>AesGcmEncrypt</big>** : encrypt byte slice data with key use AES GCM algorithm.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#AesGcmEncrypt)]
|
||||
[[play](todo)]
|
||||
- **<big>AesGcmDecrypt</big>** : decrypt byte slice data with key use AES GCM algorithm.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#AesGcmDecrypt)]
|
||||
[[play](todo)]
|
||||
- **<big>Base64StdEncode</big>** : encode string with base64 encoding.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#Base64StdEncode)]
|
||||
[[play](https://go.dev/play/p/VOaUyQUreoK)]
|
||||
@@ -451,6 +465,16 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<big>RsaDecrypt</big>** : decrypt data with ras algorithm.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaDecrypt)]
|
||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||
- **<big>GenerateRsaKeyPair</big>** : creates rsa private and public key.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
- **<big>RsaEncryptOAEP</big>** : encrypts the given data with RSA-OAEP.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaEncryptOAEP)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
- **<big>RsaDecryptOAEP</big>** : decrypts the data with RSA-OAEP
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaDecryptOAEP)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
|
||||
|
||||
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -585,8 +609,18 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>TimestampNano</big>** : returns current nano second timestamp.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#TimestampNano)]
|
||||
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
|
||||
- **<big>TrackFuncTime</big>** : tracks function execution time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#TrackFuncTime)]
|
||||
[[play](todo)]
|
||||
- **<big>DaysBetween</big>** : returns the number of days between two times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#DaysBetween)]
|
||||
[[play](todo)]
|
||||
- **<big>GenerateDatetimesBetween</big>** : returns a slice of strings between two times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#GenerateDatetimesBetween)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="datastructure"> 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. <a href="#index">index</a></h3>
|
||||
|
||||
<h3 id="datastructure"> 8. Datastructure package contains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. <a href="#index">index</a></h3>
|
||||
|
||||
```go
|
||||
import list "github.com/duke-git/lancet/v2/datastructure/list"
|
||||
@@ -598,6 +632,7 @@ import set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
import tree "github.com/duke-git/lancet/v2/datastructure/tree"
|
||||
import heap "github.com/duke-git/lancet/v2/datastructure/heap"
|
||||
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
import optional "github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
```
|
||||
|
||||
#### Structure list:
|
||||
@@ -620,6 +655,9 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datastructure/heap.md)]
|
||||
- **<big>Hashmap</big>** : hash map structure.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datastructure/hashmap.md)]
|
||||
- **<big>Optional</big>** : Optional container.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datastructure/optional.md)]
|
||||
|
||||
|
||||
<h3 id="fileutil"> 9. Fileutil package implements some basic functions for file operations. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -638,9 +676,12 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- **<big>CreateDir</big>** : create directory in absolute path.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#CreateDir)]
|
||||
[[play](https://go.dev/play/p/qUuCe1OGQnM)]
|
||||
- **<big>CopyFile</big>** :copy src file to dest file.
|
||||
- **<big>CopyFile</big>** : copy src file to dest file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#CopyFile)]
|
||||
[[play](https://go.dev/play/p/Jg9AMJMLrJi)]
|
||||
- **<big>CopyDir</big>** : copy src directory to dest directory.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#CopyDir)]
|
||||
[[play](https://go.dev/play/p/YAyFTA_UuPb)]
|
||||
- **<big>FileMode</big>** : return file's mode and permission.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#FileMode)]
|
||||
[[play](https://go.dev/play/p/2l2hI42fA3p)]
|
||||
@@ -696,13 +737,23 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
|
||||
- **<big>WriteCsvFile</big>** : write content to target csv file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteCsvFile)]
|
||||
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
|
||||
- **<big>WriteMapsToCsv</big>** : write slice of map to csv file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteMapsToCsv)]
|
||||
[[play](https://go.dev/play/p/umAIomZFV1c)]
|
||||
- **<big>WriteBytesToFile</big>** : write bytes to target file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteBytesToFile)]
|
||||
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
|
||||
- **<big>WriteStringToFile</big>** : write string to target file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteStringToFile)]
|
||||
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
|
||||
- **<big>ReadFile</big>** : read file or url.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ReadFile)]
|
||||
- **<big>ChunkRead</big>** : reads a block from the file at the specified offset and returns all lines within the block.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ChunkRead)]
|
||||
[[play](https://go.dev/play/p/r0hPmKWhsgf)]
|
||||
- **<big>ParallelChunkRead</big>** : reads the file in parallel and send each chunk of lines to the specified channel.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#ParallelChunkRead)]
|
||||
[[play](https://go.dev/play/p/teMXnCsdSEw)]
|
||||
|
||||
<h3 id="formatter"> 10. Formatter contains some functions for data formatting. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -712,7 +763,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
||||
|
||||
#### Function list:
|
||||
|
||||
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
|
||||
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by a prefix symbol char.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/formatter.md#Comma)]
|
||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||
- **<big>Pretty</big>** : pretty print data to JSON string.
|
||||
@@ -742,10 +793,10 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
|
||||
#### Function list:
|
||||
|
||||
- **<big>After</big>** : return a function that invokes passed funcation once the returned function is called more than n times.
|
||||
- **<big>After</big>** : return a function that invokes passed function once the returned function is called more than n times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#After)]
|
||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||
- **<big>Before</big>** : return a function that invokes passed funcation once the returned function is called less than n times
|
||||
- **<big>Before</big>** : return a function that invokes passed function once the returned function is called less than n times
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Before)]
|
||||
[[play](https://go.dev/play/p/0HqUDIFZ3IL)]
|
||||
- **<big>CurryFn</big>** : make a curry function.
|
||||
@@ -757,19 +808,47 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- **<big>Delay</big>** : call the function after delayed time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Delay)]
|
||||
[[play](https://go.dev/play/p/Ivtc2ZE-Tye)]
|
||||
- **<big>Debounced</big>** : creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
|
||||
- **<big>Debounced<sup>deprecated</sup></big>** : creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Debounced)]
|
||||
[[play](https://go.dev/play/p/absuEGB_GN7)]
|
||||
- **<big>Debounce</big>** : creates a debounced version of the provided function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Debounce)]
|
||||
[[play](todo)]
|
||||
- **<big>Throttle</big>** : creates a throttled version of the provided function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Throttle)]
|
||||
[[play](todo)]
|
||||
- **<big>Schedule</big>** : invoke function every duration time, util close the returned bool channel.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Schedule)]
|
||||
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
|
||||
- **<big>Pipeline</big>** : takes a list of functions and returns a function whose param will be passed into the functions one by one.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Pipeline)]
|
||||
[[play](https://go.dev/play/p/mPdUVvj6HD6)]
|
||||
- **<big>Watcher</big>** : Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.
|
||||
- **<big>AcceptIf</big>** : returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#AcceptIf)]
|
||||
[[play](https://go.dev/play/p/XlXHHtzCf7d)]
|
||||
- **<big>And</big>** : returns a composed predicate that represents the logical AND of a list of predicates.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#And)]
|
||||
[[play](https://go.dev/play/p/dTBHJMQ0zD2)]
|
||||
- **<big>Or</big>** : returns a composed predicate that represents the logical OR of a list of predicates.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Or)]
|
||||
[[play](https://go.dev/play/p/LitCIsDFNDA)]
|
||||
- **<big>Negate</big>** : returns a predicate that represents the logical negation of this predicate.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Negate)]
|
||||
[[play](https://go.dev/play/p/jbI8BtgFnVE)]
|
||||
- **<big>Nor</big>** : returns a composed predicate that represents the logical NOR of a list of predicates.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Nor)]
|
||||
[[play](https://go.dev/play/p/2KdCoBEOq84)]
|
||||
- **<big>Nand</big>** : returns a composed predicate that represents the logical Nand of a list of predicates.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Nand)]
|
||||
[[play](https://go.dev/play/p/Rb-FdNGpgSO)]
|
||||
- **<big>Xnor</big>** : returns a composed predicate that represents the logical XNOR of a list of predicates.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Xnor)]
|
||||
[[play](https://go.dev/play/p/FJxko8SFbqc)]
|
||||
- **<big>Watcher</big>** : Watcher is used for record code execution time. can start/stop/reset the watch timer. get the elapsed time of function execution.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Watcher)]
|
||||
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
||||
|
||||
|
||||
<h3 id="maputil"> 12. Maputil package includes some functions to manipulate map. <a href="#index">index</a></h3>
|
||||
|
||||
```go
|
||||
@@ -781,7 +860,7 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>MapTo</big>** : quick map any value to struct or any base type.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#MapTo)]
|
||||
[[play](https://go.dev/play/p/4K7KBEPgS5M)]
|
||||
- **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map.
|
||||
- **<big>ForEach</big>** : executes iteratee function for every key and value pair in map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ForEach)]
|
||||
[[play](https://go.dev/play/p/OaThj6iNVXK)]
|
||||
- **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function.
|
||||
@@ -799,7 +878,7 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>OmitByKeys</big>** : the opposite of FilterByKeys, extracts all the map elements which keys are not omitted.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OmitByKeys)]
|
||||
[[play](https://go.dev/play/p/jXGrWDBfSRp)]
|
||||
- **<big>OmitByValues</big>** : the opposite of FilterByValues. remov all elements whose value are in the give slice.
|
||||
- **<big>OmitByValues</big>** : the opposite of FilterByValues. remove all elements whose value are in the give slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OmitByValues)]
|
||||
[[play](https://go.dev/play/p/XB7Y10uw20_U)]
|
||||
- **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps.
|
||||
@@ -844,6 +923,72 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>HasKey</big>** : checks if map has key or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#HasKey)]
|
||||
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
||||
- **<big>GetOrSet</big>** : returns value of the given key or set the given value value if not present.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#GetOrSet)]
|
||||
[[play](https://go.dev/play/p/IVQwO1OkEJC)]
|
||||
- **<big>MapToStruct</big>** : converts map to struct.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#MapToStruct)]
|
||||
[[play](https://go.dev/play/p/7wYyVfX38Dp)]
|
||||
- **<big>ToSortedSlicesDefault</big>** : converts a map to two slices sorted by key: one for the keys and another for the values.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesDefault)]
|
||||
[[play](https://go.dev/play/p/43gEM2po-qy)]
|
||||
- **<big>ToSortedSlicesWithComparator</big>** : converts a map to two slices sorted by key and using a custom comparison function: one for the keys and another for the values.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
||||
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
|
||||
- **<big>NewOrderedMap</big>** : creates a new OrderedMap.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewOrderedMap)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Set</big>** : sets the given key-value pair for ordered map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Set)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Get</big>** : returns the value for the given key.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Get)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Delete</big>** : deletes the key-value pair for the given key.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Delete)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Clear</big>** : clears the ordered map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Clear)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Front</big>** : returns the first key-value pair.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Front)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Back</big>** : returns the last key-value pair.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Back)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Range</big>** : calls the given function for each key-value pair.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Range)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Keys</big>** : returns the keys in order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Keys)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Values</big>** : returns the values in order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Values)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Elements</big>** : returns the key-value pairs in order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Elements)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Len</big>** : returns the number of key-value pairs.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Len)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Contains</big>** : returns true if the given key exists.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Contains)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Iter</big>** : returns a channel that yields key-value pairs in order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Iter)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_ReverseIter</big>** : returns a channel that yields key-value pairs in reverse order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_ReverseIter)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_SortByKey</big>** : sorts the map by key given less function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_SortByKey)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_MarshalJSON</big>** : implements the json.Marshaler interface.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_MarshalJSON)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_UnmarshalJSON</big>** : implements the json.Unmarshaler interface.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_UnmarshalJSON)]
|
||||
[[play](todo)]
|
||||
- **<big>NewConcurrentMap</big>** : creates a ConcurrentMap with specific shard count.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewConcurrentMap)]
|
||||
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
||||
@@ -868,6 +1013,13 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>ConcurrentMap_Range</big>** : calls iterator sequentially for each key and value present in each of the shards in the map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ConcurrentMap_Range)]
|
||||
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
|
||||
- **<big>SortByKey</big>** : sorts the map by its keys and returns a new map with sorted keys.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#SortByKey)]
|
||||
[[play](todo)]
|
||||
- **<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)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -913,6 +1065,18 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>TruncRound</big>** : round off n decimal places for int64.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#TruncRound)]
|
||||
[[play](https://go.dev/play/p/aumarSHIGzP)]
|
||||
- **<big>CeilToFloat</big>** : round float up n decimal places.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#CeilToFloat)]
|
||||
[[play](https://go.dev/play/p/8hOeSADZPCo)]
|
||||
- **<big>CeilToString</big>** : round float up n decimal places, then conver to string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#CeilToString)]
|
||||
[[play](https://go.dev/play/p/wy5bYEyUKKG)]
|
||||
- **<big>FloorToFloat</big>** : round float down n decimal places.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#FloorToFloat)]
|
||||
[[play](https://go.dev/play/p/vbCBrQHZEED)]
|
||||
- **<big>FloorToString</big>** : round float down n decimal places, then conver to string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#FloorToString)]
|
||||
[[play](https://go.dev/play/p/Qk9KPd2IdDb)]
|
||||
- **<big>Range</big>** : Creates a slice of numbers from start with specified count, element step is 1.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Range)]
|
||||
[[play](https://go.dev/play/p/9ke2opxa8ZP)]
|
||||
@@ -949,9 +1113,13 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>Sum</big>** : return sum of passed numbers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Sum)]
|
||||
[[play](https://go.dev/play/p/1To2ImAMJA7)]
|
||||
- **<big>Abs</big>** : returns the absolute value of param nubmer.
|
||||
- **<big>Abs</big>** : returns the absolute value of param number.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Sum)]
|
||||
[[play](https://go.dev/play/p/fsyBh1Os-1d)]
|
||||
- **<big>Div</big>** : returns the result of x divided by y.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Div)]
|
||||
[[play](https://go.dev/play/p/WLxDdGXXYat)]
|
||||
|
||||
|
||||
<h3 id="netutil"> 14. Netutil package contains functions to get net information and send http request. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1000,7 +1168,7 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
- **<big>DecodeResponse</big>** : decode http response into target object.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#DecodeResponse)]
|
||||
[[play](https://go.dev/play/p/jUSgynekH7G)]
|
||||
- **<big>StructToUrlValues</big>** : convert struct to url valuse.
|
||||
- **<big>StructToUrlValues</big>** : convert struct to url values.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/netutil.md#StructToUrlValues)]
|
||||
[[play](https://go.dev/play/p/pFqMkM40w9z)]
|
||||
- **<big>HttpGet<sup>deprecated</sup></big>** : send http get request.
|
||||
@@ -1043,7 +1211,7 @@ import "github.com/duke-git/lancet/v2/pointer"
|
||||
- **<big>Unwrap</big>** : return the value from the pointer.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/pointer.md#Unwrap)]
|
||||
[[play](https://go.dev/play/p/cgeu3g7cjWb)]
|
||||
- **<big>UnwarpOr</big>** : UnwarpOr returns the value from the pointer or fallback if the pointer is nil.
|
||||
- **<big>UnwrapOr</big>** : UnwrapOr returns the value from the pointer or fallback if the pointer is nil.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/pointer.md#UnwrapOr)]
|
||||
[[play](https://go.dev/play/p/mmNaLC38W8C)]
|
||||
- **<big>UnwarpOrDefault</big>** : UnwarpOrDefault returns the value from the pointer or the default value if the pointer is nil.
|
||||
@@ -1082,9 +1250,37 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#UUIdV4)]
|
||||
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
||||
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
|
||||
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int that do not repeat.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandUniqueIntSlice)]
|
||||
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||
- **<big>RandSymbolChar</big>** : generate a random symbol char of specified length.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandSymbolChar)]
|
||||
[[play](https://go.dev/play/p/Im6ZJxAykOm)]
|
||||
- **<big>RandFloat</big>** : generate a random float64 number between [min, max) with specific precision.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFloat)]
|
||||
[[play](https://go.dev/play/p/zbD_tuobJtr)]
|
||||
- **<big>RandFloats</big>** : generate a slice of random float64 numbers that do not repeat.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFloats)]
|
||||
[[play](https://go.dev/play/p/I3yndUQ-rhh)]
|
||||
- **<big>RandStringSlice</big>** : generate a slice of random string of length strLen based on charset.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandStringSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandBool</big>** : generate a random boolean value (true or false).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandBool)]
|
||||
[[play](todo)]
|
||||
- **<big>RandBoolSlice</big>** : generate a random boolean slice of specified length.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandBoolSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandIntSlice</big>** : generate a slice of random int. Number range in [min, max)
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandIntSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandFromGivenSlice</big>** : generate a random element from given slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFromGivenSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandSliceFromGivenSlice</big>** : generate a random slice of length num from given slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandSliceFromGivenSlice)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1109,6 +1305,18 @@ import "github.com/duke-git/lancet/v2/retry"
|
||||
- **<big>RetryTimes</big>** : set times of retry.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryTimes)]
|
||||
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
||||
- **<big>BackoffStrategy</big>** : An interface that defines a method for calculating backoff intervals.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#BackoffStrategy)]
|
||||
- **<big>RetryWithCustomBackoff</big>** : set abitary custom backoff strategy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryWithCustomBackoff)]
|
||||
[[play](https://go.dev/play/p/jIm_o2vb5Y4)]
|
||||
- **<big>RetryWithLinearBackoff</big>** : set linear strategy backoff.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryWithLinearBackoff)]
|
||||
[[play](https://go.dev/play/p/PDet2ZQZwcB)]
|
||||
- **<big>RetryWithExponentialWithJitterBackoff</big>** : set exponential strategy backoff.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)]
|
||||
[[play](https://go.dev/play/p/xp1avQmn16X)]
|
||||
|
||||
|
||||
<h3 id="slice"> 18. Slice contains some functions to manipulate slice. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1133,7 +1341,7 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Chunk</big>** : creates a slice of elements split into groups the length of size.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Chunk)]
|
||||
[[play](https://go.dev/play/p/b4Pou5j2L_C)]
|
||||
- **<big>Compact</big>** : creates an slice with all falsey values removed. The values false, nil, 0, and "" are falsey.
|
||||
- **<big>Compact</big>** : creates an slice with all falsy values removed. The values false, nil, 0, and "" are falsy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Compact)]
|
||||
[[play](https://go.dev/play/p/pO5AnxEr3TK)]
|
||||
- **<big>Concat</big>** : creates a new slice concatenating slice with any additional slices.
|
||||
@@ -1154,9 +1362,12 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>DifferenceWith</big>** : accepts comparator which is invoked to compare elements of slice to values.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#DifferenceWith)]
|
||||
[[play](https://go.dev/play/p/v2U2deugKuV)]
|
||||
- **<big>DeleteAt</big>** : delete the element of slice from specific start index to end index - 1.
|
||||
- **<big>DeleteAt</big>** : delete the element of slice at index.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#DeleteAt)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
[[play](https://go.dev/play/p/800B1dPBYyd)]
|
||||
- **<big>DeleteRange</big>** : delete the element of slice from start index to end index(exclude).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#DeleteRange)]
|
||||
[[play](https://go.dev/play/p/945HwiNrnle)]
|
||||
- **<big>Drop</big>** : drop n elements from the start of a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Drop)]
|
||||
[[play](https://go.dev/play/p/jnPO2yQsT8H)]
|
||||
@@ -1211,10 +1422,13 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>ForEachWithBreak</big>** : iterates over elements of slice and invokes function for each element, when iteratee return false, will break the for each loop.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ForEachWithBreak)]
|
||||
[[play](https://go.dev/play/p/qScs39f3D9W)]
|
||||
- **<big>ForEachConcurrent</big>** : applies the iteratee function to each item in the slice concurrently.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ForEachConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>GroupBy</big>** : iterate over elements of the slice, each element will be group by criteria, returns two slices.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#GroupBy)]
|
||||
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
|
||||
- **<big>GroupWith</big>** : return a map composed of keys generated from the resultults of running each element of slice thru iteratee.
|
||||
- **<big>GroupWith</big>** : return a map composed of keys generated from the results of running each element of slice thru iteratee.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#GroupWith)]
|
||||
[[play](https://go.dev/play/p/ApCvMNTLO8a)]
|
||||
- **<big>IntSlice<sup>deprecated</sup></big>** : convert param to int slice.
|
||||
@@ -1238,6 +1452,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Map</big>** : creates an slice of values by running each element of slice thru iteratee function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Map)]
|
||||
[[play](https://go.dev/play/p/biaTefqPquw)]
|
||||
- **<big>MapConcurrent</big>** : applies the iteratee function to each item in the slice by concrrent.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#MapConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Merge</big>** : merge all given slices into one slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Merge)]
|
||||
[[play](https://go.dev/play/p/lbjFp784r9N)]
|
||||
@@ -1253,6 +1470,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>ReduceRight</big>** : ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ReduceRight)]
|
||||
[[play](https://go.dev/play/p/qT9dZC03A1K)]
|
||||
- **<big>ReduceConcurrent</big>** : reduces the slice to a single value by applying the reducer function to each item in the slice concurrently.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ReduceConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Replace)]
|
||||
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
||||
@@ -1304,9 +1524,18 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Unique</big>** : remove duplicate elements in slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Unique)]
|
||||
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
|
||||
- **<big>UniqueBy</big>** : call iteratee func with every item of slice, then remove duplicated.
|
||||
- **<big>UniqueBy</big>** : remove duplicate elements from the input slice based on the values returned by the iteratee function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueBy)]
|
||||
[[play](https://go.dev/play/p/UR323iZLDpv)]
|
||||
- **<big>UniqueByComparator</big>** : remove duplicate elements from the input slice using the provided comparator function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByComparator)]
|
||||
[[play](todo)]
|
||||
- **<big>UniqueByField</big>** : remove duplicate elements in struct slice by struct field.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByField)]
|
||||
[[play](https://go.dev/play/p/6cifcZSPIGu)]
|
||||
- **<big>UniqueByConcurrent</big>** : remove duplicate elements from the slice by concurrent.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Union</big>** : creates a slice of unique elements, in order, from all given slices.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Union)]
|
||||
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
|
||||
@@ -1325,6 +1554,27 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Join</big>** : join the slice item with specify separator.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Join)]
|
||||
[[play](https://go.dev/play/p/huKzqwNDD7V)]
|
||||
- **<big>Partition</big>** : partition all slice elements with the evaluation of the given predicate functions.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Partition)]
|
||||
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
||||
- **<big>Random</big>** : get a random item of slice, return its index, when slice is empty, return -1.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Random)]
|
||||
[[play](https://go.dev/play/p/UzpGQptWppw)]
|
||||
- **<big>SetToDefaultIf</big>** : set elements to their default value if they match the given predicate.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#SetToDefaultIf)]
|
||||
[[play](https://go.dev/play/p/9AXGlPRC0-A)]
|
||||
- **<big>Break</big>** : breaks a list into two parts at the point where the predicate for the first time is true.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Break)]
|
||||
- **<big>RightPadding</big>** : adds padding to the right end of a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#RightPadding)]
|
||||
[[play](https://go.dev/play/p/0_2rlLEMBXL)]
|
||||
- **<big>LeftPadding</big>** : adds padding to the left begin of a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#LeftPadding)]
|
||||
[[play](https://go.dev/play/p/jlQVoelLl2k)]
|
||||
- **<big>Frequency</big>** : counts the frequency of each element in the slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Frequency)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1346,7 +1596,7 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>FromRange</big>** : creates a number stream from start to end. both start and end are included. [start, end]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#FromRange)]
|
||||
[[play](https://go.dev/play/p/9Ex1-zcg-B-)]
|
||||
- **<big>Generate</big>** : creates a stream where each element is generated by the provided generater function.
|
||||
- **<big>Generate</big>** : creates a stream where each element is generated by the provided generator function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Generate)]
|
||||
[[play](https://go.dev/play/p/rkOWL1yA3j9)]
|
||||
- **<big>Concat</big>** : creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
||||
@@ -1358,6 +1608,9 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>Filter</big>** : returns a stream consisting of the elements of this stream that match the given predicate.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Filter)]
|
||||
[[play](https://go.dev/play/p/MFlSANo-buc)]
|
||||
- **<big>FilterConcurrent</big>** : Applies the provided filter function `predicate` to each element of the input slice concurrently.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#FilterConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Map</big>** : returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Map)]
|
||||
[[play](https://go.dev/play/p/OtNQUImdYko)]
|
||||
@@ -1391,10 +1644,10 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>FindLast</big>** : returns the last element of this stream and true, or zero value and false if the stream is empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#FindLast)]
|
||||
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
|
||||
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less fuction: a > b
|
||||
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less function: a > b
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Max)]
|
||||
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
|
||||
- **<big>Min</big>** : returns the minimum element of this stream according to the provided less function. less fuction: a < b
|
||||
- **<big>Min</big>** : returns the minimum element of this stream according to the provided less function. less function: a < b
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Min)]
|
||||
[[play](https://go.dev/play/p/vZfIDgGNRe_0)]
|
||||
- **<big>AllMatch</big>** : returns whether all elements of this stream match the provided predicate.
|
||||
@@ -1422,29 +1675,31 @@ import "github.com/duke-git/lancet/v2/structs"
|
||||
#### Function list:
|
||||
|
||||
- **<big>New</big>** : creates a `Struct` instance.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/struct.md#New)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#New)]
|
||||
- **<big>ToMap</big>** : converts a valid struct to a map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/struct.md#ToMap)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#ToMap)]
|
||||
- **<big>Fields</big>** : get all fields of a given struct, that the fields are abstract struct field.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/struct.md#Fields)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#Fields)]
|
||||
- **<big>IsStruct</big>** : check if the struct is valid.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/struct.md#IsStruct)]
|
||||
- **<big>Tag</big>** : get a `Tag` of the `Field`, `Tag` is a abstract struct field tag
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#Tag)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsStruct)]
|
||||
- **<big>Tag</big>** : get a `Tag` of the `Field`, `Tag` is a abstract struct field tag.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#Tag)]
|
||||
- **<big>Name</big>** : get the field name.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#Name)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#Name)]
|
||||
- **<big>Value</big>** : get the `Field` underlying value.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#Value)]
|
||||
- **<big>Kind</big>** : get the field's kind
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#Kind)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#Value)]
|
||||
- **<big>Kind</big>** : get the field's kind.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#Kind)]
|
||||
- **<big>IsEmbedded</big>** : check if the field is an embedded field.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#IsEmbedded)]
|
||||
- **<big>IsExported</big>** : check if the field is exporte
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#IsExported)]
|
||||
- **<big>IsZero</big>** : check if the field is zero value
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#IsZero)]
|
||||
- **<big>IsSlice</big>** : check if the field is a slice
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/structs/field.md#IsSlice)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsEmbedded)]
|
||||
- **<big>IsExported</big>** : check if the field is exported.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsExported)]
|
||||
- **<big>IsZero</big>** : check if the field is zero value.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsZero)]
|
||||
- **<big>IsSlice</big>** : check if the field is a slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsSlice)]
|
||||
- **<big>IsTargetType</big>** : check if the field is target type.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/struct.md#IsTargetType)]
|
||||
|
||||
<h3 id="strutil"> 21. Strutil package contains some functions to manipulate string. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1540,6 +1795,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>IsBlank</big>** : checks if a string is whitespace or empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#IsBlank)]
|
||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||
- **<big>IsNotBlank</big>** : checks if a string is not whitespace or not empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#IsNotBlank)]
|
||||
[[play](https://go.dev/play/p/e_oJW0RAquA)]
|
||||
- **<big>HasPrefixAny</big>** : checks if a string starts with any of an array of specified strings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#HasPrefixAny)]
|
||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||
@@ -1564,7 +1822,27 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>RemoveWhiteSpace</big>** : remove whitespace characters from a string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#RemoveWhiteSpace)]
|
||||
[[play](https://go.dev/play/p/HzLC9vsTwkf)]
|
||||
|
||||
- **<big>SubInBetween</big>** : return substring between the start and end position(excluded) of source string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#SubInBetween)]
|
||||
[[play](https://go.dev/play/p/EDbaRvjeNsv)]
|
||||
- **<big>HammingDistance</big>** : calculates the Hamming distance between two strings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#HammingDistance)]
|
||||
[[play](https://go.dev/play/p/glNdQEA9HUi)]
|
||||
- **<big>Concat</big>** : concatenates strings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Concat)]
|
||||
[[play](todo)]
|
||||
- **<big>Ellipsis</big>** : truncates a string to a specified length and appends an ellipsis.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Ellipsis)]
|
||||
[[play](todo)]
|
||||
- **<big>Shuffle</big>** : shuffle the order of characters of given string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Shuffle)]
|
||||
[[play](todo)]
|
||||
- **<big>Rotate</big>** : rotates the string by the specified number of characters.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Rotate)]
|
||||
[[play](todo)]
|
||||
- **<big>TemplateReplace</big>** : replaces the placeholders in the template string with the corresponding values in the data map.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#TemplateReplace)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="system"> 22. System package contain some functions about os, runtime, shell command. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1601,6 +1879,19 @@ import "github.com/duke-git/lancet/v2/system"
|
||||
- **<big>GetOsBits</big>** : return current os bits (32 or 64).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetOsBits)]
|
||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||
- **<big>StartProcess</big>** : start a new process with the specified name and arguments.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StartProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>StopProcess</big>** : stop a process by pid.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StopProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>KillProcess</big>** : kill a new process with the specified name and arguments.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#KillProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>GetProcessInfo</big>** : retrieves detailed process information by pid.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetProcessInfo)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1610,7 +1901,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
|
||||
#### Function list:
|
||||
|
||||
- **<big>Tuple2</big>** : represents a 2 elemnets tuple.
|
||||
- **<big>Tuple2</big>** : represents a 2 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple2)]
|
||||
[[play](https://go.dev/play/p/3sHVqBQpLYN)]
|
||||
- **<big>Tuple2_Unbox</big>** : returns values in Tuple2.
|
||||
@@ -1622,7 +1913,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip2</big>** : create a group of slice from a slice of Tuple2.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip2)]
|
||||
[[play](https://go.dev/play/p/KBecr60feXb)]
|
||||
- **<big>Tuple3</big>** : represents a 3 elemnets tuple.
|
||||
- **<big>Tuple3</big>** : represents a 3 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple3)]
|
||||
[[play](https://go.dev/play/p/FtH2sdCLlCf)]
|
||||
- **<big>Tuple3_Unbox</big>** : returns values in Tuple3.
|
||||
@@ -1634,7 +1925,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip3</big>** : create a group of slice from a slice of Tuple3.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip3)]
|
||||
[[play](https://go.dev/play/p/bba4cpAa7KO)]
|
||||
- **<big>Tuple4</big>** : represents a 4 elemnets tuple.
|
||||
- **<big>Tuple4</big>** : represents a 4 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple4)]
|
||||
[[play](https://go.dev/play/p/D2EqDz096tk)]
|
||||
- **<big>Tuple4_Unbox</big>** : returns values in Tuple4.
|
||||
@@ -1646,7 +1937,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip4</big>** : create a group of slice from a slice of Tuple4.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip4)]
|
||||
[[play](https://go.dev/play/p/rb8z4gyYSRN)]
|
||||
- **<big>Tuple5</big>** : represents a 5 elemnets tuple.
|
||||
- **<big>Tuple5</big>** : represents a 5 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple5)]
|
||||
[[play](https://go.dev/play/p/2WndmVxPg-r)]
|
||||
- **<big>Tuple5_Unbox</big>** : returns values in Tuple4.
|
||||
@@ -1658,7 +1949,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip5</big>** : create a group of slice from a slice of Tuple5.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip5)]
|
||||
[[play](https://go.dev/play/p/gyl6vKfhqPb)]
|
||||
- **<big>Tuple6</big>** : represents a 6 elemnets tuple.
|
||||
- **<big>Tuple6</big>** : represents a 6 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple6)]
|
||||
[[play](https://go.dev/play/p/VjqcCwEJZbs)]
|
||||
- **<big>Tuple6_Unbox</big>** : returns values in Tuple6.
|
||||
@@ -1670,7 +1961,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip6</big>** : create a group of slice from a slice of Tuple6.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip6)]
|
||||
[[play](https://go.dev/play/p/l41XFqCyh5E)]
|
||||
- **<big>Tuple7</big>** : represents a 7 elemnets tuple.
|
||||
- **<big>Tuple7</big>** : represents a 7 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple7)]
|
||||
[[play](https://go.dev/play/p/dzAgv_Ezub9)]
|
||||
- **<big>Tuple7_Unbox</big>** : returns values in Tuple7.
|
||||
@@ -1682,7 +1973,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip7</big>** : create a group of slice from a slice of Tuple7.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip7)]
|
||||
[[play](https://go.dev/play/p/hws_P1Fr2j3)]
|
||||
- **<big>Tuple8</big>** : represents a 8 elemnets tuple.
|
||||
- **<big>Tuple8</big>** : represents a 8 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple8)]
|
||||
[[play](https://go.dev/play/p/YA9S0rz3dRz)]
|
||||
- **<big>Tuple8_Unbox</big>** : returns values in Tuple8.
|
||||
@@ -1694,7 +1985,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip8</big>** : create a group of slice from a slice of Tuple8.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip8)]
|
||||
[[play](https://go.dev/play/p/1SndOwGsZB4)]
|
||||
- **<big>Tuple9</big>** : represents a 9 elemnets tuple.
|
||||
- **<big>Tuple9</big>** : represents a 9 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple9)]
|
||||
[[play](https://go.dev/play/p/yS2NGGtZpQr)]
|
||||
- **<big>Tuple9_Unbox</big>** : returns values in Tuple9.
|
||||
@@ -1706,7 +1997,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
- **<big>Unzip9</big>** : create a group of slice from a slice of Tuple9.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Unzip9)]
|
||||
[[play](https://go.dev/play/p/91-BU_KURSA)]
|
||||
- **<big>Tuple10</big>** : represents a 10 elemnets tuple.
|
||||
- **<big>Tuple10</big>** : represents a 10 elements tuple.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/tuple.md#Tuple10)]
|
||||
[[play](https://go.dev/play/p/799qqZg0hUv)]
|
||||
- **<big>Tuple10_Unbox</big>** : returns values in Tuple10.
|
||||
@@ -1826,6 +2117,33 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsPrintable</big>** : checks if string is all printable chars.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsPrintable)]
|
||||
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||
- **<big>IsBin</big>** : check if a give string is a valid binary value or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsBin)]
|
||||
[[play](https://go.dev/play/p/ogPeg2XJH4P)]
|
||||
- **<big>IsHex</big>** : check if a give string is a valid hexadecimal value or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsHex)]
|
||||
[[play](https://go.dev/play/p/M2qpHbEwmm7)]
|
||||
- **<big>IsBase64URL</big>** : check if a give string is a valid URL-safe Base64 encoded string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsBase64URL)]
|
||||
[[play](https://go.dev/play/p/vhl4mr8GZ6S)]
|
||||
- **<big>IsJWT</big>** : check if a give string is a valid JSON Web Token (JWT).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsJWT)]
|
||||
[[play](https://go.dev/play/p/R6Op7heJbKI)]
|
||||
- **<big>IsVisa</big>** : check if a give string is a valid visa card number or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsVisa)]
|
||||
[[play](https://go.dev/play/p/SdS2keOyJsl)]
|
||||
- **<big>IsMasterCard</big>** : check if a give string is a valid master card number or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsMasterCard)]
|
||||
[[play](https://go.dev/play/p/CwWBFRrG27b)]
|
||||
- **<big>IsAmericanExpress</big>** : check if a give string is a valid american expression card number or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsAmericanExpress)]
|
||||
[[play](https://go.dev/play/p/HIDFpcOdpkd)]
|
||||
- **<big>IsUnionPay</big>** : check if a give string is a valid union pay number or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsUnionPay)]
|
||||
[[play](https://go.dev/play/p/CUHPEwEITDf)]
|
||||
- **<big>IsChinaUnionPay</big>** : check if a give string is a valid china union pay number or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsChinaUnionPay)]
|
||||
[[play](https://go.dev/play/p/yafpdxLiymu)]
|
||||
|
||||
<h3 id="xerror"> 25. Xerror package implements helpers for errors. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1877,27 +2195,15 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
|
||||
## How to Contribute
|
||||
|
||||
#### [Contributing Guide](./CONTRIBUTING.en-US.md)
|
||||
|
||||
|
||||
## Sponsor
|
||||
|
||||
Hello, I am a software developer and have been engaged in development work for 13 years. Love open source software. And be willing to put in the energy for it. I am the creator of project lancet. Since Lancet was released as open source two years ago, it has been used by more than 1,000 internal and external projects. lancet will always be free for all users. Your support is a powerful encouragement for me to continue my struggle. Thanks! You can use WeChat to scans the following QR code or clicks the following sponsor button to initiate sponsorship.
|
||||
|
||||
<div style="position: relative;display: inline-block;">
|
||||
<img src="./docs/public/wechat_pay.png" width="260" height="260"/>
|
||||
<a href="https://en.liberapay.com/Duke_Du/donate" target="\_blank"><img src="./docs/public/sponsor_btn.png" width="220" height="60"/></a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
*Donated funds will be used to maintain this website and pay for cloud server costs. Or just buy me a cup of ☕️ when I'm sleepy writing code.*
|
||||
|
||||
#### [Contribution Guide](./CONTRIBUTION.md)
|
||||
|
||||
## Contributors
|
||||
Thank you to all the people who contributed to lancet!
|
||||
|
||||
<a href="https://github.com/duke-git/lancet/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=duke-git/lancet" />
|
||||
</a>
|
||||
</a>
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#duke-git/lancet&Date)
|
||||
|
||||
413
README_zh-CN.md
413
README_zh-CN.md
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -18,12 +18,12 @@
|
||||
lancet(柳叶刀)是一个全面、高效、可复用的go语言工具函数库。 lancet受到了java apache common包和lodash.js的启发。
|
||||
</p>
|
||||
|
||||
## <a href="https://www.golancet.cn/" target="_blank">官网</a> | [English](./README.md)
|
||||
## <a href="https://www.golancet.cn/" target="_blank">官网</a> | [English](./README.md)
|
||||
|
||||
## 特性
|
||||
|
||||
- 👏 全面、高效、可复用。
|
||||
- 💪 600+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💪 700+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖 go 标准库和 golang.org/x。
|
||||
- 🌍 所有导出函数单元测试覆盖率 100%。
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.1。</b>
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.4。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
@@ -100,6 +100,7 @@ func main() {
|
||||
- [Validator](#user-content-validator)
|
||||
- [Xerror](#user-content-xerror)
|
||||
|
||||
|
||||
<h3 id="algorithm"> 1. algorithm 包实现一些基本查找和排序算法。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
@@ -317,6 +318,15 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
- **<big>GbkToUtf8</big>** : GBK 编码转 utf8 编码。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#GbkToUtf8)]
|
||||
[[play](https://go.dev/play/p/OphmHCN_9u8)]
|
||||
- **<big>ToStdBase64</big>** : 将值转换为StdBase64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToStdBase64)]
|
||||
- **<big>ToUrlBase64</big>** : 将值转换为url Base64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToUrlBase64)]
|
||||
- **<big>ToRawStdBase64</big>** : 将值转换为RawStdBase64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawStdBase64)]
|
||||
- **<big>ToRawUrlBase64</big>** : 将值转换为RawUrlBase64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawUrlBase64)]
|
||||
|
||||
|
||||
<h3 id="cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -353,6 +363,12 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<big>AesOfbDecrypt</big>** : 使用 AES OFB 算法模式解密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesOfbDecrypt)]
|
||||
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
|
||||
- **<big>AesGcmEncrypt</big>** : 使用 AES GCM 算法模式加密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesGcmEncrypt)]
|
||||
[[play](todo)]
|
||||
- **<big>AesGcmDecrypt</big>** : 使用 AES GCM 算法模式解密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesGcmDecrypt)]
|
||||
[[play](todo)]
|
||||
- **<big>Base64StdEncode</big>** : 将字符串 base64 编码。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#Base64StdEncode)]
|
||||
[[play](https://go.dev/play/p/VOaUyQUreoK)]
|
||||
@@ -451,8 +467,18 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<big>RsaDecrypt</big>** : 用私钥文件 rsa 解密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaDecrypt)]
|
||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||
- **<big>GenerateRsaKeyPair</big>** : 创建rsa公钥私钥和key。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
- **<big>RsaEncryptOAEP</big>** : rsa OAEP加密。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaEncryptOAEP)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
- **<big>RsaDecryptOAEP</big>** : rsa OAEP解密。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaDecryptOAEP)]
|
||||
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||
|
||||
<h3 id="datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
<h3 id="datetime"> 7. datetime日期时间处理包,格式化日期,比较日期。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/datetime"
|
||||
@@ -562,9 +588,6 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>IsLeapYear</big>** :验证是否是闰年。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#IsLeapYear)]
|
||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#IsLeapYear)]
|
||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
||||
@@ -589,6 +612,16 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>TimestampNano</big>** : 返回当前纳秒级时间戳。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#TimestampNano)]
|
||||
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
|
||||
- **<big>TrackFuncTime</big>** : 测试函数执行时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#TrackFuncTime)]
|
||||
[[play](todo)]
|
||||
- **<big>DaysBetween</big>** : 返回两个日期之间的天数差。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#DaysBetween)]
|
||||
[[play](todo)]
|
||||
- **<big>GenerateDatetimesBetween</big>** : 生成从start到end的所有日期时间的字符串列表。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#GenerateDatetimesBetween)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -642,9 +675,12 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- **<big>CreateDir</big>** : 创建嵌套目录,例如/a/, /a/b/。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#CreateDir)]
|
||||
[[play](https://go.dev/play/p/qUuCe1OGQnM)]
|
||||
- **<big>CopyFile</big>** :拷贝文件,会覆盖原有的文件。
|
||||
- **<big>CopyFile</big>** : 拷贝文件,会覆盖原有的文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#CopyFile)]
|
||||
[[play](https://go.dev/play/p/Jg9AMJMLrJi)]
|
||||
- **<big>CopyDir</big>** : 拷贝目录。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#CopyDir)]
|
||||
[[play](https://go.dev/play/p/YAyFTA_UuPb)]
|
||||
- **<big>FileMode</big>** : 获取文件 mode 信息。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#FileMode)]
|
||||
[[play](https://go.dev/play/p/2l2hI42fA3p)]
|
||||
@@ -698,15 +734,27 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- **<big>ReadCsvFile</big>** : 读取 csv 文件内容到切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadCsvFile)]
|
||||
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
|
||||
- **<big>WriteCsvFile</big>** : 向 csv 文件写入内容。
|
||||
- **<big>WriteCsvFile</big>** : 向csv文件写入切片数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteCsvFile)]
|
||||
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
|
||||
- **<big>WriteMapsToCsv</big>** : 将map切片写入csv文件中。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteMapsToCsv)]
|
||||
[[play](https://go.dev/play/p/umAIomZFV1c)]
|
||||
- **<big>WriteBytesToFile</big>** : 将 bytes 写入文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteBytesToFile)]
|
||||
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
|
||||
- **<big>WriteStringToFile</big>** : 将字符串写入文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteStringToFile)]
|
||||
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
|
||||
- **<big>ReadFile</big>** : 读取文件或者URL。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadFile)]
|
||||
- **<big>ChunkRead</big>** : 从文件的指定偏移读取块并返回块内所有行。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ChunkRead)]
|
||||
[[play](https://go.dev/play/p/r0hPmKWhsgf)]
|
||||
- **<big>ParallelChunkRead</big>** : 并行读取文件并将每个块的行发送到指定通道。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ParallelChunkRead)]
|
||||
[[play](https://go.dev/play/p/teMXnCsdSEw)]
|
||||
|
||||
|
||||
|
||||
<h3 id="formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -716,7 +764,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
|
||||
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持添加前缀符号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/formatter.md#Comma)]
|
||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||
- **<big>Pretty</big>** : 返回 pretty JSON 字符串。
|
||||
@@ -761,19 +809,48 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- **<big>Delay</big>** : 延迟 delay 时间后调用函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Delay)]
|
||||
[[play](https://go.dev/play/p/Ivtc2ZE-Tye)]
|
||||
- **<big>Debounced</big>** : 创建一个 debounced 函数,该函数延迟调用 fn 直到自上次调用 debounced 函数后等待持续时间过去。
|
||||
- **<big>Debounced<sup>deprecated</sup></big>** : 创建一个 debounced 函数,该函数延迟调用 fn 直到自上次调用 debounced 函数后等待持续时间过去。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Debounced)]
|
||||
[[play](https://go.dev/play/p/absuEGB_GN7)]
|
||||
- **<big>Debounce</big>** : 创建一个函数的去抖动版本。该去抖动函数仅在上次调用后的指定延迟时间过去之后才会调用原始函数。支持取消去抖动。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Debounce)]
|
||||
[[play](todo)]
|
||||
- **<big>Throttle</big>** : 创建一个函数的节流版本。返回的函数保证在每个时间间隔内最多只会被调用一次。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Throttle)]
|
||||
[[play](todo)]
|
||||
- **<big>Schedule</big>** : 每次持续时间调用函数,直到关闭返回的 channel。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Schedule)]
|
||||
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
|
||||
- **<big>Pipeline</big>** : 从右至左执行函数列表。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Pipeline)]
|
||||
[[play](https://go.dev/play/p/mPdUVvj6HD6)]
|
||||
- **<big>AcceptIf</big>** : AcceptIf函数会返回另一个函数,该函数的签名与apply函数相同,但同时还会包含一个布尔值来表示成功或失败。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#AcceptIf)]
|
||||
[[play](https://go.dev/play/p/XlXHHtzCf7d)]
|
||||
- **<big>And</big>** : 返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑and操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#And)]
|
||||
[[play](https://go.dev/play/p/dTBHJMQ0zD2)]
|
||||
- **<big>Or</big>** : 返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑or操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Or)]
|
||||
[[play](https://go.dev/play/p/LitCIsDFNDA)]
|
||||
- **<big>Negate</big>** : 返回一个谓词函数,该谓词函数表示当前谓词的逻辑否定。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Negate)]
|
||||
[[play](https://go.dev/play/p/jbI8BtgFnVE)]
|
||||
- **<big>Nor</big>** : 返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑非或nor的操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Nor)]
|
||||
[[play](https://go.dev/play/p/2KdCoBEOq84)]
|
||||
- **<big>Nand</big>** : 返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑非与nand的操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Nand)]
|
||||
[[play](https://go.dev/play/p/Rb-FdNGpgSO)]
|
||||
- **<big>Xnor</big>** : 返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑异或xnor的操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Xnor)]
|
||||
[[play](https://go.dev/play/p/FJxko8SFbqc)]
|
||||
- **<big>Watcher</big>** : Watcher 用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Watcher)]
|
||||
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
|
||||
|
||||
|
||||
|
||||
<h3 id="maputil"> 12. maputil 包括一些操作 map 的函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
@@ -848,6 +925,72 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>HasKey</big>** : 检查 map 是否包含某个 key。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#HasKey)]
|
||||
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
||||
- **<big>GetOrSet</big>** : 返回给定键的值,如果不存在则设置该值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrSet)]
|
||||
[[play](https://go.dev/play/p/IVQwO1OkEJC)]
|
||||
- **<big>MapToStruct</big>** : 将map转成struct。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#MapToStruct)]
|
||||
[[play](https://go.dev/play/p/7wYyVfX38Dp)]
|
||||
- **<big>ToSortedSlicesDefault</big>** : 将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesDefault)]
|
||||
[[play](https://go.dev/play/p/43gEM2po-qy)]
|
||||
- **<big>ToSortedSlicesWithComparator</big>** : 将map的key和value转化成两个使用比较器函数根据key的值自定义排序规则的切片,value切片中元素的位置与key对应。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
||||
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
|
||||
- **<big>NewOrderedMap</big>** : 创建有序映射。有序映射是键值对的集合,其中键是唯一的,并且保留键插入的顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewOrderedMap)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Set</big>** : 设置给定的键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Set)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Get</big>** : 返回给定键的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Get)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Delete</big>** : 删除给定键的键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Delete)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Clear</big>** : 清空map数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Clear)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Front</big>** : 返回第一个键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Front)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Back</big>** : 返回最后一个键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Back)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Range</big>** : 为每个键值对调用给定的函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Range)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Keys</big>** : 按顺序返回键的切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Keys)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Values</big>** : 按顺序返回值的切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Values)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Elements</big>** : 按顺序返回键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Elements)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Len</big>** : 返回键值对的数量。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Len)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Contains</big>** : 如果给定的键存在则返回true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Contains)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_Iter</big>** : 返回按顺序产生键值对的通道。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Iter)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_ReverseIter</big>** : 返回以相反顺序产生键值对的通道。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_ReverseIter)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_SortByKey</big>** : 使用传入的比较函数排序map key。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_SortByKey)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_MarshalJSON</big>** : 实现json.Marshaler接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_MarshalJSON)]
|
||||
[[play](todo)]
|
||||
- **<big>OrderedMap_UnmarshalJSON</big>** : 实现json.Unmarshaler接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_UnmarshalJSON)]
|
||||
[[play](todo)]
|
||||
- **<big>NewConcurrentMap</big>** : ConcurrentMap 协程安全的 map 结构。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewConcurrentMap)]
|
||||
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
||||
@@ -872,6 +1015,12 @@ import "github.com/duke-git/lancet/v2/maputil"
|
||||
- **<big>ConcurrentMap_Range</big>** : 为 map 中每个键和值顺序调用迭代器。 如果 iterator 返回 false,则停止迭代。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ConcurrentMap_Range)]
|
||||
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
|
||||
- **<big>SortByKey</big>** : 对传入的map根据key进行排序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#SortByKey)]
|
||||
[[play](todo)]
|
||||
- **<big>GetOrDefault</big>** : 返回给定键的值,如果键不存在,则返回默认值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrDefault)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="mathutil"> 13. mathutil 包实现了一些数学计算的函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -917,6 +1066,18 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>TruncRound</big>** : 截短 n 位小数(不进行四舍五入)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#TruncRound)]
|
||||
[[play](https://go.dev/play/p/aumarSHIGzP)]
|
||||
- **<big>CeilToFloat</big>** : 向上舍入(进一法),保留n位小数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#CeilToFloat)]
|
||||
[[play](https://go.dev/play/p/8hOeSADZPCo)]
|
||||
- **<big>CeilToString</big>** : 向上舍入(进一法),保留n位小数,返回字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#CeilToString)]
|
||||
[[play](https://go.dev/play/p/wy5bYEyUKKG)]
|
||||
- **<big>FloorToFloat</big>** : 向下舍入(去尾法),保留n位小数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#FloorToFloat)]
|
||||
[[play](https://go.dev/play/p/vbCBrQHZEED)]
|
||||
- **<big>FloorToString</big>** : 向下舍入(去尾法),保留n位小数,返回字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#FloorToString)]
|
||||
[[play](https://go.dev/play/p/Qk9KPd2IdDb)]
|
||||
- **<big>Range</big>** : 根据指定的起始值和数量,创建一个数字切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Range)]
|
||||
[[play](https://go.dev/play/p/9ke2opxa8ZP)]
|
||||
@@ -956,6 +1117,10 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>Abs</big>** : 求绝对值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Sum)]
|
||||
[[play](https://go.dev/play/p/fsyBh1Os-1d)]
|
||||
- **<big>Div</big>** : 除法运算。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Div)]
|
||||
[[play](https://go.dev/play/p/WLxDdGXXYat)]
|
||||
|
||||
|
||||
<h3 id="netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1086,9 +1251,37 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- **<big>UUIdV4</big>** : 生成 UUID v4 字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#UUIdV4)]
|
||||
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
||||
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为 n 的随机 int 切片。
|
||||
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的随机int切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandUniqueIntSlice)]
|
||||
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||
- **<big>RandSymbolChar</big>** : 生成给定长度的随机符号字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSymbolChar)]
|
||||
[[play](https://go.dev/play/p/Im6ZJxAykOm)]
|
||||
- **<big>RandFloat</big>** : 生成随机float64数字,可以指定范围和精度。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFloat)]
|
||||
[[play](https://go.dev/play/p/zbD_tuobJtr)]
|
||||
- **<big>RandFloats</big>** : 生成随机float64数字切片,可以指定长度,范围和精度.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFloats)]
|
||||
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||
- **<big>RandStringSlice</big>** : 生成随机字符串slice。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandStringSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandBool</big>** : 生成随机bool值(true or false)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBool)]
|
||||
[[play](todo)]
|
||||
- **<big>RandBoolSlice</big>** : 生成特定长度的随机bool slice。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBoolSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandIntSlice</big>** : 生成一个特定长度的随机int切片,数值范围[min, max)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandIntSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandFromGivenSlice</big>** : 从给定切片中随机生成元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFromGivenSlice)]
|
||||
[[play](todo)]
|
||||
- **<big>RandSliceFromGivenSlice</big>** : 从给定切片中生成长度为 num 的随机切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSliceFromGivenSlice)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1107,14 +1300,24 @@ import "github.com/duke-git/lancet/v2/retry"
|
||||
- **<big>RetryFunc</big>** : 重试执行的函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryFunc)]
|
||||
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
||||
- **<big>RetryDuration</big>** : 设置重试间隔时间,默认 3 秒。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryDuration)]
|
||||
[[play](https://go.dev/play/p/nk2XRmagfVF)]
|
||||
- **<big>RetryTimes</big>** : 设置重试次数,默认 5。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryTimes)]
|
||||
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
||||
- **<big>BackoffStrategy</big>** : 定义计算退避间隔的方法的接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#BackoffStrategy)]
|
||||
- **<big>RetryWithCustomBackoff</big>** : 设置自定义退避策略。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryWithCustomBackoff)]
|
||||
[[play](https://go.dev/play/p/jIm_o2vb5Y4)]
|
||||
- **<big>RetryWithLinearBackoff</big>** : 设置线性策略退避。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryWithLinearBackoff)]
|
||||
[[play](https://go.dev/play/p/PDet2ZQZwcB)]
|
||||
- **<big>RetryWithExponentialWithJitterBackoff</big>** : 设置指数策略退避。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryWithExponentialWithJitterBackoff)]
|
||||
[[play](https://go.dev/play/p/xp1avQmn16X)]
|
||||
|
||||
<h3 id="slice"> 18. slice 包含操作切片的方法集合。 [回到目录](#index)
|
||||
|
||||
|
||||
<h3 id="slice"> 18. slice 包含操作切片的方法集合。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
@@ -1158,9 +1361,12 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>DifferenceWith</big>** : 接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#DifferenceWith)]
|
||||
[[play](https://go.dev/play/p/v2U2deugKuV)]
|
||||
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
|
||||
- **<big>DeleteAt</big>** : 删除切片中指定索引到的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#DeleteAt)]
|
||||
[[play](https://go.dev/play/p/pJ-d6MUWcvK)]
|
||||
[[play](https://go.dev/play/p/800B1dPBYyd)]
|
||||
- **<big>DeleteRange</big>** : 删除切片中指定开始索引到结束索引的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#DeleteRange)]
|
||||
[[play](https://go.dev/play/p/945HwiNrnle)]
|
||||
- **<big>Drop</big>** : 从切片头部删除 n 个元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Drop)]
|
||||
[[play](https://go.dev/play/p/jnPO2yQsT8H)]
|
||||
@@ -1212,6 +1418,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ForEach)]
|
||||
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
|
||||
- **<big>ForEachConcurrent</big>** : 对slice并发执行foreach操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ForEachConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>ForEachWithBreak</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数,当 iteratee 函数返回 false 时,终止遍历。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ForEachWithBreak)]
|
||||
[[play](https://go.dev/play/p/qScs39f3D9W)]
|
||||
@@ -1242,6 +1451,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Map</big>** : 对 slice 中的每个元素执行 map 函数以创建一个新切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Map)]
|
||||
[[play](https://go.dev/play/p/biaTefqPquw)]
|
||||
- **<big>MapConcurrent</big>** : 对slice并发执行map操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#MapConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Merge</big>** : 合并多个切片(不会消除重复元素)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Merge)]
|
||||
[[play](https://go.dev/play/p/lbjFp784r9N)]
|
||||
@@ -1257,6 +1469,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>ReduceRight</big>** : 类似 ReduceBy 操作,迭代切片元素顺序从右至左。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ReduceRight)]
|
||||
[[play](https://go.dev/play/p/qT9dZC03A1K)]
|
||||
- **<big>ReduceConcurrent</big>** : 对切片元素执行并发reduce操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ReduceConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Replace)]
|
||||
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
||||
@@ -1308,9 +1523,18 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Unique</big>** : 删除切片中的重复元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Unique)]
|
||||
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
|
||||
- **<big>UniqueBy</big>** : 对切片的每个元素调用 iteratee 函数,然后删除重复元素。
|
||||
- **<big>UniqueBy</big>** : 根据迭代函数返回的值,从输入切片中移除重复元素。此函数保持元素的顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueBy)]
|
||||
[[play](https://go.dev/play/p/UR323iZLDpv)]
|
||||
- **<big>UniqueByComparator</big>** : 使用提供的比较器函数从输入切片中移除重复元素。此函数保持元素的顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByComparator)]
|
||||
[[play](todo)]
|
||||
- **<big>UniqueByField</big>** : 根据struct字段对struct切片去重复。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByField)]
|
||||
[[play](https://go.dev/play/p/6cifcZSPIGu)]
|
||||
- **<big>UniqueByConcurrent</big>** : 并发的从输入切片中移除重复元素,结果保持元素的顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Union</big>** : 合并多个切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Union)]
|
||||
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
|
||||
@@ -1323,12 +1547,32 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Without</big>** : 创建一个不包括所有给定值的切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Without)]
|
||||
[[play](https://go.dev/play/p/bwhEXEypThg)]
|
||||
- **<big>KeyBy</big>** :将切片每个元素调用函数后转为 map。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#KeyBy)]
|
||||
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
||||
- **<big>Join</big>** : 用指定的分隔符链接切片元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Join)]
|
||||
[[play](https://go.dev/play/p/huKzqwNDD7V)]
|
||||
- **<big>Partition</big>** : 根据给定的predicate判断函数分组切片元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Partition)]
|
||||
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
||||
- **<big>Random</big>** : 随机返回切片中元素以及下标, 当切片长度为0时返回下标-1。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Random)]
|
||||
[[play](https://go.dev/play/p/UzpGQptWppw)]
|
||||
- **<big>SetToDefaultIf</big>** : 根据给定给定的predicate判定函数来修改切片中的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#SetToDefaultIf)]
|
||||
[[play](https://go.dev/play/p/9AXGlPRC0-A)]
|
||||
- **<big>Break</big>** : 根据判断函数将切片分成两部分。它开始附加到与函数匹配的第一个元素之后的第二个切片。第一个匹配之后的所有元素都包含在第二个切片中,无论它们是否与函数匹配。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Break)]
|
||||
- **<big>RightPadding</big>** : 在切片的右部添加元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#RightPadding)]
|
||||
[[play](https://go.dev/play/p/0_2rlLEMBXL)]
|
||||
- **<big>LeftPadding</big>** : 在切片的左部添加元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#LeftPadding)]
|
||||
[[play](https://go.dev/play/p/jlQVoelLl2k)]
|
||||
- **<big>Frequency</big>** : 计算切片中每个元素出现的频率。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Frequency)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1356,12 +1600,15 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>Concat</big>** : 创建一个延迟连接 stream,其元素是第一个 stream 的所有元素,后跟第二个 stream 的全部元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#Concat)]
|
||||
[[play](https://go.dev/play/p/HM4OlYk_OUC)]
|
||||
- **<big>Distinct</big>** : 创建并返回一个 stream,用于删除重复的项。
|
||||
- **<big>Distinct</big>** : 创建并返回一个stream,用于删除重复的项。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#Distinct)]
|
||||
[[play](https://go.dev/play/p/eGkOSrm64cB)]
|
||||
- **<big>Filter</big>** : 返回一个通过判定函数的 stream。
|
||||
- **<big>Filter</big>** : 返回一个通过判定函数的stream。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#Filter)]
|
||||
[[play](https://go.dev/play/p/MFlSANo-buc)]
|
||||
- **<big>FilterConcurrent</big>** : 对slice并发执行filter操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#FilterConcurrent)]
|
||||
[[play](todo)]
|
||||
- **<big>Map</big>** : 返回一个 stream,该 stream 由将给定函数应用于源 stream 元素的元素组成。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#Map)]
|
||||
[[play](https://go.dev/play/p/OtNQUImdYko)]
|
||||
@@ -1417,6 +1664,7 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#ToSlice)]
|
||||
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||
|
||||
|
||||
<h3 id="structs"> 20. structs 提供操作 struct, tag, field 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
@@ -1426,31 +1674,33 @@ import "github.com/duke-git/lancet/v2/structs"
|
||||
#### 函数列表:
|
||||
|
||||
- **<big>New</big>** : `Struct`结构体的构造函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/struct.md#New)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#New)]
|
||||
- **<big>ToMap</big>** : 将一个合法的 struct 对象转换为 map[string]any。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/struct.md#ToMap)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#ToMap)]
|
||||
- **<big>Fields</big>** : 获取一个 struct 对象的属性列表。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/struct.md#Fields)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Fields)]
|
||||
- **<big>Field</big>** : 根据属性名获取一个 struct 对象的属性。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/struct.md#Fields)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Fields)]
|
||||
- **<big>IsStruct</big>** : 判断是否为一个合法的 struct 对象。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/struct.md#IsStruct)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsStruct)]
|
||||
- **<big>Tag</big>** : 获取`Field`的`Tag`,默认的 tag key 是 json。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#Tag)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Tag)]
|
||||
- **<big>Name</big>** : 获取属性名。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#Name)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Name)]
|
||||
- **<big>Value</big>** : 获取`Field`属性的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#Value)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Value)]
|
||||
- **<big>Kind</big>** : 获取属性 Kind。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#Kind)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#Kind)]
|
||||
- **<big>IsEmbedded</big>** : 判断属性是否为嵌入。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#IsEmbedded)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsEmbedded)]
|
||||
- **<big>IsExported</big>** : 判断属性是否导出。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#IsExported)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsExported)]
|
||||
- **<big>IsZero</big>** : 判断属性是否为零值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#IsZero)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsZero)]
|
||||
- **<big>IsSlice</big>** : 判断属性是否是切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/structs/field.md#IsSlice)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsSlice)]
|
||||
- **<big>IsTargetType</big>** : 判断属性是否是目标类型。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/struct.md#IsTargetType)]
|
||||
|
||||
<h3 id="strutil"> 21. strutil 包含字符串处理的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1547,6 +1797,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>IsBlank</big>** : 检查字符串是否为空格或空。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#IsBlank)]
|
||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||
- **<big>IsNotBlank</big>** : 检查字符串是否不为空。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#IsNotBlank)]
|
||||
[[play](https://go.dev/play/p/e_oJW0RAquA)]
|
||||
- **<big>HasPrefixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个开头。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#HasPrefixAny)]
|
||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||
@@ -1571,7 +1824,27 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>RemoveWhiteSpace</big>** : 删除字符串中的空格。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#RemoveWhiteSpace)]
|
||||
[[play](https://go.dev/play/p/HzLC9vsTwkf)]
|
||||
|
||||
- **<big>SubInBetween</big>** : 获取字符串中指定的起始字符串start和终止字符串end直接的子字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#SubInBetween)]
|
||||
[[play](https://go.dev/play/p/EDbaRvjeNsv)]
|
||||
- **<big>HammingDistance</big>** : 计算两个字符串之间的汉明距离。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#HammingDistance)]
|
||||
[[play](https://go.dev/play/p/glNdQEA9HUi)]
|
||||
- **<big>Concat</big>** : 拼接字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Concat)]
|
||||
[[play](todo)]
|
||||
- **<big>Ellipsis</big>** : 将字符串截断到指定长度,并在末尾添加省略号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Ellipsis)]
|
||||
[[play](todo)]
|
||||
- **<big>Shuffle</big>** : 打乱给定字符串中的字符顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Shuffle)]
|
||||
[[play](todo)]
|
||||
- **<big>Rotate</big>** : 按指定的字符数旋转字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Rotate)]
|
||||
[[play](todo)]
|
||||
- **<big>TemplateReplace</big>** : 将模板字符串中的占位符替换为map中的相应值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#TemplateReplace)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="system"> 22. system 包含 os, runtime, shell command 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1608,6 +1881,20 @@ import "github.com/duke-git/lancet/v2/system"
|
||||
- **<big>GetOsBits</big>** : 获取当前操作系统位数(32/64)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system#GetOsBits)]
|
||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||
- **<big>StartProcess</big>** :创建进程。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StartProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>StopProcess</big>** : 停止进程。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StopProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>KillProcess</big>** : 杀掉进程。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#KillProcess)]
|
||||
[[play](todo)]
|
||||
- **<big>GetProcessInfo</big>** : 根据进程id获取进程信息。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)]
|
||||
[[play](todo)]
|
||||
|
||||
|
||||
|
||||
<h3 id="tuple"> 23. Tuple 包实现一个元组数据类型。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1833,6 +2120,33 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsPrintable)]
|
||||
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||
- **<big>IsBin</big>** : 检查字符串是否是有效的二进制数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsBin)]
|
||||
[[play](https://go.dev/play/p/ogPeg2XJH4P)]
|
||||
- **<big>IsHex</big>** : 检查字符串是否是有效的十六进制数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsHex)]
|
||||
[[play](https://go.dev/play/p/M2qpHbEwmm7)]
|
||||
- **<big>IsBase64URL</big>** : 检查字符串是否是有效的 base64 url。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsBase64URL)]
|
||||
[[play](https://go.dev/play/p/vhl4mr8GZ6S)]
|
||||
- **<big>IsJWT</big>** : 检查字符串是否是有效的 JSON Web Token (JWT)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsJWT)]
|
||||
[[play](https://go.dev/play/p/R6Op7heJbKI)]
|
||||
- **<big>IsVisa</big>** : 检查字符串是否是有效的 visa 卡号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsVisa)]
|
||||
[[play](https://go.dev/play/p/SdS2keOyJsl)]
|
||||
- **<big>IsMasterCard</big>** : 检查字符串是否是有效的 MasterCard 卡号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsMasterCard)]
|
||||
[[play](https://go.dev/play/p/CwWBFRrG27b)]
|
||||
- **<big>IsAmericanExpress</big>** : 检查字符串是否是有效的 American Express 卡号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsAmericanExpress)]
|
||||
[[play](https://go.dev/play/p/HIDFpcOdpkd)]
|
||||
- **<big>IsUnionPay</big>** : 检查字符串是否是有效的美国银联卡号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsUnionPay)]
|
||||
[[play](https://go.dev/play/p/CUHPEwEITDf)]
|
||||
- **<big>IsChinaUnionPay</big>** : 检查字符串是否是有效的中国银联卡号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsChinaUnionPay)]
|
||||
[[play](https://go.dev/play/p/yafpdxLiymu)]
|
||||
|
||||
<h3 id="xerror"> 25. xerror 包实现一些错误处理函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -1855,7 +2169,7 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Wrap)]
|
||||
[[play](https://go.dev/play/p/RpjJ5u5sc97)]
|
||||
- **<big>XError_Unwrap</big>** : 解构 XEerror 为 error 对象。适配 github.com/pkg/errors。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Unwrap)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Unwrap)
|
||||
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
|
||||
- **<big>XError_With</big>** : 添加与 XError 对象的键和值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_With)]
|
||||
@@ -1884,22 +2198,7 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
|
||||
## 如何贡献代码
|
||||
|
||||
#### [贡献代码指南](./CONTRIBUTING.zh-CN.md)
|
||||
|
||||
## 赞助
|
||||
|
||||
您好,我是一名软件开发者,从事开发工作 13 年。热爱软件开源。并愿意为此付出精力。是开源项目lancet的作者。Lancet 自两年前开源发布以来,已有超过 1000 个内外部项目使用。lancet一直会对所有用户免费。您的支持是对我继续奋斗的有力鼓励。谢谢! 微信扫描以下二维码或点击以下赞助按钮发起赞助。
|
||||
|
||||
<div style="position: relative;display: inline-block;">
|
||||
<img src="./docs/public/wechat_pay.png" width="260" height="260"/>
|
||||
<a href="https://liberapay.com/Duke_Du/donate" target="\_blank"><img src="./docs/public/sponsor_btn.png" width="220" height="60"/></a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
*捐赠的资金将用于后续lancet官网的维护和云服务器的费用支付。或者当我写代码困倦时,给我买杯 ☕️。*
|
||||
|
||||
#### [代码贡献指南](./CONTRIBUTION.zh-CN.md)
|
||||
|
||||
## 贡献者
|
||||
|
||||
@@ -1908,3 +2207,7 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
<a href="https://github.com/duke-git/lancet/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=duke-git/lancet" />
|
||||
</a>
|
||||
|
||||
## GitHub Stars
|
||||
|
||||
[](https://star-history.com/#duke-git/lancet&Date)
|
||||
@@ -4,7 +4,7 @@
|
||||
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph.
|
||||
package algorithm
|
||||
|
||||
import "github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
import "github.com/duke-git/lancet/v2/constraints"
|
||||
|
||||
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
|
||||
|
||||
@@ -23,7 +23,7 @@ func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int {
|
||||
// BinarySearch return the index of target within a sorted slice, use binary search (recursive call itself).
|
||||
// If not found return -1.
|
||||
// Play: https://go.dev/play/p/t6MeGiUSN47
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int {
|
||||
if highIndex < lowIndex || len(sortedSlice) == 0 {
|
||||
return -1
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, com
|
||||
// BinaryIterativeSearch return the index of target within a sorted slice, use binary search (no recursive).
|
||||
// If not found return -1.
|
||||
// Play: https://go.dev/play/p/Anozfr8ZLH3
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int {
|
||||
startIndex := lowIndex
|
||||
endIndex := highIndex
|
||||
|
||||
|
||||
@@ -3,24 +3,29 @@
|
||||
|
||||
package algorithm
|
||||
|
||||
import "github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
import "github.com/duke-git/lancet/v2/constraints"
|
||||
|
||||
// BubbleSort applys the bubble sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/GNdv7Jg2Taj
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func BubbleSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
breakTag := false
|
||||
for j := 0; j < len(slice)-1-i; j++ {
|
||||
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
|
||||
if isCurrGreatThanNext {
|
||||
swap(slice, j, j+1)
|
||||
breakTag = true
|
||||
}
|
||||
}
|
||||
if !breakTag {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// InsertionSort applys the insertion sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/G5LJiWgJJW6
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func InsertionSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
for j := i; j > 0; j-- {
|
||||
isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1
|
||||
@@ -35,7 +40,7 @@ func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
|
||||
// SelectionSort applys the selection sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/oXovbkekayS
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func SelectionSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
min := i
|
||||
for j := i + 1; j < len(slice); j++ {
|
||||
@@ -49,7 +54,7 @@ func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
|
||||
// ShellSort applys the shell sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/3ibkszpJEu3
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func ShellSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
size := len(slice)
|
||||
|
||||
gap := 1
|
||||
@@ -69,11 +74,11 @@ func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
|
||||
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1.
|
||||
// Play: https://go.dev/play/p/7Y7c1Elk3ax
|
||||
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func QuickSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
quickSort(slice, 0, len(slice)-1, comparator)
|
||||
}
|
||||
|
||||
func quickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
func quickSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
|
||||
if lowIndex < highIndex {
|
||||
p := partition(slice, lowIndex, highIndex, comparator)
|
||||
quickSort(slice, lowIndex, p-1, comparator)
|
||||
@@ -82,7 +87,7 @@ func quickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
|
||||
}
|
||||
|
||||
// partition split slice into two parts
|
||||
func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
|
||||
func partition[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) int {
|
||||
p := slice[highIndex]
|
||||
i := lowIndex
|
||||
for j := lowIndex; j < highIndex; j++ {
|
||||
@@ -99,7 +104,7 @@ func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
|
||||
|
||||
// HeapSort applys the heap sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/u6Iwa1VZS_f
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func HeapSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
size := len(slice)
|
||||
|
||||
for i := size/2 - 1; i >= 0; i-- {
|
||||
@@ -111,7 +116,7 @@ func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
}
|
||||
}
|
||||
|
||||
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
func sift[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
|
||||
i := lowIndex
|
||||
j := 2*i + 1
|
||||
|
||||
@@ -133,11 +138,11 @@ func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraint
|
||||
|
||||
// MergeSort applys the merge sort algorithm to sort the collection, will change the original collection data.
|
||||
// Play: https://go.dev/play/p/ydinn9YzUJn
|
||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) {
|
||||
func MergeSort[T any](slice []T, comparator constraints.Comparator) {
|
||||
mergeSort(slice, 0, len(slice)-1, comparator)
|
||||
}
|
||||
|
||||
func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
|
||||
if lowIndex < highIndex {
|
||||
mid := (lowIndex + highIndex) / 2
|
||||
mergeSort(slice, lowIndex, mid, comparator)
|
||||
@@ -146,7 +151,7 @@ func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
|
||||
}
|
||||
}
|
||||
|
||||
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) {
|
||||
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator constraints.Comparator) {
|
||||
i := lowIndex
|
||||
j := midIndex + 1
|
||||
temp := []T{}
|
||||
@@ -175,7 +180,7 @@ func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lance
|
||||
|
||||
// CountSort applys the count sort algorithm to sort the collection, don't change the original collection data.
|
||||
// Play: https://go.dev/play/p/tB-Umgm0DrP
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
|
||||
func CountSort[T any](slice []T, comparator constraints.Comparator) []T {
|
||||
size := len(slice)
|
||||
out := make([]T, size)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ type people struct {
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/v2/lancetconstraints/constraints.go/Comparator
|
||||
// Compare implements github.com/duke-git/lancet/v2/constraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
|
||||
@@ -70,7 +70,7 @@ func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind)
|
||||
|
||||
switch operator {
|
||||
case equal:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) == 0 {
|
||||
if bytes.Equal(bytesObj1, bytesObj2) {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package compare
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -11,6 +12,7 @@ func TestEqual(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
// basic type
|
||||
assert.Equal(true, Equal(1, 1))
|
||||
assert.Equal(true, Equal(int64(1), int64(1)))
|
||||
assert.Equal(true, Equal("a", "a"))
|
||||
@@ -25,6 +27,7 @@ func TestEqual(t *testing.T) {
|
||||
assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3}))
|
||||
assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}))
|
||||
|
||||
// time
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
time3 := time1.Add(time.Second)
|
||||
@@ -32,6 +35,7 @@ func TestEqual(t *testing.T) {
|
||||
assert.Equal(false, Equal(time1, time2))
|
||||
assert.Equal(true, Equal(time2, time3))
|
||||
|
||||
// struct
|
||||
st1 := struct {
|
||||
A string
|
||||
B string
|
||||
@@ -58,6 +62,19 @@ func TestEqual(t *testing.T) {
|
||||
|
||||
assert.Equal(true, Equal(st1, st2))
|
||||
assert.Equal(false, Equal(st1, st3))
|
||||
|
||||
//byte slice
|
||||
bs1 := []byte("hello")
|
||||
bs2 := []byte("hello")
|
||||
assert.Equal(true, Equal(bs1, bs2))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, Equal(jsonNumber1, jsonNumber2))
|
||||
|
||||
}
|
||||
|
||||
func TestEqualValue(t *testing.T) {
|
||||
@@ -69,6 +86,13 @@ func TestEqualValue(t *testing.T) {
|
||||
assert.Equal(true, EqualValue(1, "1"))
|
||||
|
||||
assert.Equal(false, EqualValue(1, "2"))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, EqualValue(jsonNumber1, 123))
|
||||
}
|
||||
|
||||
func TestLessThan(t *testing.T) {
|
||||
@@ -85,6 +109,17 @@ func TestLessThan(t *testing.T) {
|
||||
|
||||
assert.Equal(false, LessThan(1, 1))
|
||||
assert.Equal(false, LessThan(1, int64(1)))
|
||||
|
||||
bs1 := []byte("hello1")
|
||||
bs2 := []byte("hello2")
|
||||
assert.Equal(true, LessThan(bs1, bs2))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`124`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, LessThan(jsonNumber1, jsonNumber2))
|
||||
}
|
||||
|
||||
func TestGreaterThan(t *testing.T) {
|
||||
@@ -102,6 +137,17 @@ func TestGreaterThan(t *testing.T) {
|
||||
assert.Equal(false, GreaterThan(1, 2))
|
||||
assert.Equal(false, GreaterThan(int64(2), 1))
|
||||
assert.Equal(false, GreaterThan("b", "c"))
|
||||
|
||||
bs1 := []byte("hello1")
|
||||
bs2 := []byte("hello2")
|
||||
assert.Equal(true, GreaterThan(bs2, bs1))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`124`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, GreaterThan(jsonNumber2, jsonNumber1))
|
||||
}
|
||||
|
||||
func TestLessOrEqual(t *testing.T) {
|
||||
@@ -119,6 +165,17 @@ func TestLessOrEqual(t *testing.T) {
|
||||
|
||||
assert.Equal(false, LessOrEqual(2, 1))
|
||||
assert.Equal(false, LessOrEqual(1, int64(2)))
|
||||
|
||||
bs1 := []byte("hello1")
|
||||
bs2 := []byte("hello2")
|
||||
assert.Equal(true, LessOrEqual(bs1, bs2))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`124`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, LessOrEqual(jsonNumber1, jsonNumber2))
|
||||
}
|
||||
|
||||
func TestGreaterOrEqual(t *testing.T) {
|
||||
@@ -137,6 +194,17 @@ func TestGreaterOrEqual(t *testing.T) {
|
||||
assert.Equal(false, GreaterOrEqual(1, 2))
|
||||
assert.Equal(false, GreaterOrEqual(int64(2), 1))
|
||||
assert.Equal(false, GreaterOrEqual("b", "c"))
|
||||
|
||||
bs1 := []byte("hello1")
|
||||
bs2 := []byte("hello2")
|
||||
assert.Equal(true, GreaterOrEqual(bs2, bs1))
|
||||
|
||||
// json.Number
|
||||
var jsonNumber1, jsonNumber2 json.Number
|
||||
json.Unmarshal([]byte(`123`), &jsonNumber1)
|
||||
json.Unmarshal([]byte(`124`), &jsonNumber2)
|
||||
|
||||
assert.Equal(true, GreaterOrEqual(jsonNumber2, jsonNumber1))
|
||||
}
|
||||
|
||||
func TestInDelta(t *testing.T) {
|
||||
|
||||
@@ -49,9 +49,7 @@ func Or[T, U any](a T, b U) bool {
|
||||
// Xor returns true if a or b but not both is truthy.
|
||||
// Play: https://go.dev/play/p/gObZrW7ZbG8
|
||||
func Xor[T, U any](a T, b U) bool {
|
||||
valA := Bool(a)
|
||||
valB := Bool(b)
|
||||
return (valA || valB) && valA != valB
|
||||
return Bool(a) != Bool(b)
|
||||
}
|
||||
|
||||
// Nor returns true if neither a nor b is truthy.
|
||||
@@ -63,9 +61,7 @@ func Nor[T, U any](a T, b U) bool {
|
||||
// Xnor returns true if both a and b or neither a nor b are truthy.
|
||||
// Play: https://go.dev/play/p/OuDB9g51643
|
||||
func Xnor[T, U any](a T, b U) bool {
|
||||
valA := Bool(a)
|
||||
valB := Bool(b)
|
||||
return (valA && valB) || (!valA && !valB)
|
||||
return Bool(a) == Bool(b)
|
||||
}
|
||||
|
||||
// Nand returns false if both a and b are truthy.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package lancetconstraints contain some comstomer constraints.
|
||||
package lancetconstraints
|
||||
// Package constraints contain some custom interface.
|
||||
package constraints
|
||||
|
||||
// Comparator is for comparing two values
|
||||
type Comparator interface {
|
||||
@@ -6,6 +6,7 @@ package convertor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
@@ -394,3 +395,91 @@ func GbkToUtf8(bs []byte) ([]byte, error) {
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// ToStdBase64 convert data to standard base64 encoding.
|
||||
// Play: https://go.dev/play/p/_fLJqJD3NMo
|
||||
func ToStdBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
case []byte:
|
||||
return base64.StdEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
return base64.StdEncoding.EncodeToString([]byte(value.(string)))
|
||||
case error:
|
||||
return base64.StdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(marshal)
|
||||
}
|
||||
}
|
||||
|
||||
// ToUrlBase64 convert data to URL base64 encoding.
|
||||
// Play: https://go.dev/play/p/C_d0GlvEeUR
|
||||
func ToUrlBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
case []byte:
|
||||
return base64.URLEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
return base64.URLEncoding.EncodeToString([]byte(value.(string)))
|
||||
case error:
|
||||
return base64.URLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(marshal)
|
||||
}
|
||||
}
|
||||
|
||||
// ToRawStdBase64 convert data to raw standard base64 encoding.
|
||||
// Play: https://go.dev/play/p/wSAr3sfkDcv
|
||||
func ToRawStdBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
case []byte:
|
||||
return base64.RawStdEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
return base64.RawStdEncoding.EncodeToString([]byte(value.(string)))
|
||||
case error:
|
||||
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return base64.RawStdEncoding.EncodeToString(marshal)
|
||||
}
|
||||
}
|
||||
|
||||
// ToRawUrlBase64 convert data to raw URL base64 encoding.
|
||||
// Play: https://go.dev/play/p/HwdDPFcza1O
|
||||
func ToRawUrlBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
case []byte:
|
||||
return base64.RawURLEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
return base64.RawURLEncoding.EncodeToString([]byte(value.(string)))
|
||||
case error:
|
||||
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return base64.RawURLEncoding.EncodeToString(marshal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package convertor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -391,3 +392,182 @@ func ExampleGbkToUtf8() {
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleToStdBase64() {
|
||||
// if you want to see the result, please use 'base64.StdEncoding.DecodeString()' to decode the result
|
||||
|
||||
afterEncode := ToStdBase64(nil)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = ToStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = ToStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = ToStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = ToStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = ToStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = ToStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = ToStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
//
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
func ExampleToUrlBase64() {
|
||||
// if you want to see the result, please use 'base64.URLEncoding.DecodeString()' to decode the result
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode := ToUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = ToUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = ToUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = ToUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = ToUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = ToUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = ToUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
func ExampleToRawStdBase64() {
|
||||
// if you want to see the result, please use 'base64.RawStdEncoding.DecodeString()' to decode the result
|
||||
stringVal := "hello"
|
||||
afterEncode := ToRawStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = ToRawStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = ToRawStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = ToRawStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = ToRawStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = ToRawStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = ToRawStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
func ExampleToRawUrlBase64() {
|
||||
// if you want to see the result, please use 'base64.RawURLEncoding.DecodeString()' to decode the result
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode := ToRawUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = ToRawUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = ToRawUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = ToRawUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = ToRawUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = ToRawUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = ToRawUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package convertor
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
@@ -461,3 +465,279 @@ func TestGbkToUtf8(t *testing.T) {
|
||||
assert.Equal(true, utf8.Valid(utf8Data))
|
||||
assert.Equal("hello", string(utf8Data))
|
||||
}
|
||||
|
||||
func TestToStdBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestToStdBase64")
|
||||
|
||||
r1 := ToStdBase64("abc")
|
||||
d1, _ := base64.StdEncoding.DecodeString(r1)
|
||||
assert.Equal("abc", string(d1))
|
||||
|
||||
r2 := ToStdBase64([]byte("abc"))
|
||||
d2, _ := base64.StdEncoding.DecodeString(r2)
|
||||
assert.Equal("abc", string(d2))
|
||||
|
||||
r3 := ToStdBase64(123)
|
||||
d3, _ := base64.StdEncoding.DecodeString(r3)
|
||||
assert.Equal("123", string(d3))
|
||||
|
||||
r4 := ToStdBase64(11.11)
|
||||
d4, _ := base64.StdEncoding.DecodeString(r4)
|
||||
assert.Equal("11.11", string(d4))
|
||||
|
||||
r5 := ToStdBase64(map[string]any{"name": "duke", "quantity": 1})
|
||||
d5, _ := base64.StdEncoding.DecodeString(r5)
|
||||
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||
|
||||
r6 := ToStdBase64([]int64{7, 5, 9, 4, 23})
|
||||
d6, _ := base64.StdEncoding.DecodeString(r6)
|
||||
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||
|
||||
r7 := ToStdBase64([]string{"7", "5", "9", "4", "23"})
|
||||
d7, _ := base64.StdEncoding.DecodeString(r7)
|
||||
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||
|
||||
r8 := ToStdBase64(nil)
|
||||
d8, _ := base64.StdEncoding.DecodeString(r8)
|
||||
assert.Equal("", string(d8))
|
||||
|
||||
ch := make(chan int, 3)
|
||||
ch <- 1
|
||||
ch <- 2
|
||||
r9 := ToStdBase64(ch)
|
||||
d9, _ := base64.StdEncoding.DecodeString(r9)
|
||||
assert.Equal("", string(d9))
|
||||
|
||||
r10 := ToStdBase64(io.EOF)
|
||||
d10, _ := base64.StdEncoding.DecodeString(r10)
|
||||
assert.Equal("EOF", string(d10))
|
||||
|
||||
r11 := ToStdBase64(errors.New("test"))
|
||||
d11, _ := base64.StdEncoding.DecodeString(r11)
|
||||
assert.Equal("test", string(d11))
|
||||
|
||||
typedNil := (*int)(nil)
|
||||
r12 := ToStdBase64(typedNil)
|
||||
d12, _ := base64.StdEncoding.DecodeString(r12)
|
||||
assert.Equal("", string(d12))
|
||||
|
||||
type nilInterface interface {
|
||||
}
|
||||
var nI nilInterface = nil
|
||||
d13, _ := base64.StdEncoding.DecodeString(ToStdBase64(nI))
|
||||
assert.Equal("", string(d13))
|
||||
|
||||
var p unsafe.Pointer
|
||||
d14, _ := base64.StdEncoding.DecodeString(ToStdBase64(p))
|
||||
assert.Equal("", string(d14))
|
||||
}
|
||||
|
||||
func TestToUrlBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestToUrlBase64")
|
||||
|
||||
r1 := ToUrlBase64("abc")
|
||||
d1, _ := base64.URLEncoding.DecodeString(r1)
|
||||
assert.Equal("abc", string(d1))
|
||||
|
||||
r2 := ToUrlBase64([]byte("abc"))
|
||||
d2, _ := base64.URLEncoding.DecodeString(r2)
|
||||
assert.Equal("abc", string(d2))
|
||||
|
||||
r3 := ToUrlBase64(123)
|
||||
d3, _ := base64.URLEncoding.DecodeString(r3)
|
||||
assert.Equal("123", string(d3))
|
||||
|
||||
r4 := ToUrlBase64(11.11)
|
||||
d4, _ := base64.URLEncoding.DecodeString(r4)
|
||||
assert.Equal("11.11", string(d4))
|
||||
|
||||
r5 := ToUrlBase64(map[string]any{"name": "duke", "quantity": 1})
|
||||
d5, _ := base64.URLEncoding.DecodeString(r5)
|
||||
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||
|
||||
r6 := ToUrlBase64([]int64{7, 5, 9, 4, 23})
|
||||
d6, _ := base64.URLEncoding.DecodeString(r6)
|
||||
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||
|
||||
r7 := ToUrlBase64([]string{"7", "5", "9", "4", "23"})
|
||||
d7, _ := base64.URLEncoding.DecodeString(r7)
|
||||
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||
|
||||
r8 := ToUrlBase64(nil)
|
||||
d8, _ := base64.URLEncoding.DecodeString(r8)
|
||||
assert.Equal("", string(d8))
|
||||
|
||||
ch := make(chan int, 3)
|
||||
ch <- 1
|
||||
ch <- 2
|
||||
r9 := ToUrlBase64(ch)
|
||||
d9, _ := base64.URLEncoding.DecodeString(r9)
|
||||
assert.Equal("", string(d9))
|
||||
|
||||
r10 := ToUrlBase64(io.EOF)
|
||||
d10, _ := base64.URLEncoding.DecodeString(r10)
|
||||
assert.Equal("EOF", string(d10))
|
||||
|
||||
r11 := ToUrlBase64(errors.New("test"))
|
||||
d11, _ := base64.URLEncoding.DecodeString(r11)
|
||||
assert.Equal("test", string(d11))
|
||||
|
||||
typedNil := (*int)(nil)
|
||||
r12 := ToUrlBase64(typedNil)
|
||||
d12, _ := base64.URLEncoding.DecodeString(r12)
|
||||
assert.Equal("", string(d12))
|
||||
|
||||
type nilInterface interface {
|
||||
}
|
||||
var nI nilInterface = nil
|
||||
d13, _ := base64.URLEncoding.DecodeString(ToUrlBase64(nI))
|
||||
assert.Equal("", string(d13))
|
||||
|
||||
var p unsafe.Pointer
|
||||
d14, _ := base64.URLEncoding.DecodeString(ToUrlBase64(p))
|
||||
assert.Equal("", string(d14))
|
||||
|
||||
r15 := ToUrlBase64("4+3/4?=")
|
||||
d15, _ := base64.URLEncoding.DecodeString(r15)
|
||||
assert.Equal("4+3/4?=", string(d15))
|
||||
}
|
||||
|
||||
func TestToRawStdBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestToRawStdBase64")
|
||||
|
||||
r1 := ToRawStdBase64("abc")
|
||||
d1, _ := base64.RawStdEncoding.DecodeString(r1)
|
||||
assert.Equal("abc", string(d1))
|
||||
|
||||
r2 := ToRawStdBase64([]byte("abc"))
|
||||
d2, _ := base64.RawStdEncoding.DecodeString(r2)
|
||||
assert.Equal("abc", string(d2))
|
||||
|
||||
r3 := ToRawStdBase64(123)
|
||||
d3, _ := base64.RawStdEncoding.DecodeString(r3)
|
||||
assert.Equal("123", string(d3))
|
||||
|
||||
r4 := ToRawStdBase64(11.11)
|
||||
d4, _ := base64.RawStdEncoding.DecodeString(r4)
|
||||
assert.Equal("11.11", string(d4))
|
||||
|
||||
r5 := ToRawStdBase64(map[string]any{"name": "duke", "quantity": 1})
|
||||
d5, _ := base64.RawStdEncoding.DecodeString(r5)
|
||||
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||
|
||||
r6 := ToRawStdBase64([]int64{7, 5, 9, 4, 23})
|
||||
d6, _ := base64.RawStdEncoding.DecodeString(r6)
|
||||
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||
|
||||
r7 := ToRawStdBase64([]string{"7", "5", "9", "4", "23"})
|
||||
d7, _ := base64.RawStdEncoding.DecodeString(r7)
|
||||
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||
|
||||
r8 := ToRawStdBase64(nil)
|
||||
d8, _ := base64.RawStdEncoding.DecodeString(r8)
|
||||
assert.Equal("", string(d8))
|
||||
|
||||
ch := make(chan int, 3)
|
||||
ch <- 1
|
||||
ch <- 2
|
||||
r9 := ToRawStdBase64(ch)
|
||||
d9, _ := base64.RawStdEncoding.DecodeString(r9)
|
||||
assert.Equal("", string(d9))
|
||||
|
||||
r10 := ToRawStdBase64(io.EOF)
|
||||
d10, _ := base64.RawStdEncoding.DecodeString(r10)
|
||||
assert.Equal("EOF", string(d10))
|
||||
|
||||
r11 := ToRawStdBase64(errors.New("test"))
|
||||
d11, _ := base64.RawStdEncoding.DecodeString(r11)
|
||||
assert.Equal("test", string(d11))
|
||||
|
||||
typedNil := (*int)(nil)
|
||||
r12 := ToRawStdBase64(typedNil)
|
||||
d12, _ := base64.RawStdEncoding.DecodeString(r12)
|
||||
assert.Equal("", string(d12))
|
||||
|
||||
type nilInterface interface {
|
||||
}
|
||||
var nI nilInterface = nil
|
||||
d13, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(nI))
|
||||
assert.Equal("", string(d13))
|
||||
|
||||
var p unsafe.Pointer
|
||||
d14, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(p))
|
||||
assert.Equal("", string(d14))
|
||||
}
|
||||
|
||||
func TestToRawUrlBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestToRawUrlBase64")
|
||||
|
||||
r1 := ToRawUrlBase64("abc")
|
||||
d1, _ := base64.RawURLEncoding.DecodeString(r1)
|
||||
assert.Equal("abc", string(d1))
|
||||
|
||||
r2 := ToRawUrlBase64([]byte("abc"))
|
||||
d2, _ := base64.RawURLEncoding.DecodeString(r2)
|
||||
assert.Equal("abc", string(d2))
|
||||
|
||||
r3 := ToRawUrlBase64(123)
|
||||
d3, _ := base64.RawURLEncoding.DecodeString(r3)
|
||||
assert.Equal("123", string(d3))
|
||||
|
||||
r4 := ToRawUrlBase64(11.11)
|
||||
d4, _ := base64.RawURLEncoding.DecodeString(r4)
|
||||
assert.Equal("11.11", string(d4))
|
||||
|
||||
r5 := ToRawUrlBase64(map[string]any{"name": "duke", "quantity": 1})
|
||||
d5, _ := base64.RawURLEncoding.DecodeString(r5)
|
||||
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
|
||||
|
||||
r6 := ToRawUrlBase64([]int64{7, 5, 9, 4, 23})
|
||||
d6, _ := base64.RawURLEncoding.DecodeString(r6)
|
||||
assert.Equal("[7,5,9,4,23]", string(d6))
|
||||
|
||||
r7 := ToRawUrlBase64([]string{"7", "5", "9", "4", "23"})
|
||||
d7, _ := base64.RawURLEncoding.DecodeString(r7)
|
||||
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
|
||||
|
||||
r8 := ToRawUrlBase64(nil)
|
||||
d8, _ := base64.RawURLEncoding.DecodeString(r8)
|
||||
assert.Equal("", string(d8))
|
||||
|
||||
ch := make(chan int, 3)
|
||||
ch <- 1
|
||||
ch <- 2
|
||||
r9 := ToRawUrlBase64(ch)
|
||||
d9, _ := base64.RawURLEncoding.DecodeString(r9)
|
||||
assert.Equal("", string(d9))
|
||||
|
||||
r10 := ToRawUrlBase64(io.EOF)
|
||||
d10, _ := base64.RawURLEncoding.DecodeString(r10)
|
||||
assert.Equal("EOF", string(d10))
|
||||
|
||||
r11 := ToRawUrlBase64(errors.New("test"))
|
||||
d11, _ := base64.RawURLEncoding.DecodeString(r11)
|
||||
assert.Equal("test", string(d11))
|
||||
|
||||
typedNil := (*int)(nil)
|
||||
r12 := ToRawUrlBase64(typedNil)
|
||||
d12, _ := base64.RawURLEncoding.DecodeString(r12)
|
||||
assert.Equal("", string(d12))
|
||||
|
||||
type nilInterface interface {
|
||||
}
|
||||
var nI nilInterface = nil
|
||||
d13, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(nI))
|
||||
assert.Equal("", string(d13))
|
||||
|
||||
var p unsafe.Pointer
|
||||
d14, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(p))
|
||||
assert.Equal("", string(d14))
|
||||
|
||||
r15 := ToRawUrlBase64("4+3/4?=")
|
||||
d15, _ := base64.RawURLEncoding.DecodeString(r15)
|
||||
assert.Equal("4+3/4?=", string(d15))
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"crypto/des"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
@@ -75,6 +76,11 @@ func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/IOq_g8_lKZD
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, _ := aes.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
@@ -94,6 +100,11 @@ func AesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/IOq_g8_lKZD
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
@@ -110,6 +121,11 @@ func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/SpaZO0-5Nsp
|
||||
func AesCtrCrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
@@ -125,6 +141,11 @@ func AesCtrCrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/tfkF10B13kH
|
||||
func AesCfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -147,6 +168,11 @@ func AesCfbEncrypt(data, key []byte) []byte {
|
||||
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/tfkF10B13kH
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
if len(encrypted) < aes.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
}
|
||||
@@ -166,6 +192,11 @@ func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/VtHxtkUj-3F
|
||||
func AesOfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -188,6 +219,11 @@ func AesOfbEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/VtHxtkUj-3F
|
||||
func AesOfbDecrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -208,6 +244,56 @@ func AesOfbDecrypt(data, key []byte) []byte {
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// AesGcmEncrypt encrypt data with key use AES GCM algorithm
|
||||
// Play: todo
|
||||
func AesGcmEncrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ciphertext := gcm.Seal(nonce, nonce, data, nil)
|
||||
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
// AesGcmDecrypt decrypt data with key use AES GCM algorithm
|
||||
// Play: todo
|
||||
func AesGcmDecrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
nonceSize := gcm.NonceSize()
|
||||
if len(data) < nonceSize {
|
||||
panic("ciphertext too short")
|
||||
}
|
||||
|
||||
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
|
||||
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return plaintext
|
||||
}
|
||||
|
||||
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/8qivmPeZy4P
|
||||
@@ -254,6 +340,11 @@ func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/4cC4QvWfe3_1
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
@@ -274,6 +365,11 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/4cC4QvWfe3_1
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := encrypted[:des.BlockSize]
|
||||
@@ -290,6 +386,11 @@ func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/9-T6OjKpcdw
|
||||
func DesCtrCrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
@@ -305,6 +406,11 @@ func DesCtrCrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/y-eNxcFBlxL
|
||||
func DesCfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -326,6 +432,11 @@ func DesCfbEncrypt(data, key []byte) []byte {
|
||||
// len(encrypted) should be great than 16, len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/y-eNxcFBlxL
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
if len(encrypted) < des.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
@@ -340,9 +451,14 @@ func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
}
|
||||
|
||||
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/74KmNadjN1J
|
||||
func DesOfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -364,6 +480,11 @@ func DesOfbEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/74KmNadjN1J
|
||||
func DesOfbDecrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
}
|
||||
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -505,3 +626,32 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
||||
}
|
||||
return plainText
|
||||
}
|
||||
|
||||
// GenerateRsaKeyPair create rsa private and public key.
|
||||
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey) {
|
||||
privateKey, _ := rsa.GenerateKey(rand.Reader, keySize)
|
||||
return privateKey, &privateKey.PublicKey
|
||||
}
|
||||
|
||||
// RsaEncryptOAEP encrypts the given data with RSA-OAEP.
|
||||
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error) {
|
||||
encryptedBytes, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &key, data, label)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return encryptedBytes, nil
|
||||
}
|
||||
|
||||
// RsaDecryptOAEP decrypts the data with RSA-OAEP.
|
||||
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error) {
|
||||
decryptedBytes, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, ciphertext, label)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return decryptedBytes, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package cryptor
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func ExampleAesEcbEncrypt() {
|
||||
data := "hello"
|
||||
@@ -127,6 +129,34 @@ func ExampleAesOfbDecrypt() {
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleAesGcmEncrypt() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := AesGcmEncrypt([]byte(data), []byte(key))
|
||||
|
||||
decrypted := AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleAesGcmDecrypt() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := AesGcmEncrypt([]byte(data), []byte(key))
|
||||
|
||||
decrypted := AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleDesEcbEncrypt() {
|
||||
data := "hello"
|
||||
key := "abcdefgh"
|
||||
@@ -484,3 +514,25 @@ func ExampleSha512WithBase64() {
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
|
||||
func ExampleRsaEncryptOAEP() {
|
||||
pri, pub := GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := RsaEncryptOAEP(data, label, *pub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decrypted, err := RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
|
||||
@@ -150,3 +150,35 @@ func TestRsaEncrypt(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
assert.Equal(string(data), string(decrypted))
|
||||
}
|
||||
|
||||
func TestRsaEncryptOAEP(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
t.Parallel()
|
||||
|
||||
pri, pub := GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := RsaEncryptOAEP(data, label, *pub)
|
||||
assert.IsNil(err)
|
||||
|
||||
decrypted, err := RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal("hello world", string(decrypted))
|
||||
}
|
||||
|
||||
func TestAesGcmEncrypt(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := AesGcmEncrypt([]byte(data), []byte(key))
|
||||
decrypted := AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesGcmEncrypt")
|
||||
assert.Equal(data, string(decrypted))
|
||||
}
|
||||
|
||||
@@ -123,6 +123,25 @@ func (hm *HashMap) Iterate(iteratee func(key, value any)) {
|
||||
}
|
||||
}
|
||||
|
||||
// FilterByValue returns a filtered HashMap.
|
||||
// If any value is not matching the perdicate function then it returns nil
|
||||
// otherwise it returns the HashMap with selected values.
|
||||
func (hm *HashMap) FilterByValue(perdicate func(value any) bool) *HashMap {
|
||||
var filteredHM *HashMap
|
||||
if hm.size > 0 {
|
||||
for i := 0; i < len(hm.table); i++ {
|
||||
item := hm.table[i]
|
||||
if item != nil && perdicate(item.value) {
|
||||
if filteredHM == nil {
|
||||
filteredHM = NewHashMap()
|
||||
}
|
||||
filteredHM.Put(item.key, item.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredHM
|
||||
}
|
||||
|
||||
// Keys returns a slice of the hashmap's keys (random order)
|
||||
func (hm *HashMap) Keys() []any {
|
||||
keys := make([]any, int(hm.size))
|
||||
@@ -168,6 +187,11 @@ func (hm *HashMap) resize() {
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns current size of Hashmap
|
||||
func (hm *HashMap) Size() uint64 {
|
||||
return hm.size
|
||||
}
|
||||
|
||||
func (hm *HashMap) hash(key any) uint64 {
|
||||
h := fnv.New64a()
|
||||
_, _ = h.Write([]byte(fmt.Sprintf("%v", key)))
|
||||
|
||||
@@ -105,3 +105,24 @@ func TestHashMap_GetOrDefault(t *testing.T) {
|
||||
assert.Equal(1, hm.GetOrDefault("a", 5))
|
||||
assert.Equal(5, hm.GetOrDefault("d", 5))
|
||||
}
|
||||
|
||||
func TestHashMap_FilterByValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_FilterByValue")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
hm.Put("d", 4)
|
||||
hm.Put("e", 5)
|
||||
hm.Put("f", 6)
|
||||
|
||||
filteredHM := hm.FilterByValue(func(value any) bool {
|
||||
return value.(int) == 1 || value.(int) == 3
|
||||
})
|
||||
|
||||
assert.Equal(uint64(2), filteredHM.Size())
|
||||
}
|
||||
|
||||
@@ -7,18 +7,18 @@ package datastructure
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
"github.com/duke-git/lancet/v2/constraints"
|
||||
)
|
||||
|
||||
// MaxHeap implements a binary max heap
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
// type T should implements Compare function in constraints.Comparator interface.
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
|
||||
// NewMaxHeap returns a MaxHeap instance with the given comparator.
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
func NewMaxHeap[T any](comparator constraints.Comparator) *MaxHeap[T] {
|
||||
return &MaxHeap[T]{
|
||||
data: make([]T, 0),
|
||||
comparator: comparator,
|
||||
@@ -26,7 +26,7 @@ func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
}
|
||||
|
||||
// BuildMaxHeap builds a MaxHeap instance with data and given comparator.
|
||||
func BuildMaxHeap[T any](data []T, comparator lancetconstraints.Comparator) *MaxHeap[T] {
|
||||
func BuildMaxHeap[T any](data []T, comparator constraints.Comparator) *MaxHeap[T] {
|
||||
heap := &MaxHeap[T]{
|
||||
data: make([]T, 0, len(data)),
|
||||
comparator: comparator,
|
||||
|
||||
@@ -90,6 +90,35 @@ func lastIndexOf[T any](o T, e []T, start int, end int) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying the
|
||||
// functional predicate f(T) bool
|
||||
// if not found return -1.
|
||||
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int {
|
||||
index := -1
|
||||
data := l.getList()
|
||||
for i := len(data) - 1; i >= 0; i-- {
|
||||
if f(data[i]) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// IndexOfFunc returns the first index satisfying the functional predicate f(v) bool
|
||||
// if not found return -1.
|
||||
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int {
|
||||
index := -1
|
||||
data := l.getList()
|
||||
for i, v := range data {
|
||||
if f(v) {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
// get returns the element at the specified position in this list.
|
||||
func get[T any](o []T, index int) *T {
|
||||
return &o[index]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestCopyOnWriteList_ValueOf(t *testing.T) {
|
||||
@@ -233,3 +234,35 @@ func TestCopyOnWriteList_SubList(t *testing.T) {
|
||||
subList = list.SubList(11, 1)
|
||||
assert.Equal([]int{}, subList)
|
||||
}
|
||||
|
||||
func TestCopyOnWriteListIndexOfFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIndexOfFunc")
|
||||
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3})
|
||||
i := list.IndexOfFunc(func(a int) bool { return a == 1 })
|
||||
assert.Equal(0, i)
|
||||
|
||||
i = list.IndexOfFunc(func(a int) bool { return a == 4 })
|
||||
assert.Equal(-1, i)
|
||||
}
|
||||
|
||||
func TestNewCopyOnWriteListLastIndexOfFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLastIndexOfFunc")
|
||||
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
||||
i := list.LastIndexOfFunc(func(a int) bool { return a == 3 })
|
||||
assert.Equal(5, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 10 })
|
||||
assert.Equal(-1, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 4 })
|
||||
assert.Equal(6, i)
|
||||
|
||||
i = list.LastIndexOfFunc(func(a int) bool { return a == 1 })
|
||||
assert.Equal(0, i)
|
||||
}
|
||||
|
||||
108
datastructure/optional/optional.go
Normal file
108
datastructure/optional/optional.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package optional
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Optional is a type that may or may not contain a non-nil value.
|
||||
type Optional[T any] struct {
|
||||
value *T
|
||||
mu *sync.RWMutex
|
||||
}
|
||||
|
||||
// Default returns an default Optional instance.
|
||||
func Default[T any]() Optional[T] {
|
||||
return Optional[T]{mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// Of returns an Optional with a non-nil value.
|
||||
func Of[T any](value T) Optional[T] {
|
||||
return Optional[T]{value: &value, mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// FromNillable returns an Optional for a given value, which may be nil.
|
||||
func FromNillable[T any](value *T) Optional[T] {
|
||||
if value == nil {
|
||||
return Default[T]()
|
||||
}
|
||||
return Optional[T]{value: value, mu: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
// IsNotNil checks if there is a value present.
|
||||
func (o Optional[T]) IsNotNil() bool {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
return o.value != nil
|
||||
}
|
||||
|
||||
// IsNil checks if the Optional is nil.
|
||||
func (o Optional[T]) IsNil() bool {
|
||||
return !o.IsNotNil()
|
||||
}
|
||||
|
||||
// IfNotNil performs the given action with the value if a value is not nil.
|
||||
func (o Optional[T]) IfNotNil(action func(value T)) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
action(*o.value)
|
||||
}
|
||||
}
|
||||
|
||||
// IfNotNilOrElse performs the action with the value if present, otherwise performs the fallback action.
|
||||
func (o Optional[T]) IfNotNilOrElse(action func(value T), fallbackAction func()) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
action(*o.value)
|
||||
} else {
|
||||
fallbackAction()
|
||||
}
|
||||
}
|
||||
|
||||
// Unwarp returns the value if not nil, otherwise panics.
|
||||
func (o Optional[T]) Unwarp() T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value == nil {
|
||||
panic("Optional.Get: no value present")
|
||||
}
|
||||
return *o.value
|
||||
}
|
||||
|
||||
// OrElse returns the value if is not nil, otherwise returns other.
|
||||
func (o Optional[T]) OrElse(other T) T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
return *o.value
|
||||
}
|
||||
return other
|
||||
}
|
||||
|
||||
// OrElseGet returns the value if is not nil, otherwise invokes action and returns the result.
|
||||
func (o Optional[T]) OrElseGet(action func() T) T {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value != nil {
|
||||
return *o.value
|
||||
}
|
||||
return action()
|
||||
}
|
||||
|
||||
// OrElseTrigger returns the value if present, otherwise returns an error.
|
||||
func (o Optional[T]) OrElseTrigger(errorHandler func() error) (T, error) {
|
||||
o.mu.RLock()
|
||||
defer o.mu.RUnlock()
|
||||
|
||||
if o.value == nil {
|
||||
return *new(T), errorHandler()
|
||||
}
|
||||
return *o.value, nil
|
||||
}
|
||||
151
datastructure/optional/optional_test.go
Normal file
151
datastructure/optional/optional_test.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package optional
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEmpty")
|
||||
opt := Default[int]()
|
||||
|
||||
assert.ShouldBeTrue(opt.IsNil())
|
||||
}
|
||||
|
||||
func TestOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOf")
|
||||
value := 42
|
||||
opt := Of(value)
|
||||
|
||||
assert.ShouldBeTrue(opt.IsNotNil())
|
||||
assert.Equal(opt.Unwarp(), value)
|
||||
}
|
||||
|
||||
func TestFromNillable(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOfNullable")
|
||||
var value *int = nil
|
||||
opt := FromNillable(value)
|
||||
|
||||
assert.ShouldBeFalse(opt.IsNotNil())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = FromNillable(value)
|
||||
|
||||
assert.ShouldBeTrue(opt.IsNotNil())
|
||||
}
|
||||
|
||||
func TestOrElse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElse")
|
||||
optDefault := Default[int]()
|
||||
defaultValue := 100
|
||||
|
||||
val := optDefault.OrElse(defaultValue)
|
||||
assert.Equal(val, defaultValue)
|
||||
|
||||
optWithValue := Of(42)
|
||||
val = optWithValue.OrElse(defaultValue)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestOrElseGetHappyPath(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElseGetHappyPath")
|
||||
optWithValue := Of(42)
|
||||
action := func() int { return 100 }
|
||||
|
||||
val := optWithValue.OrElseGet(action)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestOrElseGet(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOrElseGet")
|
||||
optDefault := Default[int]()
|
||||
action := func() int { return 100 }
|
||||
|
||||
val := optDefault.OrElseGet(action)
|
||||
assert.Equal(val, action())
|
||||
}
|
||||
|
||||
func TestOrElseTrigger(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "OrElseTrigger")
|
||||
optDefault := Default[int]()
|
||||
_, err := optDefault.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
assert.Equal(err.Error(), "no value")
|
||||
|
||||
optWithValue := Of(42)
|
||||
val, err := optWithValue.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal(val, 42)
|
||||
}
|
||||
|
||||
func TestIfNotNil(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "IfNotNil")
|
||||
called := false
|
||||
action := func(value int) { called = true }
|
||||
|
||||
optDefault := Default[int]()
|
||||
optDefault.IfNotNil(action)
|
||||
|
||||
assert.ShouldBeFalse(called)
|
||||
|
||||
called = false // Reset for next test
|
||||
optWithValue := Of(42)
|
||||
optWithValue.IfNotNil(action)
|
||||
|
||||
assert.ShouldBeTrue(called)
|
||||
}
|
||||
|
||||
func TestIfNotNilOrElse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIfNotNilOrElse")
|
||||
|
||||
// Test when value is present
|
||||
calledWithValue := false
|
||||
valueAction := func(value int) { calledWithValue = true }
|
||||
fallbackAction := func() { t.Errorf("Empty action should not be called when value is present") }
|
||||
|
||||
optWithValue := Of(42)
|
||||
optWithValue.IfNotNilOrElse(valueAction, fallbackAction)
|
||||
|
||||
assert.ShouldBeTrue(calledWithValue)
|
||||
|
||||
// Test when value is not present
|
||||
calledWithEmpty := false
|
||||
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
|
||||
fallbackAction = func() { calledWithEmpty = true }
|
||||
|
||||
optDefault := Default[int]()
|
||||
optDefault.IfNotNilOrElse(valueAction, fallbackAction)
|
||||
|
||||
assert.ShouldBeTrue(calledWithEmpty)
|
||||
}
|
||||
|
||||
func TestGetWithPanicStandard(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGetWithPanicStandard")
|
||||
|
||||
// Test when value is present
|
||||
optWithValue := Of(42)
|
||||
func() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.IsNil(r)
|
||||
}()
|
||||
val := optWithValue.Unwarp()
|
||||
if val != 42 {
|
||||
t.Errorf("Expected Unwarp to return 42, got %v", val)
|
||||
}
|
||||
}()
|
||||
|
||||
// Test when value is not present
|
||||
optDefault := Default[int]()
|
||||
func() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
assert.IsNotNil(r)
|
||||
}()
|
||||
_ = optDefault.Unwarp()
|
||||
}()
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// ArrayQueue implements queue with slice
|
||||
type ArrayQueue[T any] struct {
|
||||
items []T
|
||||
data []T
|
||||
head int
|
||||
tail int
|
||||
capacity int
|
||||
@@ -21,7 +21,7 @@ type ArrayQueue[T any] struct {
|
||||
|
||||
func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
|
||||
return &ArrayQueue[T]{
|
||||
items: make([]T, 0, capacity),
|
||||
data: make([]T, 0, capacity),
|
||||
head: 0,
|
||||
tail: 0,
|
||||
capacity: capacity,
|
||||
@@ -33,7 +33,7 @@ func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
|
||||
func (q *ArrayQueue[T]) Data() []T {
|
||||
items := []T{}
|
||||
for i := q.head; i < q.tail; i++ {
|
||||
items = append(items, q.items[i])
|
||||
items = append(items, q.data[i])
|
||||
}
|
||||
return items
|
||||
}
|
||||
@@ -55,40 +55,71 @@ func (q *ArrayQueue[T]) IsFull() bool {
|
||||
|
||||
// Front return front value of queue
|
||||
func (q *ArrayQueue[T]) Front() T {
|
||||
return q.items[0]
|
||||
return q.data[0]
|
||||
}
|
||||
|
||||
// Back return back value of queue
|
||||
func (q *ArrayQueue[T]) Back() T {
|
||||
return q.items[q.size-1]
|
||||
return q.data[q.size-1]
|
||||
}
|
||||
|
||||
// EnQueue put element into queue
|
||||
func (q *ArrayQueue[T]) Enqueue(item T) bool {
|
||||
if q.head == 0 && q.tail == q.capacity {
|
||||
return false
|
||||
} else if q.head != 0 && q.tail == q.capacity {
|
||||
for i := q.head; i < q.tail; i++ {
|
||||
q.items[i-q.head] = q.items[i]
|
||||
if q.tail < q.capacity {
|
||||
q.data = append(q.data, item)
|
||||
// q.tail++
|
||||
q.data[q.tail] = item
|
||||
} else {
|
||||
//upgrade
|
||||
if q.head > 0 {
|
||||
for i := 0; i < q.tail-q.head; i++ {
|
||||
q.data[i] = q.data[i+q.head]
|
||||
}
|
||||
q.tail -= q.head
|
||||
q.head = 0
|
||||
} else {
|
||||
if q.capacity < 65536 {
|
||||
if q.capacity == 0 {
|
||||
q.capacity = 1
|
||||
}
|
||||
q.capacity *= 2
|
||||
} else {
|
||||
q.capacity += 2 ^ 16
|
||||
}
|
||||
|
||||
tmp := make([]T, q.capacity, q.capacity)
|
||||
copy(tmp, q.data)
|
||||
q.data = tmp
|
||||
}
|
||||
q.tail = q.tail - q.head
|
||||
q.head = 0
|
||||
|
||||
q.data[q.tail] = item
|
||||
}
|
||||
|
||||
q.items = append(q.items, item)
|
||||
q.tail++
|
||||
q.size++
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
|
||||
func (q *ArrayQueue[T]) Dequeue() (T, bool) {
|
||||
var item T
|
||||
if q.head == q.tail {
|
||||
if q.size == 0 {
|
||||
return item, false
|
||||
}
|
||||
item = q.items[q.head]
|
||||
|
||||
item = q.data[q.head]
|
||||
q.head++
|
||||
|
||||
if q.head >= 1024 || q.head*2 > q.tail {
|
||||
q.capacity -= q.head
|
||||
q.tail -= q.head
|
||||
tmp := make([]T, q.capacity, q.capacity)
|
||||
copy(tmp, q.data[q.head:])
|
||||
q.data = tmp
|
||||
q.head = 0
|
||||
}
|
||||
|
||||
q.size--
|
||||
return item, true
|
||||
}
|
||||
@@ -96,7 +127,7 @@ func (q *ArrayQueue[T]) Dequeue() (T, bool) {
|
||||
// Clear the queue data
|
||||
func (q *ArrayQueue[T]) Clear() {
|
||||
capacity := q.capacity
|
||||
q.items = make([]T, 0, capacity)
|
||||
q.data = make([]T, 0, capacity)
|
||||
q.head = 0
|
||||
q.tail = 0
|
||||
q.size = 0
|
||||
@@ -105,7 +136,7 @@ func (q *ArrayQueue[T]) Clear() {
|
||||
|
||||
// Contain checks if the value is in queue or not
|
||||
func (q *ArrayQueue[T]) Contain(value T) bool {
|
||||
for _, v := range q.items {
|
||||
for _, v := range q.data {
|
||||
if reflect.DeepEqual(v, value) {
|
||||
return true
|
||||
}
|
||||
@@ -117,7 +148,7 @@ func (q *ArrayQueue[T]) Contain(value T) bool {
|
||||
func (q *ArrayQueue[T]) Print() {
|
||||
info := "["
|
||||
for i := q.head; i < q.tail; i++ {
|
||||
info += fmt.Sprintf("%+v, ", q.items[i])
|
||||
info += fmt.Sprintf("%+v, ", q.data[i])
|
||||
}
|
||||
info += "]"
|
||||
fmt.Println(info)
|
||||
|
||||
@@ -11,7 +11,7 @@ func TestArrayQueue_Enqueue(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
|
||||
|
||||
queue := NewArrayQueue[int](5)
|
||||
queue := NewArrayQueue[int](2)
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
@@ -8,20 +8,20 @@ package datastructure
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
"github.com/duke-git/lancet/v2/constraints"
|
||||
)
|
||||
|
||||
// PriorityQueue is a priority queue implemented by binary heap tree
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
// type T should implements Compare function in constraints.Comparator interface.
|
||||
type PriorityQueue[T any] struct {
|
||||
items []T
|
||||
size int
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
|
||||
// NewPriorityQueue return a pointer of PriorityQueue
|
||||
// param `comparator` is used to compare values in the queue
|
||||
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T] {
|
||||
func NewPriorityQueue[T any](capacity int, comparator constraints.Comparator) *PriorityQueue[T] {
|
||||
return &PriorityQueue[T]{
|
||||
items: make([]T, capacity+1),
|
||||
size: 0,
|
||||
|
||||
@@ -4,19 +4,21 @@
|
||||
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
|
||||
package datastructure
|
||||
|
||||
import "sort"
|
||||
|
||||
// Set is a data container, like slice, but element of set is not duplicate.
|
||||
type Set[T comparable] map[T]struct{}
|
||||
|
||||
// NewSet return a instance of set
|
||||
func NewSet[T comparable](items ...T) Set[T] {
|
||||
set := make(Set[T])
|
||||
// New create a instance of set from given values.
|
||||
func New[T comparable](items ...T) Set[T] {
|
||||
set := make(Set[T], len(items))
|
||||
set.Add(items...)
|
||||
return set
|
||||
}
|
||||
|
||||
// NewSetFromSlice create a set from slice
|
||||
func NewSetFromSlice[T comparable](items []T) Set[T] {
|
||||
set := make(Set[T])
|
||||
// FromSlice create a set from given slice.
|
||||
func FromSlice[T comparable](items []T) Set[T] {
|
||||
set := make(Set[T], len(items))
|
||||
for _, item := range items {
|
||||
set.Add(item)
|
||||
}
|
||||
@@ -77,8 +79,7 @@ func (s Set[T]) ContainAll(other Set[T]) bool {
|
||||
|
||||
// Clone return a copy of set
|
||||
func (s Set[T]) Clone() Set[T] {
|
||||
set := NewSet[T]()
|
||||
set.Add(s.Values()...)
|
||||
set := FromSlice(s.ToSlice())
|
||||
return set
|
||||
}
|
||||
|
||||
@@ -116,14 +117,11 @@ func (s Set[T]) Size() int {
|
||||
}
|
||||
|
||||
// Values return all values of set
|
||||
// Deprecated: Values function is deprecated and will be removed in future versions. Please use ToSlice() function instead.
|
||||
//
|
||||
// The ToSlice() function provides the same functionality as Values and returns a slice containing all values of the set.
|
||||
func (s Set[T]) Values() []T {
|
||||
result := make([]T, 0, len(s))
|
||||
|
||||
s.Iterate(func(value T) {
|
||||
result = append(result, value)
|
||||
})
|
||||
|
||||
return result
|
||||
return s.ToSlice()
|
||||
}
|
||||
|
||||
// Union creates a new set contain all element of set s and other
|
||||
@@ -135,7 +133,7 @@ func (s Set[T]) Union(other Set[T]) Set[T] {
|
||||
|
||||
// Intersection creates a new set whose element both be contained in set s and other
|
||||
func (s Set[T]) Intersection(other Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
set := New[T]()
|
||||
s.Iterate(func(value T) {
|
||||
if other.Contain(value) {
|
||||
set.Add(value)
|
||||
@@ -147,7 +145,7 @@ func (s Set[T]) Intersection(other Set[T]) Set[T] {
|
||||
|
||||
// SymmetricDifference creates a new set whose element is in set1 or set2, but not in both sets
|
||||
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
set := New[T]()
|
||||
s.Iterate(func(value T) {
|
||||
if !other.Contain(value) {
|
||||
set.Add(value)
|
||||
@@ -163,9 +161,9 @@ func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
|
||||
return set
|
||||
}
|
||||
|
||||
// Minus creates an set of whose element in origin set but not in compared set
|
||||
// Minus creates a set of whose element in origin set but not in compared set
|
||||
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
set := New[T]()
|
||||
|
||||
s.Iterate(func(value T) {
|
||||
if !comparedSet.Contain(value) {
|
||||
@@ -189,11 +187,34 @@ func (s Set[T]) EachWithBreak(iteratee func(item T) bool) {
|
||||
// Pop delete the top element of set then return it, if set is empty, return nil-value of T and false.
|
||||
func (s Set[T]) Pop() (v T, ok bool) {
|
||||
if len(s) > 0 {
|
||||
items := s.Values()
|
||||
item := items[len(s)-1]
|
||||
delete(s, item)
|
||||
return item, true
|
||||
for item := range s {
|
||||
v = item
|
||||
delete(s, item)
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
|
||||
return v, false
|
||||
}
|
||||
|
||||
// ToSlice returns a slice containing all values of the set.
|
||||
func (s Set[T]) ToSlice() []T {
|
||||
if s.IsEmpty() {
|
||||
return []T{}
|
||||
}
|
||||
result := make([]T, 0, s.Size())
|
||||
s.Iterate(func(value T) {
|
||||
result = append(result, value)
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ToSortedSlice returns a sorted slice containing all values of the set.
|
||||
func (s Set[T]) ToSortedSlice(less func(v1, v2 T) bool) []T {
|
||||
result := s.ToSlice()
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return less(result[i], result[j])
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestSet_NewSetFromSlice(t *testing.T) {
|
||||
func TestSet_FromSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
|
||||
assert := internal.NewAssert(t, "TestSet_FromSlice")
|
||||
|
||||
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
|
||||
s1 := FromSlice([]int{1, 2, 2, 3})
|
||||
assert.Equal(3, s1.Size())
|
||||
assert.Equal(true, s1.Contain(1))
|
||||
assert.Equal(true, s1.Contain(2))
|
||||
assert.Equal(true, s1.Contain(3))
|
||||
|
||||
s2 := NewSetFromSlice([]int{})
|
||||
s2 := FromSlice([]int{})
|
||||
assert.Equal(0, s2.Size())
|
||||
}
|
||||
|
||||
@@ -26,10 +28,10 @@ func TestSet_Add(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Add")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
cmpSet := NewSet(1, 2, 3)
|
||||
cmpSet := New(1, 2, 3)
|
||||
|
||||
assert.Equal(true, set.Equal(cmpSet))
|
||||
}
|
||||
@@ -39,12 +41,12 @@ func TestSet_AddIfNotExist(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
assert.Equal(false, set.AddIfNotExist(1))
|
||||
assert.Equal(true, set.AddIfNotExist(4))
|
||||
assert.Equal(NewSet(1, 2, 3, 4), set)
|
||||
assert.Equal(New(1, 2, 3, 4), set)
|
||||
}
|
||||
|
||||
func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||
@@ -52,7 +54,7 @@ func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
set.Add(1, 2)
|
||||
|
||||
ok := set.AddIfNotExistBy(3, func(val int) bool {
|
||||
@@ -75,7 +77,7 @@ func TestSet_Contain(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
assert.Equal(true, set.Contain(1))
|
||||
@@ -87,9 +89,9 @@ func TestSet_ContainAll(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(1, 2)
|
||||
set3 := NewSet(1, 2, 3, 4)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(1, 2)
|
||||
set3 := New(1, 2, 3, 4)
|
||||
|
||||
assert.Equal(true, set1.ContainAll(set2))
|
||||
assert.Equal(false, set1.ContainAll(set3))
|
||||
@@ -100,7 +102,7 @@ func TestSet_Clone(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Clone")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
assert.Equal(true, set1.Size() == set2.Size())
|
||||
@@ -112,11 +114,11 @@ func TestSet_Delete(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Delete")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
set.Add(1, 2, 3)
|
||||
set.Delete(3)
|
||||
|
||||
assert.Equal(true, set.Equal(NewSet(1, 2)))
|
||||
assert.Equal(true, set.Equal(New(1, 2)))
|
||||
}
|
||||
|
||||
func TestSet_Equal(t *testing.T) {
|
||||
@@ -124,9 +126,9 @@ func TestSet_Equal(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Equal")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(1, 2, 3)
|
||||
set3 := NewSet(1, 2, 3, 4)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(1, 2, 3)
|
||||
set3 := New(1, 2, 3, 4)
|
||||
|
||||
assert.Equal(true, set1.Equal(set2))
|
||||
assert.Equal(false, set1.Equal(set3))
|
||||
@@ -137,7 +139,7 @@ func TestSet_Iterate(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Iterate")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
set := New(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(value int) {
|
||||
arr = append(arr, value)
|
||||
@@ -151,7 +153,7 @@ func TestSet_IsEmpty(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
||||
|
||||
set := NewSet[int]()
|
||||
set := New[int]()
|
||||
assert.Equal(true, set.IsEmpty())
|
||||
}
|
||||
|
||||
@@ -160,7 +162,7 @@ func TestSet_Size(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Size")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
set := New(1, 2, 3)
|
||||
assert.Equal(3, set.Size())
|
||||
}
|
||||
|
||||
@@ -169,7 +171,7 @@ func TestSet_Values(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Values")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
set := New(1, 2, 3)
|
||||
values := set.Values()
|
||||
|
||||
assert.Equal(3, len(values))
|
||||
@@ -180,12 +182,12 @@ func TestSet_Union(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Union")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(2, 3, 4, 5)
|
||||
|
||||
unionSet := set1.Union(set2)
|
||||
|
||||
assert.Equal(NewSet(1, 2, 3, 4, 5), unionSet)
|
||||
assert.Equal(New(1, 2, 3, 4, 5), unionSet)
|
||||
}
|
||||
|
||||
func TestSet_Intersection(t *testing.T) {
|
||||
@@ -193,11 +195,11 @@ func TestSet_Intersection(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Intersection")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(2, 3, 4, 5)
|
||||
intersectionSet := set1.Intersection(set2)
|
||||
|
||||
assert.Equal(NewSet(2, 3), intersectionSet)
|
||||
assert.Equal(New(2, 3), intersectionSet)
|
||||
}
|
||||
|
||||
func TestSet_SymmetricDifference(t *testing.T) {
|
||||
@@ -205,10 +207,10 @@ func TestSet_SymmetricDifference(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(2, 3, 4, 5)
|
||||
|
||||
assert.Equal(NewSet(1, 4, 5), set1.SymmetricDifference(set2))
|
||||
assert.Equal(New(1, 4, 5), set1.SymmetricDifference(set2))
|
||||
}
|
||||
|
||||
func TestSet_Minus(t *testing.T) {
|
||||
@@ -216,16 +218,16 @@ func TestSet_Minus(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Minus")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
set3 := NewSet(2, 3)
|
||||
set1 := New(1, 2, 3)
|
||||
set2 := New(2, 3, 4, 5)
|
||||
set3 := New(2, 3)
|
||||
|
||||
assert.Equal(NewSet(1), set1.Minus(set2))
|
||||
assert.Equal(NewSet(4, 5), set2.Minus(set3))
|
||||
assert.Equal(New(1), set1.Minus(set2))
|
||||
assert.Equal(New(4, 5), set2.Minus(set3))
|
||||
}
|
||||
|
||||
func TestEachWithBreak(t *testing.T) {
|
||||
// s := NewSet(1, 2, 3, 4, 5)
|
||||
// s := New(1, 2, 3, 4, 5)
|
||||
|
||||
// var sum int
|
||||
|
||||
@@ -241,22 +243,93 @@ func TestEachWithBreak(t *testing.T) {
|
||||
// assert.Equal(6, sum)
|
||||
}
|
||||
|
||||
// func TestPop(t *testing.T) {
|
||||
// assert := internal.NewAssert(t, "TestPop")
|
||||
func TestPop(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestSet_Pop")
|
||||
|
||||
// s := NewSet[int]()
|
||||
s := New[int]()
|
||||
|
||||
// val, ok := s.Pop()
|
||||
// assert.Equal(0, val)
|
||||
// assert.Equal(false, ok)
|
||||
val, ok := s.Pop()
|
||||
assert.Equal(0, val)
|
||||
assert.Equal(false, ok)
|
||||
|
||||
// s.Add(1)
|
||||
// s.Add(2)
|
||||
// s.Add(3)
|
||||
s = New(1, 2, 3, 4, 5)
|
||||
sl := s.ToSlice()
|
||||
|
||||
// // s = NewSet(1, 2, 3, 4, 5)
|
||||
val, ok = s.Pop()
|
||||
assert.Equal(false, s.Contain(val))
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(len(sl)-1, s.Size())
|
||||
|
||||
// val, ok = s.Pop()
|
||||
// assert.Equal(3, val)
|
||||
// assert.Equal(true, ok)
|
||||
// }
|
||||
var found bool
|
||||
|
||||
for _, v := range sl {
|
||||
if v == val {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(true, found)
|
||||
}
|
||||
|
||||
func TestSet_ToSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_ToSlice")
|
||||
|
||||
set1 := FromSlice([]int{6, 3, 1, 5, 6, 7, 1})
|
||||
set2 := FromSlice([]float64{-2.65, 4.25, 4.25 - 3.14, 0})
|
||||
set3 := New[string]()
|
||||
|
||||
slice1 := set1.ToSlice()
|
||||
slice2 := set2.ToSlice()
|
||||
slice3 := set3.ToSlice()
|
||||
|
||||
sort.Ints(slice1)
|
||||
sort.Float64s(slice2)
|
||||
|
||||
assert.Equal(5, len(slice1))
|
||||
assert.Equal(4, len(slice2))
|
||||
assert.Equal(0, len(slice3))
|
||||
|
||||
assert.Equal(true, reflect.DeepEqual(slice1, []int{1, 3, 5, 6, 7}))
|
||||
assert.Equal(true, reflect.DeepEqual(slice2, []float64{-2.65, 0, 1.11, 4.25}))
|
||||
assert.Equal("[]string", reflect.TypeOf(slice3).String())
|
||||
}
|
||||
|
||||
func TestSet_ToSortedSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_ToSortedSlice")
|
||||
|
||||
set1 := FromSlice([]int{6, 3, 1, 5, 6, 7, 1})
|
||||
set2 := FromSlice([]float64{-2.65, 4.25, 4.25 - 3.14, 0})
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
set3 := FromSlice([]Person{{"Tom", 20}, {"Jerry", 18}, {"Spike", 25}})
|
||||
|
||||
slice1 := set1.ToSortedSlice(func(v1, v2 int) bool {
|
||||
return v1 < v2
|
||||
})
|
||||
slice2 := set2.ToSortedSlice(func(v1, v2 float64) bool {
|
||||
return v2 < v1
|
||||
})
|
||||
slice3 := set3.ToSortedSlice(func(v1, v2 Person) bool {
|
||||
return v1.Age < v2.Age
|
||||
})
|
||||
|
||||
assert.Equal(5, len(slice1))
|
||||
assert.Equal(4, len(slice2))
|
||||
assert.Equal(3, len(slice3))
|
||||
|
||||
assert.Equal(true, reflect.DeepEqual(slice1, []int{1, 3, 5, 6, 7}))
|
||||
assert.Equal(true, reflect.DeepEqual(slice2, []float64{4.25, 1.11, 0, -2.65}))
|
||||
assert.Equal(true, reflect.DeepEqual(slice3, []Person{
|
||||
{"Jerry", 18},
|
||||
{"Tom", 20},
|
||||
{"Spike", 25},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -7,22 +7,22 @@ package datastructure
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/duke-git/lancet/v2/constraints"
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
// BSTree is a binary search tree data structure in which each node has at most two children,
|
||||
// which are referred to as the left child and the right child.
|
||||
// In BSTree: leftNode < rootNode < rightNode
|
||||
// type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
// type T should implements Compare function in constraints.Comparator interface.
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
|
||||
// NewBSTree create a BSTree pointer
|
||||
// param `comparator` is used to compare values in the tree
|
||||
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T] {
|
||||
func NewBSTree[T any](rootData T, comparator constraints.Comparator) *BSTree[T] {
|
||||
root := datastructure.NewTreeNode(rootData)
|
||||
return &BSTree[T]{root, comparator}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool {
|
||||
}
|
||||
|
||||
func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T],
|
||||
comparator lancetconstraints.Comparator) bool {
|
||||
comparator constraints.Comparator) bool {
|
||||
result := false
|
||||
|
||||
if superTreeRoot != nil && subTreeRoot != nil {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/duke-git/lancet/v2/constraints"
|
||||
"github.com/duke-git/lancet/v2/datastructure"
|
||||
"github.com/duke-git/lancet/v2/lancetconstraints"
|
||||
)
|
||||
|
||||
func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
|
||||
@@ -86,7 +86,7 @@ func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T)
|
||||
}
|
||||
}
|
||||
|
||||
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) {
|
||||
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator constraints.Comparator) {
|
||||
if comparator.Compare(newNode.Value, rootNode.Value) == -1 {
|
||||
if rootNode.Left == nil {
|
||||
rootNode.Left = newNode
|
||||
@@ -103,7 +103,7 @@ func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], compara
|
||||
}
|
||||
|
||||
// todo, delete root node failed
|
||||
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator lancetconstraints.Comparator) *datastructure.TreeNode[T] {
|
||||
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator constraints.Comparator) *datastructure.TreeNode[T] {
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func calculateDepth[T any](node *datastructure.TreeNode[T], depth int) int {
|
||||
return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1))
|
||||
}
|
||||
|
||||
func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) bool {
|
||||
func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], comparator constraints.Comparator) bool {
|
||||
if subTreeRoot == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ package datetime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -381,3 +382,64 @@ func TimestampNano(timezone ...string) int64 {
|
||||
|
||||
return t.UnixNano()
|
||||
}
|
||||
|
||||
// TrackFuncTime track the time of function execution.
|
||||
// call it at top of the func like `defer TrackFuncTime(time.Now())()`
|
||||
// Play: todo
|
||||
func TrackFuncTime(pre time.Time) func() {
|
||||
callerName := getCallerName()
|
||||
return func() {
|
||||
elapsed := time.Since(pre)
|
||||
fmt.Printf("Function %s execution time:\t %v", callerName, elapsed)
|
||||
}
|
||||
}
|
||||
|
||||
func getCallerName() string {
|
||||
pc, _, _, ok := runtime.Caller(2)
|
||||
if !ok {
|
||||
return "Unknown"
|
||||
}
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
fullName := fn.Name()
|
||||
if lastDot := strings.LastIndex(fullName, "."); lastDot != -1 {
|
||||
return fullName[lastDot+1:]
|
||||
}
|
||||
|
||||
return fullName
|
||||
}
|
||||
|
||||
// DaysBetween returns the number of days between two times.
|
||||
// Play: todo
|
||||
func DaysBetween(start, end time.Time) int {
|
||||
duration := end.Sub(start)
|
||||
days := int(duration.Hours() / 24)
|
||||
|
||||
return days
|
||||
}
|
||||
|
||||
// GenerateDatetimesBetween returns a slice of strings between two times.
|
||||
// layout: the format of the datetime string
|
||||
// interval: the interval between two datetimes
|
||||
// Play: todo
|
||||
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error) {
|
||||
var result []string
|
||||
|
||||
if start.After(end) {
|
||||
start, end = end, start
|
||||
}
|
||||
|
||||
duration, err := time.ParseDuration(interval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for current := start; !current.After(end); current = current.Add(duration) {
|
||||
result = append(result, current.Format(layout))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -408,3 +408,32 @@ func ExampleIsWeekend() {
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleDaysBetween() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
result := DaysBetween(start, end)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 9
|
||||
}
|
||||
|
||||
func ExampleGenerateDatetimesBetween() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC)
|
||||
|
||||
layout := "2006-01-02 15:04:05"
|
||||
interval := "1h"
|
||||
|
||||
result, err := GenerateDatetimesBetween(start, end, layout, interval)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00]
|
||||
// <nil>
|
||||
}
|
||||
|
||||
@@ -410,3 +410,114 @@ func TestTimestamp(t *testing.T) {
|
||||
ts4 := TimestampNano()
|
||||
t.Log(ts4)
|
||||
}
|
||||
|
||||
func TestTrackFuncTime(t *testing.T) {
|
||||
defer TrackFuncTime(time.Now())()
|
||||
|
||||
var n int
|
||||
for i := 0; i < 5000000; i++ {
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
func TestDaysBetween(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDaysBetween")
|
||||
|
||||
tests := []struct {
|
||||
start time.Time
|
||||
end time.Time
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC),
|
||||
expected: 9,
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
expected: -9,
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.December, 31, 0, 0, 0, 0, time.UTC),
|
||||
expected: 365,
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.March, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.March, 31, 0, 0, 0, 0, time.UTC),
|
||||
expected: 30,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := DaysBetween(tt.start, tt.end)
|
||||
assert.Equal(tt.expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateDatetimesBetween(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGenerateDatetimesBetween")
|
||||
|
||||
tests := []struct {
|
||||
start time.Time
|
||||
end time.Time
|
||||
layout string
|
||||
interval string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC),
|
||||
layout: "2006-01-02 15:04:05",
|
||||
interval: "30m",
|
||||
expected: []string{
|
||||
"2024-09-01 00:00:00",
|
||||
"2024-09-01 00:30:00",
|
||||
"2024-09-01 01:00:00",
|
||||
"2024-09-01 01:30:00",
|
||||
"2024-09-01 02:00:00",
|
||||
},
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
layout: "2006-01-02 15:04:05",
|
||||
interval: "1h",
|
||||
expected: []string{"2024-09-01 00:00:00"},
|
||||
},
|
||||
{
|
||||
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||
end: time.Date(2024, time.September, 1, 3, 0, 0, 0, time.UTC),
|
||||
layout: "2006-01-02 15:04:05",
|
||||
interval: "2h",
|
||||
expected: []string{
|
||||
"2024-09-01 00:00:00",
|
||||
"2024-09-01 02:00:00",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result, err := GenerateDatetimesBetween(tt.start, tt.end, tt.layout, tt.interval)
|
||||
|
||||
assert.Equal(tt.expected, result)
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
t.Run("Invalid interval", func(t *testing.T) {
|
||||
_, err := GenerateDatetimesBetween(time.Now(), time.Now(), "2006-01-02 15:04:05", "invalid")
|
||||
if err == nil {
|
||||
t.Fatal("Expected error, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ export const slugify = (str: string): string =>
|
||||
export const commonConfig = defineConfig({
|
||||
title: 'Lancet',
|
||||
appearance: true,
|
||||
ignoreDeadLinks: true,
|
||||
|
||||
markdown: {
|
||||
theme: {
|
||||
@@ -83,7 +84,7 @@ export const commonConfig = defineConfig({
|
||||
|
||||
footer: {
|
||||
copyright: 'Copyright © 2023-present Duke Du',
|
||||
message: '备案号: 京ICP备2023022770号',
|
||||
message: '<a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2023022770号-1</a>',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -42,7 +42,7 @@ export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
|
||||
},
|
||||
{
|
||||
text: 'Contribution',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.en-US.md',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTION.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
|
||||
},
|
||||
{
|
||||
text: '参与贡献',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.zh-CN.md',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTION.zh-CN.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ outline: deep
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
background: #ecefff;
|
||||
background: #10b981;
|
||||
border: 1px solid;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -43,12 +43,12 @@ import (
|
||||
|
||||
### <span id="BubbleSort">BubbleSort</span>
|
||||
|
||||
<p>冒泡排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>冒泡排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func BubbleSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||
@@ -91,12 +91,12 @@ func main() {
|
||||
|
||||
### <span id="InsertionSort">InsertionSort</span>
|
||||
|
||||
<p>插入排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>插入排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func InsertionSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||
@@ -117,7 +117,7 @@ type people struct {
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
|
||||
// Compare implements github.com/duke-git/lancet/constraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
@@ -154,12 +154,12 @@ func main() {
|
||||
|
||||
### <span id="SelectionSort">SelectionSort</span>
|
||||
|
||||
<p>选择排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>选择排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func SelectionSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||
@@ -202,12 +202,12 @@ func main() {
|
||||
|
||||
### <span id="ShellSort">ShellSort</span>
|
||||
|
||||
<p>希尔排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>希尔排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func ShellSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||
@@ -250,12 +250,12 @@ func main() {
|
||||
|
||||
### <span id="QuickSort">QuickSort</span>
|
||||
|
||||
<p>快速排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>快速排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||
func QuickSort[T any](slice []T comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||
@@ -298,12 +298,12 @@ func main() {
|
||||
|
||||
### <span id="HeapSort">HeapSort</span>
|
||||
|
||||
<p>堆排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>堆排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func HeapSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||
@@ -346,12 +346,12 @@ func main() {
|
||||
|
||||
### <span id="MergeSort">MergeSort</span>
|
||||
|
||||
<p>归并排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>归并排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func MergeSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||
@@ -394,12 +394,12 @@ func main() {
|
||||
|
||||
### <span id="CountSort">CountSort</span>
|
||||
|
||||
<p>计数排序,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>计数排序,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
func CountSort[T any](slice []T, comparator constraints.Comparator) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||
@@ -443,12 +443,12 @@ func main() {
|
||||
|
||||
### <span id="BinarySearch">BinarySearch</span>
|
||||
|
||||
<p>二分递归查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>二分递归查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||
@@ -494,12 +494,12 @@ func main() {
|
||||
|
||||
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
|
||||
|
||||
<p>二分迭代查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包lancetconstraints.Comparator。</p>
|
||||
<p>二分迭代查找,返回元素索引,未找到元素返回-1,参数comparator需要实现包constraints.Comparator。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||
|
||||
@@ -43,6 +43,10 @@ import (
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
- [ToStdBase64](#ToStdBase64)
|
||||
- [ToUrlBase64](#ToUrlBase64)
|
||||
- [ToRawStdBase64](#ToRawStdBase64)
|
||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -876,3 +880,272 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToStdBase64">ToStdBase64</span>
|
||||
|
||||
<p>将值转换为StdBase64编码的字符串。error类型的数据也会把error的原因进行编码,复杂的结构会转为JSON格式的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToStdBase64(value any) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_fLJqJD3NMo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
afterEncode := convertor.ToStdBase64(nil)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
afterEncode = convertor.ToStdBase64("")
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = convertor.ToStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
//
|
||||
//
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### <span id="ToUrlBase64">ToUrlBase64</span>
|
||||
|
||||
<p>值转换为 ToUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToUrlBase64(value any) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C_d0GlvEeUR)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
afterEncode := convertor.ToUrlBase64(nil)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = convertor.ToUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
//
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### <span id="ToRawStdBase64">ToRawStdBase64</span>
|
||||
|
||||
<p>值转换为 ToRawStdBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToRawStdBase64(value any) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wSAr3sfkDcv)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = convertor.ToRawStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToRawStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToRawStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode := convertor.ToRawStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToRawUrlBase64">ToRawUrlBase64</span>
|
||||
|
||||
<p>值转换为 ToRawUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
|
||||
|
||||
<b>函数签名:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HwdDPFcza1O)</span></b>
|
||||
|
||||
```go
|
||||
func ToRawUrlBase64(value any) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode := convertor.ToRawUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToRawUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToRawUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToRawUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToRawUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToRawUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# Cryptor
|
||||
|
||||
cryptor包包含数据加密和解密功能。支持 base64, md5, hmac, hash, aes, des, rsa。
|
||||
cryptor 包包含数据加密和解密功能。支持 base64, md5, hmac, hash, aes, des, rsa。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -32,6 +32,8 @@ import (
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [AesGcmEncrypt](#AesGcmEncrypt)
|
||||
- [AesGcmDecrypt](#AesGcmDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
@@ -65,6 +67,9 @@ import (
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
|
||||
- [RsaEncryptOAEP](#RsaEncryptOAEP)
|
||||
- [RsaDecryptOAEP](#RsaDecryptOAEP)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -376,6 +381,74 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesGcmEncrypt">AesGcmEncrypt</span>
|
||||
|
||||
<p>使用AES GCM算法模式加密数据。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AesGcmEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesGcmEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesGcmDecrypt">AesGcmDecrypt</span>
|
||||
|
||||
<p>使用AES GCM算法解密数据。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AesGcmDecrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesGcmEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Base64StdEncode">Base64StdEncode</span>
|
||||
|
||||
<p>将字符串base64编码。</p>
|
||||
@@ -988,13 +1061,13 @@ import (
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
hms := cryptor.HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1051,10 +1124,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1080,10 +1153,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1109,10 +1182,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1195,10 +1268,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1255,10 +1328,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1315,10 +1388,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1423,3 +1496,114 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateRsaKeyPair">GenerateRsaKeyPair</span>
|
||||
|
||||
<p>创建rsa公钥私钥和key。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaEncryptOAEP">RsaEncryptOAEP</span>
|
||||
|
||||
<p>rsa OAEP加密。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaDecryptOAEP">RsaDecryptOAEP</span>
|
||||
|
||||
<p>rsa OAEP解密。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
- [Remove](#Remove)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [IndexOfFunc](#IndexOfFunc)
|
||||
- [LastIndexOfFunc](#LastIndexOfFunc)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Contain](#Contain)
|
||||
- [ValueOf](#ValueOf)
|
||||
@@ -198,6 +200,58 @@ func main() {
|
||||
|
||||
```
|
||||
|
||||
### <span id="IndexOfFunc">IndexOfFunc</span>
|
||||
<p>返回第一个满足判断函数f(v)的元素的索引,如果找不到则返回-1。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 1 })) //0
|
||||
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOfFunc">LastIndexOfFunc</span>
|
||||
<p>返回最后一个满足判断函数f(v)的元素的索引,如果找不到则返回-1。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 1 })) // 3
|
||||
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### IsEmpty
|
||||
|
||||
如果此列表不包含任何元素,则返回 true。
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
- [Iterate](#Iterate)
|
||||
- [Keys](#Keys)
|
||||
- [Values](#Values)
|
||||
- [FilterByValue](#FilterByValue)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -276,7 +277,7 @@ func main() {
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>返回hashmap所有值的切片 (随机顺序).</p>
|
||||
<p>返回hashmap所有值的切片 (随机顺序)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -306,3 +307,40 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="FilterByValue">FilterByValue</span>
|
||||
|
||||
<p>返回一个过滤后的HashMap。 如果任何值与 perdicate 函数不匹配,则返回 nil,否则返回包含选定值的 HashMap。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) FilterByValue(perdicate func(value any) bool) *HashMap
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := hashmap.NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
hm.Put("d", 4)
|
||||
hm.Put("e", 5)
|
||||
hm.Put("f", 6)
|
||||
|
||||
filteredHM := hm.FilterByValue(func(value any) bool {
|
||||
return value.(int) == 1 || value.(int) == 3
|
||||
})
|
||||
|
||||
fmt.Println(filteredHM.Size()) //2
|
||||
}
|
||||
```
|
||||
|
||||
@@ -44,9 +44,9 @@ MaxHeap是通过slice实现的二叉堆树,根节点的key既大于等于左
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
func NewMaxHeap[T any](comparator constraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
|
||||
412
docs/api/packages/datastructure/optional.md
Normal file
412
docs/api/packages/datastructure/optional.md
Normal file
@@ -0,0 +1,412 @@
|
||||
# Optional
|
||||
Optional类型代表一个可选的值,它要么包含一个实际值,要么为空。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go](https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Of](#Of)
|
||||
- [FromNillable](#FromNillable)
|
||||
- [Default](#Default)
|
||||
- [IsNotNil](#IsNotNil)
|
||||
- [IsNil](#IsNil)
|
||||
- [IsNotNil](#IsNotNil)
|
||||
- [IfNotNilOrElse](#IfNotNilOrElse)
|
||||
- [Umwarp](#Umwarp)
|
||||
- [OrElse](#OrElse)
|
||||
- [OrElseGet](#OrElseGet)
|
||||
- [OrElseTrigger](#OrElseTrigger)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Of">Of</span>
|
||||
<p>返回一个包含非空值的Optional。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Of[T any](value T) Optional[T]
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value := 42
|
||||
opt := optional.Of(value)
|
||||
|
||||
fmt.Println(opt.Get())
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FromNillable">FromNillable</span>
|
||||
<p>返回一个包含给定值的Optional,该值可能为空 (nil)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FromNillable[T any](value *T) Optional[T]
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var value *int = nil
|
||||
opt := optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Default">Default</span>
|
||||
<p>返回一个空Optional实例。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Default[T any]() Optional[T]
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
fmt.Println(optDefault.IsNil())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsNil">IsNil</span>
|
||||
<p>验证Optional是否为空。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IsNil() bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
fmt.Println(optDefault.IsNil())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsNotNil">IsNotNil</span>
|
||||
<p>检查当前Optional内是否存在值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IsNotNil() bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var value *int = nil
|
||||
opt := optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IfNotNil">IfNotNil</span>
|
||||
<p>如果值存在,则使用action方法执行给定的操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IfNotNil(action func(value T))
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
called := false
|
||||
action := func(value int) { called = true }
|
||||
|
||||
optDefault := optional.Default[int]()
|
||||
optDefault.IfNotNil(action)
|
||||
|
||||
fmt.Println(called)
|
||||
|
||||
called = false // Reset for next test
|
||||
optWithValue := optional.Of(42)
|
||||
optWithValue.IfNotNil(action)
|
||||
|
||||
fmt.Println(optWithValue.IsNotNil())
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IfNotNilOrElse">IfNotNilOrElse</span>
|
||||
<p>根据是否存在值执行相应的操作:有值则执行指定操作,没有值则执行默认操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IfNotNilOrElse(action func(value T), fallbackAction func())
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
calledWithValue := false
|
||||
valueAction := func(value int) { calledWithValue = true }
|
||||
emptyAction := func() { t.Errorf("Empty action should not be called when value is present") }
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
optWithValue.IfNotNilOrElse(valueAction, emptyAction)
|
||||
|
||||
fmt.Println(calledWithValue)
|
||||
|
||||
calledWithEmpty := false
|
||||
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
|
||||
emptyAction = func() { calledWithEmpty = true }
|
||||
|
||||
optDefault := optional.Default[int]()
|
||||
optDefault.IfNotNilOrElse(valueAction, emptyAction)
|
||||
|
||||
fmt.Println(calledWithEmpty)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
<p>如果存在,返回该值,否则引发panic。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) Unwrap() T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value := 42
|
||||
opt := optional.Of(value)
|
||||
|
||||
fmt.Println(opt.Unwrap())
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OrElse">OrElse</span>
|
||||
<p>检查Optional值是否存在,如果存在,则直接返回该值。如果不存在,返回参数other值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) OrElse(other T) T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Empty[int]()
|
||||
val := optDefault.OrElse(100)
|
||||
fmt.Println(val)
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
val = optWithValue.OrElse(100)
|
||||
fmt.Println(val)
|
||||
|
||||
// Output:
|
||||
// 100
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OrElseGet">OrElseGet</span>
|
||||
<p>检查Optional值是否存在,如果存在,则直接返回该值。如果不存在,则调用一个提供的函数 (supplier),并返回该函数的执行结果。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) OrElseGet(action func() T) T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
action := func() int { return 100 }
|
||||
|
||||
val := optDefault.OrElseGet(action)
|
||||
fmt.Println(val)
|
||||
|
||||
// Output:
|
||||
// 100
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="OrElseTrigger">OrElseTrigger</span>
|
||||
<p>检查Optional值是否存在,如果存在,则直接返回该值,否则返回错误。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
OrElseTrigger(errorHandler func() error) (T, error)
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
_, err := optDefault.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
fmt.Println(err.Error())
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
val, err := optWithValue.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
fmt.Println(val)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// no value
|
||||
// 42
|
||||
// nil
|
||||
}
|
||||
```
|
||||
@@ -1100,12 +1100,12 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T]
|
||||
func NewPriorityQueue[T any](capacity int, comparator constraints.Comparator) *PriorityQueue[T]
|
||||
|
||||
type PriorityQueue[T any] struct {
|
||||
items []T
|
||||
size int
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Set
|
||||
|
||||
Set 集合数据结构,类似列表。Set 中元素不重复。
|
||||
集合数据结构,类似列表。Set中元素不重复。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [NewSetFromSlice](#NewSetFromSlice)
|
||||
- [Values](#Values)
|
||||
- [New](#New)
|
||||
- [FromSlice](#FromSlice)
|
||||
- [Values<sup>deprecated</sup>](#Values)
|
||||
- [Add](#Add)
|
||||
- [AddIfNotExist](#AddIfNotExist)
|
||||
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||
@@ -40,20 +40,23 @@ import (
|
||||
- [Intersection](#Intersection)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
- [Pop](#Pop)
|
||||
- [ToSlice](#ToSlice)
|
||||
- [ToSortedSlice](#ToSortedSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="NewSet">NewSet</span>
|
||||
### <span id="New">New</span>
|
||||
|
||||
<p>返回Set结构体对象</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type Set[T comparable] map[T]bool
|
||||
func NewSet[T comparable](items ...T) Set[T]
|
||||
type Set[T comparable] map[T]struct{}
|
||||
func New[T comparable](items ...T) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
@@ -67,19 +70,19 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
st := set.New[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NewSetFromSlice">NewSetFromSlice</span>
|
||||
### <span id="FromSlice">FromSlice</span>
|
||||
|
||||
<p>基于切片创建集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewSetFromSlice[T comparable](items []T) Set[T]
|
||||
func FromSlice[T comparable](items []T) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
@@ -93,14 +96,16 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSetFromSlice([]int{1, 2, 2, 3})
|
||||
st := set.FromSlice([]int{1, 2, 2, 3})
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>获取集合中所有元素的切片</p>
|
||||
<p>获取集合中所有元素的切片。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`ToSlice`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -119,7 +124,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
st := set.New[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
@@ -145,7 +150,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
@@ -173,7 +178,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
r1 := st.AddIfNotExist(1)
|
||||
@@ -206,7 +211,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2)
|
||||
|
||||
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||
@@ -245,7 +250,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
set.Delete(3)
|
||||
@@ -274,7 +279,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Contain(1)) //true
|
||||
@@ -303,9 +308,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(1, 2)
|
||||
set3 := set.New(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
fmt.Println(set1.ContainAll(set3)) //false
|
||||
@@ -333,7 +338,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
|
||||
fmt.Println(set1.Size()) //3
|
||||
}
|
||||
@@ -360,7 +365,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
fmt.Println(set1.Size() == set2.Size()) //true
|
||||
@@ -389,9 +394,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2, 3)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(1, 2, 3)
|
||||
set3 := set.New(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.Equal(set2)) //true
|
||||
fmt.Println(set1.Equal(set3)) //false
|
||||
@@ -419,7 +424,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(item int) {
|
||||
arr = append(arr, item)
|
||||
@@ -450,7 +455,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet(1, 2, 3, 4, 5)
|
||||
s := set.New(1, 2, 3, 4, 5)
|
||||
|
||||
var sum int
|
||||
|
||||
@@ -487,8 +492,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet()
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New()
|
||||
|
||||
fmt.Println(set1.IsEmpty()) //false
|
||||
fmt.Println(set2.IsEmpty()) //true
|
||||
@@ -516,8 +521,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.Union(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,2,3,4,5
|
||||
@@ -545,8 +550,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.Intersection(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //2,3
|
||||
@@ -574,8 +579,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,4,5
|
||||
@@ -603,9 +608,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set.New(2, 3)
|
||||
|
||||
res1 := set1.Minus(set2)
|
||||
fmt.Println(res1.Values()) //1
|
||||
@@ -636,7 +641,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet[int]()
|
||||
s := set.New[int]()
|
||||
s.Add(1)
|
||||
s.Add(2)
|
||||
s.Add(3)
|
||||
@@ -647,3 +652,58 @@ func main() {
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToSlice">ToSlice</span>
|
||||
|
||||
<p>以切片的形式返回集合中所有的元素(无序)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ToSlice() (v T, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
func main() {
|
||||
s := set.New(1, 2, 3, 4, 5)
|
||||
|
||||
val := s.ToSlice()
|
||||
fmt.Println(val) // [2 3 4 5 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToSortedSlice">ToSortedSlice</span>
|
||||
|
||||
<p>以切片的形式返回集合中所有的元素(按给定的规则排序)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ToSortedSlice() (v T, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
func main() {
|
||||
s1 := set.New(1, 2, 3, 4, 5)
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
s2 := FromSlice([]Person{{"Tom", 20}, {"Jerry", 18}, {"Spike", 25}})
|
||||
|
||||
res1 := s1.ToSortedSlice(func(v1, v2 int) bool {
|
||||
return v1 < v2
|
||||
})
|
||||
|
||||
res2 := s2.ToSortedSlice(func(v1, v2 Person) bool {
|
||||
return v1.Age < v2.Age
|
||||
})
|
||||
|
||||
fmt.Println(res1) // [1 2 3 4 5]
|
||||
fmt.Println(res2) // [{Jerry 18} {Tom 20} {Spike 25}]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -41,7 +41,7 @@ import (
|
||||
## 文档
|
||||
|
||||
## 1. BSTree
|
||||
BSTree是一种二叉搜索树数据结构,其中每个节点有两个孩子,分别称为左孩子和右孩子。 在 BSTree 中:leftNode < rootNode < rightNode。 T类型应该实现lancetconstraints.Comparator。
|
||||
BSTree是一种二叉搜索树数据结构,其中每个节点有两个孩子,分别称为左孩子和右孩子。 在 BSTree 中:leftNode < rootNode < rightNode。 T类型应该实现constraints.Comparator。
|
||||
|
||||
### <span id="NewBSTree">NewBSTree</span>
|
||||
<p>返回BSTree指针实例</p>
|
||||
@@ -49,11 +49,11 @@ BSTree是一种二叉搜索树数据结构,其中每个节点有两个孩子
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T]
|
||||
func NewBSTree[T any](rootData T, comparator constraints.Comparator) *BSTree[T]
|
||||
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
|
||||
type TreeNode[T any] struct {
|
||||
|
||||
@@ -64,6 +64,9 @@ import (
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
- [TrackFuncTime](#TrackFuncTime)
|
||||
- [DaysBetween](#DaysBetween)
|
||||
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1334,7 +1337,7 @@ import (
|
||||
func main() {
|
||||
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
|
||||
|
||||
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
|
||||
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -1464,4 +1467,107 @@ func main() {
|
||||
// Output:
|
||||
// 1690363051331788000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TrackFuncTime">TrackFuncTime</span>
|
||||
|
||||
<p>测试函数执行时间。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TrackFuncTime(pre time.Time) func()
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer datetime.TrackFuncTime(time.Now())()
|
||||
|
||||
var n int
|
||||
for i := 0; i < 5000000; i++ {
|
||||
n++
|
||||
}
|
||||
|
||||
fmt.Println(1) // Function main execution time: 1.460287ms
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DaysBetween">DaysBetween</span>
|
||||
|
||||
<p>返回两个日期之间的天数差。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DaysBetween(start, end time.Time) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
result := datetime.DaysBetween(start, end)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 9
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateDatetimesBetween">GenerateDatetimesBetween</span>
|
||||
|
||||
<p>生成从start到end的所有日期时间的字符串列表。layout参数表示时间格式,例如"2006-01-02 15:04:05",interval参数表示时间间隔,例如"1h"表示1小时,"30m"表示30分钟。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC)
|
||||
|
||||
layout := "2006-01-02 15:04:05"
|
||||
interval := "1h"
|
||||
|
||||
result, err := datetime.GenerateDatetimesBetween(start, end, layout, interval)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00]
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [CopyDir](#CopyDir)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -45,8 +46,12 @@ import (
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
- [ReadFile](#ReadFile)
|
||||
- [ChunkRead](#ChunkRead)
|
||||
- [ParallelChunkRead](#ParallelChunkRead)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -160,6 +165,34 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CopyDir">CopyDir</span>
|
||||
|
||||
<p>拷贝文件夹到目标路径,会递归复制文件夹下所有的文件及文件夹,并且访问权限也与源文件夹保持一致。当dstPath存在时会返回error</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CopyDir(srcPath string, dstPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YAyFTA_UuPb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test_src", "./test_dest")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CurrentPath">CurrentPath</span>
|
||||
|
||||
<p>返回当前位置的绝对路径。</p>
|
||||
@@ -668,7 +701,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadCsvFile(filepath string) ([][]string, error)
|
||||
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
||||
@@ -700,7 +733,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
||||
@@ -742,6 +775,59 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||
|
||||
<p>将map切片写入csv文件中。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// filepath: CSV文件路径。
|
||||
// records: 写入文件的map切片。map值必须为基本类型。会以map键的字母顺序写入。
|
||||
// appendToExistingFile: 是否为追加写模式。
|
||||
// delimiter: CSV文件分割符。
|
||||
// headers: CSV文件表头顺序(需要与map key保持一致),不指定时按字母排序。
|
||||
func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune, headers ...[]string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/umAIomZFV1c)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fpath := "./test.csv"
|
||||
fileutil.CreateFile(fpath)
|
||||
|
||||
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
|
||||
records := []map[string]any{
|
||||
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||
}
|
||||
|
||||
headers := []string{"Name", "Age", "Gender"}
|
||||
err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadCsvFile(csvFilePath, ';')
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||
|
||||
<p>将bytes写入文件。</p>
|
||||
@@ -839,3 +925,155 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReadFile">ReadFile</span>
|
||||
|
||||
<p>读取文件或者URL。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uNep3Tr8fqF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
reader, fn, err := fileutil.ReadFile("https://httpbin.org/robots.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fn()
|
||||
|
||||
dat, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(dat))
|
||||
|
||||
// Output:
|
||||
// User-agent: *
|
||||
// Disallow: /deny
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ChunkRead">ChunkRead</span>
|
||||
|
||||
<p>从文件的指定偏移读取块并返回块内所有行。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ChunkRead(file *os.File, offset int64, size int, bufPool *sync.Pool) ([]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/r0hPmKWhsgf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100
|
||||
|
||||
// test1.csv file content:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
filePath := "./testdata/test1.csv" // 替换为你的文件路径
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, defaultChunkSizeMB*mb)
|
||||
},
|
||||
}
|
||||
|
||||
lines, err := fileutil.ChunkRead(f, 0, 100, &bufPool)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(lines[0])
|
||||
fmt.Println(lines[1])
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ParallelChunkRead">ParallelChunkRead</span>
|
||||
|
||||
<p>并行读取文件并将每个块的行发送到指定通道。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// filePath:文件路径
|
||||
// chunkSizeMB: 分块的大小(单位MB,设置为0时使用默认100MB),设置过大反而不利,视情调整
|
||||
// maxGoroutine: 并发读取分块的数量,设置为0时使用CPU核心数
|
||||
// linesCh: 用于接收返回结果的通道。
|
||||
func ParallelChunkRead(filePath string, linesCh chan<- []string, chunkSizeMB, maxGoroutine int) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/teMXnCsdSEw)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100 // 默认值
|
||||
|
||||
numParsers := runtime.NumCPU()
|
||||
|
||||
linesCh := make(chan []string, numParsers)
|
||||
|
||||
// test1.csv file content:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
filePath := "./testdata/test1.csv"
|
||||
|
||||
go fileutil.ParallelChunkRead(filePath, linesCh, defaultChunkSizeMB, numParsers)
|
||||
|
||||
var totalLines int
|
||||
for lines := range linesCh {
|
||||
totalLines += len(lines)
|
||||
|
||||
for _, line := range lines {
|
||||
fmt.Println(line)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(totalLines)
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
// 2
|
||||
}
|
||||
```
|
||||
@@ -37,12 +37,12 @@ import (
|
||||
|
||||
### <span id="Comma">Comma</span>
|
||||
|
||||
<p>用逗号每隔3位分割数字/字符串,支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
||||
<p>用逗号每隔3位分割数字/字符串,支持添加前缀符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||
func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSymbol string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||
|
||||
@@ -7,6 +7,7 @@ function 函数包控制函数执行流程,包含部分函数式编程。
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/predicate.go](https://github.com/duke-git/lancet/blob/main/function/predicate.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,11 +28,21 @@ import (
|
||||
- [Before](#Before)
|
||||
- [CurryFn](#CurryFn)
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Debounce](#Debounce)
|
||||
- [Debounced<sup>deprecated</sup>](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Schedule](#Schedule)
|
||||
- [Pipeline](#Pipeline)
|
||||
- [Watcher](#Watcher)
|
||||
- [And](#And)
|
||||
- [Or](#Or)
|
||||
- [Negate](#Negate)
|
||||
- [Nor](#Nor)
|
||||
- [Xnor](#Xnor)
|
||||
- [Nand](#Nand)
|
||||
- [AcceptIf](#AcceptIf)
|
||||
- [Throttle](#Throttle)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -184,9 +195,58 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Debounce">Debounce</span>
|
||||
|
||||
<p>创建一个函数的去抖动版本。该去抖动函数仅在上次调用后的指定延迟时间过去之后才会调用原始函数。支持取消去抖动。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func())
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
callCount := 0
|
||||
fn := func() {
|
||||
callCount++
|
||||
}
|
||||
|
||||
debouncedFn, _ := function.Debounce(fn, 500*time.Millisecond)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
debouncedFn()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println(callCount)
|
||||
|
||||
debouncedFn()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println(callCount)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Debounced">Debounced</span>
|
||||
|
||||
<p>创建一个debounced函数,该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。</p>
|
||||
<p>创建一个函数的去抖动版本。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用. 使用 `Debounce` 代替.
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -404,3 +464,323 @@ func longRunningTask() {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### <span id="And">And</span>
|
||||
|
||||
<p>返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑and操作。只有当所有谓词判断函数对于给定的值都返回true时,返回true, 否则返回false。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func And[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dTBHJMQ0zD2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isNumericAndLength5 := function.And(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(isNumericAndLength5("12345"))
|
||||
fmt.Println(isNumericAndLength5("1234"))
|
||||
fmt.Println(isNumericAndLength5("abcde"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Or">Or</span>
|
||||
|
||||
<p>返回一个复合谓词判断函数,该判断函数表示一组谓词的逻辑or操作。只有当所有谓词判断函数对于给定的值都返回false时,返回false, 否则返回true。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Or[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/LitCIsDFNDA)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
containsDigitOrSpecialChar := function.Or(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return strings.ContainsAny(s, "!@#$%") },
|
||||
)
|
||||
|
||||
fmt.Println(containsDigitOrSpecialChar("hello!"))
|
||||
fmt.Println(containsDigitOrSpecialChar("hello"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Negate">Negate</span>
|
||||
|
||||
<p>返回一个谓词函数,该谓词函数表示当前谓词的逻辑否定。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Negate[T any](predicate func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jbI8BtgFnVE)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Define some simple predicates for demonstration
|
||||
isUpperCase := func(s string) bool {
|
||||
return strings.ToUpper(s) == s
|
||||
}
|
||||
isLowerCase := func(s string) bool {
|
||||
return strings.ToLower(s) == s
|
||||
}
|
||||
isMixedCase := function.Negate(function.Or(isUpperCase, isLowerCase))
|
||||
|
||||
fmt.Println(isMixedCase("ABC"))
|
||||
fmt.Println(isMixedCase("AbC"))
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Nor">Nor</span>
|
||||
|
||||
<p>返回一个组合谓词函数,表示给定值上所有谓词逻辑非或 (nor) 的结果。只有当所有谓词函数对给定值都返回false时,该组合谓词函数才返回true。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Nor[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2KdCoBEOq84)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
match := function.Nor(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(match("dbcdckkeee"))
|
||||
|
||||
|
||||
match = function.Nor(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(match("0123456789"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Nand">Nand</span>
|
||||
|
||||
<p>返回一个复合谓词函数,表示给定谓词函数列表的逻辑非与 (NAND)。仅当列表中所有函数对给定参数返回false时,才返回true,否则返回false。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Nand[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rb-FdNGpgSO)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isNumericAndLength5 := function.Nand(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(isNumericAndLength5("12345"))
|
||||
fmt.Println(isNumericAndLength5("1234"))
|
||||
fmt.Println(isNumericAndLength5("abcdef"))
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Xnor">Xnor</span>
|
||||
|
||||
<p>返回一个复合谓词函数,表示给定一组谓词函数的逻辑异或 (XNOR)。只有当所有 谓词函数对给参数都返回true或false时,该谓词函数才返回true。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Xnor[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FJxko8SFbqc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isEven := func(i int) bool { return i%2 == 0 }
|
||||
isPositive := func(i int) bool { return i > 0 }
|
||||
|
||||
match := function.Xnor(isEven, isPositive)
|
||||
|
||||
fmt.Println(match(2))
|
||||
fmt.Println(match(-3))
|
||||
fmt.Println(match(3))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AcceptIf">AcceptIf</span>
|
||||
|
||||
<p>AcceptIf函数会返回另一个函数,该函数的签名与 apply 函数相同,但同时还会包含一个布尔值来表示成功或失败。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XlXHHtzCf7d)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
adder := function.AcceptIf(
|
||||
function.And(
|
||||
func(x int) bool {
|
||||
return x > 10
|
||||
}, func(x int) bool {
|
||||
return x%2 == 0
|
||||
}),
|
||||
func(x int) int {
|
||||
return x + 1
|
||||
},
|
||||
)
|
||||
|
||||
result, ok := adder(20)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
result, ok = adder(21)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 21
|
||||
// true
|
||||
// 0
|
||||
// false
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### <span id="Throttle">Throttle</span>
|
||||
|
||||
<p>创建一个函数的节流版本。返回的函数保证在每个时间间隔内最多只会被调用一次。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Throttle(fn func(), interval time.Duration) func()
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
callCount := 0
|
||||
|
||||
fn := func() {
|
||||
callCount++
|
||||
}
|
||||
|
||||
throttledFn := function.Throttle(fn, 1*time.Second)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
throttledFn()
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
fmt.Println(callCount)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,10 @@ import (
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
- [CeilToFloat](#CeilToFloat)
|
||||
- [CeilToString](#CeilToString)
|
||||
- [FloorToFloat](#FloorToFloat)
|
||||
- [FloorToString](#FloorToString)
|
||||
- [Range](#Range)
|
||||
- [RangeWithStep](#RangeWithStep)
|
||||
- [AngleToRadian](#AngleToRadian)
|
||||
@@ -47,6 +51,7 @@ import (
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
- [Abs](#Abs)
|
||||
- [Div](#Div)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -392,7 +397,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToFloat(x float64, n int) float64
|
||||
func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ghyb528JRJL)</span></b>
|
||||
@@ -428,7 +433,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToString(x float64, n int) string
|
||||
func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kZwpBRAcllO)</span></b>
|
||||
@@ -464,7 +469,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aumarSHIGzP)</span></b>
|
||||
@@ -493,6 +498,150 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CeilToFloat">CeilToFloat</span>
|
||||
|
||||
<p>向上舍入(进一法),保留n位小数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CeilToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8hOeSADZPCo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.CeilToFloat(3.14159, 1)
|
||||
result2 := mathutil.CeilToFloat(3.14159, 2)
|
||||
result3 := mathutil.CeilToFloat(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.2
|
||||
// 3.15
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CeilToString">CeilToString</span>
|
||||
|
||||
<p>向上舍入(进一法),保留n位小数,返回字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CeilToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wy5bYEyUKKG)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.CeilToString(3.14159, 1)
|
||||
result2 := mathutil.CeilToString(3.14159, 2)
|
||||
result3 := mathutil.CeilToString(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.2
|
||||
// 3.15
|
||||
// 5.0000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FloorToFloat">FloorToFloat</span>
|
||||
|
||||
<p>向下舍入(去尾法),保留n位小数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FloorToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vbCBrQHZEED)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.FloorToFloat(3.14159, 1)
|
||||
result2 := mathutil.FloorToFloat(3.14159, 2)
|
||||
result3 := mathutil.FloorToFloat(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.1
|
||||
// 3.14
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FloorToString">FloorToString</span>
|
||||
|
||||
<p>向下舍入(去尾法),保留n位小数,返回字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FloorToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Qk9KPd2IdDb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.FloorToString(3.14159, 1)
|
||||
result2 := mathutil.FloorToString(3.14159, 2)
|
||||
result3 := mathutil.FloorToString(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.1
|
||||
// 3.14
|
||||
// 5.0000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Range">Range</span>
|
||||
|
||||
<p>根据指定的起始值和数量,创建一个数字切片。</p>
|
||||
@@ -965,16 +1114,52 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := Abs(-1)
|
||||
result2 := Abs(-0.1)
|
||||
result3 := Abs(float32(0.2))
|
||||
result2 := Abs(-0.1)
|
||||
result3 := Abs(float32(0.2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 0.1
|
||||
// 0.2
|
||||
// Output:
|
||||
// 1
|
||||
// 0.1
|
||||
// 0.2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Div">Div</span>
|
||||
|
||||
<p>除法运算。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Div[T constraints.Float | constraints.Integer](x T, y T) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WLxDdGXXYat)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Div(9, 4)
|
||||
result2 := mathutil.Div(1, 2)
|
||||
result3 := mathutil.Div(0, 666)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 2.25
|
||||
// 0.5
|
||||
// 0
|
||||
}
|
||||
```
|
||||
@@ -624,7 +624,9 @@ func main() {
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
|
||||
<p>发送http get请求。(已废弃:使用SendRequest)</p>
|
||||
<p>发送http get请求。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`SendRequest`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -666,7 +668,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
|
||||
<p>发送http post请求。(已废弃:使用SendRequest)</p>
|
||||
<p>发送http post请求。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`SendRequest`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -713,7 +717,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
|
||||
<p>发送http put请求。(已废弃:使用SendRequest)</p>
|
||||
<p>发送http put请求。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`SendRequest`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -763,7 +769,9 @@ func main() {
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
|
||||
<p>发送http delete请求。(已废弃:使用SendRequest)</p>
|
||||
<p>发送http delete请求。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`SendRequest`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -802,7 +810,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
|
||||
<p>发送http patch请求。(已废弃:使用SendRequest)</p>
|
||||
<p>发送http patch请求。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`SendRequest`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
- [Of](#Of)
|
||||
- [Unwrap](#Unwrap)
|
||||
- [ExtractPointer](#ExtractPointer)
|
||||
- [UnwarpOr](#UnwarpOr)
|
||||
- [UnwarpOrDefault](#UnwarpOrDefault)
|
||||
- [UnwrapOr](#UnwrapOr)
|
||||
- [UnwrapOrDefault](#UnwrapOrDefault)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -136,14 +136,14 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnwarpOr">UnwarpOr</span>
|
||||
### <span id="UnwrapOr">UnwrapOr</span>
|
||||
|
||||
<p>返回指针的值,如果指针为零值,则返回fallback。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
UnwarpOr[T any](p *T, fallback T) T
|
||||
UnwrapOr[T any](p *T, fallback T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mmNaLC38W8C)</span></b>
|
||||
@@ -163,10 +163,10 @@ func main() {
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOr(&a, 456)
|
||||
result2 := pointer.UnwarpOr(&b, "abc")
|
||||
result3 := pointer.UnwarpOr(c, 456)
|
||||
result4 := pointer.UnwarpOr(d, "def")
|
||||
result1 := pointer.UnwrapOr(&a, 456)
|
||||
result2 := pointer.UnwrapOr(&b, "abc")
|
||||
result3 := pointer.UnwrapOr(c, 456)
|
||||
result4 := pointer.UnwrapOr(d, "def")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -181,14 +181,14 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
|
||||
### <span id="UnwrapOrDefault">UnwrapOrDefault</span>
|
||||
|
||||
<p>返回指针的值,如果指针为零值,则返回相应零值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
UnwarpOrDefault[T any](p *T) T
|
||||
UnwrapOrDefault[T any](p *T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZnGIHf8_o4E)</span></b>
|
||||
@@ -208,10 +208,10 @@ func main() {
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOrDefault(&a)
|
||||
result2 := pointer.UnwarpOrDefault(&b)
|
||||
result3 := pointer.UnwarpOrDefault(c)
|
||||
result4 := pointer.UnwarpOrDefault(d)
|
||||
result1 := pointer.UnwrapOrDefault(&a)
|
||||
result2 := pointer.UnwrapOrDefault(&b)
|
||||
result3 := pointer.UnwrapOrDefault(c)
|
||||
result4 := pointer.UnwrapOrDefault(d)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
@@ -25,12 +25,22 @@ import (
|
||||
- [RandBytes](#RandBytes)
|
||||
- [RandInt](#RandInt)
|
||||
- [RandString](#RandString)
|
||||
- [RandFromGivenSlice](#RandFromGivenSlice)
|
||||
- [RandSliceFromGivenSlice](#RandSliceFromGivenSlice)
|
||||
- [RandUpper](#RandUpper)
|
||||
- [RandLower](#RandLower)
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [RandSymbolChar](#RandSymbolChar)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandIntSlice](#RandIntSlice)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
- [RandFloat](#RandFloat)
|
||||
- [RandFloats](#RandFloats)
|
||||
- [RandStringSlice](#RandStringSlice)
|
||||
- [RandBool](#RandBool)
|
||||
- [RandBoolSlice](#RandBoolSlice)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -114,6 +124,60 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFromGivenSlice">RandFromGivenSlice</span>
|
||||
|
||||
<p>从给定切片中随机生成元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandFromGivenSlice[T any](slice []T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nicknames := []string{"张三", "李四", "王五", "赵六", "钱七"}
|
||||
randElm := random.RandFromGivenSlice(nicknames)
|
||||
fmt.Println(randElm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandSliceFromGivenSlice">RandSliceFromGivenSlice</span>
|
||||
|
||||
<p>从给定切片中生成长度为 num 的随机切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon","mango", "nectarine", "orange"}
|
||||
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
|
||||
fmt.Println(chosen3goods)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUpper">RandUpper</span>
|
||||
|
||||
<p>生成给定长度的随机大写字母字符串</p>
|
||||
@@ -218,6 +282,32 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandSymbolChar">RandSymbolChar</span>
|
||||
|
||||
<p>生成给定长度的随机符号字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandSymbolChar(length int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Im6ZJxAykOm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandSymbolChar(6)
|
||||
fmt.Println(randStr) // 随机特殊字符字符串,例如: @#(_")
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UUIdV4">UUIdV4</span>
|
||||
|
||||
<p>生成UUID v4字符串</p>
|
||||
@@ -247,14 +337,40 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
### <span id="RandIntSlice">RandIntSlice</span>
|
||||
|
||||
<p>生成一个不重复的长度为n的随机int切片。</p>
|
||||
<p>生成一个特定长度的随机int切片,数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(n, min, max int) []int
|
||||
func RandIntSlice(length, min, max int) []int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[1 2 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>生成一个特定长度的,数值不重复的随机int切片,数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(length, min, max int) []int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uBkRSOz73Ec)</span></b>
|
||||
@@ -272,3 +388,136 @@ func main() {
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFloat">RandFloat</span>
|
||||
|
||||
<p>生成一个随机float64数值,可以指定精度。数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandFloat(min, max float64, precision int) float64
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zbD_tuobJtr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
floatNumber := random.RandFloat(1.0, 5.0, 2)
|
||||
fmt.Println(floatNumber) //2.14 (random number)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFloats">RandFloats</span>
|
||||
|
||||
<p>生成一个特定长度的随机float64切片,可以指定数值精度。数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandFloats(n int, min, max float64, precision int) []float64
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/I3yndUQ-rhh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
floatNumbers := random.RandFloats(5, 1.0, 5.0, 2)
|
||||
fmt.Println(floatNumber) //[3.42 3.99 1.3 2.38 4.23] (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandStringSlice">RandStringSlice</span>
|
||||
|
||||
<p>生成随机字符串slice. 字符串类型需要是以下几种或者它们的组合: random.Numeral, random.LowwerLetters, random.UpperLetters random.Letters, random.SymbolChars, random.AllChars。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandStringSlice(charset string, sliceLen, strLen int) []string
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := random.RandStringSlice(random.Letters, 4, 6)
|
||||
fmt.Println(strs)
|
||||
|
||||
// output random string slice like below:
|
||||
//[CooSMq RUFjDz FAeMPf heRyGv]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandBool">RandBool</span>
|
||||
|
||||
<p>生成随机bool值(true or false)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandBool() bool
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandBool()
|
||||
fmt.Println(result) // true or false (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandBoolSlice">RandBoolSlice</span>
|
||||
|
||||
<p>生成特定长度的随机bool slice。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandBoolSlice(length int) []bool
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandBoolSlice(2)
|
||||
fmt.Println(result) // [true false] (random)
|
||||
}
|
||||
```
|
||||
@@ -27,6 +27,10 @@ import (
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
- [BackoffStrategy](#BackoffStrategy)
|
||||
- [RetryWithCustomBackoff](#RetryWithCustomBackoff)
|
||||
- [RetryWithLinearBackoff](#RetryWithLinearBackoff)
|
||||
- [RetryWithExponentialWithJitterBackoff](#RetryWithExponentialWithJitterBackoff)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -66,7 +70,7 @@ func main() {
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
duration := retry.RetryWithLinearBackoff(time.Microsecond*50)
|
||||
|
||||
retry.Retry(increaseNumber,
|
||||
duration,
|
||||
@@ -112,7 +116,7 @@ func main() {
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
duration := retry.RetryWithLinearBackoff(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
@@ -169,52 +173,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RetryDuration">RetryDuration</span>
|
||||
|
||||
<p>设置重试间隔时间,默认3秒</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Retry">Retry</span>
|
||||
|
||||
<p>重试执行函数retryFunc,直到函数运行成功,或被context停止</p>
|
||||
@@ -247,7 +205,7 @@ func main() {
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
duration := retry.RetryDuration(time.Microsecond*50)
|
||||
duration := retry.RetryWithLinearBackoff(time.Microsecond*50)
|
||||
|
||||
err := retry.Retry(increaseNumber, duration)
|
||||
if err != nil {
|
||||
@@ -260,3 +218,201 @@ func main() {
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BackoffStrategy">BackoffStrategy</span>
|
||||
|
||||
<p>定义计算退避间隔的方法的接口。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// BackoffStrategy is an interface that defines a method for calculating backoff intervals.
|
||||
type BackoffStrategy interface {
|
||||
// CalculateInterval returns the time.Duration after which the next retry attempt should be made.
|
||||
CalculateInterval() time.Duration
|
||||
}
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
type ExampleCustomBackoffStrategy struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
|
||||
return c.interval + 1
|
||||
}
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry,Retry(increaseNumber, retry.RetryWithCustomBackoff(&示例CustomBackoffStrategy{interval: time.Microsecond * 50}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RetryWithCustomBackoff">RetryWithCustomBackoff</span>
|
||||
|
||||
<p>设置自定义退避策略。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryWithCustomBackoff(backoffStrategy BackoffStrategy) Option
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jIm_o2vb5Y4)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
type ExampleCustomBackoffStrategy struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
|
||||
return c.interval + 1
|
||||
}
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry,Retry(increaseNumber, retry.RetryWithCustomBackoff(&示例CustomBackoffStrategy{interval: time.Microsecond * 50}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RetryWithLinearBackoff">RetryWithLinearBackoff</span>
|
||||
|
||||
<p>设置线性策略退避。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryWithLinearBackoff(interval time.Duration) Option
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/PDet2ZQZwcB)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryWithLinearBackoff(time.Microsecond*50))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RetryWithExponentialWithJitterBackoff">RetryWithExponentialWithJitterBackoff</span>
|
||||
|
||||
<p>设置指数策略退避。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RetryWithExponentialWithJitterBackoff(interval time.Duration, base uint64, maxJitter time.Duration) Option
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xp1avQmn16X)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryWithExponentialWithJitterBackoff(time.Microsecond*50, 2, time.Microsecond*25))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
@@ -6,7 +6,8 @@ slice 包包含操作切片的方法集合。
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice_concurrent.go](https://github.com/duke-git/lancet/blob/main/slice/slice_concurrent.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -35,6 +36,7 @@ import (
|
||||
- [DifferenceBy](#DifferenceBy)
|
||||
- [DifferenceWith](#DifferenceWith)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [DeleteRange](#DeleteRange)
|
||||
- [Drop](#Drop)
|
||||
- [DropRight](#DropRight)
|
||||
- [DropWhile](#DropWhile)
|
||||
@@ -43,6 +45,7 @@ import (
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
- [Filter](#Filter)
|
||||
- [FilterConcurrent](#FilterConcurrent)
|
||||
- [Find<sup>deprecated</sup>](#Find)
|
||||
- [FindBy](#FindBy)
|
||||
- [FindLast<sup>deprecated</sup>](#FindLast)
|
||||
@@ -50,6 +53,7 @@ import (
|
||||
- [Flatten](#Flatten)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](#ForEach)
|
||||
- [ForEachConcurrent](#ForEachConcurrent)
|
||||
- [ForEachWithBreak](#ForEachWithBreak)
|
||||
- [GroupBy](#GroupBy)
|
||||
- [GroupWith](#GroupWith)
|
||||
@@ -60,11 +64,13 @@ import (
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [Map](#Map)
|
||||
- [MapConcurrent](#MapConcurrent)
|
||||
- [FilterMap](#FilterMap)
|
||||
- [FlatMap](#FlatMap)
|
||||
- [Merge](#Merge)
|
||||
- [Reverse](#Reverse)
|
||||
- [Reduce<sup>deprecated</sup>](#Reduce)
|
||||
- [ReduceConcurrent](#ReduceConcurrent)
|
||||
- [ReduceBy](#ReduceBy)
|
||||
- [ReduceRight](#ReduceRight)
|
||||
- [Replace](#Replace)
|
||||
@@ -85,6 +91,9 @@ import (
|
||||
- [ToSlicePointer](#ToSlicePointer)
|
||||
- [Unique](#Unique)
|
||||
- [UniqueBy](#UniqueBy)
|
||||
- [UniqueByComparator](#UniqueByComparator)
|
||||
- [UniqueByField](#UniqueByField)
|
||||
- [UniqueByConcurrent](#UniqueByConcurrent)
|
||||
- [Union](#Union)
|
||||
- [UnionBy](#UnionBy)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
@@ -92,6 +101,11 @@ import (
|
||||
- [KeyBy](#KeyBy)
|
||||
- [Join](#Join)
|
||||
- [Partition](#Partition)
|
||||
- [SetToDefaultIf](#SetToDefaultIf)
|
||||
- [Break](#Break)
|
||||
- [RightPadding](#RightPadding)
|
||||
- [LeftPadding](#LeftPadding)
|
||||
- [Frequency](#Frequency)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -317,12 +331,12 @@ func main() {
|
||||
|
||||
### <span id="Concat">Concat</span>
|
||||
|
||||
<p>合并多个slices到slice中</p>
|
||||
<p>创建一个新的切片,将传入的切片拼接起来返回。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Concat[T any](slice []T, slices ...[]T) []T
|
||||
func Concat[T any](slices ...[]T) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
||||
@@ -516,15 +530,15 @@ func main() {
|
||||
|
||||
### <span id="DeleteAt">DeleteAt</span>
|
||||
|
||||
<p>删除切片中指定开始索引到结束索引的元素</p>
|
||||
<p>删除切片中指定索引的元素(不修改原切片)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DeleteAt[T any](slice []T, start int, end ...int)
|
||||
func DeleteAt[T any](slice []T, index int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pJ-d6MUWcvK)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/800B1dPBYyd)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -533,18 +547,66 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DeleteAt([]string{"a", "b", "c"}, -1)
|
||||
result2 := slice.DeleteAt([]string{"a", "b", "c"}, 0)
|
||||
result3 := slice.DeleteAt([]string{"a", "b", "c"}, 0, 2)
|
||||
chars := []string{"a", "b", "c", "d", "e"}
|
||||
|
||||
result1 := slice.DeleteAt(chars, 0)
|
||||
result2 := slice.DeleteAt(chars, 4)
|
||||
result3 := slice.DeleteAt(chars, 5)
|
||||
result4 := slice.DeleteAt(chars, 6)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [c]
|
||||
// [b c d e]
|
||||
// [a b c d]
|
||||
// [a b c d]
|
||||
// [a b c d]
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DeleteRange">DeleteRange</span>
|
||||
|
||||
<p>删除切片中指定索引范围的元素(不修改原切片)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DeleteRange[T any](slice []T, start, end int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/945HwiNrnle)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chars := []string{"a", "b", "c", "d", "e"}
|
||||
|
||||
result1 := DeleteRange(chars, 0, 0)
|
||||
result2 := DeleteRange(chars, 0, 1)
|
||||
result3 := DeleteRange(chars, 0, 3)
|
||||
result4 := DeleteRange(chars, 0, 4)
|
||||
result5 := DeleteRange(chars, 0, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// [a b c d e]
|
||||
// [b c d e]
|
||||
// [d e]
|
||||
// [e]
|
||||
// []
|
||||
|
||||
}
|
||||
```
|
||||
@@ -843,10 +905,46 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Find">Find (废弃:使用 FindBy)</span>
|
||||
### <span id="FilterConcurrent">FilterConcurrent</span>
|
||||
|
||||
<p>对slice并发执行filter操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result := slice.FilterConcurrent(nums, isEven, 2)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [2 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Find">Find</span>
|
||||
|
||||
<p>遍历slice的元素,返回第一个通过predicate函数真值测试的元素</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`FindBy`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -915,10 +1013,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast(废弃:使用 FindLastBy)</span>
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`FindLastBy`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1082,6 +1182,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ForEachConcurrent">ForEachConcurrent</span>
|
||||
|
||||
<p>对slice并发执行foreach操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numThreads int)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
|
||||
result := make([]int, len(nums))
|
||||
|
||||
addOne := func(index int, value int) {
|
||||
result[index] = value + 1
|
||||
}
|
||||
|
||||
slice.ForEachConcurrent(nums, addOne, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [2 3 4 5 6 7 8 9]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ForEachWithBreak">ForEachWithBreak</span>
|
||||
|
||||
<p>遍历切片的元素并为每个元素调用iteratee函数,当iteratee函数返回false时,终止遍历。</p>
|
||||
@@ -1190,10 +1327,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IntSlice">IntSlice (已弃用: 使用 go1.18+泛型代替)</span>
|
||||
### <span id="IntSlice">IntSlice</span>
|
||||
|
||||
<p>将接口切片转换为int切片</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用go1.18+泛型代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1219,10 +1358,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="InterfaceSlice">InterfaceSlice(已弃用: 使用 go1.18+泛型代替)</span>
|
||||
### <span id="InterfaceSlice">InterfaceSlice</span>
|
||||
|
||||
<p>将值转换为接口切片</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用go1.18+泛型代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1387,7 +1528,7 @@ func main() {
|
||||
|
||||
### <span id="Map">Map</span>
|
||||
|
||||
<p>对slice中的每个元素执行map函数以创建一个新切片</p>
|
||||
<p>对slice中的每个元素执行map函数以创建一个新切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1419,6 +1560,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MapConcurrent">MapConcurrent</span>
|
||||
|
||||
<p>对slice并发执行map操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U, numThreads int) []U
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6}
|
||||
|
||||
result := slice.MapConcurrent(nums, func(_, n int) int {
|
||||
return n * n
|
||||
}, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [1 4 9 16 25 36]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FilterMap">FilterMap</span>
|
||||
|
||||
<p>返回一个将filter和map操作应用于给定切片的切片。 iteratee回调函数应该返回两个值:1,结果值。2,结果值是否应该被包含在返回的切片中。</p>
|
||||
@@ -1493,6 +1666,8 @@ func main() {
|
||||
|
||||
<p>合并多个切片(不会消除重复元素).</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`Concat`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1552,7 +1727,9 @@ func main() {
|
||||
|
||||
### <span id="Reduce">Reduce</span>
|
||||
|
||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果(废弃:建议使用ReduceBy)</p>
|
||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`ReduceBy`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1584,6 +1761,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReduceConcurrent">ReduceConcurrent</span>
|
||||
|
||||
<p>对切片元素执行并发reduce操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item T, agg T) T, numThreads int) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
|
||||
result := slice.ReduceConcurrent(nums, 0, func(_ int, item, agg int) int {
|
||||
return agg + item
|
||||
}, 1)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 55
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReduceBy">ReduceBy</span>
|
||||
|
||||
<p>对切片元素执行reduce操作。</p>
|
||||
@@ -2078,10 +2287,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StringSlice">StringSlice(已弃用: 使用 go1.18+泛型代替)</span>
|
||||
### <span id="StringSlice">StringSlice</span>
|
||||
|
||||
<p>将接口切片转换为字符串切片</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用go1.18+泛型代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -2230,12 +2441,12 @@ func main() {
|
||||
|
||||
### <span id="UniqueBy">UniqueBy</span>
|
||||
|
||||
<p>对切片的每个元素调用iteratee函数,然后删除重复元素</p>
|
||||
<p>根据迭代函数返回的值,从输入切片中移除重复元素。此函数保持元素的顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T
|
||||
func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UR323iZLDpv)</span></b>
|
||||
@@ -2255,7 +2466,114 @@ func main() {
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [1 2 0]
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByComparator">UniqueByComparator</span>
|
||||
|
||||
<p>使用提供的比较器函数从输入切片中移除重复元素。此函数保持元素的顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uniqueNums := slice.UniqueByComparator([]int{1, 2, 3, 1, 2, 4, 5, 6, 4}, func(item int, other int) bool {
|
||||
return item == other
|
||||
})
|
||||
|
||||
caseInsensitiveStrings := slice.UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
||||
return strings.ToLower(item) == strings.ToLower(other)
|
||||
})
|
||||
|
||||
fmt.Println(uniqueNums)
|
||||
fmt.Println(caseInsensitiveStrings)
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4 5 6]
|
||||
// [apple banana cherry date]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByConcurrent">UniqueByConcurrent</span>
|
||||
|
||||
<p>并发的从输入切片中移除重复元素,结果保持元素的顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UniqueByConcurrent[T comparable](slice []T, comparator func(item T, other T) bool, numThreads int) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 1, 2, 4, 5, 6, 4, 7}
|
||||
comparator := func(item int, other int) bool { return item == other }
|
||||
|
||||
result := slice.UniqueByConcurrent(nums, comparator, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// [1 2 3 4 5 6 7]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByField">UniqueByField</span>
|
||||
|
||||
<p>根据struct字段对struct切片去重复。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UniqueByField[T any](slice []T, field string) ([]T, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6cifcZSPIGu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type User struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
users := []User{
|
||||
{ID: 1, Name: "a"},
|
||||
{ID: 2, Name: "b"},
|
||||
{ID: 1, Name: "c"},
|
||||
}
|
||||
|
||||
result, err := slice.UniqueByField(users, "ID")
|
||||
if err != nil {
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [{1 a} {2 b}]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2464,7 +2782,7 @@ func main() {
|
||||
func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lkQ3Ri2NQhV)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -2475,17 +2793,195 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.Partition(nums)
|
||||
result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
|
||||
result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })
|
||||
result1 := slice.Partition(nums)
|
||||
result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
|
||||
result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [[1 2 3 4 5]]
|
||||
// [[2 4] [1 3 5]]
|
||||
// [[1 2] [3 4] [5]]
|
||||
// Output:
|
||||
// [[1 2 3 4 5]]
|
||||
// [[2 4] [1 3 5]]
|
||||
// [[1 2] [3 4] [5]]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Random">Random</span>
|
||||
|
||||
<p>随机返回切片中元素以及下标, 当切片长度为0时返回下标-1</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Random[T any](slice []T) (val T, idx int)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UzpGQptWppw)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
val, idx := slice.Random(nums)
|
||||
if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
|
||||
fmt.Println("okk")
|
||||
}
|
||||
// Output:
|
||||
// okk
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SetToDefaultIf">SetToDefaultIf</span>
|
||||
|
||||
<p>根据给定给定的predicate判定函数来修改切片中的元素。对于满足的元素,将其替换为指定的默认值,同时保持元素在切片中的位置不变。函数返回修改后的切片以及被修改的元素个数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SetToDefaultIf[T any](slice []T, predicate func(T) bool) ([]T, int)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9AXGlPRC0-A)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := []string{"a", "b", "a", "c", "d", "a"}
|
||||
modifiedStrs, count := slice.SetToDefaultIf(strs, func(s string) bool { return "a" == s })
|
||||
|
||||
fmt.Println(modifiedStrs)
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// [ b c d ]
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Break">Break</span>
|
||||
|
||||
<p>根据判断函数将切片分成两部分。它开始附加到与函数匹配的第一个元素之后的第二个切片。第一个匹配之后的所有元素都包含在第二个切片中,无论它们是否与函数匹配。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yLYcBTyeQIz)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
even := func(n int) bool { return n%2 == 0 }
|
||||
|
||||
resultEven, resultAfterFirstEven := slice.Break(nums, even)
|
||||
|
||||
fmt.Println(resultEven)
|
||||
fmt.Println(resultAfterFirstEven)
|
||||
|
||||
// Output:
|
||||
// [1]
|
||||
// [2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RightPadding">RightPadding</span>
|
||||
|
||||
<p>在切片的右部添加元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0_2rlLEMBXL)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
padded := slice.RightPadding(nums, 0, 3)
|
||||
fmt.Println(padded)
|
||||
// Output:
|
||||
// [1 2 3 4 5 0 0 0]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LeftPadding">LeftPadding</span>
|
||||
|
||||
<p>在切片的左部添加元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jlQVoelLl2k)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
padded := slice.LeftPadding(nums, 0, 3)
|
||||
fmt.Println(padded)
|
||||
// Output:
|
||||
// [0 0 0 1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Frequency">Frequency</span>
|
||||
|
||||
<p>计算切片中每个元素出现的频率。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Frequency[T comparable](slice []T) map[T]int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := []string{"a", "b", "b", "c", "c", "c"}
|
||||
result := slice.Frequency(strs)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// map[a:1 b:2 c:3]
|
||||
}
|
||||
```
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
- [IsExported](#IsExported)
|
||||
- [IsZero](#IsZero)
|
||||
- [IsSlice](#IsSlice)
|
||||
- [IsTargetType](#IsTargetType)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -531,4 +532,45 @@ func main() {
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsTargetType">IsTargetType</span>
|
||||
|
||||
<p>判断属性是否是目标类型</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsTargetType(targetType reflect.Kind) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(n.IsTargetType(reflect.String))
|
||||
fmt.Println(a.IsTargetType(reflect.Slice))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -49,6 +49,7 @@ import (
|
||||
- [StringToBytes](#StringToBytes)
|
||||
- [BytesToString](#BytesToString)
|
||||
- [IsBlank](#IsBlank)
|
||||
- [IsNotBlank](#IsNotBlank)
|
||||
- [HasPrefixAny](#HasPrefixAny)
|
||||
- [HasSuffixAny](#HasSuffixAny)
|
||||
- [IndexOffset](#IndexOffset)
|
||||
@@ -59,6 +60,15 @@ import (
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
- [SubInBetween](#SubInBetween)
|
||||
- [HammingDistance](#HammingDistance)
|
||||
- [Concat](#Concat)
|
||||
- [Ellipsis](#Ellipsis)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [Rotate](#Rotate)
|
||||
- [TemplateReplace](#TemplateReplace)
|
||||
- [RegexMatchAllGroups](#RegexMatchAllGroups)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1075,6 +1085,45 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsNotBlank">IsNotBlank</span>
|
||||
|
||||
<p>Checks if a string is not whitespace or not empty.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsNotBlank(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/e_oJW0RAquA)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsNotBlank("")
|
||||
result2 := strutil.IsNotBlank(" ")
|
||||
result3 := strutil.IsNotBlank("\t\v\f\n")
|
||||
result4 := strutil.IsNotBlank(" 中文")
|
||||
result5 := strutil.IsNotBlank(" world ")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HasPrefixAny">HasPrefixAny</span>
|
||||
|
||||
<p>检查字符串是否以指定字符串数组中的任何一个开头。</p>
|
||||
@@ -1422,3 +1471,261 @@ func main() {
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SubInBetween">SubInBetween</span>
|
||||
|
||||
<p>获取字符串中指定的起始字符串start和终止字符串end直接的子字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SubInBetween(str string, start string, end string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EDbaRvjeNsv)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "abcde"
|
||||
|
||||
result1 := strutil.SubInBetween(str, "", "de")
|
||||
result2 := strutil.SubInBetween(str, "a", "d")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// abc
|
||||
// bc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HammingDistance">HammingDistance</span>
|
||||
|
||||
<p>计算两个字符串之间的汉明距离。汉明距离是指对应符号不同的位置数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HammingDistance(a, b string) (int, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/glNdQEA9HUi)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
result1, _ := strutil.HammingDistance("de", "de")
|
||||
result2, _ := strutil.HammingDistance("a", "d")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
|
||||
```
|
||||
### <span id="Concat">Concat</span>
|
||||
|
||||
<p>拼接字符串。length是拼接后字符串的长度,如果不确定则传0或负数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Concat(length int, str ...string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
|
||||
result2 := strutil.Concat(11, "Go", " ", "Language")
|
||||
result3 := strutil.Concat(0, "An apple a ", "day,", "keeps the", " doctor away")
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// Hello World!
|
||||
// Go Language
|
||||
// An apple a day,keeps the doctor away
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Ellipsis">Ellipsis</span>
|
||||
|
||||
<p>将字符串截断到指定长度,并在末尾添加省略号。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Ellipsis(str string, length int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Ellipsis("hello world", 5)
|
||||
result2 := strutil.Ellipsis("你好,世界!", 2)
|
||||
result3 := strutil.Ellipsis("😀😃😄😁😆", 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// hello...
|
||||
// 你好...
|
||||
// 😀😃😄...
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Shuffle">Shuffle</span>
|
||||
|
||||
<p>打乱给定字符串中的字符顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Shuffle(str string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := strutil.Shuffle("hello")
|
||||
fmt.Println(result) //olelh (random order)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Rotate">Rotate</span>
|
||||
|
||||
<p>按指定的字符数旋转字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Rotate(str string, shift int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := Rotate("Hello", 0)
|
||||
result2 := Rotate("Hello", 1)
|
||||
result3 := Rotate("Hello", 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// Hello
|
||||
// oHell
|
||||
// loHel
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TemplateReplace">TemplateReplace</span>
|
||||
|
||||
<p>将模板字符串中的占位符替换为map中的相应值。占位符括在花括号中,例如 {key}。例如,模板字符串为“Hello, {name}!”,map为{"name": "world"},结果将为“Hello, world!”。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TemplateReplace(template string, data map[string]string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||
data := map[string]string{
|
||||
"name": "Bob",
|
||||
"age": "20",
|
||||
}
|
||||
|
||||
result := strutil.TemplateReplace(template, data)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// Hello, my name is Bob, I'm 20 years old.
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RegexMatchAllGroups">RegexMatchAllGroups</span>
|
||||
|
||||
<p>使用正则表达式匹配字符串中的所有子组并返回结果。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RegexMatchAllGroups(pattern, str string) [][]string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pattern := `(\w+\.+\w+)@(\w+)\.(\w+)`
|
||||
str := "Emails: john.doe@example.com and jane.doe@example.com"
|
||||
|
||||
result := strutil.RegexMatchAllGroups(pattern, str)
|
||||
|
||||
fmt.Println(result[0])
|
||||
fmt.Println(result[1])
|
||||
|
||||
// Output:
|
||||
// [john.doe@example.com john.doe example com]
|
||||
// [jane.doe@example.com jane.doe example com]
|
||||
}
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# System
|
||||
|
||||
system 包含 os, runtime, shell command 相关函数。
|
||||
system 包含 os, 运行time, shell command 相关函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -31,6 +31,11 @@ import (
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
- [StartProcess](#StartProcess)
|
||||
- [StopProcess](#StopProcess)
|
||||
- [KillProcess](#KillProcess)
|
||||
- [GetProcessInfo](#GetProcessInfo)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -241,13 +246,14 @@ func main() {
|
||||
|
||||
### <span id="ExecCommand">ExecCommand</span>
|
||||
|
||||
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-a(linux),dir(windows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
|
||||
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-a(linux),dir(windows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。
|
||||
函数的第二个参数是cmd选项控制参数,类型是func(*exec.Cmd),可以通过这个参数设置cmd属性。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type (
|
||||
Option func(*exec.Cmd)
|
||||
Option func(*exec.Cmd)
|
||||
)
|
||||
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||
```
|
||||
@@ -262,7 +268,9 @@ import (
|
||||
|
||||
func main() {
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
stdout, stderr, err := system.ExecCommand("ls", func(cmd *exec.Cmd) {
|
||||
cmd.Dir = "/tmp"
|
||||
})
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
@@ -305,3 +313,132 @@ func main() {
|
||||
fmt.Println(osBit) // 32 or 64
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StartProcess">StartProcess</span>
|
||||
|
||||
<p>创建进程。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StartProcess(command string, args ...string) (int, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "2")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(pid)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StopProcess">StopProcess</span>
|
||||
|
||||
<p>停止进程。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StopProcess(pid int) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "10")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
err = system.StopProcess(pid)
|
||||
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="KillProcess">KillProcess</span>
|
||||
|
||||
<p>杀掉进程。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func KillProcess(pid int) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "10")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
err = system.KillProcess(pid)
|
||||
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetProcessInfo">GetProcessInfo</span>
|
||||
|
||||
<p>根据进程id获取进程信息。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetProcessInfo(pid int) (*ProcessInfo, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("ls", "-a")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
processInfo, err := system.GetProcessInfo(pid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(processInfo)
|
||||
}
|
||||
```
|
||||
@@ -67,7 +67,6 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="ContainChinese">ContainChinese</span>
|
||||
@@ -80,7 +79,7 @@ import (
|
||||
func ContainChinese(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/7DpU0uElYeM)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/7DpU0uElYeM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -114,7 +113,7 @@ func main() {
|
||||
func ContainLetter(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/lqFD04Yyewp)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/lqFD04Yyewp)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -148,7 +147,7 @@ func main() {
|
||||
func ContainLower(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Srqi1ItvnAA)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Srqi1ItvnAA)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -182,7 +181,7 @@ func main() {
|
||||
func ContainUpper(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/CmWeBEk27-z)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/CmWeBEk27-z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -216,7 +215,7 @@ func main() {
|
||||
func IsAlpha(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/7Q5sGOz2izQ)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/7Q5sGOz2izQ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -250,7 +249,7 @@ func main() {
|
||||
func IsAllUpper(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/ZHctgeK1n4Z)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ZHctgeK1n4Z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -284,7 +283,7 @@ func main() {
|
||||
func IsAllLower(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/GjqCnOfV6cM)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/GjqCnOfV6cM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -318,7 +317,7 @@ func main() {
|
||||
func IsASCII(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/hfQNPLX0jNa)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/hfQNPLX0jNa)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -358,7 +357,7 @@ func main() {
|
||||
func IsBase64(base64 string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/sWHEySAt6hl)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/sWHEySAt6hl)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -389,7 +388,7 @@ func main() {
|
||||
func IsChineseMobile(mobileNum string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/GPYUlGTOqe3)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/GPYUlGTOqe3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -420,7 +419,7 @@ func main() {
|
||||
func IsChineseIdNum(id string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/d8EWhl2UGDF)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/d8EWhl2UGDF)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -451,7 +450,7 @@ func main() {
|
||||
func IsChinesePhone(phone string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/RUD_-7YZJ3I)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/RUD_-7YZJ3I)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -482,7 +481,7 @@ func main() {
|
||||
func IsCreditCard(creditCart string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/sNwwL6B0-v4)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/sNwwL6B0-v4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -513,7 +512,7 @@ func main() {
|
||||
func IsDns(dns string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/jlYApVLLGTZ)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/jlYApVLLGTZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -547,7 +546,7 @@ func main() {
|
||||
func IsEmail(email string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Os9VaFlT33G)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Os9VaFlT33G)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -578,7 +577,7 @@ func main() {
|
||||
func IsEmptyString(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/dpzgUjFnBCX)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/dpzgUjFnBCX)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -612,7 +611,7 @@ func main() {
|
||||
func IsInt(v any) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/eFoIHbgzl-z)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/eFoIHbgzl-z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -649,7 +648,7 @@ func main() {
|
||||
func IsFloat(v any) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/vsyG-sxr99_Z)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/vsyG-sxr99_Z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -686,7 +685,7 @@ func main() {
|
||||
func IsNumber(v any) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/mdJHOAvtsvF)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/mdJHOAvtsvF)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -713,7 +712,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsIntStr">IsIntStr</span>
|
||||
|
||||
<p>验证字符串是否是可以转换为整数。</p>
|
||||
@@ -724,7 +722,7 @@ func main() {
|
||||
func IsIntStr(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/jQRtFv-a0Rk)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/jQRtFv-a0Rk)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -761,7 +759,7 @@ func main() {
|
||||
func IsFloatStr(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/LOYwS_Oyl7U)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/LOYwS_Oyl7U)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -798,7 +796,7 @@ func main() {
|
||||
func IsNumberStr(s string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/LzaKocSV79u)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/LzaKocSV79u)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -835,7 +833,7 @@ func main() {
|
||||
func IsJSON(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/8Kip1Itjiil)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/8Kip1Itjiil)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -872,7 +870,7 @@ func main() {
|
||||
func IsRegexMatch(s, regex string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/z_XeZo_litG)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/z_XeZo_litG)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -893,8 +891,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsIp">IsIp</span>
|
||||
|
||||
<p>验证字符串是否是ip地址。</p>
|
||||
@@ -905,7 +901,7 @@ func main() {
|
||||
func IsIp(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/FgcplDvmxoD)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/FgcplDvmxoD)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -942,7 +938,7 @@ func main() {
|
||||
func IsIpV4(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/zBGT99EjaIu)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zBGT99EjaIu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -973,7 +969,7 @@ func main() {
|
||||
func IsIpV6(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/AHA0r0AzIdC)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/AHA0r0AzIdC)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1004,7 +1000,7 @@ func main() {
|
||||
func IsStrongPassword(password string, length int) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/QHdVcSQ3uDg)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/QHdVcSQ3uDg)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1035,7 +1031,7 @@ func main() {
|
||||
func IsUrl(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/pbJGa7F98Ka)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/pbJGa7F98Ka)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1070,7 +1066,7 @@ func main() {
|
||||
func IsWeakPassword(password string, length int) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/wqakscZH5gH)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/wqakscZH5gH)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1101,7 +1097,7 @@ func main() {
|
||||
func IsZeroValue(value any) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/UMrwaDCi_t4)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/UMrwaDCi_t4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1138,7 +1134,7 @@ func main() {
|
||||
func IsGBK(data []byte) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/E2nt3unlmzP)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/E2nt3unlmzP)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1160,7 +1156,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsPrintable">IsPrintable</span>
|
||||
|
||||
<p>检查字符串是否全部为可打印字符。</p>
|
||||
@@ -1171,7 +1166,7 @@ func main() {
|
||||
func IsPrintable(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Pe1FE2gdtTP)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Pe1FE2gdtTP)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1211,7 +1206,7 @@ func main() {
|
||||
func IsBin(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ogPeg2XJH4P)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1248,7 +1243,7 @@ func main() {
|
||||
func IsHex(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/M2qpHbEwmm7)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1285,7 +1280,7 @@ func main() {
|
||||
func IsBase64URL(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/vhl4mr8GZ6S)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1322,7 +1317,7 @@ func main() {
|
||||
func IsJWT(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/R6Op7heJbKI)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1353,7 +1348,7 @@ func main() {
|
||||
func IsVisa(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/SdS2keOyJsl)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1384,7 +1379,7 @@ func main() {
|
||||
func IsMasterCard(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/CwWBFRrG27b)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1415,7 +1410,7 @@ func main() {
|
||||
func IsAmericanExpress(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/HIDFpcOdpkd)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1436,7 +1431,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsUnionPay">IsVisa</span>
|
||||
### <span id="IsUnionPay">IsUnionPay</span>
|
||||
|
||||
<p>检查字符串是否是有效的美国银联卡号。</p>
|
||||
|
||||
@@ -1446,7 +1441,7 @@ func main() {
|
||||
func IsUnionPay(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/CUHPEwEITDf)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1477,7 +1472,7 @@ func main() {
|
||||
func IsChinaUnionPay(v string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/yafpdxLiymu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
|
||||
@@ -27,7 +27,7 @@ outline: deep
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
background: #ecefff;
|
||||
background: #059669;
|
||||
border: 1px solid;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
@@ -43,12 +43,12 @@ import (
|
||||
|
||||
### <span id="BubbleSort">BubbleSort</span>
|
||||
|
||||
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with bubble sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func BubbleSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||
@@ -91,12 +91,12 @@ func main() {
|
||||
|
||||
### <span id="InsertionSort">InsertionSort</span>
|
||||
|
||||
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with insertion sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func InsertionSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||
@@ -117,7 +117,7 @@ type people struct {
|
||||
// PeopleAageComparator sort people slice by age field
|
||||
type peopleAgeComparator struct{}
|
||||
|
||||
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
|
||||
// Compare implements github.com/duke-git/lancet/constraints/constraints.go/Comparator
|
||||
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
|
||||
p1, _ := v1.(people)
|
||||
p2, _ := v2.(people)
|
||||
@@ -154,12 +154,12 @@ func main() {
|
||||
|
||||
### <span id="SelectionSort">SelectionSort</span>
|
||||
|
||||
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with selection sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func SelectionSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||
@@ -202,12 +202,12 @@ func main() {
|
||||
|
||||
### <span id="ShellSort">ShellSort</span>
|
||||
|
||||
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with shell sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func ShellSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||
@@ -250,12 +250,12 @@ func main() {
|
||||
|
||||
### <span id="QuickSort">QuickSort</span>
|
||||
|
||||
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with quick sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||
func QuickSort[T any](slice []T comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||
@@ -298,12 +298,12 @@ func main() {
|
||||
|
||||
### <span id="HeapSort">HeapSort</span>
|
||||
|
||||
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with heap sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func HeapSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||
@@ -346,12 +346,12 @@ func main() {
|
||||
|
||||
### <span id="MergeSort">MergeSort</span>
|
||||
|
||||
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with merge sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
func MergeSort[T any](slice []T, comparator constraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||
@@ -394,12 +394,12 @@ func main() {
|
||||
|
||||
### <span id="CountSort">CountSort</span>
|
||||
|
||||
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
|
||||
<p>Sort slice with count sort algorithm. Param comparator should implements constraints.Comparator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
func CountSort[T any](slice []T, comparator constraints.Comparator) []T
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||
@@ -448,7 +448,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||
@@ -499,7 +499,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||
|
||||
@@ -43,6 +43,10 @@ import (
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
- [ToStdBase64](#ToStdBase64)
|
||||
- [ToUrlBase64](#ToUrlBase64)
|
||||
- [ToRawStdBase64](#ToRawStdBase64)
|
||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -567,6 +571,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="EncodeByte">EncodeByte</span>
|
||||
|
||||
<p>Encode data to byte slice.</p>
|
||||
@@ -632,69 +637,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DeepClone">DeepClone</span>
|
||||
|
||||
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DeepClone[T any](src T) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/j4DP5dquxnk)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Struct struct {
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
unexported string
|
||||
}
|
||||
|
||||
cases := []interface{}{
|
||||
true,
|
||||
1,
|
||||
0.1,
|
||||
map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
},
|
||||
&Struct{
|
||||
Str: "test",
|
||||
Int: 1,
|
||||
Float: 0.1,
|
||||
Bool: true,
|
||||
Nil: nil,
|
||||
// unexported: "can't be cloned",
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range cases {
|
||||
cloned := convertor.DeepClone(item)
|
||||
|
||||
isPointerEqual := &cloned == &item
|
||||
fmt.Println(cloned, isPointerEqual)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// true false
|
||||
// 1 false
|
||||
// 0.1 false
|
||||
// map[a:1 b:2] false
|
||||
// &{test 1 0.1 true <nil> } false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CopyProperties">CopyProperties</span>
|
||||
|
||||
@@ -775,41 +717,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToInterface">ToInterface</span>
|
||||
|
||||
<p>Converts reflect value to its interface type.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/syqw0-WG7Xd)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Utf8ToGbk">Utf8ToGbk</span>
|
||||
|
||||
<p>Converts utf8 encoding data to GBK encoding data.</p>
|
||||
@@ -875,4 +782,338 @@ func main() {
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToStdBase64">ToStdBase64</span>
|
||||
|
||||
<p>Convert a value to a string encoded in standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON formatted string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToStdBase64(value any) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/_fLJqJD3NMo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
afterEncode := convertor.ToStdBase64(nil)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
afterEncode = convertor.ToStdBase64("")
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = convertor.ToStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
//
|
||||
//
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToUrlBase64">ToUrlBase64</span>
|
||||
|
||||
<p>Convert a value to a string encoded in url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON formatted string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToUrlBase64(value any) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/C_d0GlvEeUR)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
afterEncode := convertor.ToUrlBase64(nil)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode = convertor.ToUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
//
|
||||
// aGVsbG8=
|
||||
// aGVsbG8=
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
|
||||
// MTIzLjQ1Ng==
|
||||
// dHJ1ZQ==
|
||||
// ZXJy
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### <span id="ToRawStdBase64">ToRawStdBase64</span>
|
||||
|
||||
<p>Convert a value to a string encoded in raw standard Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON formatted string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToRawStdBase64(value any) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/wSAr3sfkDcv)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode := convertor.ToRawStdBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToRawStdBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToRawStdBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToRawStdBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToRawStdBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToRawStdBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToRawUrlBase64">ToRawUrlBase64</span>
|
||||
|
||||
<p> Convert a value to a string encoded in raw url Base64. Error data of type "error" will also be encoded, and complex structures will be converted to a JSON formatted string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToRawUrlBase64(value any) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/HwdDPFcza1O)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
stringVal := "hello"
|
||||
afterEncode := convertor.ToRawUrlBase64(stringVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
byteSliceVal := []byte("hello")
|
||||
afterEncode = convertor.ToRawUrlBase64(byteSliceVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
intVal := 123
|
||||
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
||||
A string
|
||||
B int
|
||||
}{"hello", 3}}
|
||||
afterEncode = convertor.ToRawUrlBase64(mapVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
floatVal := 123.456
|
||||
afterEncode = convertor.ToRawUrlBase64(floatVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
boolVal := true
|
||||
afterEncode = convertor.ToRawUrlBase64(boolVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
errVal := errors.New("err")
|
||||
afterEncode = convertor.ToRawUrlBase64(errVal)
|
||||
fmt.Println(afterEncode)
|
||||
|
||||
// Output:
|
||||
// aGVsbG8
|
||||
// aGVsbG8
|
||||
// MTIz
|
||||
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
|
||||
// MTIzLjQ1Ng
|
||||
// dHJ1ZQ
|
||||
// ZXJy
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DeepClone">DeepClone</span>
|
||||
|
||||
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DeepClone[T any](src T) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/j4DP5dquxnk)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Struct struct {
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
unexported string
|
||||
}
|
||||
|
||||
cases := []interface{}{
|
||||
true,
|
||||
1,
|
||||
0.1,
|
||||
map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
},
|
||||
&Struct{
|
||||
Str: "test",
|
||||
Int: 1,
|
||||
Float: 0.1,
|
||||
Bool: true,
|
||||
Nil: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range cases {
|
||||
cloned := convertor.DeepClone(item)
|
||||
|
||||
isPointerEqual := &cloned == &item
|
||||
fmt.Println(cloned, isPointerEqual)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// true false
|
||||
// 1 false
|
||||
// 0.1 false
|
||||
// map[a:1 b:2] false
|
||||
// &{test 1 0.1 true <nil> } false
|
||||
}
|
||||
```
|
||||
@@ -1,18 +1,18 @@
|
||||
# Cryptor
|
||||
|
||||
Package cryptor contains some functions for data encryption and decryption. Support base64, md5, hmac, aes, des, rsa.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
|
||||
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
@@ -23,49 +23,53 @@ import (
|
||||
|
||||
## Index
|
||||
|
||||
- [AesEcbEncrypt](#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||
- [Md5Byte](#Md5Byte)
|
||||
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha1WithBase64](#Sha1WithBase64)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha256WithBase64](#Sha256WithBase64)
|
||||
- [Sha512](#Sha512)
|
||||
- [Sha512WithBase64](#Sha512WithBase64)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
|
||||
- [AesEcbEncrypt](#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [AesGcmEncrypt](#AesGcmEncrypt)
|
||||
- [AesGcmDecrypt](#AesGcmDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||
- [Md5Byte](#Md5Byte)
|
||||
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha1WithBase64](#Sha1WithBase64)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha256WithBase64](#Sha256WithBase64)
|
||||
- [Sha512](#Sha512)
|
||||
- [Sha512WithBase64](#Sha512WithBase64)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
|
||||
- [RsaEncryptOAEP](#RsaEncryptOAEP)
|
||||
- [RsaDecryptOAEP](#RsaDecryptOAEP)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -80,6 +84,7 @@ import (
|
||||
```go
|
||||
func AesEcbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
|
||||
|
||||
```go
|
||||
@@ -113,6 +118,7 @@ func main() {
|
||||
```go
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
|
||||
|
||||
```go
|
||||
@@ -146,6 +152,7 @@ func main() {
|
||||
```go
|
||||
func AesCbcEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/IOq_g8_lKZD)</span></b>
|
||||
|
||||
```go
|
||||
@@ -339,6 +346,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesCfbDecrypt">AesOfbDecrypt</span>
|
||||
|
||||
<p>Decrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
|
||||
@@ -373,6 +381,74 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesGcmEncrypt">AesGcmEncrypt</span>
|
||||
|
||||
<p>Encrypt data with key use AES GCM algorithm.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AesGcmEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run]()</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesGcmEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesGcmDecrypt">AesGcmDecrypt</span>
|
||||
|
||||
<p>Decrypt data with key use AES GCM algorithm.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AesGcmDecrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run]()</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := "hello"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
encrypted := cryptor.AesGcmEncrypt([]byte(data), []byte(key))
|
||||
decrypted := cryptor.AesGcmDecrypt(encrypted, []byte(key))
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Base64StdEncode">Base64StdEncode</span>
|
||||
|
||||
<p>Encode string with base64 encoding.</p>
|
||||
@@ -382,6 +458,7 @@ func main() {
|
||||
```go
|
||||
func Base64StdEncode(s string) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/VOaUyQUreoK)</span></b>
|
||||
|
||||
```go
|
||||
@@ -400,6 +477,7 @@ func main() {
|
||||
// aGVsbG8=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Base64StdDecode">Base64StdDecode</span>
|
||||
|
||||
<p>Decode a base64 encoded string.</p>
|
||||
@@ -463,6 +541,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesEcbDecrypt">DesEcbDecrypt</span>
|
||||
|
||||
<p>Decrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p>
|
||||
@@ -565,6 +644,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesCtrCrypt">DesCtrCrypt</span>
|
||||
|
||||
<p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
|
||||
@@ -632,6 +712,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesCfbDecrypt">DesCfbDecrypt</span>
|
||||
|
||||
<p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
|
||||
@@ -665,6 +746,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesOfbEncrypt">DesOfbEncrypt</span>
|
||||
|
||||
<p>Enecrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
|
||||
@@ -698,6 +780,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesOfbDecrypt">DesOfbDecrypt</span>
|
||||
|
||||
<p>Decrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
|
||||
@@ -988,7 +1071,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Md5String">Md5String</span>
|
||||
|
||||
<p>Get the md5 value of string.</p>
|
||||
@@ -1366,11 +1448,11 @@ func main() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
@@ -1378,7 +1460,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RsaDecrypt">RsaDecrypt</span>
|
||||
|
||||
<p>Decrypt data with private key file useing ras algorithm.</p>
|
||||
@@ -1404,11 +1485,11 @@ func main() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
@@ -1416,5 +1497,113 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateRsaKeyPair">GenerateRsaKeyPair</span>
|
||||
|
||||
<p>Creates rsa private and public key.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaEncryptOAEP">RsaEncryptOAEP</span>
|
||||
|
||||
<p>Encrypts the given data with RSA-OAEP.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaDecryptOAEP">RsaDecryptOAEP</span>
|
||||
|
||||
<p>Decrypts the data with RSA-OAEP.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pri, pub := cryptor.GenerateRsaKeyPair(1024)
|
||||
|
||||
data := []byte("hello world")
|
||||
label := []byte("123456")
|
||||
|
||||
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
- [Remove](#Remove)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [IndexOfFunc](#IndexOfFunc)
|
||||
- [LastIndexOfFunc](#LastIndexOfFunc)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Contain](#Contain)
|
||||
- [ValueOf](#ValueOf)
|
||||
@@ -197,6 +199,59 @@ func main() {
|
||||
|
||||
```
|
||||
|
||||
|
||||
### <span id="IndexOfFunc">IndexOfFunc</span>
|
||||
<p> IndexOfFunc returns the first index satisfying the functional predicate f(v) bool. if not found return -1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1, 2, 3})
|
||||
|
||||
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 1 })) //0
|
||||
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOfFunc">LastIndexOfFunc</span>
|
||||
<p>LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying the functional predicate f(T) bool. if not found return -1.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1, 2, 3, 1})
|
||||
|
||||
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 1 })) // 3
|
||||
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 0 })) //-1
|
||||
}
|
||||
```
|
||||
|
||||
### IsEmpty
|
||||
|
||||
Returns true if this list does not contain any elements.
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
- [Iterate](#Iterate)
|
||||
- [Keys](#Keys)
|
||||
- [Values](#Values)
|
||||
- [FilterByValue](#FilterByValue)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -311,4 +312,77 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FilterByValue">FilterByValue</span>
|
||||
|
||||
<p>Returns a filtered HashMap.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (hm *HashMap) FilterByValue(perdicate func(value any) bool) *HashMap
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
hm := hashmap.NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
hm.Put("d", 4)
|
||||
hm.Put("e", 5)
|
||||
hm.Put("f", 6)
|
||||
|
||||
filteredHM := hm.FilterByValue(func(value any) bool {
|
||||
return value.(int) == 1 || value.(int) == 3
|
||||
})
|
||||
|
||||
fmt.Println(filteredHM.Size()) //2
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="ToInterface">ToInterface</span>
|
||||
|
||||
<p>Converts reflect value to its interface type.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/syqw0-WG7Xd)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -44,9 +44,9 @@ MaxHeap is a binary heap tree implemented by slice, The key of the root node is
|
||||
```go
|
||||
type MaxHeap[T any] struct {
|
||||
data []T
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
|
||||
func NewMaxHeap[T any](comparator constraints.Comparator) *MaxHeap[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
|
||||
416
docs/en/api/packages/datastructure/optional.md
Normal file
416
docs/en/api/packages/datastructure/optional.md
Normal file
@@ -0,0 +1,416 @@
|
||||
# Optional
|
||||
Optional is a type that may or may not contain a non-nil value.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go](https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [Of](#Of)
|
||||
- [FromNillable](#FromNillable)
|
||||
- [Default](#Default)
|
||||
- [IsNotNil](#IsNotNil)
|
||||
- [IsNil](#IsNil)
|
||||
- [IsNotNil](#IsNotNil)
|
||||
- [IfNotNilOrElse](#IfNotNilOrElse)
|
||||
- [Umwarp](#Umwarp)
|
||||
- [OrElse](#OrElse)
|
||||
- [OrElseGet](#OrElseGet)
|
||||
- [OrElseTrigger](#OrElseTrigger)
|
||||
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="Of">Of</span>
|
||||
<p>Returns an Optional with a non-nil value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Of[T any](value T) Optional[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value := 42
|
||||
opt := optional.Of(value)
|
||||
|
||||
fmt.Println(opt.Get())
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FromNillable">FromNillable</span>
|
||||
<p>Returns an Optional for a given value, which may be nil.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FromNillable[T any](value *T) Optional[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var value *int = nil
|
||||
opt := optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Default">Default</span>
|
||||
<p>Returns an default Optional instance.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Default[T any]() Optional[T]
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
fmt.Println(optDefault.IsNil())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsNil">IsNil</span>
|
||||
<p>Checks if the Optional is nil.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IsNil() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
fmt.Println(optDefault.IsNil())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsNotNil">IsNotNil</span>
|
||||
<p>Checks if there is a value not nil.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IsNotNil() bool
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var value *int = nil
|
||||
opt := optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
value = new(int)
|
||||
*value = 42
|
||||
opt = optional.FromNillable(value)
|
||||
|
||||
fmt.Println(opt.IsNotNil())
|
||||
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IfNotNil">IfNotNil</span>
|
||||
<p>Performs the given action with the value if a value is present.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IfNotNil(action func(value T))
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
called := false
|
||||
action := func(value int) { called = true }
|
||||
|
||||
optDefault := optional.Default[int]()
|
||||
optDefault.IfNotNil(action)
|
||||
|
||||
fmt.Println(called)
|
||||
|
||||
called = false // Reset for next test
|
||||
optWithValue := optional.Of(42)
|
||||
optWithValue.IfNotNil(action)
|
||||
|
||||
fmt.Println(optWithValue.IsNotNil())
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IfNotNilOrElse">IfNotNilOrElse</span>
|
||||
<p>Performs the action with the value if not nil, otherwise performs the fallback action.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) IfNotNilOrElse(action func(value T), fallbackAction func())
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
calledWithValue := false
|
||||
valueAction := func(value int) { calledWithValue = true }
|
||||
emptyAction := func() { t.Errorf("Empty action should not be called when value is present") }
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
optWithValue.IfNotNilOrElse(valueAction, emptyAction)
|
||||
|
||||
fmt.Println(calledWithValue)
|
||||
|
||||
calledWithEmpty := false
|
||||
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
|
||||
emptyAction = func() { calledWithEmpty = true }
|
||||
|
||||
optDefault := optional.Default[int]()
|
||||
optDefault.IfNotNilOrElse(valueAction, emptyAction)
|
||||
|
||||
fmt.Println(calledWithEmpty)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
<p>Returns the value if not nil, otherwise panics.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) Unwrap() T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value := 42
|
||||
opt := optional.Of(value)
|
||||
|
||||
fmt.Println(opt.Unwrap())
|
||||
|
||||
// Output:
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OrElse">OrElse</span>
|
||||
<p>Returns the value if not nill, otherwise returns other.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) OrElse(other T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
val := optDefault.OrElse(100)
|
||||
fmt.Println(val)
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
val = optWithValue.OrElse(100)
|
||||
fmt.Println(val)
|
||||
|
||||
// Output:
|
||||
// 100
|
||||
// 42
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OrElseGet">OrElseGet</span>
|
||||
<p>Returns the value if not nil, otherwise invokes action and returns the result.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (o Optional[T]) OrElseGet(action func() T) T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
action := func() int { return 100 }
|
||||
|
||||
val := optDefault.OrElseGet(action)
|
||||
fmt.Println(val)
|
||||
|
||||
// Output:
|
||||
// 100
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OrElseTrigger">OrElseTrigger</span>
|
||||
<p>Returns the value if present, otherwise returns an error.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
OrElseTrigger(errorHandler func() error) (T, error)
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datastructure/optional"
|
||||
)
|
||||
|
||||
func main() {
|
||||
optDefault := optional.Default[int]()
|
||||
_, err := optDefault.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
fmt.Println(err.Error())
|
||||
|
||||
optWithValue := optional.Of(42)
|
||||
val, err := optWithValue.OrElseTrigger(func() error { return errors.New("no value") })
|
||||
|
||||
fmt.Println(val)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// no value
|
||||
// 42
|
||||
// nil
|
||||
}
|
||||
```
|
||||
@@ -1100,12 +1100,12 @@ Common queue implemented by slice.
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T]
|
||||
func NewPriorityQueue[T any](capacity int, comparator constraints.Comparator) *PriorityQueue[T]
|
||||
|
||||
type PriorityQueue[T any] struct {
|
||||
items []T
|
||||
size int
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
|
||||
## Index
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [NewSetFromSlice](#NewSetFromSlice)
|
||||
- [Values](#Values)
|
||||
- [New](#New)
|
||||
- [FromSlice](#FromSlice)
|
||||
- [Values<sup>deprecated</sup>](#Values)
|
||||
- [Add](#Add)
|
||||
- [AddIfNotExist](#AddIfNotExist)
|
||||
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||
@@ -41,20 +41,23 @@ import (
|
||||
- [Intersection](#Intersection)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
- [Pop](#Pop)
|
||||
- [ToSlice](#ToSlice)
|
||||
- [ToSortedSlice](#ToSortedSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="NewSet">NewSet</span>
|
||||
### <span id="New">New</span>
|
||||
|
||||
<p>Create a set instance</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type Set[T comparable] map[T]bool
|
||||
func NewSet[T comparable](items ...T) Set[T]
|
||||
type Set[T comparable] map[T]struct{}
|
||||
func New[T comparable](items ...T) Set[T]
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
@@ -68,19 +71,19 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
st := set.New[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NewSetFromSlice">NewSetFromSlice</span>
|
||||
### <span id="FromSlice">FromSlice</span>
|
||||
|
||||
<p>Create a set from slice</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewSetFromSlice[T comparable](items []T) Set[T]
|
||||
func FromSlice[T comparable](items []T) Set[T]
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
@@ -94,14 +97,16 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSetFromSlice([]int{1, 2, 2, 3})
|
||||
st := set.FromSlice([]int{1, 2, 2, 3})
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>Return slice of all set data</p>
|
||||
<p>Return slice of all set data.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `ToSlice` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -120,7 +125,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int](1,2,2,3)
|
||||
st := set.New[int](1,2,2,3)
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
}
|
||||
```
|
||||
@@ -146,7 +151,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Values()) //1,2,3
|
||||
@@ -174,7 +179,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
r1 := st.AddIfNotExist(1)
|
||||
@@ -207,7 +212,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2)
|
||||
|
||||
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||
@@ -246,7 +251,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
set.Delete(3)
|
||||
@@ -275,7 +280,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
st := set.NewSet[int]()
|
||||
st := set.New[int]()
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
fmt.Println(st.Contain(1)) //true
|
||||
@@ -304,9 +309,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(1, 2)
|
||||
set3 := set.New(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
fmt.Println(set1.ContainAll(set3)) //false
|
||||
@@ -334,7 +339,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
|
||||
fmt.Println(set1.Size()) //3
|
||||
}
|
||||
@@ -361,7 +366,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set1.Clone()
|
||||
|
||||
fmt.Println(set1.Size() == set2.Size()) //true
|
||||
@@ -390,9 +395,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2, 3)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(1, 2, 3)
|
||||
set3 := set.New(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.Equal(set2)) //true
|
||||
fmt.Println(set1.Equal(set3)) //false
|
||||
@@ -420,7 +425,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
arr := []int{}
|
||||
set.Iterate(func(item int) {
|
||||
arr = append(arr, item)
|
||||
@@ -451,7 +456,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet(1, 2, 3, 4, 5)
|
||||
s := set.New(1, 2, 3, 4, 5)
|
||||
|
||||
var sum int
|
||||
|
||||
@@ -488,8 +493,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet()
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New()
|
||||
|
||||
fmt.Println(set1.IsEmpty()) //false
|
||||
fmt.Println(set2.IsEmpty()) //true
|
||||
@@ -517,8 +522,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.Union(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,2,3,4,5
|
||||
@@ -546,8 +551,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.Intersection(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //2,3
|
||||
@@ -575,8 +580,8 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,4,5
|
||||
@@ -604,9 +609,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
set1 := set.New(1, 2, 3)
|
||||
set2 := set.New(2, 3, 4, 5)
|
||||
set3 := set.New(2, 3)
|
||||
|
||||
res1 := set1.Minus(set2)
|
||||
fmt.Println(res1.Values()) //1
|
||||
@@ -637,7 +642,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet[int]()
|
||||
s := set.New[int]()
|
||||
s.Add(1)
|
||||
s.Add(2)
|
||||
s.Add(3)
|
||||
@@ -648,3 +653,58 @@ func main() {
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToSlice">ToSlice</span>
|
||||
|
||||
<p>returns a slice containing all values of the set.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ToSlice() (v T, ok bool)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
func main() {
|
||||
s := set.New(1, 2, 3, 4, 5)
|
||||
|
||||
val := s.ToSlice()
|
||||
fmt.Println(val) // [2 3 4 5 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToSortedSlice">ToSortedSlice</span>
|
||||
|
||||
<p>returns a sorted slice containing all values of the set</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) ToSortedSlice() (v T, ok bool)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
func main() {
|
||||
s1 := set.New(1, 2, 3, 4, 5)
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
s2 := FromSlice([]Person{{"Tom", 20}, {"Jerry", 18}, {"Spike", 25}})
|
||||
|
||||
res1 := s1.ToSortedSlice(func(v1, v2 int) bool {
|
||||
return v1 < v2
|
||||
})
|
||||
|
||||
res2 := s2.ToSortedSlice(func(v1, v2 Person) bool {
|
||||
return v1.Age < v2.Age
|
||||
})
|
||||
|
||||
fmt.Println(res1) // [1 2 3 4 5]
|
||||
fmt.Println(res2) // [{Jerry 18} {Tom 20} {Spike 25}]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -41,7 +41,7 @@ import (
|
||||
## Documentation
|
||||
|
||||
## 1. BSTree
|
||||
BSTree is a binary search tree data structure in which each node has at two children, which are referred to as the left child and the right child. In BSTree: leftNode < rootNode < rightNode. Type T should implements Compare function in lancetconstraints.Comparator interface.
|
||||
BSTree is a binary search tree data structure in which each node has at two children, which are referred to as the left child and the right child. In BSTree: leftNode < rootNode < rightNode. Type T should implements Compare function in constraints.Comparator interface.
|
||||
|
||||
### <span id="NewBSTree">NewBSTree</span>
|
||||
<p>Make a BSTree pointer instance</p>
|
||||
@@ -49,11 +49,11 @@ BSTree is a binary search tree data structure in which each node has at two chil
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T]
|
||||
func NewBSTree[T any](rootData T, comparator constraints.Comparator) *BSTree[T]
|
||||
|
||||
type BSTree[T any] struct {
|
||||
root *datastructure.TreeNode[T]
|
||||
comparator lancetconstraints.Comparator
|
||||
comparator constraints.Comparator
|
||||
}
|
||||
|
||||
type TreeNode[T any] struct {
|
||||
|
||||
@@ -65,6 +65,10 @@ import (
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
- [TrackFuncTime](#TrackFuncTime)
|
||||
- [DaysBetween](#DaysBetween)
|
||||
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1465,3 +1469,106 @@ func main() {
|
||||
// 1690363051331788000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TrackFuncTime">TrackFuncTime</span>
|
||||
|
||||
<p>Tracks function execution time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TrackFuncTime(pre time.Time) func()
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer datetime.TrackFuncTime(time.Now())()
|
||||
|
||||
var n int
|
||||
for i := 0; i < 5000000; i++ {
|
||||
n++
|
||||
}
|
||||
|
||||
fmt.Println(1) // Function main execution time: 1.460287ms
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DaysBetween">DaysBetween</span>
|
||||
|
||||
<p>Returns the number of days between two times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DaysBetween(start, end time.Time) int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
result := datetime.DaysBetween(start, end)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 9
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateDatetimesBetween">GenerateDatetimesBetween</span>
|
||||
|
||||
<p>Returns a slice of strings between two times. `layout`: the format of the datetime string.`interval`: the interval between two datetimes.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||
end := time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC)
|
||||
|
||||
layout := "2006-01-02 15:04:05"
|
||||
interval := "1h"
|
||||
|
||||
result, err := datetime.GenerateDatetimesBetween(start, end, layout, interval)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00]
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [CopyDir](#CopyDir)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -45,8 +46,12 @@ import (
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
- [ReadFile](#ReadFile)
|
||||
- [ChunkRead](#ChunkRead)
|
||||
- [ParallelChunkRead](#ParallelChunkRead)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -160,6 +165,34 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CopyDir">CopyDir</span>
|
||||
|
||||
<p>Copy src directory to dst directory, it will copy all files and directories recursively. the access permission will be the same as the source directory. if dstPath exists, it will return an error.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CopyDir(srcPath string, dstPath string) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/YAyFTA_UuPb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test_src", "./test_dest")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CurrentPath">CurrentPath</span>
|
||||
|
||||
<p>return current absolute path.</p>
|
||||
@@ -668,7 +701,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReadCsvFile(filepath string) ([][]string, error)
|
||||
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
||||
@@ -700,7 +733,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
||||
@@ -742,6 +775,59 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||
|
||||
<p>Write slice of map to csv file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// filepath: path of the CSV file.
|
||||
// records: slice of maps to be written. the value of map should be basic type. The maps will be sorted by key in alphabeta order, then be written into csv file.
|
||||
// appendToExistingFile: If true, data will be appended to the file if it exists.
|
||||
// delimiter: Delimiter to use in the CSV file.
|
||||
// headers: order of the csv column headers, needs to be consistent with the key of the map.
|
||||
func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune, headers ...[]string) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/umAIomZFV1c)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fpath := "./test.csv"
|
||||
fileutil.CreateFile(fpath)
|
||||
|
||||
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
|
||||
records := []map[string]any{
|
||||
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||
}
|
||||
|
||||
headers := []string{"Name", "Age", "Gender"}
|
||||
err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadCsvFile(csvFilePath, ';')
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||
|
||||
<p>Writes bytes to target file.</p>
|
||||
@@ -839,3 +925,153 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReadFile">ReadFile</span>
|
||||
|
||||
<p>Read File or URL.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/uNep3Tr8fqF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
reader, fn, err := fileutil.ReadFile("https://httpbin.org/robots.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fn()
|
||||
|
||||
dat, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(string(dat))
|
||||
// Output:
|
||||
// User-agent: *
|
||||
// Disallow: /deny
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ChunkRead">ChunkRead</span>
|
||||
|
||||
<p>reads a block from the file at the specified offset and returns all lines within the block.</p>
|
||||
|
||||
<b>Signature :</b>
|
||||
|
||||
```go
|
||||
func ChunkRead(file *os.File, offset int64, size int, bufPool *sync.Pool) ([]string, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/r0hPmKWhsgf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100
|
||||
|
||||
// test1.csv file content:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
filePath := "./testdata/test1.csv"
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, defaultChunkSizeMB*mb)
|
||||
},
|
||||
}
|
||||
|
||||
lines, err := fileutil.ChunkRead(f, 0, 100, &bufPool)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(lines[0])
|
||||
fmt.Println(lines[1])
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ParallelChunkRead">ParallelChunkRead</span>
|
||||
|
||||
<p>Reads the file in parallel and send each chunk of lines to the specified channel.</p>
|
||||
|
||||
<b>Signature :</b>
|
||||
|
||||
```go
|
||||
// filePath: file path.
|
||||
// chunkSizeMB: The size of the block (in MB, the default is 100MB when set to 0). Setting it too large will be detrimental. Adjust it as appropriate.
|
||||
// maxGoroutine: The number of concurrent read chunks, the number of CPU cores used when set to 0.
|
||||
// linesCh: The channel used to receive the returned results.
|
||||
func ParallelChunkRead(filePath string, linesCh chan<- []string, chunkSizeMB, maxGoroutine int) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/teMXnCsdSEw)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100 // 默认值
|
||||
|
||||
numParsers := runtime.NumCPU()
|
||||
|
||||
linesCh := make(chan []string, numParsers)
|
||||
|
||||
// test1.csv file content:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
filePath := "./testdata/test1.csv"
|
||||
|
||||
go fileutil.ParallelChunkRead(filePath, linesCh, defaultChunkSizeMB, numParsers)
|
||||
|
||||
var totalLines int
|
||||
for lines := range linesCh {
|
||||
totalLines += len(lines)
|
||||
|
||||
for _, line := range lines {
|
||||
fmt.Println(line)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(totalLines)
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
// 2
|
||||
}
|
||||
```
|
||||
@@ -37,12 +37,12 @@ import (
|
||||
|
||||
### <span id="Comma">Comma</span>
|
||||
|
||||
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
||||
<p>Add comma to a number value by every 3 numbers from right to left. ahead by a prefix symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||
func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSymbol string) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||
|
||||
@@ -7,6 +7,7 @@ Package function can control the flow of function execution and support part of
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/predicate.go](https://github.com/duke-git/lancet/blob/main/function/predicate.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -27,11 +28,21 @@ import (
|
||||
- [Before](#Before)
|
||||
- [CurryFn](#CurryFn)
|
||||
- [Compose](#Compose)
|
||||
- [Debounced](#Debounced)
|
||||
- [Debounce](#Debounce)
|
||||
- [Debounced<sup>deprecated</sup>](#Debounced)
|
||||
- [Delay](#Delay)
|
||||
- [Schedule](#Schedule)
|
||||
- [Pipeline](#Pipeline)
|
||||
- [Watcher](#Watcher)
|
||||
- [And](#And)
|
||||
- [Or](#Or)
|
||||
- [Negate](#Negate)
|
||||
- [Nor](#Nor)
|
||||
- [Xnor](#Xnor)
|
||||
- [Nand](#Nand)
|
||||
- [AcceptIf](#AcceptIf)
|
||||
- [Throttle](#Throttle)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -183,11 +194,59 @@ func main() {
|
||||
// ABCDE
|
||||
}
|
||||
```
|
||||
### <span id="Debounce">Debounce</span>
|
||||
|
||||
<p>Creates a debounced version of the provided function. The debounced function will only invoke the original function after the specified delay has passed since the last time it was invoked. It also supports canceling the debounce.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func())
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
callCount := 0
|
||||
fn := func() {
|
||||
callCount++
|
||||
}
|
||||
|
||||
debouncedFn, _ := function.Debounce(fn, 500*time.Millisecond)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
debouncedFn()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println(callCount)
|
||||
|
||||
debouncedFn()
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println(callCount)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Debounced">Debounced</span>
|
||||
|
||||
<p>Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `Debounce` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -403,3 +462,324 @@ func longRunningTask() {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### <span id="And">And</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical AND of a list of predicates. It evaluates to true only if all predicates evaluate to true for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func And[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/dTBHJMQ0zD2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isNumericAndLength5 := function.And(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(isNumericAndLength5("12345"))
|
||||
fmt.Println(isNumericAndLength5("1234"))
|
||||
fmt.Println(isNumericAndLength5("abcde"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Or">Or</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical OR of a list of predicates. It evaluates to true if at least one of the predicates evaluates to true for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Or[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/LitCIsDFNDA)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
containsDigitOrSpecialChar := function.Or(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return strings.ContainsAny(s, "!@#$%") },
|
||||
)
|
||||
|
||||
fmt.Println(containsDigitOrSpecialChar("hello!"))
|
||||
fmt.Println(containsDigitOrSpecialChar("hello"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Negate">Negate</span>
|
||||
|
||||
<p>Returns a predicate that represents the logical negation of this predicate.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Negate[T any](predicate func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/jbI8BtgFnVE)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Define some simple predicates for demonstration
|
||||
isUpperCase := func(s string) bool {
|
||||
return strings.ToUpper(s) == s
|
||||
}
|
||||
isLowerCase := func(s string) bool {
|
||||
return strings.ToLower(s) == s
|
||||
}
|
||||
isMixedCase := function.Negate(function.Or(isUpperCase, isLowerCase))
|
||||
|
||||
fmt.Println(isMixedCase("ABC"))
|
||||
fmt.Println(isMixedCase("AbC"))
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Nor">Nor</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical NOR of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Nor[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/2KdCoBEOq84)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
match := function.Nor(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(match("dbcdckkeee"))
|
||||
|
||||
|
||||
match = function.Nor(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(match("0123456789"))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Nand">Nand</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Nand[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Rb-FdNGpgSO)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isNumericAndLength5 := function.Nand(
|
||||
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
|
||||
func(s string) bool { return len(s) == 5 },
|
||||
)
|
||||
|
||||
fmt.Println(isNumericAndLength5("12345"))
|
||||
fmt.Println(isNumericAndLength5("1234"))
|
||||
fmt.Println(isNumericAndLength5("abcdef"))
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Xnor">Xnor</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical XNOR of a list of predicates. It evaluates to true only if all predicates evaluate to true or false for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Xnor[T any](predicates ...func(T) bool) func(T) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/FJxko8SFbqc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isEven := func(i int) bool { return i%2 == 0 }
|
||||
isPositive := func(i int) bool { return i > 0 }
|
||||
|
||||
match := function.Xnor(isEven, isPositive)
|
||||
|
||||
fmt.Println(match(2))
|
||||
fmt.Println(match(-3))
|
||||
fmt.Println(match(3))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AcceptIf">AcceptIf</span>
|
||||
|
||||
<p>AcceptIf returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure. A predicate function that takes an argument of type T and returns a bool. An apply function that also takes an argument of type T and returns a modified value of the same type.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/XlXHHtzCf7d)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
adder := function.AcceptIf(
|
||||
function.And(
|
||||
func(x int) bool {
|
||||
return x > 10
|
||||
}, func(x int) bool {
|
||||
return x%2 == 0
|
||||
}),
|
||||
func(x int) int {
|
||||
return x + 1
|
||||
},
|
||||
)
|
||||
|
||||
result, ok := adder(20)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
result, ok = adder(21)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 21
|
||||
// true
|
||||
// 0
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Throttle">Throttle</span>
|
||||
|
||||
<p>Throttle creates a throttled version of the provided function. The returned function guarantees that it will only be invoked at most once per interval.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Throttle(fn func(), interval time.Duration) func()
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
)
|
||||
|
||||
func main() {
|
||||
callCount := 0
|
||||
|
||||
fn := func() {
|
||||
callCount++
|
||||
}
|
||||
|
||||
throttledFn := function.Throttle(fn, 1*time.Second)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
throttledFn()
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
fmt.Println(callCount)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,10 @@ import (
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
- [CeilToFloat](#CeilToFloat)
|
||||
- [CeilToString](#CeilToString)
|
||||
- [FloorToFloat](#FloorToFloat)
|
||||
- [FloorToString](#FloorToString)
|
||||
- [Range](#Range)
|
||||
- [RangeWithStep](#RangeWithStep)
|
||||
- [AngleToRadian](#AngleToRadian)
|
||||
@@ -47,6 +51,7 @@ import (
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
- [Abs](#Abs)
|
||||
- [Div](#Div)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -392,7 +397,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RoundToFloat(x float64, n int) float64
|
||||
func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ghyb528JRJL)</span></b>
|
||||
@@ -428,7 +433,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RoundToString(x float64, n int) string
|
||||
func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/kZwpBRAcllO)</span></b>
|
||||
@@ -464,7 +469,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/aumarSHIGzP)</span></b>
|
||||
@@ -493,6 +498,150 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CeilToFloat">CeilToFloat</span>
|
||||
|
||||
<p>Round float up n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CeilToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/8hOeSADZPCo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.CeilToFloat(3.14159, 1)
|
||||
result2 := mathutil.CeilToFloat(3.14159, 2)
|
||||
result3 := mathutil.CeilToFloat(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.2
|
||||
// 3.15
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CeilToString">CeilToString</span>
|
||||
|
||||
<p>Round float up n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func CeilToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/wy5bYEyUKKG)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.CeilToString(3.14159, 1)
|
||||
result2 := mathutil.CeilToString(3.14159, 2)
|
||||
result3 := mathutil.CeilToString(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.2
|
||||
// 3.15
|
||||
// 5.0000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FloorToFloat">FloorToFloat</span>
|
||||
|
||||
<p>Round float down n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FloorToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/vbCBrQHZEED)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.FloorToFloat(3.14159, 1)
|
||||
result2 := mathutil.FloorToFloat(3.14159, 2)
|
||||
result3 := mathutil.FloorToFloat(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.1
|
||||
// 3.14
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FloorToString">FloorToString</span>
|
||||
|
||||
<p>Round float down n decimal places.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FloorToString[T constraints.Float | constraints.Integer](x T, n int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Qk9KPd2IdDb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.FloorToString(3.14159, 1)
|
||||
result2 := mathutil.FloorToString(3.14159, 2)
|
||||
result3 := mathutil.FloorToString(5, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3.1
|
||||
// 3.14
|
||||
// 5.0000
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Range">Range</span>
|
||||
|
||||
<p>Creates a slice of numbers from start with specified count, element step is 1.</p>
|
||||
@@ -964,17 +1113,52 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := Abs(-1)
|
||||
result2 := Abs(-0.1)
|
||||
result3 := Abs(float32(0.2))
|
||||
result1 := mathutil.Abs(-1)
|
||||
result2 := mathutil.Abs(-0.1)
|
||||
result3 := mathutil.Abs(float32(0.2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 0.1
|
||||
// 0.2
|
||||
// Output:
|
||||
// 1
|
||||
// 0.1
|
||||
// 0.2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Div">Div</span>
|
||||
|
||||
<p>Returns the result of x divided by y.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Div[T constraints.Float | constraints.Integer](x T, y T) float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/WLxDdGXXYat)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Div(9, 4)
|
||||
result2 := mathutil.Div(1, 2)
|
||||
result3 := mathutil.Div(0, 666)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
// Output:
|
||||
// 2.25
|
||||
// 0.5
|
||||
// 0
|
||||
}
|
||||
```
|
||||
@@ -624,7 +624,9 @@ func main() {
|
||||
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
|
||||
<p>Send http get request. (Deprecated: use SendRequest for replacement)</p>
|
||||
<p>Send http get request.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `SendRequest` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -666,7 +668,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
|
||||
<p>Send http post request.(Deprecated: use SendRequest for replacement)</p>
|
||||
<p>Send http post request.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `SendRequest` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -713,7 +717,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
|
||||
<p>Send http put request. (Deprecated: use SendRequest for replacement)</p>
|
||||
<p>Send http put request.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `SendRequest` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -763,7 +769,9 @@ func main() {
|
||||
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
|
||||
<p>Send http delete request. (Deprecated: use SendRequest for replacement)</p>
|
||||
<p>Send http delete request.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `SendRequest` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -802,7 +810,9 @@ func main() {
|
||||
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
|
||||
<p>Send http patch request. (Deprecated: use SendRequest for replacement)</p>
|
||||
<p>Send http patch request.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `SendRequest` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
|
||||
- [Of](#Of)
|
||||
- [Unwrap](#Unwrap)
|
||||
- [UnwarpOr](#UnwarpOr)
|
||||
- [UnwarpOrDefault](#UnwarpOrDefault)
|
||||
- [UnwrapOr](#UnwrapOr)
|
||||
- [UnwrapOrDefault](#UnwrapOrDefault)
|
||||
- [ExtractPointer](#ExtractPointer)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -103,13 +103,13 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="UnwarpOr">UnwarpOr</span>
|
||||
### <span id="UnwrapOr">UnwrapOr</span>
|
||||
|
||||
<p>Returns the value from the pointer or fallback if the pointer is nil.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
```go
|
||||
UnwarpOr[T any](p *T, fallback T) T
|
||||
UnwrapOr[T any](p *T, fallback T) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/mmNaLC38W8C)</span></b>
|
||||
@@ -129,10 +129,10 @@ func main() {
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOr(&a, 456)
|
||||
result2 := pointer.UnwarpOr(&b, "abc")
|
||||
result3 := pointer.UnwarpOr(c, 456)
|
||||
result4 := pointer.UnwarpOr(d, "def")
|
||||
result1 := pointer.UnwrapOr(&a, 456)
|
||||
result2 := pointer.UnwrapOr(&b, "abc")
|
||||
result3 := pointer.UnwrapOr(c, 456)
|
||||
result4 := pointer.UnwrapOr(d, "def")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -148,13 +148,13 @@ func main() {
|
||||
```
|
||||
|
||||
|
||||
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
|
||||
### <span id="UnwrapOrDefault">UnwrapOrDefault</span>
|
||||
|
||||
<p>Returns the value from the pointer or the default value if the pointer is nil.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
```go
|
||||
UnwarpOrDefault[T any](p *T) T
|
||||
UnwrapOrDefault[T any](p *T) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ZnGIHf8_o4E)</span></b>
|
||||
@@ -174,10 +174,10 @@ func main() {
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOrDefault(&a)
|
||||
result2 := pointer.UnwarpOrDefault(&b)
|
||||
result3 := pointer.UnwarpOrDefault(c)
|
||||
result4 := pointer.UnwarpOrDefault(d)
|
||||
result1 := pointer.UnwrapOrDefault(&a)
|
||||
result2 := pointer.UnwrapOrDefault(&b)
|
||||
result3 := pointer.UnwrapOrDefault(c)
|
||||
result4 := pointer.UnwrapOrDefault(d)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
@@ -25,12 +25,21 @@ import (
|
||||
- [RandBytes](#RandBytes)
|
||||
- [RandInt](#RandInt)
|
||||
- [RandString](#RandString)
|
||||
- [RandFromGivenSlice](#RandFromGivenSlice)
|
||||
- [RandSliceFromGivenSlice](#RandSliceFromGivenSlice)
|
||||
- [RandUpper](#RandUpper)
|
||||
- [RandLower](#RandLower)
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [RandSymbolChar](#RandSymbolChar)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandIntSlice](#RandIntSlice)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
- [RandFloat](#RandFloat)
|
||||
- [RandFloats](#RandFloats)
|
||||
- [RandStringSlice](#RandStringSlice)
|
||||
- [RandBool](#RandBool)
|
||||
- [RandBoolSlice](#RandBoolSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -114,6 +123,60 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFromGivenSlice">RandFromGivenSlice</span>
|
||||
|
||||
<p>Generate a random element from given slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandFromGivenSlice[T any](slice []T) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randomSet := []any{"a", 8, "hello", true, 1.1}
|
||||
randElm := random.RandFromGivenSlice(randomSet)
|
||||
fmt.Println(randElm)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandSliceFromGivenSlice">RandSliceFromGivenSlice</span>
|
||||
|
||||
<p>Generate a random slice of length num from given slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange"}
|
||||
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
|
||||
fmt.Println(chosen3goods)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUpper">RandUpper</span>
|
||||
|
||||
<p>Generate a random upper case string</p>
|
||||
@@ -218,6 +281,32 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandSymbolChar">RandSymbolChar</span>
|
||||
|
||||
<p>Generate a random symbol char of specified length.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandSymbolChar(length int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Im6ZJxAykOm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
randStr := random.RandSymbolChar(6)
|
||||
fmt.Println(randStr) // random string like: @#(_")
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UUIdV4">UUIdV4</span>
|
||||
|
||||
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
||||
@@ -247,15 +336,41 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandIntSlice">RandIntSlice</span>
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>Generate a slice of random int of length n that do not repeat.</p>
|
||||
<p>Generate a slice of random int. Number range in [min, max)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(n, min, max int) []int
|
||||
func RandIntSlice(length, min, max int) []int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[1 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>Generate a slice of random int of length that do not repeat. Number range in [min, max)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(length, min, max int) []int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/uBkRSOz73Ec)</span></b>
|
||||
@@ -273,3 +388,137 @@ func main() {
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFloat">RandFloat</span>
|
||||
|
||||
<p>Generate a random float64 number between [min, max) with specific precision.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandFloat(min, max float64, precision int) float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/zbD_tuobJtr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
floatNumber := random.RandFloat(1.0, 5.0, 2)
|
||||
fmt.Println(floatNumber) //2.14 (random number)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandFloats">RandFloats</span>
|
||||
|
||||
<p>Generate a slice of random float64 numbers of length n that do not repeat. Number range in [min, max)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandFloats(length int, min, max float64, precision int) []float64
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/I3yndUQ-rhh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
floatNumbers := random.RandFloats(5, 1.0, 5.0, 2)
|
||||
fmt.Println(floatNumbers) //[3.42 3.99 1.3 2.38 4.23] (random)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RandStringSlice">RandStringSlice</span>
|
||||
|
||||
<p>Generate a slice of random string of length strLen based on charset. chartset should be one of the following: random.Numeral, random.LowwerLetters, random.UpperLetters random.Letters, random.SymbolChars, random.AllChars. or a combination of them.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandStringSlice(charset string, sliceLen, strLen int) []string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := random.RandStringSlice(random.Letters, 4, 6)
|
||||
fmt.Println(strs)
|
||||
|
||||
// output random string slice like below:
|
||||
//[CooSMq RUFjDz FAeMPf heRyGv]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandBool">RandBool</span>
|
||||
|
||||
<p>Generate a random boolean value (true or false).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandBool() bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandBool()
|
||||
fmt.Println(result) // true or false (random)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandBoolSlice">RandBoolSlice</span>
|
||||
|
||||
<p>Generates a random boolean slice of specified length.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandBoolSlice(length int) []bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandBoolSlice(2)
|
||||
fmt.Println(result) // [true false] (random)
|
||||
}
|
||||
```
|
||||
@@ -27,6 +27,10 @@ import (
|
||||
- [RetryFunc](#RetryFunc)
|
||||
- [RetryDuration](#RetryDuration)
|
||||
- [RetryTimes](#RetryTimes)
|
||||
- [BackoffStrategy](#BackoffStrategy)
|
||||
- [RetryWithCustomBackoff](#RetryWithCustomBackoff)
|
||||
- [RetryWithLinearBackoff](#RetryWithLinearBackoff)
|
||||
- [RetryWithExponentialWithJitterBackoff](#RetryWithExponentialWithJitterBackoff)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -259,3 +263,202 @@ func main() {
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="BackoffStrategy">BackoffStrategy</span>
|
||||
|
||||
<p>An interface that defines a method for calculating backoff intervals.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
// BackoffStrategy is an interface that defines a method for calculating backoff intervals.
|
||||
type BackoffStrategy interface {
|
||||
// CalculateInterval returns the time.Duration after which the next retry attempt should be made.
|
||||
CalculateInterval() time.Duration
|
||||
}
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
type ExampleCustomBackoffStrategy struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
|
||||
return c.interval + 1
|
||||
}
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry,Retry(increaseNumber, retry.RetryWithCustomBackoff(&ExampleCustomBackoffStrategy{interval: time.Microsecond * 50}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RetryWithCustomBackoff">RetryWithCustomBackoff</span>
|
||||
|
||||
<p>Set abitary custom backoff strategy.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RetryWithCustomBackoff(backoffStrategy BackoffStrategy) Option
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/jIm_o2vb5Y4)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
type ExampleCustomBackoffStrategy struct {
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
|
||||
return c.interval + 1
|
||||
}
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryWithCustomBackoff(&ExampleCustomBackoffStrategy{interval: time.Microsecond * 50}))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RetryWithLinearBackoff">RetryWithLinearBackoff</span>
|
||||
|
||||
<p>Set linear strategy backoff.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RetryWithLinearBackoff(interval time.Duration) Option
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/nk2XRmagfVF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryWithLinearBackoff(time.Microsecond*50))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RetryWithExponentialWithJitterBackoff">RetryWithExponentialWithJitterBackoff</span>
|
||||
|
||||
<p>Set exponential strategy backoff.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RetryWithExponentialWithJitterBackoff(interval time.Duration, base uint64, maxJitter time.Duration) Option
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/xp1avQmn16X)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"log"
|
||||
"github.com/duke-git/lancet/v2/retry"
|
||||
)
|
||||
|
||||
func main() {
|
||||
number := 0
|
||||
increaseNumber := func() error {
|
||||
number++
|
||||
if number == 3 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("error occurs")
|
||||
}
|
||||
|
||||
err := retry.Retry(increaseNumber, retry.RetryWithExponentialWithJitterBackoff(time.Microsecond*50, 2, time.Microsecond*25))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(number)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
@@ -6,7 +6,8 @@ Package slice implements some functions to manipulate slice.
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/slice/slice_concurrent.go](https://github.com/duke-git/lancet/blob/main/slice/slice_concurrent.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -35,6 +36,7 @@ import (
|
||||
- [DifferenceBy](#DifferenceBy)
|
||||
- [DifferenceWith](#DifferenceWith)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [DeleteRange](#DeleteRange)
|
||||
- [Drop](#Drop)
|
||||
- [DropRight](#DropRight)
|
||||
- [DropWhile](#DropWhile)
|
||||
@@ -43,6 +45,7 @@ import (
|
||||
- [EqualWith](#EqualWith)
|
||||
- [Every](#Every)
|
||||
- [Filter](#Filter)
|
||||
- [FilterConcurrent](#FilterConcurrent)
|
||||
- [Find<sup>deprecated</sup>](#Find)
|
||||
- [FindBy](#FindBy)
|
||||
- [FindLast<sup>deprecated</sup>](#FindLast)
|
||||
@@ -50,6 +53,7 @@ import (
|
||||
- [Flatten](#Flatten)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](#ForEach)
|
||||
- [ForEachConcurrent](#ForEachConcurrent)
|
||||
- [ForEachWithBreak](#ForEachWithBreak)
|
||||
- [GroupBy](#GroupBy)
|
||||
- [GroupWith](#GroupWith)
|
||||
@@ -60,11 +64,13 @@ import (
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [Map](#Map)
|
||||
- [MapConcurrent](#MapConcurrent)
|
||||
- [FilterMap](#FilterMap)
|
||||
- [FlatMap](#FlatMap)
|
||||
- [Merge](#Merge)
|
||||
- [Reverse](#Reverse)
|
||||
- [Reduce<sup>deprecated</sup>](#Reduce)
|
||||
- [ReduceConcurrent](#ReduceConcurrent)
|
||||
- [ReduceBy](#ReduceBy)
|
||||
- [ReduceRight](#ReduceRight)
|
||||
- [Replace](#Replace)
|
||||
@@ -85,12 +91,21 @@ import (
|
||||
- [ToSlicePointer](#ToSlicePointer)
|
||||
- [Unique](#Unique)
|
||||
- [UniqueBy](#UniqueBy)
|
||||
- [UniqueByComparator](#UniqueByComparator)
|
||||
- [UniqueByField](#UniqueByField)
|
||||
- [UniqueByConcurrent](#UniqueByConcurrent)
|
||||
- [Union](#Union)
|
||||
- [UnionBy](#UnionBy)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
- [Without](#Without)
|
||||
- [KeyBy](#KeyBy)
|
||||
- [Join](#Join)
|
||||
- [Partition](#Partition)
|
||||
- [SetToDefaultIf](#SetToDefaultIf)
|
||||
- [Break](#Break)
|
||||
- [RightPadding](#RightPadding)
|
||||
- [LeftPadding](#LeftPadding)
|
||||
- [Frequency](#Frequency)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -315,12 +330,12 @@ func main() {
|
||||
|
||||
### <span id="Concat">Concat</span>
|
||||
|
||||
<p>Creates a new slice concatenating slice with any additional slices.</p>
|
||||
<p>Concat creates a new slice concatenating slice with any additional slices.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Concat[T any](slice []T, slices ...[]T) []T
|
||||
func Concat[T any](slices ...[]T) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
||||
@@ -514,15 +529,15 @@ func main() {
|
||||
|
||||
### <span id="DeleteAt">DeleteAt</span>
|
||||
|
||||
<p>Delete the element of slice from start index to end index - 1.</p>
|
||||
<p>Delete delete the element of slice at index.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DeleteAt[T any](slice []T, start int, end ...int)
|
||||
func DeleteAt[T any](slice []T, index int)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/pJ-d6MUWcvK)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/800B1dPBYyd)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -531,18 +546,66 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.DeleteAt([]string{"a", "b", "c"}, -1)
|
||||
result2 := slice.DeleteAt([]string{"a", "b", "c"}, 0)
|
||||
result3 := slice.DeleteAt([]string{"a", "b", "c"}, 0, 2)
|
||||
chars := []string{"a", "b", "c", "d", "e"}
|
||||
|
||||
result1 := slice.DeleteAt(chars, 0)
|
||||
result2 := slice.DeleteAt(chars, 4)
|
||||
result3 := slice.DeleteAt(chars, 5)
|
||||
result4 := slice.DeleteAt(chars, 6)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [a b c]
|
||||
// [b c]
|
||||
// [c]
|
||||
// [b c d e]
|
||||
// [a b c d]
|
||||
// [a b c d]
|
||||
// [a b c d]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DeleteRange">DeleteRange</span>
|
||||
|
||||
<p>Delete the element of slice from start index to end index(exclude)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DeleteRange[T any](slice []T, start, end int) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/945HwiNrnle)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chars := []string{"a", "b", "c", "d", "e"}
|
||||
|
||||
result1 := slice.DeleteRange(chars, 0, 0)
|
||||
result2 := slice.DeleteRange(chars, 0, 1)
|
||||
result3 := slice.DeleteRange(chars, 0, 3)
|
||||
result4 := slice.DeleteRange(chars, 0, 4)
|
||||
result5 := slice.DeleteRange(chars, 0, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// [a b c d e]
|
||||
// [b c d e]
|
||||
// [d e]
|
||||
// [e]
|
||||
// []
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@@ -840,10 +903,46 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Find">Find(deprecated: use FindBy)</span>
|
||||
### <span id="FilterConcurrent">FilterConcurrent</span>
|
||||
|
||||
<p>Applies the provided filter function `predicate` to each element of the input slice concurrently.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result := slice.FilterConcurrent(nums, isEven, 2)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [2 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Find">Find</span>
|
||||
|
||||
<p>Iterates over elements of slice, returning the first one that passes a truth test on function.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `FindBy` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -912,10 +1011,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast(deprecated: use FindLastBy)</span>
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>iterates over elements of slice from end to begin, returning the last one that passes a truth test on function.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `FindLastBy` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -1079,6 +1180,42 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ForEachConcurrent">ForEachConcurrent</span>
|
||||
|
||||
<p>Applies the iteratee function to each item in the slice concurrently.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numThreads int)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
|
||||
result := make([]int, len(nums))
|
||||
|
||||
addOne := func(index int, value int) {
|
||||
result[index] = value + 1
|
||||
}
|
||||
|
||||
slice.ForEachConcurrent(nums, addOne, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [2 3 4 5 6 7 8 9]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ForEachWithBreak">ForEachWithBreak</span>
|
||||
|
||||
<p>Iterates over elements of slice and invokes function for each element, when iteratee return false, will break the for each loop.</p>
|
||||
@@ -1187,10 +1324,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IntSlice">IntSlice (Deprecated: use generic feature of go1.18+ for replacement)</span>
|
||||
### <span id="IntSlice">IntSlice</span>
|
||||
|
||||
<p>Convert interface slice to int slice.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. Use generic feature of go1.18+ for replacement.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -1216,10 +1355,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="InterfaceSlice">InterfaceSlice (Deprecated: use generic feature of go1.18+ for replacement)</span>
|
||||
### <span id="InterfaceSlice">InterfaceSlice</span>
|
||||
|
||||
<p>Convert value to interface slice.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. Use generic feature of go1.18+ for replacement.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -1416,6 +1557,36 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MapConcurrent">MapConcurrent</span>
|
||||
|
||||
<p>Applies the iteratee function to each item in the slice by concrrent.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U, numThreads int) []U
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6}
|
||||
|
||||
result := slice.MapConcurrent(nums, func(_, n int) int { return n * n }, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [1 4 9 16 25 36]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FilterMap">FilterMap</span>
|
||||
|
||||
<p>Returns a slice which apply both filtering and mapping to the given slice. iteratee callback function should returntwo values: 1, mapping result. 2, whether the result element should be included or not.</p>
|
||||
@@ -1490,6 +1661,8 @@ func main() {
|
||||
|
||||
<p>Merge all given slices into one slice.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `Concat` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -1549,7 +1722,9 @@ func main() {
|
||||
|
||||
### <span id="Reduce">Reduce</span>
|
||||
|
||||
<p>Reduce slice.(Deprecated: use ReduceBy)</p>
|
||||
<p>Reduce slice.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `ReduceBy` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -1581,6 +1756,39 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReduceConcurrent">ReduceConcurrent</span>
|
||||
|
||||
<p>Reduces the slice to a single value by applying the reducer function to each item in the slice concurrently.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item T, agg T) T, numThreads int) T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
|
||||
result := slice.ReduceConcurrent(nums, 0, func(_ int, item, agg int) int {
|
||||
return agg + item
|
||||
}, 1)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 55
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="ReduceBy">ReduceBy</span>
|
||||
|
||||
<p>Produces a value from slice by accumulating the result of each element as passed through the reducer function.</p>
|
||||
@@ -2075,10 +2283,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StringSlice">StringSlice (Deprecated: use generic feature of go1.18+ for replacement)</span>
|
||||
### <span id="StringSlice">StringSlice</span>
|
||||
|
||||
<p>Convert interface slice to string slice.</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use generic feature of go1.18+ for replacement
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -2227,12 +2437,12 @@ func main() {
|
||||
|
||||
### <span id="UniqueBy">UniqueBy</span>
|
||||
|
||||
<p>Call iteratee func with every item of slice, then remove duplicated.</p>
|
||||
<p>Removes duplicate elements from the input slice based on the values returned by the iteratee function. this function maintains the order of the elements.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T
|
||||
func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/UR323iZLDpv)</span></b>
|
||||
@@ -2252,7 +2462,114 @@ func main() {
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [1 2 0]
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByComparator">UniqueByComparator</span>
|
||||
|
||||
<p>Removes duplicate elements from the input slice using the provided comparator function. The function maintains the order of the elements.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uniqueNums := slice.UniqueByComparator([]int{1, 2, 3, 1, 2, 4, 5, 6, 4}, func(item int, other int) bool {
|
||||
return item == other
|
||||
})
|
||||
|
||||
caseInsensitiveStrings := slice.UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
||||
return strings.ToLower(item) == strings.ToLower(other)
|
||||
})
|
||||
|
||||
fmt.Println(uniqueNums)
|
||||
fmt.Println(caseInsensitiveStrings)
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4 5 6]
|
||||
// [apple banana cherry date]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByConcurrent">UniqueByConcurrent</span>
|
||||
|
||||
<p>Removes duplicate elements from the slice by parallel.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UniqueByConcurrent[T comparable](slice []T, comparator func(item T, other T) bool, numThreads int) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 1, 2, 4, 5, 6, 4, 7}
|
||||
comparator := func(item int, other int) bool { return item == other }
|
||||
|
||||
result := slice.UniqueByConcurrent(nums,comparator, 4)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// [1 2 3 4 5 6 7]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UniqueByField">UniqueByField</span>
|
||||
|
||||
<p>Remove duplicate elements in struct slice by struct field.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func UniqueByField[T any](slice []T, field string) ([]T, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Runs](https://go.dev/play/p/6cifcZSPIGu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type User struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
users := []User{
|
||||
{ID: 1, Name: "a"},
|
||||
{ID: 2, Name: "b"},
|
||||
{ID: 1, Name: "c"},
|
||||
}
|
||||
|
||||
result, err := slice.UniqueByField(users, "ID")
|
||||
if err != nil {
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [{1 a} {2 b}]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2461,7 +2778,7 @@ func main() {
|
||||
func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/lkQ3Ri2NQhV)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -2472,17 +2789,194 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.Partition(nums)
|
||||
result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
|
||||
result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })
|
||||
result1 := slice.Partition(nums)
|
||||
result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
|
||||
result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// [[1 2 3 4 5]]
|
||||
// [[2 4] [1 3 5]]
|
||||
// [[1 2] [3 4] [5]]
|
||||
// Output:
|
||||
// [[1 2 3 4 5]]
|
||||
// [[2 4] [1 3 5]]
|
||||
// [[1 2] [3 4] [5]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Random">Random</span>
|
||||
|
||||
<p>Random get a random item of slice, return idx=-1 when slice is empty. </p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Random[T any](slice []T) (val T, idx int)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/UzpGQptWppw)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
val, idx := slice.Random(nums)
|
||||
if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
|
||||
fmt.Println("okk")
|
||||
}
|
||||
// Output:
|
||||
// okk
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SetToDefaultIf">SetToDefaultIf</span>
|
||||
|
||||
<p>Sets elements to their default value if they match the given predicate. It retains the positions of the elements in the slice. It returns slice of T and the count of modified slice items</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SetToDefaultIf[T any](slice []T, predicate func(T) bool) ([]T, int)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/9AXGlPRC0-A)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := []string{"a", "b", "a", "c", "d", "a"}
|
||||
modifiedStrs, count := slice.SetToDefaultIf(strs, func(s string) bool { return "a" == s })
|
||||
|
||||
fmt.Println(modifiedStrs)
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// [ b c d ]
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Break">Break</span>
|
||||
|
||||
<p>Splits a slice into two based on a predicate function. It starts appending to the second slice after the first element that matches the predicate. All elements after the first match are included in the second slice, regardless of whether they match the predicate or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/yLYcBTyeQIz)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
even := func(n int) bool { return n%2 == 0 }
|
||||
|
||||
resultEven, resultAfterFirstEven := slice.Break(nums, even)
|
||||
|
||||
fmt.Println(resultEven)
|
||||
fmt.Println(resultAfterFirstEven)
|
||||
|
||||
// Output:
|
||||
// [1]
|
||||
// [2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RightPadding">RightPadding</span>
|
||||
|
||||
<p>RightPadding adds padding to the right end of a slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/0_2rlLEMBXL)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
padded := slice.RightPadding(nums, 0, 3)
|
||||
fmt.Println(padded)
|
||||
// Output:
|
||||
// [1 2 3 4 5 0 0 0]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LeftPadding">LeftPadding</span>
|
||||
|
||||
<p>LeftPadding adds padding to the left begin of a slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/jlQVoelLl2k)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
padded := slice.LeftPadding(nums, 0, 3)
|
||||
fmt.Println(padded)
|
||||
// Output:
|
||||
// [0 0 0 1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Frequency">Frequency</span>
|
||||
|
||||
<p>Counts the frequency of each element in the slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Frequency[T comparable](slice []T) map[T]int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := []string{"a", "b", "b", "c", "c", "c"}
|
||||
result := slice.Frequency(strs)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// map[a:1 b:2 c:3]
|
||||
}
|
||||
```
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
- [IsExported](#IsExported)
|
||||
- [IsZero](#IsZero)
|
||||
- [IsSlice](#IsSlice)
|
||||
- [IsTargetType](#IsTargetType)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -533,3 +534,44 @@ func main() {
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsTargetType">IsTargetType</span>
|
||||
|
||||
<p>check if a struct field type is target type or not</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsTargetType(targetType reflect.Kind) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(n.IsTargetType(reflect.String))
|
||||
fmt.Println(a.IsTargetType(reflect.Slice))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -49,6 +49,7 @@ import (
|
||||
- [StringToBytes](#StringToBytes)
|
||||
- [BytesToString](#BytesToString)
|
||||
- [IsBlank](#IsBlank)
|
||||
- [IsNotBlank](#IsNotBlank)
|
||||
- [HasPrefixAny](#HasPrefixAny)
|
||||
- [HasSuffixAny](#HasSuffixAny)
|
||||
- [IndexOffset](#IndexOffset)
|
||||
@@ -59,6 +60,14 @@ import (
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
- [SubInBetween](#SubInBetween)
|
||||
- [HammingDistance](#HammingDistance)
|
||||
- [Concat](#Concat)
|
||||
- [Ellipsis](#Ellipsis)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [Rotate](#Rotate)
|
||||
- [TemplateReplace](#TemplateReplace)
|
||||
- [RegexMatchAllGroups](#RegexMatchAllGroups)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1076,6 +1085,45 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsNotBlank">IsNotBlank</span>
|
||||
|
||||
<p>Checks if a string is not whitespace or not empty.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsNotBlank(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/e_oJW0RAquA)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsNotBlank("")
|
||||
result2 := strutil.IsNotBlank(" ")
|
||||
result3 := strutil.IsNotBlank("\t\v\f\n")
|
||||
result4 := strutil.IsNotBlank(" 中文")
|
||||
result5 := strutil.IsNotBlank(" world ")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HasPrefixAny">HasPrefixAny</span>
|
||||
|
||||
<p>Checks if a string starts with any of an array of specified strings.</p>
|
||||
@@ -1423,3 +1471,261 @@ func main() {
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="SubInBetween">SubInBetween</span>
|
||||
|
||||
<p>Return substring between the start and end position(excluded) of source string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SubInBetween(str string, start string, end string) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/EDbaRvjeNsv)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "abcde"
|
||||
|
||||
result1 := strutil.SubInBetween(str, "", "de")
|
||||
result2 := strutil.SubInBetween(str, "a", "d")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// abc
|
||||
// bc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HammingDistance">HammingDistance</span>
|
||||
|
||||
<p>HammingDistance calculates the Hamming distance between two strings. The Hamming distance is the number of positions at which the corresponding symbols are different.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HammingDistance(a, b string) (int, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/glNdQEA9HUi)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
result1, _ := strutil.HammingDistance("de", "de")
|
||||
result2, _ := strutil.HammingDistance("a", "d")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Concat">Concat</span>
|
||||
|
||||
<p>Concatenates strings. <b>length</b> is the length of the concatenated string. If unsure, pass 0 or a negative number.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Concat(length int, str ...string) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
|
||||
result2 := strutil.Concat(11, "Go", " ", "Language")
|
||||
result3 := strutil.Concat(0, "An apple a ", "day,", "keeps the", " doctor away")
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// Hello World!
|
||||
// Go Language
|
||||
// An apple a day,keeps the doctor away
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Ellipsis">Ellipsis</span>
|
||||
|
||||
<p>Truncates a string to a specified length and appends an ellipsis.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Ellipsis(str string, length int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Ellipsis("hello world", 5)
|
||||
result2 := strutil.Ellipsis("你好,世界!", 2)
|
||||
result3 := strutil.Ellipsis("😀😃😄😁😆", 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// hello...
|
||||
// 你好...
|
||||
// 😀😃😄...
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Shuffle">Shuffle</span>
|
||||
|
||||
<p>Shuffle the order of characters of given string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Shuffle(str string) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := strutil.Shuffle("hello")
|
||||
fmt.Println(result) //olelh (random order)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Rotate">Rotate</span>
|
||||
|
||||
<p>Rotates the string by the specified number of characters.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Rotate(str string, shift int) string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := Rotate("Hello", 0)
|
||||
result2 := Rotate("Hello", 1)
|
||||
result3 := Rotate("Hello", 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// Hello
|
||||
// oHell
|
||||
// loHel
|
||||
}
|
||||
```
|
||||
### <span id="TemplateReplace">TemplateReplace</span>
|
||||
|
||||
<p>Replaces the placeholders in the template string with the corresponding values in the data map.The placeholders are enclosed in curly braces, e.g. {key}. for example, the template string is "Hello, {name}!", and the data map is {"name": "world"}, the result will be "Hello, world!".</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TemplateReplace(template string, data map[string]string string
|
||||
```
|
||||
|
||||
<b>example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||
data := map[string]string{
|
||||
"name": "Bob",
|
||||
"age": "20",
|
||||
}
|
||||
|
||||
result := strutil.TemplateReplace(template, data)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// Hello, my name is Bob, I'm 20 years old.
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RegexMatchAllGroups">RegexMatchAllGroups</span>
|
||||
|
||||
<p>Matches all subgroups in a string using a regular expression and returns the result.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RegexMatchAllGroups(pattern, str string) [][]string
|
||||
```
|
||||
|
||||
<b>example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pattern := `(\w+\.+\w+)@(\w+)\.(\w+)`
|
||||
str := "Emails: john.doe@example.com and jane.doe@example.com"
|
||||
|
||||
result := strutil.RegexMatchAllGroups(pattern, str)
|
||||
|
||||
fmt.Println(result[0])
|
||||
fmt.Println(result[1])
|
||||
|
||||
// Output:
|
||||
// [john.doe@example.com john.doe example com]
|
||||
// [jane.doe@example.com jane.doe example com]
|
||||
}
|
||||
```
|
||||
@@ -31,6 +31,11 @@ import (
|
||||
- [CompareOsEnv](#CompareOsEnv)
|
||||
- [ExecCommand](#ExecCommand)
|
||||
- [GetOsBits](#GetOsBits)
|
||||
- [StartProcess](#StartProcess)
|
||||
- [StopProcess](#StopProcess)
|
||||
- [KillProcess](#KillProcess)
|
||||
- [GetProcessInfo](#GetProcessInfo)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -242,13 +247,14 @@ func main() {
|
||||
|
||||
### <span id="ExecCommand">ExecCommand</span>
|
||||
|
||||
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p>
|
||||
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.
|
||||
The second parameter of the function is the cmd option control parameter. The type is func(*exec.Cmd). You can set the cmd attribute through this parameter.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
type (
|
||||
Option func(*exec.Cmd)
|
||||
Option func(*exec.Cmd)
|
||||
)
|
||||
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||
```
|
||||
@@ -263,7 +269,9 @@ import (
|
||||
|
||||
func main() {
|
||||
// linux or mac
|
||||
stdout, stderr, err := system.ExecCommand("ls")
|
||||
stdout, stderr, err := system.ExecCommand("ls", func(cmd *exec.Cmd) {
|
||||
cmd.Dir = "/tmp"
|
||||
})
|
||||
fmt.Println("std out: ", stdout)
|
||||
fmt.Println("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
@@ -285,7 +293,7 @@ func main() {
|
||||
|
||||
### <span id="GetOsBits">GetOsBits</span>
|
||||
|
||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
|
||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -306,3 +314,132 @@ func main() {
|
||||
fmt.Println(osBit) // 32 or 64
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StartProcess">StartProcess</span>
|
||||
|
||||
<p>Start a new process with the specified name and arguments.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func StartProcess(command string, args ...string) (int, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "2")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(pid)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StopProcess">StopProcess</span>
|
||||
|
||||
<p>Stop a process by pid.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func StopProcess(pid int) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "10")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
err = system.StopProcess(pid)
|
||||
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="KillProcess">KillProcess</span>
|
||||
|
||||
<p>Kill a process by pid.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func KillProcess(pid int) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("sleep", "10")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
err = system.KillProcess(pid)
|
||||
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetProcessInfo">GetProcessInfo</span>
|
||||
|
||||
<p>Retrieves detailed process information by pid.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetProcessInfo(pid int) (*ProcessInfo, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/system"
|
||||
)
|
||||
|
||||
func main() {
|
||||
pid, err := system.StartProcess("ls", "-a")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
processInfo, err := system.GetProcessInfo(pid)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(processInfo)
|
||||
}
|
||||
```
|
||||
@@ -81,7 +81,7 @@ import (
|
||||
func ContainChinese(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/7DpU0uElYeM)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/7DpU0uElYeM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -115,7 +115,7 @@ func main() {
|
||||
func ContainLetter(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/lqFD04Yyewp)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/lqFD04Yyewp)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -149,7 +149,7 @@ func main() {
|
||||
func ContainLower(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Srqi1ItvnAA)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Srqi1ItvnAA)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -183,7 +183,7 @@ func main() {
|
||||
func ContainUpper(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/CmWeBEk27-z)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/CmWeBEk27-z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -217,7 +217,7 @@ func main() {
|
||||
func IsAlpha(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/7Q5sGOz2izQ)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/7Q5sGOz2izQ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -251,7 +251,7 @@ func main() {
|
||||
func IsAllUpper(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ZHctgeK1n4Z)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/ZHctgeK1n4Z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -285,7 +285,7 @@ func main() {
|
||||
func IsAllLower(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/GjqCnOfV6cM)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/GjqCnOfV6cM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -319,7 +319,7 @@ func main() {
|
||||
func IsASCII(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/hfQNPLX0jNa)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/hfQNPLX0jNa)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -359,7 +359,7 @@ func main() {
|
||||
func IsBase64(base64 string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/sWHEySAt6hl)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/sWHEySAt6hl)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -390,7 +390,7 @@ func main() {
|
||||
func IsChineseMobile(mobileNum string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/GPYUlGTOqe3)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/GPYUlGTOqe3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -421,7 +421,7 @@ func main() {
|
||||
func IsChineseIdNum(id string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/d8EWhl2UGDF)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/d8EWhl2UGDF)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -452,7 +452,7 @@ func main() {
|
||||
func IsChinesePhone(phone string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/RUD_-7YZJ3I)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/RUD_-7YZJ3I)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -483,7 +483,7 @@ func main() {
|
||||
func IsCreditCard(creditCart string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/sNwwL6B0-v4)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/sNwwL6B0-v4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -514,7 +514,7 @@ func main() {
|
||||
func IsDns(dns string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/jlYApVLLGTZ)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/jlYApVLLGTZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -548,7 +548,7 @@ func main() {
|
||||
func IsEmail(email string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Os9VaFlT33G)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Os9VaFlT33G)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -579,7 +579,7 @@ func main() {
|
||||
func IsEmptyString(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/dpzgUjFnBCX)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/dpzgUjFnBCX)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -613,7 +613,7 @@ func main() {
|
||||
func IsInt(v any) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/eFoIHbgzl-z)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/eFoIHbgzl-z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -650,7 +650,7 @@ func main() {
|
||||
func IsFloat(v any) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/vsyG-sxr99_Z)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/vsyG-sxr99_Z)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -687,7 +687,7 @@ func main() {
|
||||
func IsNumber(v any) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/mdJHOAvtsvF)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/mdJHOAvtsvF)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -724,7 +724,7 @@ func main() {
|
||||
func IsIntStr(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/jQRtFv-a0Rk)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/jQRtFv-a0Rk)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -761,7 +761,7 @@ func main() {
|
||||
func IsFloatStr(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/LOYwS_Oyl7U)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/LOYwS_Oyl7U)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -798,7 +798,7 @@ func main() {
|
||||
func IsNumberStr(s string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/LzaKocSV79u)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/LzaKocSV79u)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -835,7 +835,7 @@ func main() {
|
||||
func IsJSON(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/8Kip1Itjiil)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/8Kip1Itjiil)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -872,7 +872,7 @@ func main() {
|
||||
func IsRegexMatch(s, regex string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/z_XeZo_litG)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/z_XeZo_litG)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -903,7 +903,7 @@ func main() {
|
||||
func IsIp(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/FgcplDvmxoD)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/FgcplDvmxoD)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -940,7 +940,7 @@ func main() {
|
||||
func IsIpV4(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zBGT99EjaIu)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/zBGT99EjaIu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -971,7 +971,7 @@ func main() {
|
||||
func IsIpV6(ipstr string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/AHA0r0AzIdC)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/AHA0r0AzIdC)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1002,7 +1002,7 @@ func main() {
|
||||
func IsStrongPassword(password string, length int) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/QHdVcSQ3uDg)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/QHdVcSQ3uDg)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1033,7 +1033,7 @@ func main() {
|
||||
func IsUrl(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/pbJGa7F98Ka)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/pbJGa7F98Ka)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1068,7 +1068,7 @@ func main() {
|
||||
func IsWeakPassword(password string, length int) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/wqakscZH5gH)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/wqakscZH5gH)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1099,7 +1099,7 @@ func main() {
|
||||
func IsZeroValue(value any) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/UMrwaDCi_t4)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/UMrwaDCi_t4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1136,7 +1136,7 @@ func main() {
|
||||
func IsGBK(data []byte) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/E2nt3unlmzP)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/E2nt3unlmzP)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1168,7 +1168,7 @@ func main() {
|
||||
func IsPrintable(str string) bool
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Pe1FE2gdtTP)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/Pe1FE2gdtTP)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1208,7 +1208,7 @@ func main() {
|
||||
func IsBin(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/ogPeg2XJH4P)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1245,7 +1245,7 @@ func main() {
|
||||
func IsHex(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/M2qpHbEwmm7)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1282,7 +1282,7 @@ func main() {
|
||||
func IsBase64URL(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/vhl4mr8GZ6S)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1319,7 +1319,7 @@ func main() {
|
||||
func IsJWT(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/R6Op7heJbKI)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1350,7 +1350,7 @@ func main() {
|
||||
func IsVisa(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/SdS2keOyJsl)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1381,7 +1381,7 @@ func main() {
|
||||
func IsMasterCard(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/CwWBFRrG27b)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1412,7 +1412,7 @@ func main() {
|
||||
func IsAmericanExpress(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/HIDFpcOdpkd)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1443,7 +1443,7 @@ func main() {
|
||||
func IsUnionPay(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/CUHPEwEITDf)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -1474,7 +1474,7 @@ func main() {
|
||||
func IsChinaUnionPay(v string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/yafpdxLiymu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
|
||||
@@ -30,7 +30,7 @@ We are excited that you are interested in contributing to lancet. Before submitt
|
||||
|
||||
- Before submitting a PR, please execute the unit test command: `go test -v ./...` to ensure that all unit test tasks should pass.
|
||||
|
||||
- Make sure PRs are created to `v2` branch instead of `master` branch.
|
||||
- Make sure PRs are created to `rc` branch instead of other branch.
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ features:
|
||||
details: Well structure, test for every exported function.
|
||||
---
|
||||
|
||||
<p style="position:relative; top: -316px;left: 560px;">
|
||||
<p style="position:relative; inline-block;top: -330px;left: 30%">
|
||||
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||
</p>
|
||||
|
||||
@@ -30,7 +30,7 @@ Lancet 的成长离不开大家的支持,如果你愿意为 Lancet 贡献代
|
||||
|
||||
- 提交 PR 前请执行单元测试命令:go test -v ./...,确保所有单元测试任务通过。
|
||||
|
||||
- 确保 PR 是提交到 `v2` 分支,而不是 `main` 分支。
|
||||
- 确保 PR 是提交到 `rc` 分支,而不是其他分支。
|
||||
|
||||
- 如果是修复 bug,请在 PR 中给出描述信息。
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ features:
|
||||
details: 结构良好,测试每个导出的函数。
|
||||
---
|
||||
|
||||
<p style="position:relative;display: inline-block;top: -316px;left: 32%">
|
||||
<p style="position:relative;display: inline-block;top: -330px;left: 30%">
|
||||
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||
</p>
|
||||
|
||||
1171
docs/package-lock.json
generated
1171
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,6 @@
|
||||
"docs:preview": "vitepress preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitepress": "^1.0.0-rc.4"
|
||||
"vitepress": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
341
fileutil/file.go
341
fileutil/file.go
@@ -18,12 +18,70 @@ import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
// FileReader is a reader supporting offset seeking and reading one
|
||||
// line at a time, this is especially useful for large files
|
||||
type FileReader struct {
|
||||
*bufio.Reader
|
||||
file *os.File
|
||||
offset int64
|
||||
}
|
||||
|
||||
// NewFileReader creates the FileReader struct for reading
|
||||
func NewFileReader(path string) (*FileReader, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FileReader{
|
||||
file: f,
|
||||
Reader: bufio.NewReader(f),
|
||||
offset: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ReadLine reads and returns one line at a time excluding the trailing '\r' and '\n'
|
||||
func (f *FileReader) ReadLine() (string, error) {
|
||||
data, err := f.Reader.ReadBytes('\n')
|
||||
f.offset += int64(len(data))
|
||||
if err == nil || err == io.EOF {
|
||||
for len(data) > 0 && (data[len(data)-1] == '\r' || data[len(data)-1] == '\n') {
|
||||
data = data[:len(data)-1]
|
||||
}
|
||||
return string(data), err
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Offset returns the current offset of the file
|
||||
func (f *FileReader) Offset() int64 {
|
||||
return f.offset
|
||||
}
|
||||
|
||||
// SeekOffset sets the current offset of the reading
|
||||
func (f *FileReader) SeekOffset(offset int64) error {
|
||||
_, err := f.file.Seek(offset, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.Reader = bufio.NewReader(f.file)
|
||||
f.offset = offset
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close takes care of the opened file
|
||||
func (f *FileReader) Close() error {
|
||||
return f.file.Close()
|
||||
}
|
||||
|
||||
// IsExist checks if a file or directory exists.
|
||||
// Play: https://go.dev/play/p/nKKXt8ZQbmh
|
||||
func IsExist(path string) bool {
|
||||
@@ -56,6 +114,50 @@ func CreateDir(absPath string) error {
|
||||
return os.MkdirAll(absPath, os.ModePerm)
|
||||
}
|
||||
|
||||
// CopyDir copy src directory to dst directory, it will copy all files and directories recursively.
|
||||
// the access permission will be the same as the source directory.
|
||||
// if dstPath exists, it will return an error.
|
||||
// Play: https://go.dev/play/p/YAyFTA_UuPb
|
||||
func CopyDir(srcPath string, dstPath string) error {
|
||||
srcInfo, err := os.Stat(srcPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get source directory info: %w", err)
|
||||
}
|
||||
|
||||
if !srcInfo.IsDir() {
|
||||
return fmt.Errorf("source path is not a directory: %s", srcPath)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(dstPath, 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create destination directory: %w", err)
|
||||
}
|
||||
|
||||
entries, err := os.ReadDir(srcPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read source directory: %w", err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
srcDir := filepath.Join(srcPath, entry.Name())
|
||||
dstDir := filepath.Join(dstPath, entry.Name())
|
||||
|
||||
if entry.IsDir() {
|
||||
err := CopyDir(srcDir, dstDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := CopyFile(srcDir, dstDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsDir checks if the path is directory or not.
|
||||
// Play: https://go.dev/play/p/WkVwEKqtOWk
|
||||
func IsDir(path string) bool {
|
||||
@@ -320,7 +422,7 @@ func UnZip(zipFile string, destPath string) error {
|
||||
defer zipReader.Close()
|
||||
|
||||
for _, f := range zipReader.File {
|
||||
//issue#62: fix ZipSlip bug
|
||||
// issue#62: fix ZipSlip bug
|
||||
path, err := safeFilepathJoin(destPath, f.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -491,7 +593,7 @@ func CurrentPath() string {
|
||||
var absPath string
|
||||
_, filename, _, ok := runtime.Caller(1)
|
||||
if ok {
|
||||
absPath = path.Dir(filename)
|
||||
absPath = filepath.Dir(filename)
|
||||
}
|
||||
|
||||
return absPath
|
||||
@@ -507,6 +609,25 @@ func FileSize(path string) (int64, error) {
|
||||
return f.Size(), nil
|
||||
}
|
||||
|
||||
// DirSize walks the folder recursively and returns folder size in bytes.
|
||||
func DirSize(path string) (int64, error) {
|
||||
var size int64
|
||||
err := filepath.WalkDir(path, func(_ string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !d.IsDir() {
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size += info.Size()
|
||||
}
|
||||
return err
|
||||
})
|
||||
return size, err
|
||||
}
|
||||
|
||||
// MTime returns file modified time.
|
||||
// Play: https://go.dev/play/p/s_Tl7lZoAaY
|
||||
func MTime(filepath string) (int64, error) {
|
||||
@@ -535,7 +656,7 @@ func Sha(filepath string, shaType ...int) (string, error) {
|
||||
} else if shaType[0] == 512 {
|
||||
h = sha512.New()
|
||||
} else {
|
||||
return "", errors.New("param `shaType` should be 1, 256 or 512.")
|
||||
return "", errors.New("param `shaType` should be 1, 256 or 512")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,15 +674,19 @@ func Sha(filepath string, shaType ...int) (string, error) {
|
||||
|
||||
// ReadCsvFile read file content into slice.
|
||||
// Play: https://go.dev/play/p/OExTkhGEd3_u
|
||||
func ReadCsvFile(filepath string) ([][]string, error) {
|
||||
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error) {
|
||||
f, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
csvReader := csv.NewReader(f)
|
||||
records, err := csvReader.ReadAll()
|
||||
reader := csv.NewReader(f)
|
||||
if len(delimiter) > 0 {
|
||||
reader.Comma = delimiter[0]
|
||||
}
|
||||
|
||||
records, err := reader.ReadAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -570,8 +695,10 @@ func ReadCsvFile(filepath string) ([][]string, error) {
|
||||
}
|
||||
|
||||
// WriteCsvFile write content to target csv file.
|
||||
// append: append to existing csv file
|
||||
// delimiter: specifies csv delimiter
|
||||
// Play: https://go.dev/play/p/dAXm58Q5U1o
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error {
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error {
|
||||
flag := os.O_RDWR | os.O_CREATE
|
||||
|
||||
if append {
|
||||
@@ -586,7 +713,19 @@ func WriteCsvFile(filepath string, records [][]string, append bool) error {
|
||||
defer f.Close()
|
||||
|
||||
writer := csv.NewWriter(f)
|
||||
writer.Comma = ','
|
||||
// 设置默认分隔符为逗号,除非另外指定
|
||||
if len(delimiter) > 0 {
|
||||
writer.Comma = delimiter[0]
|
||||
} else {
|
||||
writer.Comma = ','
|
||||
}
|
||||
|
||||
// 遍历所有记录并处理包含分隔符或双引号的单元格
|
||||
for i := range records {
|
||||
for j := range records[i] {
|
||||
records[i][j] = escapeCSVField(records[i][j], writer.Comma)
|
||||
}
|
||||
}
|
||||
|
||||
return writer.WriteAll(records)
|
||||
}
|
||||
@@ -624,3 +763,187 @@ func WriteBytesToFile(filepath string, content []byte) error {
|
||||
_, err = f.Write(content)
|
||||
return err
|
||||
}
|
||||
|
||||
// ReadFile get file reader by a url or a local file
|
||||
// Play: https://go.dev/play/p/uNep3Tr8fqF
|
||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) {
|
||||
switch {
|
||||
case validator.IsUrl(path):
|
||||
resp, err := http.Get(path)
|
||||
if err != nil {
|
||||
return nil, func() {}, err
|
||||
}
|
||||
return resp.Body, func() { resp.Body.Close() }, nil
|
||||
case IsExist(path):
|
||||
reader, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, func() {}, err
|
||||
}
|
||||
return reader, func() { reader.Close() }, nil
|
||||
default:
|
||||
return nil, func() {}, errors.New("unknown file type")
|
||||
}
|
||||
}
|
||||
|
||||
// escapeCSVField 处理单元格内容,如果包含分隔符,则用双引号包裹
|
||||
func escapeCSVField(field string, delimiter rune) string {
|
||||
// 替换所有的双引号为两个双引号
|
||||
escapedField := strings.ReplaceAll(field, "\"", "\"\"")
|
||||
|
||||
// 如果字段包含分隔符、双引号或换行符,用双引号包裹整个字段
|
||||
if strings.ContainsAny(escapedField, string(delimiter)+"\"\n") {
|
||||
escapedField = fmt.Sprintf("\"%s\"", escapedField)
|
||||
}
|
||||
|
||||
return escapedField
|
||||
}
|
||||
|
||||
// WriteMapsToCsv write slice of map to csv file.
|
||||
// Play: https://go.dev/play/p/umAIomZFV1c
|
||||
// filepath: Path to the CSV file.
|
||||
// records: Slice of maps to be written. the value of map should be basic type.
|
||||
// the maps will be sorted by key in alphabeta order, then be written into csv file.
|
||||
// appendToExistingFile: If true, data will be appended to the file if it exists.
|
||||
// delimiter: Delimiter to use in the CSV file.
|
||||
// headers: order of the csv column headers, needs to be consistent with the key of the map.
|
||||
func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune,
|
||||
headers ...[]string) error {
|
||||
for _, record := range records {
|
||||
for _, value := range record {
|
||||
if !isCsvSupportedType(value) {
|
||||
return errors.New("unsupported value type detected; only basic types are supported: \nbool, rune, string, int, int64, float32, float64, uint, byte, complex128, complex64, uintptr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var columnHeaders []string
|
||||
if len(headers) > 0 {
|
||||
columnHeaders = headers[0]
|
||||
} else {
|
||||
for key := range records[0] {
|
||||
columnHeaders = append(columnHeaders, key)
|
||||
}
|
||||
// sort keys in alphabeta order
|
||||
sort.Strings(columnHeaders)
|
||||
}
|
||||
|
||||
var datasToWrite [][]string
|
||||
if !appendToExistingFile {
|
||||
datasToWrite = append(datasToWrite, columnHeaders)
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
var row []string
|
||||
for _, h := range columnHeaders {
|
||||
row = append(row, fmt.Sprintf("%v", record[h]))
|
||||
}
|
||||
datasToWrite = append(datasToWrite, row)
|
||||
}
|
||||
|
||||
return WriteCsvFile(filepath, datasToWrite, appendToExistingFile, delimiter)
|
||||
}
|
||||
|
||||
// check if the value of map which to be written into csv is basic type.
|
||||
func isCsvSupportedType(v interface{}) bool {
|
||||
switch v.(type) {
|
||||
case bool, rune, string, int, int64, float32, float64, uint, byte, complex128, complex64, uintptr:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// ChunkRead reads a block from the file at the specified offset and returns all lines within the block
|
||||
// Play: https://go.dev/play/p/r0hPmKWhsgf
|
||||
func ChunkRead(file *os.File, offset int64, size int, bufPool *sync.Pool) ([]string, error) {
|
||||
buf := bufPool.Get().([]byte)[:size] // 从Pool获取缓冲区并调整大小
|
||||
n, err := file.ReadAt(buf, offset) // 从指定偏移读取数据到缓冲区
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
buf = buf[:n] // 调整切片以匹配实际读取的字节数
|
||||
|
||||
var lines []string
|
||||
var lineStart int
|
||||
for i, b := range buf {
|
||||
if b == '\n' {
|
||||
line := string(buf[lineStart:i]) // 不包括换行符
|
||||
lines = append(lines, line)
|
||||
lineStart = i + 1 // 设置下一行的开始
|
||||
}
|
||||
}
|
||||
|
||||
if lineStart < len(buf) { // 处理块末尾的行
|
||||
line := string(buf[lineStart:])
|
||||
lines = append(lines, line)
|
||||
}
|
||||
bufPool.Put(buf) // 读取完成后,将缓冲区放回Pool
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
// ParallelChunkRead reads the file in parallel and send each chunk of lines to the specified channel.
|
||||
// filePath 文件路径
|
||||
// chunkSizeMB 分块的大小(单位MB,设置为0时使用默认100MB),设置过大反而不利,视情调整
|
||||
// maxGoroutine 并发读取分块的数量,设置为0时使用CPU核心数
|
||||
// linesCh用于接收返回结果的通道。
|
||||
// Play: https://go.dev/play/p/teMXnCsdSEw
|
||||
func ParallelChunkRead(filePath string, linesCh chan<- []string, chunkSizeMB, maxGoroutine int) error {
|
||||
if chunkSizeMB == 0 {
|
||||
chunkSizeMB = 100
|
||||
}
|
||||
chunkSize := chunkSizeMB * 1024 * 1024
|
||||
// 内存复用
|
||||
bufPool := sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, chunkSize)
|
||||
},
|
||||
}
|
||||
|
||||
if maxGoroutine == 0 {
|
||||
maxGoroutine = runtime.NumCPU() // 设置为0时使用CPU核心数
|
||||
}
|
||||
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
info, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
chunkOffsetCh := make(chan int64, maxGoroutine)
|
||||
|
||||
// 分配工作
|
||||
go func() {
|
||||
for i := int64(0); i < info.Size(); i += int64(chunkSize) {
|
||||
chunkOffsetCh <- i
|
||||
}
|
||||
close(chunkOffsetCh)
|
||||
}()
|
||||
|
||||
// 启动工作协程
|
||||
for i := 0; i < maxGoroutine; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
for chunkOffset := range chunkOffsetCh {
|
||||
chunk, err := ChunkRead(f, chunkOffset, chunkSize, &bufPool)
|
||||
if err == nil {
|
||||
linesCh <- chunk
|
||||
}
|
||||
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有解析完成后关闭行通道
|
||||
wg.Wait()
|
||||
close(linesCh)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package fileutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func ExampleIsExist() {
|
||||
@@ -330,6 +334,28 @@ func ExampleWriteCsvFile() {
|
||||
// [[Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
|
||||
func ExampleWriteMapsToCsv() {
|
||||
csvFilePath := "./testdata/test3.csv"
|
||||
records := []map[string]any{
|
||||
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||
}
|
||||
|
||||
headers := []string{"Name", "Age", "Gender"}
|
||||
err := WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
content, err := ReadCsvFile(csvFilePath, ';')
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
|
||||
func ExampleWriteStringToFile() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
@@ -385,3 +411,81 @@ func ExampleWriteBytesToFile() {
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleReadFile() {
|
||||
reader, fn, err := ReadFile("https://httpbin.org/robots.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fn()
|
||||
|
||||
dat, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(string(dat))
|
||||
|
||||
// Output:
|
||||
// User-agent: *
|
||||
// Disallow: /deny
|
||||
}
|
||||
|
||||
func ExampleChunkRead() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100
|
||||
|
||||
filePath := "./testdata/test1.csv"
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, defaultChunkSizeMB*mb)
|
||||
},
|
||||
}
|
||||
|
||||
lines, err := ChunkRead(f, 0, 100, &bufPool)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(lines[0])
|
||||
fmt.Println(lines[1])
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
}
|
||||
|
||||
func ExampleParallelChunkRead() {
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100 // 默认值
|
||||
|
||||
numParsers := runtime.NumCPU()
|
||||
|
||||
linesCh := make(chan []string, numParsers)
|
||||
filePath := "./testdata/test1.csv"
|
||||
|
||||
go ParallelChunkRead(filePath, linesCh, defaultChunkSizeMB, numParsers)
|
||||
|
||||
var totalLines int
|
||||
for lines := range linesCh {
|
||||
totalLines += len(lines)
|
||||
|
||||
for _, line := range lines {
|
||||
fmt.Println(line)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(totalLines)
|
||||
|
||||
// Output:
|
||||
// Lili,22,female
|
||||
// Jim,21,male
|
||||
// 2
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -26,7 +31,7 @@ func TestCreateFile(t *testing.T) {
|
||||
|
||||
assert := internal.NewAssert(t, "TestCreateFile")
|
||||
|
||||
f := "./text.txt"
|
||||
f := "./testdata/text.txt"
|
||||
if CreateFile(f) {
|
||||
file, err := os.Open(f)
|
||||
assert.IsNil(err)
|
||||
@@ -339,10 +344,14 @@ func TestSha(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSha")
|
||||
|
||||
sha1, err := Sha("./testdata/test.txt", 1)
|
||||
sha256, err := Sha("./testdata/test.txt", 256)
|
||||
sha512, err := Sha("./testdata/test.txt", 512)
|
||||
|
||||
assert.IsNil(err)
|
||||
|
||||
sha256, err := Sha("./testdata/test.txt", 256)
|
||||
assert.IsNil(err)
|
||||
|
||||
sha512, err := Sha("./testdata/test.txt", 512)
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal("dda3cf10c5a6ff6c6659a497bf7261b287af2bc7", sha1)
|
||||
assert.Equal("aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35", sha256)
|
||||
assert.Equal("d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870", sha512)
|
||||
@@ -378,11 +387,36 @@ func TestWriteCsvFile(t *testing.T) {
|
||||
|
||||
assert.Equal(2, len(readContent))
|
||||
assert.Equal(3, len(readContent[0]))
|
||||
assert.Equal("Lili", content[0][0])
|
||||
assert.Equal("Lili", readContent[0][0])
|
||||
|
||||
// RemoveFile(csvFilePath)
|
||||
}
|
||||
|
||||
func TestWriteMapsToCsv(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteMapsToCSV")
|
||||
|
||||
csvFilePath := "./testdata/test4.csv"
|
||||
records := []map[string]any{
|
||||
{"Name": "Lili", "Age": "22", "Gender": "female"},
|
||||
{"Name": "Jim", "Age": "21", "Gender": "male"},
|
||||
}
|
||||
|
||||
headers := []string{"Name", "Age", "Gender"}
|
||||
err := WriteMapsToCsv(csvFilePath, records, false, ';', headers)
|
||||
|
||||
assert.IsNil(err)
|
||||
|
||||
content, err := ReadCsvFile(csvFilePath, ';')
|
||||
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(3, len(content))
|
||||
assert.Equal(3, len(content[0]))
|
||||
assert.Equal("Lili", content[1][0])
|
||||
assert.Equal("22", content[1][1])
|
||||
assert.Equal("female", content[1][2])
|
||||
}
|
||||
|
||||
func TestWriteStringToFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
||||
|
||||
@@ -457,3 +491,131 @@ func TestWriteBytesToFile(t *testing.T) {
|
||||
|
||||
os.Remove(filepath)
|
||||
}
|
||||
|
||||
func TestReadFile(t *testing.T) {
|
||||
reader, close, err := ReadFile("https://httpbin.org/robots.txt")
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
defer close()
|
||||
|
||||
dat, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
want := `User-agent: *
|
||||
Disallow: /deny
|
||||
`
|
||||
internal.NewAssert(t, "TestReadFile").Equal(want, string(dat))
|
||||
}
|
||||
|
||||
func TestReadlineFile(t *testing.T) {
|
||||
path := "./testdata/demo.csv"
|
||||
reader, err := NewFileReader(path)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
indexMap := make(map[string]int64)
|
||||
defer reader.Close()
|
||||
for {
|
||||
offset := reader.Offset()
|
||||
line, err := reader.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
indexMap[line] = offset
|
||||
}
|
||||
|
||||
lines, err := ReadFileByLine(path)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
for _, line := range lines {
|
||||
offset, ok := indexMap[line]
|
||||
if !ok {
|
||||
t.Fail()
|
||||
}
|
||||
if err = reader.SeekOffset(offset); err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
lineRead, err := reader.ReadLine()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
internal.NewAssert(t, "TestReadlineFile").Equal(line, lineRead)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCopyDir")
|
||||
|
||||
src := "./testdata"
|
||||
dest := "./testdata_copy"
|
||||
|
||||
err := CopyDir(src, dest)
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(true, IsExist(dest))
|
||||
|
||||
filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
|
||||
destPath := strings.Replace(path, src, dest, 1)
|
||||
assert.Equal(true, IsExist(destPath))
|
||||
return nil
|
||||
})
|
||||
|
||||
os.RemoveAll(dest)
|
||||
}
|
||||
|
||||
func TestParallelChunkRead(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestParallelChunkRead")
|
||||
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100 // 默认值
|
||||
|
||||
numParsers := runtime.NumCPU()
|
||||
|
||||
linesCh := make(chan []string, numParsers)
|
||||
filePath := "./testdata/test1.csv" // 替换为你的文件路径
|
||||
|
||||
go ParallelChunkRead(filePath, linesCh, defaultChunkSizeMB, numParsers)
|
||||
|
||||
var totalLines int
|
||||
for lines := range linesCh {
|
||||
totalLines += len(lines)
|
||||
|
||||
assert.Equal("Lili,22,female", lines[0])
|
||||
assert.Equal("Jim,21,male", lines[1])
|
||||
}
|
||||
|
||||
assert.Equal(2, totalLines)
|
||||
}
|
||||
|
||||
func TestChunkRead(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestChunkRead")
|
||||
|
||||
const mb = 1024 * 1024
|
||||
const defaultChunkSizeMB = 100 // 默认值
|
||||
|
||||
filePath := "./testdata/test1.csv" // 替换为你的文件路径
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 0, defaultChunkSizeMB*mb)
|
||||
},
|
||||
}
|
||||
|
||||
lines, err := ChunkRead(f, 0, 100, &bufPool)
|
||||
|
||||
assert.Equal("Lili,22,female", lines[0])
|
||||
assert.Equal("Jim,21,male", lines[1])
|
||||
|
||||
}
|
||||
|
||||
1
fileutil/testdata/test01/demo2.csv
vendored
Normal file
1
fileutil/testdata/test01/demo2.csv
vendored
Normal file
@@ -0,0 +1 @@
|
||||
makj1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user