mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-05 13:22:26 +08:00
Compare commits
275 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8120c4db78 | ||
|
|
0d0f213d36 | ||
|
|
41d4bbf0e3 | ||
|
|
fed1d5220e | ||
|
|
29a8318d6e | ||
|
|
3696213e5d | ||
|
|
90a3b87b67 | ||
|
|
a7b28ee864 | ||
|
|
f2823014f2 | ||
|
|
4181c42805 | ||
|
|
a09f5623d6 | ||
|
|
a9c75b081d | ||
|
|
db479ef1bc | ||
|
|
df8121fbbd | ||
|
|
0e7297cb97 | ||
|
|
2e619e48a3 | ||
|
|
3069acba4a | ||
|
|
fc43138a0e | ||
|
|
1e56e9964c | ||
|
|
f861e18bc3 | ||
|
|
e27df00fa8 | ||
|
|
23e61f1acf | ||
|
|
cb308f628c | ||
|
|
7653afa919 | ||
|
|
a0d97cf38e | ||
|
|
1f6bab467c | ||
|
|
2e5b9bc200 | ||
|
|
ab89f0aee1 | ||
|
|
1f64e02df4 | ||
|
|
d4b425e39c | ||
|
|
a1652c7523 | ||
|
|
ecafed511c | ||
|
|
4ffff0e3f3 | ||
|
|
8ebb8a028e | ||
|
|
995ffb799f | ||
|
|
3cd546d7f2 | ||
|
|
7fb49515ce | ||
|
|
8f3ea60636 | ||
|
|
58a37b7e8d | ||
|
|
6bd61460d3 | ||
|
|
05b85a2131 | ||
|
|
1eb793420e | ||
|
|
05f9854945 | ||
|
|
3be706e23f | ||
|
|
b5e7312353 | ||
|
|
95a894e53f | ||
|
|
8322951475 | ||
|
|
6b2c91b0f6 | ||
|
|
ec161f335d | ||
|
|
d1a8f37a71 | ||
|
|
a769257017 | ||
|
|
f3579fc142 | ||
|
|
de877e5278 | ||
|
|
08f14d2b08 | ||
|
|
0ed2b11ba1 | ||
|
|
643edc1468 | ||
|
|
e2ff83649a | ||
|
|
a7fecfc73b | ||
|
|
8bbae69175 | ||
|
|
840ea8f3c5 | ||
|
|
a4e89bd7c1 | ||
|
|
2015d36b08 | ||
|
|
921f218ef7 | ||
|
|
0a2cc9c928 | ||
|
|
ed93aae970 | ||
|
|
1671f7856a | ||
|
|
1008dd4956 | ||
|
|
a254ebdc8e | ||
|
|
0bc11001a4 | ||
|
|
85d98ad915 | ||
|
|
cb08613ac3 | ||
|
|
bad1b05224 | ||
|
|
527328739a | ||
|
|
213e2b4ead | ||
|
|
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 |
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)
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,7 +8,7 @@ fileutil/*.link
|
||||
fileutil/unzip/*
|
||||
fileutil/tempdir/*
|
||||
slice/testdata/*
|
||||
cryptor/*.pem
|
||||
# cryptor/*.pem
|
||||
test
|
||||
docs/node_modules
|
||||
docs/.vitepress/cache
|
||||
|
||||
@@ -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 中给出描述信息。
|
||||
|
||||
551
README.md
551
README.md
@@ -4,12 +4,13 @@
|
||||
<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)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
[](https://gurubase.io/g/lancet)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -24,7 +25,7 @@
|
||||
## 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 +33,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.2. </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.6. </b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||
@@ -201,10 +202,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 +248,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 +319,21 @@ 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)]
|
||||
[[play](https://go.dev/play/p/_fLJqJD3NMo)]
|
||||
- **<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)]
|
||||
[[play](https://go.dev/play/p/C_d0GlvEeUR)]
|
||||
- **<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)]
|
||||
[[play](https://go.dev/play/p/wSAr3sfkDcv)]
|
||||
- **<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)]
|
||||
[[play](https://go.dev/play/p/HwdDPFcza1O)]
|
||||
- **<big>ToBigInt</big>** : converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/convertor.md#ToBigInt)]
|
||||
[[play](https://go.dev/play/p/X3itkCxwB_x)]
|
||||
|
||||
<h3 id="cryptor"> 6. Cryptor package is for data encryption and decryption. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -354,6 +370,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](https://go.dev/play/p/rUt0-DmsPCs)]
|
||||
- **<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](https://go.dev/play/p/rUt0-DmsPCs)]
|
||||
- **<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)]
|
||||
@@ -447,10 +469,10 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
[[play](https://go.dev/play/p/zutRHrDqs0X)]
|
||||
- **<big>RsaEncrypt</big>** : encrypt data with ras algorithm.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaEncrypt)]
|
||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||
[[play](https://go.dev/play/p/7_zo6mrx-eX)]
|
||||
- **<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)]
|
||||
[[play](https://go.dev/play/p/7_zo6mrx-eX)]
|
||||
- **<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)]
|
||||
@@ -460,7 +482,12 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<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)]
|
||||
|
||||
- **<big>RsaSign</big>** : signs the data with RSA.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaSign)]
|
||||
[[play](https://go.dev/play/p/qhsbf8BJ6Mf)]
|
||||
- **<big>RsaVerifySign</big>** : verifies the signature of the data with RSA.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaVerifySign)]
|
||||
[[play](https://go.dev/play/p/qhsbf8BJ6Mf)]
|
||||
|
||||
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -479,9 +506,24 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>AddMinute</big>** : add or sub day to the time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddMinute)]
|
||||
[[play](https://go.dev/play/p/nT1heB1KUUK)]
|
||||
- **<big>AddWeek</big>** : add or sub week to time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddWeek)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddMonth</big>** : add or sub months to time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddMonth)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddYear</big>** : add or sub year to the time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddYear)]
|
||||
[[play](https://go.dev/play/p/MqW2ujnBx10)]
|
||||
- **<big>AddDaySafe</big>** : add or sub days to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddDaySafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddMonthSafe</big>** : add or sub months to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddMonthSafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddYearSafe</big>** : Add or sub years to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#AddYearSafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#BeginOfMinute)]
|
||||
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
|
||||
@@ -595,8 +637,26 @@ 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](https://go.dev/play/p/QBSEdfXHPTp)]
|
||||
- **<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](https://go.dev/play/p/qD6qGb3TbOy)]
|
||||
- **<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](https://go.dev/play/p/6kHBpAxD9ZC)]
|
||||
- **<big>Min</big>** : returns the earliest time among the given times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#Min)]
|
||||
[[play](https://go.dev/play/p/MCIDvHNOGGb)]
|
||||
- **<big>Max</big>** : returns the latest time among the given times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#Max)]
|
||||
[[play](https://go.dev/play/p/9m6JMk1LB7-)]
|
||||
- **<big>MaxMin</big>** : returns the latest and earliest time among the given times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#MaxMin)]
|
||||
[[play](https://go.dev/play/p/rbW51cDtM_2)]
|
||||
|
||||
<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"
|
||||
@@ -608,6 +668,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:
|
||||
@@ -630,6 +691,48 @@ 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="eventbus"> 9. EventBus is an event bus used for handling events within an application. <a href="#index">Index</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/eventbus"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- **<big>NewEventBus</big>** : Create an EventBus instance.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#NewEventBus)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Subscribe</big>** : subscribes to an event with a specific event topic and listener function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#Subscribe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Unsubscribe</big>** : unsubscribes from an event with a specific event topic and listener function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#Unsubscribe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Publish</big>** : publishes an event with a specific event topic and data payload.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#Publish)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>ClearListeners</big>** : clears all the listeners.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#ClearListeners)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>ClearListenersByTopic</big>** : clears all the listeners by topic.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#ClearListenersByTopic)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetListenersCount</big>** : returns the number of listeners for a specific event topic.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#GetListenersCount)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetAllListenersCount</big>** : returns the total number of all listeners.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#GetAllListenersCount)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetEvents</big>** : returns all the events topics.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#GetEvents)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>SetErrorHandler</big>** : sets the error handler function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/eventbus.md#SetErrorHandler)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
|
||||
<h3 id="fileutil"> 9. Fileutil package implements some basic functions for file operations. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -648,9 +751,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)]
|
||||
@@ -706,7 +812,9 @@ 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)]
|
||||
@@ -715,6 +823,15 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
[[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)]
|
||||
- **<big>GetExeOrDllVersion</big>** : Get the version of exe or dll file on windows os.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#GetExeOrDllVersion)]
|
||||
[[play](https://go.dev/play/p/iLRrDBhE38E)]
|
||||
|
||||
<h3 id="formatter"> 10. Formatter contains some functions for data formatting. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -724,7 +841,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.
|
||||
@@ -754,10 +871,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.
|
||||
@@ -769,19 +886,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](https://go.dev/play/p/-dGFrYn_1Zi)]
|
||||
- **<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](https://go.dev/play/p/HpoMov-tJSN)]
|
||||
- **<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
|
||||
@@ -793,7 +938,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.
|
||||
@@ -811,7 +956,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.
|
||||
@@ -856,6 +1001,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](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<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](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<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](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<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](ttps://go.dev/play/p/5bIi4yaZ3K-)]
|
||||
- **<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](https://go.dev/play/p/8LwoJyEfuFr)]
|
||||
- **<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](https://go.dev/play/p/ty57XSimpoe)]
|
||||
- **<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](https://go.dev/play/p/rQMjp1yQmpa)]
|
||||
- **<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](https://go.dev/play/p/U-KpORhc7LZ)]
|
||||
- **<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](https://go.dev/play/p/Vv_y9ExKclA)]
|
||||
- **<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](https://go.dev/play/p/TWj5n1-PUfx)]
|
||||
- **<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](https://go.dev/play/p/4BHG4kKz6bB)]
|
||||
- **<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](https://go.dev/play/p/cLe6z2VX5N-)]
|
||||
- **<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](https://go.dev/play/p/QuwqqnzwDNX)]
|
||||
- **<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](https://go.dev/play/p/tlq2tdvicPt)]
|
||||
- **<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](https://go.dev/play/p/8Q0ssg6hZzO)]
|
||||
- **<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](https://go.dev/play/p/N7hjD_alZPq)]
|
||||
- **<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](https://go.dev/play/p/C-wAwydIAC7)]
|
||||
- **<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](https://go.dev/play/p/t_pkwerIRVx)]
|
||||
- **<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)]
|
||||
@@ -880,6 +1091,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](https://go.dev/play/p/PVdmBSnm6P_W)]
|
||||
- **<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](https://go.dev/play/p/99QjSYSBdiM)]
|
||||
|
||||
|
||||
<h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -925,6 +1143,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)]
|
||||
@@ -961,9 +1191,24 @@ 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)]
|
||||
- **<big>Variance</big>** : returns the variance of numbers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Variance)]
|
||||
[[play](https://go.dev/play/p/uHuV4YgXf8F)]
|
||||
- **<big>StdDev</big>** : returns the standard deviation of numbers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#StdDev)]
|
||||
[[play](https://go.dev/play/p/FkNZDXvHD2l)]
|
||||
- **<big>Permutation</big>** : calculates P(n, k).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Permutation)]
|
||||
[[play](https://go.dev/play/p/MgobwH_FOxj)]
|
||||
- **<big>Combination</big>** : calculates C(n, k).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/mathutil.md#Combination)]
|
||||
[[play](https://go.dev/play/p/ENFQRDQUFi9)]
|
||||
|
||||
<h3 id="netutil"> 14. Netutil package contains functions to get net information and send http request. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1012,7 +1257,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.
|
||||
@@ -1055,7 +1300,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.
|
||||
@@ -1094,15 +1339,39 @@ 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.
|
||||
- **<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)]
|
||||
- **<big>RandFloat</big>** : Generate a random float64 number between [min, max) with specific precision.
|
||||
[[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)]
|
||||
- **<big>RandFloats</big>** : Generate a slice of random float64 numbers of length n that do not repeat.
|
||||
[[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](https://go.dev/play/p/2_-PiDv3tGn)]
|
||||
- **<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](https://go.dev/play/p/to6BLc26wBv)]
|
||||
- **<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](https://go.dev/play/p/o-VSjPjnILI)]
|
||||
- **<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](https://go.dev/play/p/GATTQ5xTEG8)]
|
||||
- **<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](https://go.dev/play/p/UrkWueF6yYo)]
|
||||
- **<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](https://go.dev/play/p/68UikN9d6VT)]
|
||||
- **<big>RandNumberOfLength</big>** : generates a random int number of specified length.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandNumberOfLength)]
|
||||
[[play](https://go.dev/play/p/oyZbuV7bu7b)]
|
||||
|
||||
<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>
|
||||
|
||||
@@ -1127,6 +1396,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>
|
||||
|
||||
@@ -1151,7 +1432,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.
|
||||
@@ -1172,9 +1453,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)]
|
||||
@@ -1193,6 +1477,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>EqualWith</big>** : checks if two slices are equal with comparator func.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#EqualWith)]
|
||||
[[play](https://go.dev/play/p/b9iygtgsHI1)]
|
||||
- **<big>EqualUnordered</big>** : Checks if two slices are equal: the same length and all elements value are equal (unordered).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#EqualUnordered)]
|
||||
[[play](todo)]
|
||||
- **<big>Every</big>** : return true if all of the values in the slice pass the predicate function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Every)]
|
||||
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
|
||||
@@ -1229,10 +1516,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](https://go.dev/play/p/kT4XW7DKVoV)]
|
||||
- **<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.
|
||||
@@ -1256,6 +1546,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](https://go.dev/play/p/H1ehfPkPen0)]
|
||||
- **<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)]
|
||||
@@ -1271,6 +1564,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](https://go.dev/play/p/Tjwe6OtaG07)]
|
||||
- **<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)]
|
||||
@@ -1283,6 +1579,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Shuffle</big>** : shuffle the slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Shuffle)]
|
||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||
- **<big>ShuffleCopy</big>** : return a new slice with elements shuffled.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ShuffleCopy)]
|
||||
[[play](todo)]
|
||||
- **<big>IsAscending</big>** : Checks if a slice is ascending order.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#IsAscending)]
|
||||
[[play](https://go.dev/play/p/9CtsFjet4SH)]
|
||||
@@ -1322,9 +1621,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)]
|
||||
[[play](https://go.dev/play/p/GY7JE4yikrl)]
|
||||
- **<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](https://go.dev/play/p/rwSacr-ZHsR)]
|
||||
- **<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](https://go.dev/play/p/wXZ7LcYRMGL)]
|
||||
- **<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)]
|
||||
@@ -1348,6 +1656,27 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
[[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](https://go.dev/play/p/CW3UVNdUZOq)]
|
||||
- **<big>JoinFunc</big>** : joins the slice elements into a single string with the given separator.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#JoinFunc)]
|
||||
[[play](https://go.dev/play/p/55ib3SB5fM2)]
|
||||
- **<big>ConcatBy</big>** : concats the elements of a slice into a single value using the provided separator and connector function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ConcatBy)]
|
||||
[[play](https://go.dev/play/p/6QcUpcY4UMW)]
|
||||
|
||||
<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>
|
||||
|
||||
@@ -1369,7 +1698,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.
|
||||
@@ -1381,6 +1710,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](https://go.dev/play/p/t_pkwerIRVx)]
|
||||
- **<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)]
|
||||
@@ -1396,6 +1728,9 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>Reverse</big>** : returns a stream whose elements are reverse order of given stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Reverse)]
|
||||
[[play](https://go.dev/play/p/A8_zkJnLHm4)]
|
||||
- **<big>ReverseCopy</big>** : returns a new slice of element order is reversed to the given slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#ReverseCopy)]
|
||||
[[play](todo)]
|
||||
- **<big>Range</big>** : returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#Range)]
|
||||
[[play](https://go.dev/play/p/indZY5V2f4j)]
|
||||
@@ -1414,10 +1749,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.
|
||||
@@ -1435,6 +1770,12 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>ToSlice</big>** : returns the elements in the stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#ToSlice)]
|
||||
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||
- **<big>IndexOf</big>** : returns the index of the first occurrence of the specified element in this stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#IndexOf)]
|
||||
[[play](https://go.dev/play/p/tBV5Nc-XDX2)]
|
||||
- **<big>LastIndexOf</big>** : returns the index of the last occurrence of the specified element in this stream.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#LastIndexOf)]
|
||||
[[play](https://go.dev/play/p/CjeoNw2eac_G)]
|
||||
|
||||
<h3 id="structs"> 20. Structs package provides several high level functions to manipulate struct, tag, and field. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1445,29 +1786,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>
|
||||
|
||||
@@ -1590,7 +1933,36 @@ 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](https://go.dev/play/p/gD52SZHr4Kp)]
|
||||
- **<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](https://go.dev/play/p/i1vbdQiQVRR)]
|
||||
- **<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](https://go.dev/play/p/iStFwBwyGY7)]
|
||||
- **<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](https://go.dev/play/p/Kf03iOeT5bd)]
|
||||
- **<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](https://go.dev/play/p/cXSuFvyZqv9)]
|
||||
- **<big>RegexMatchAllGroups</big>** : matches all subgroups in a string using a regular expression and returns the result.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#RegexMatchAllGroups)]
|
||||
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
|
||||
- **<big>ExtractContent</big>** : extracts the content between the start and end strings in the source string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#ExtractContent)]
|
||||
[[play](https://go.dev/play/p/Ay9UIk7Rum9)]
|
||||
- **<big>FindAllOccurrences</big>** : Returns the positions of all occurrences of a substring in a string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#FindAllOccurrences)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="system"> 22. System package contain some functions about os, runtime, shell command. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1627,6 +1999,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](https://go.dev/play/p/5GVol6ryS_X)]
|
||||
- **<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](https://go.dev/play/p/jJZhRYGGcmD)]
|
||||
- **<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](https://go.dev/play/p/XKmvV-ExBWa)]
|
||||
- **<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](https://go.dev/play/p/NQDVywEYYx7)]
|
||||
|
||||
|
||||
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. <a href="#index">index</a></h3>
|
||||
|
||||
@@ -1636,7 +2021,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.
|
||||
@@ -1648,7 +2033,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.
|
||||
@@ -1660,7 +2045,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.
|
||||
@@ -1672,7 +2057,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.
|
||||
@@ -1684,7 +2069,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.
|
||||
@@ -1696,7 +2081,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.
|
||||
@@ -1708,7 +2093,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.
|
||||
@@ -1720,7 +2105,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.
|
||||
@@ -1732,7 +2117,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.
|
||||
@@ -1831,6 +2216,9 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsIpV6</big>** : check if the string is ipv6.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsIpV6)]
|
||||
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
|
||||
- **<big>IsIpPort</big>** : check if the string is ip:port.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsIpPort)]
|
||||
[[play](todo)]
|
||||
- **<big>IsStrongPassword</big>** : check if the string is strong password.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/validator.md#IsStrongPassword)]
|
||||
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
|
||||
@@ -1864,19 +2252,19 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<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 nubmer or not.
|
||||
- **<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 nubmer or not.
|
||||
- **<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 nubmer or not.
|
||||
- **<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 nubmer or not.
|
||||
- **<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 nubmer or not.
|
||||
- **<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)]
|
||||
|
||||
@@ -1927,30 +2315,21 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
- **<big>TryUnwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, TryUnwrap panics with err.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/xerror.md#TryUnwrap)]
|
||||
[[play](https://go.dev/play/p/acyZVkNZEeW)]
|
||||
- **<big>TryCatch</big>** : simple simulation of Java-style try-catch.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/xerror.md#TryCatch)]
|
||||
[[play](https://go.dev/play/p/D5Mdb0mRj0P)]
|
||||
|
||||
## 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 [lancet](https://www.golancet.cn/en/) 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)
|
||||
|
||||
557
README_zh-CN.md
557
README_zh-CN.md
@@ -4,12 +4,13 @@
|
||||
<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)
|
||||
[](https://codecov.io/gh/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||
[](https://gurubase.io/g/lancet)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -23,7 +24,7 @@
|
||||
## 特性
|
||||
|
||||
- 👏 全面、高效、可复用。
|
||||
- 💪 600+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💪 700+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖 go 标准库和 golang.org/x。
|
||||
- 🌍 所有导出函数单元测试覆盖率 100%。
|
||||
|
||||
@@ -37,7 +38,7 @@
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.2。</b>
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.6。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
@@ -100,6 +101,7 @@ func main() {
|
||||
- [Validator](#user-content-validator)
|
||||
- [Xerror](#user-content-xerror)
|
||||
|
||||
|
||||
<h3 id="algorithm"> 1. algorithm 包实现一些基本查找和排序算法。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
@@ -317,6 +319,21 @@ 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)]
|
||||
[[play](https://go.dev/play/p/_fLJqJD3NMo)]
|
||||
- **<big>ToUrlBase64</big>** : 将值转换为url Base64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToUrlBase64)]
|
||||
[[play](https://go.dev/play/p/C_d0GlvEeUR)]
|
||||
- **<big>ToRawStdBase64</big>** : 将值转换为RawStdBase64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawStdBase64)]
|
||||
[[play](https://go.dev/play/p/wSAr3sfkDcv)]
|
||||
- **<big>ToRawUrlBase64</big>** : 将值转换为RawUrlBase64编码的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToRawUrlBase64)]
|
||||
[[play](https://go.dev/play/p/HwdDPFcza1O)]
|
||||
- **<big>ToBigInt</big>** : 将整数转为*big.Int。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/convertor.md#ToBigInt)]
|
||||
[[play](https://go.dev/play/p/X3itkCxwB_x)]
|
||||
|
||||
<h3 id="cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -353,6 +370,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](https://go.dev/play/p/rUt0-DmsPCs)]
|
||||
- **<big>AesGcmDecrypt</big>** : 使用 AES GCM 算法模式解密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesGcmDecrypt)]
|
||||
[[play](https://go.dev/play/p/rUt0-DmsPCs)]
|
||||
- **<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)]
|
||||
@@ -447,10 +470,10 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
[[play](https://go.dev/play/p/zutRHrDqs0X)]
|
||||
- **<big>RsaEncrypt</big>** : 用公钥文件 ras 加密数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaEncrypt)]
|
||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||
[[play](https://go.dev/play/p/7_zo6mrx-eX)]
|
||||
- **<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)]
|
||||
[[play](https://go.dev/play/p/7_zo6mrx-eX)]
|
||||
- **<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)]
|
||||
@@ -460,9 +483,14 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
||||
- **<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)]
|
||||
- **<big>RsaSign</big>** : 应用RSA算法签名数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaSign)]
|
||||
[[play](https://go.dev/play/p/qhsbf8BJ6Mf)]
|
||||
- **<big>RsaVerifySign</big>** : 验证数据的签名是否符合RSA算法。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaVerifySign)]
|
||||
[[play](https://go.dev/play/p/qhsbf8BJ6Mf)]
|
||||
|
||||
|
||||
<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"
|
||||
@@ -479,9 +507,24 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>AddMinute</big>** : 将日期加/减分钟数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddMinute)]
|
||||
[[play](https://go.dev/play/p/nT1heB1KUUK)]
|
||||
- **<big>AddWeek</big>** : 将日期加/减星期数.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddWeek)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddMonth</big>** : 将日期加/减月数.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddMonth)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddYear</big>** : 将日期加/减分年数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddYear)]
|
||||
[[play](https://go.dev/play/p/MqW2ujnBx10)]
|
||||
- **<big>AddDaySafe</big>** : 增加/减少指定的天数,并确保日期是有效日期。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddDaySafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddMonthSafe</big>** : 增加/减少指定的月份,并确保日期是有效日期。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddMonthSafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>AddYearSafe</big>** : 增加/减少指定的年份,并确保日期是有效日期。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#AddYearSafe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BeginOfMinute)]
|
||||
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
|
||||
@@ -596,6 +639,25 @@ 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](https://go.dev/play/p/QBSEdfXHPTp)]
|
||||
- **<big>DaysBetween</big>** : 返回两个日期之间的天数差。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#DaysBetween)]
|
||||
[[play](https://go.dev/play/p/qD6qGb3TbOy)]
|
||||
- **<big>GenerateDatetimesBetween</big>** : 生成从start到end的所有日期时间的字符串列表。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#GenerateDatetimesBetween)]
|
||||
[[play](https://go.dev/play/p/6kHBpAxD9ZC)]
|
||||
- **<big>Min</big>** : 返回最早时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#Min)]
|
||||
[[play](https://go.dev/play/p/MCIDvHNOGGb)]
|
||||
- **<big>Max</big>** : 返回最晚时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#Max)]
|
||||
[[play](https://go.dev/play/p/9m6JMk1LB7-)]
|
||||
- **<big>MaxMin</big>** : 返回最早和最晚时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#MaxMin)]
|
||||
[[play](https://go.dev/play/p/rbW51cDtM_2)]
|
||||
|
||||
|
||||
<h3 id="datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
@@ -632,7 +694,46 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
|
||||
- **<big>Hashmap</big>** : 哈希映射。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datastructure/hashmap.md)]
|
||||
|
||||
<h3 id="fileutil"> 9. fileutil 包含文件基本操作。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="eventbus"> 9. EventbBus是一个事件总线,用于在应用程序中处理事件。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/eventbus"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
|
||||
- **<big>NewEventBus</big>** : 创建EventBus实例。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#NewEventBus)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Subscribe</big>** : 订阅具有特定事件主题和监听函数的事件。支持异步,事件优先级,事件过滤器。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#Subscribe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Unsubscribe</big>** : 取消订阅具有特定事件主题的事件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#Unsubscribe)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>Publish</big>** : 发布一个带有特定事件主题和数据负载的事件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#Publish)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>ClearListeners</big>** : 清空所有事件监听器。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#ClearListeners)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>ClearListenersByTopic</big>** : 清空特定事件监听器。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#ClearListenersByTopic)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetListenersCount</big>** : 获取特定事件的监听器数量。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#GetListenersCount)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetAllListenersCount</big>** : 获取所有事件的监听器数量。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#GetAllListenersCount)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>GetEvents</big>** : 获取所有事件的topic。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#GetEvents)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
- **<big>SetErrorHandler</big>** : 设置事件的错误处理函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/eventbus.md#SetErrorHandler)]
|
||||
[[play](https://go.dev/play/p/todo)]
|
||||
|
||||
<h3 id="fileutil"> 10. fileutil 包含文件基本操作。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/fileutil"
|
||||
@@ -649,9 +750,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)]
|
||||
@@ -705,9 +809,11 @@ 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)]
|
||||
@@ -716,8 +822,18 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
[[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)]
|
||||
- **<big>GetExeOrDllVersion</big>** : 返回exe,dll文件版本号(仅Window平台)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#GetExeOrDllVersion)]
|
||||
[[play](https://go.dev/play/p/iLRrDBhE38E)]
|
||||
|
||||
<h3 id="formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
<h3 id="formatter"> 11. formatter 格式化器包含一些数据格式化处理方法。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/formatter"
|
||||
@@ -725,7 +841,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 字符串。
|
||||
@@ -747,7 +863,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/formatter.md#ParseBinaryBytes)]
|
||||
[[play](https://go.dev/play/p/69v1tTT62x8)]
|
||||
|
||||
<h3 id="function"> 11. function 函数包控制函数执行流程,包含部分函数式编程。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="function"> 12. function 函数包控制函数执行流程,包含部分函数式编程。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/function"
|
||||
@@ -770,20 +886,49 @@ 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](https://go.dev/play/p/-dGFrYn_1Zi)]
|
||||
- **<big>Throttle</big>** : 创建一个函数的节流版本。返回的函数保证在每个时间间隔内最多只会被调用一次。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Throttle)]
|
||||
[[play](https://go.dev/play/p/HpoMov-tJSN)]
|
||||
- **<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>
|
||||
|
||||
|
||||
<h3 id="maputil"> 13. maputil 包括一些操作 map 的函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
@@ -857,6 +1002,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](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<big>OrderedMap_Set</big>** : 设置给定的键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Set)]
|
||||
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<big>OrderedMap_Get</big>** : 返回给定键的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Get)]
|
||||
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
|
||||
- **<big>OrderedMap_Delete</big>** : 删除给定键的键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Delete)]
|
||||
[[play](ttps://go.dev/play/p/5bIi4yaZ3K-)]
|
||||
- **<big>OrderedMap_Clear</big>** : 清空map数据。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Clear)]
|
||||
[[play](https://go.dev/play/p/8LwoJyEfuFr)]
|
||||
- **<big>OrderedMap_Front</big>** : 返回第一个键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Front)]
|
||||
[[play](https://go.dev/play/p/ty57XSimpoe)]
|
||||
- **<big>OrderedMap_Back</big>** : 返回最后一个键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Back)]
|
||||
[[play](https://go.dev/play/p/rQMjp1yQmpa)]
|
||||
- **<big>OrderedMap_Range</big>** : 为每个键值对调用给定的函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Range)]
|
||||
[[play](https://go.dev/play/p/U-KpORhc7LZ)]
|
||||
- **<big>OrderedMap_Keys</big>** : 按顺序返回键的切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Keys)]
|
||||
[[play](https://go.dev/play/p/Vv_y9ExKclA)]
|
||||
- **<big>OrderedMap_Values</big>** : 按顺序返回值的切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Values)]
|
||||
[[play](https://go.dev/play/p/TWj5n1-PUfx)]
|
||||
- **<big>OrderedMap_Elements</big>** : 按顺序返回键值对。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Elements)]
|
||||
[[play](https://go.dev/play/p/4BHG4kKz6bB)]
|
||||
- **<big>OrderedMap_Len</big>** : 返回键值对的数量。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Len)]
|
||||
[[play](https://go.dev/play/p/cLe6z2VX5N-)]
|
||||
- **<big>OrderedMap_Contains</big>** : 如果给定的键存在则返回true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Contains)]
|
||||
[[play](https://go.dev/play/p/QuwqqnzwDNX)]
|
||||
- **<big>OrderedMap_Iter</big>** : 返回按顺序产生键值对的通道。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Iter)]
|
||||
[[play](https://go.dev/play/p/tlq2tdvicPt)]
|
||||
- **<big>OrderedMap_ReverseIter</big>** : 返回以相反顺序产生键值对的通道。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_ReverseIter)]
|
||||
[[play](https://go.dev/play/p/8Q0ssg6hZzO)]
|
||||
- **<big>OrderedMap_SortByKey</big>** : 使用传入的比较函数排序map key。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_SortByKey)]
|
||||
[[play](https://go.dev/play/p/N7hjD_alZPq)]
|
||||
- **<big>OrderedMap_MarshalJSON</big>** : 实现json.Marshaler接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_MarshalJSON)]
|
||||
[[play](https://go.dev/play/p/C-wAwydIAC7)]
|
||||
- **<big>OrderedMap_UnmarshalJSON</big>** : 实现json.Unmarshaler接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_UnmarshalJSON)]
|
||||
[[play](https://go.dev/play/p/8C3MvJ3-mut)]
|
||||
- **<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)]
|
||||
@@ -881,8 +1092,14 @@ 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](https://go.dev/play/p/PVdmBSnm6P_W)]
|
||||
- **<big>GetOrDefault</big>** : 返回给定键的值,如果键不存在,则返回默认值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrDefault)]
|
||||
[[play](https://go.dev/play/p/99QjSYSBdiM)]
|
||||
|
||||
<h3 id="mathutil"> 13. mathutil 包实现了一些数学计算的函数。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="mathutil"> 14. mathutil 包实现了一些数学计算的函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/mathutil"
|
||||
@@ -926,6 +1143,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)]
|
||||
@@ -965,8 +1194,23 @@ 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)]
|
||||
- **<big>Variance</big>** : 计算方差。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Variance)]
|
||||
[[play](https://go.dev/play/p/uHuV4YgXf8F)]
|
||||
- **<big>StdDev</big>** : 计算标准差。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#StdDev)]
|
||||
[[play](https://go.dev/play/p/FkNZDXvHD2l)]
|
||||
- **<big>Permutation</big>** : 计算排列数P(n, k)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Permutation)]
|
||||
[[play](https://go.dev/play/p/MgobwH_FOxj)]
|
||||
- **<big>Combination</big>** : 计算组合数C(n, k)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/mathutil.md#Combination)]
|
||||
[[play](https://go.dev/play/p/ENFQRDQUFi9)]
|
||||
|
||||
<h3 id="netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="netutil"> 15. netutil 网络包支持获取 ip 地址,发送 http 请求。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/netutil"
|
||||
@@ -1039,7 +1283,7 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/netutil.md#IsTelnetConnected)]
|
||||
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
|
||||
|
||||
<h3 id="pointer"> 15. pointer 包支持一些指针类型的操作。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="pointer"> 16. pointer 包支持一些指针类型的操作。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/pointer"
|
||||
@@ -1063,7 +1307,7 @@ import "github.com/duke-git/lancet/v2/pointer"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/pointer.md#UnwrapOrDefault)]
|
||||
[[play](https://go.dev/play/p/ZnGIHf8_o4E)]
|
||||
|
||||
<h3 id="random"> 16. random 随机数生成器包,可以生成随机[]bytes, int, string。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="random"> 17. random 随机数生成器包,可以生成随机[]bytes, int, string。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/random"
|
||||
@@ -1095,19 +1339,41 @@ 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/uBkRSOz73Ec)]
|
||||
[[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/uBkRSOz73Ec)]
|
||||
[[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](https://go.dev/play/p/2_-PiDv3tGn)]
|
||||
- **<big>RandBool</big>** : 生成随机bool值(true or false)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBool)]
|
||||
[[play](https://go.dev/play/p/to6BLc26wBv)]
|
||||
- **<big>RandBoolSlice</big>** : 生成特定长度的随机bool slice。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBoolSlice)]
|
||||
[[play](https://go.dev/play/p/o-VSjPjnILI)]
|
||||
- **<big>RandIntSlice</big>** : 生成一个特定长度的随机int切片,数值范围[min, max)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandIntSlice)]
|
||||
[[play](https://go.dev/play/p/GATTQ5xTEG8)]
|
||||
- **<big>RandFromGivenSlice</big>** : 从给定切片中随机生成元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFromGivenSlice)]
|
||||
[[play](https://go.dev/play/p/UrkWueF6yYo)]
|
||||
- **<big>RandSliceFromGivenSlice</big>** : 从给定切片中生成长度为 num 的随机切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSliceFromGivenSlice)]
|
||||
[[play](https://go.dev/play/p/68UikN9d6VT)]
|
||||
- **<big>RandNumberOfLength</big>** : 生成指定长度的随机数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandNumberOfLength)]
|
||||
[[play](https://go.dev/play/p/oyZbuV7bu7b)]
|
||||
|
||||
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="retry"> 18. retry 重试执行函数直到函数运行成功或被 context cancel。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/retry"
|
||||
@@ -1124,14 +1390,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。
|
||||
- **<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 包含操作切片的方法集合。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
|
||||
<h3 id="slice"> 19. slice 包含操作切片的方法集合。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/slice"
|
||||
@@ -1175,9 +1451,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)]
|
||||
@@ -1196,6 +1475,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>EqualWith</big>** : 检查两个切片是否相等,相等条件:对两个切片的元素调用比较函数 comparator,返回 true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#EqualWith)]
|
||||
[[play](https://go.dev/play/p/b9iygtgsHI1)]
|
||||
- **<big>EqualUnordered</big>** : 检查两个切片是否相等,元素数量相同,值相等,不考虑元素顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#EqualUnordered)]
|
||||
[[play](todo)]
|
||||
- **<big>Every</big>** : 如果切片中的所有值都通过谓词函数,则返回 true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Every)]
|
||||
[[play](https://go.dev/play/p/R8U6Sl-j8cD)]
|
||||
@@ -1229,6 +1511,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](https://go.dev/play/p/kT4XW7DKVoV)]
|
||||
- **<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)]
|
||||
@@ -1259,12 +1544,18 @@ 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](https://go.dev/play/p/H1ehfPkPen0)]
|
||||
- **<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)]
|
||||
- **<big>Reverse</big>** : 反转切片中的元素顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Reverse)]
|
||||
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
||||
- **<big>ReverseCopy</big>** : 反转切片中的元素顺序, 不改变原slice。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#ReverseCopy)]
|
||||
[[play](todo)]
|
||||
- **<big>Reduce<sup>deprecated</sup></big>** : 将切片中的元素依次运行 iteratee 函数,返回运行结果。(废弃:建议使用 ReduceBy)
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Reduce)]
|
||||
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
||||
@@ -1274,6 +1565,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](https://go.dev/play/p/Tjwe6OtaG07)]
|
||||
- **<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)]
|
||||
@@ -1286,6 +1580,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Shuffle)]
|
||||
[[play](https://go.dev/play/p/YHvhnWGU3Ge)]
|
||||
- **<big>ShuffleCopy</big>** : 随机打乱切片中的元素顺序, 不改变原切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ShuffleCopy)]
|
||||
[[play](todo)]
|
||||
- **<big>IsAscending</big>** : 检查切片元素是否按升序排列。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#IsAscending)]
|
||||
[[play](https://go.dev/play/p/9CtsFjet4SH)]
|
||||
@@ -1325,9 +1622,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)]
|
||||
[[play](https://go.dev/play/p/GY7JE4yikrl)]
|
||||
- **<big>UniqueByComparator</big>** : 使用提供的比较器函数从输入切片中移除重复元素。此函数保持元素的顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByComparator)]
|
||||
[[play](https://go.dev/play/p/rwSacr-ZHsR)]
|
||||
- **<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](https://go.dev/play/p/wXZ7LcYRMGL)]
|
||||
- **<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)]
|
||||
@@ -1340,7 +1646,6 @@ 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>** : 用指定的分隔符链接切片元素。
|
||||
@@ -1351,9 +1656,29 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
[[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](https://go.dev/play/p/CW3UVNdUZOq)]
|
||||
- **<big>JoinFunc</big>** : 将切片元素用给定的分隔符连接成一个单一的字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#JoinFunc)]
|
||||
[[play](https://go.dev/play/p/55ib3SB5fM2)]
|
||||
- **<big>ConcatBy</big>** : 将切片中的元素连接成一个值,使用指定的分隔符和连接器函数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ConcatBy)]
|
||||
[[play](https://go.dev/play/p/6QcUpcY4UMW)]
|
||||
|
||||
|
||||
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="stream"> 20. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/stream"
|
||||
@@ -1379,12 +1704,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](https://go.dev/play/p/t_pkwerIRVx)]
|
||||
- **<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)]
|
||||
@@ -1439,8 +1767,14 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>ToSlice</big>** : 返回 stream 中的元素切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#ToSlice)]
|
||||
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||
- **<big>IndexOf</big>** : 返回在stream中找到值的第一个匹配项的索引,如果找不到值,则返回-1。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#IndexOf)]
|
||||
[[play](https://go.dev/play/p/tBV5Nc-XDX2)]
|
||||
- **<big>LastIndexOf</big>** : 返回在stream中找到值的最后一个匹配项的索引,如果找不到值,则返回-1。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#LastIndexOf)]
|
||||
[[play](https://go.dev/play/p/CjeoNw2eac_G)]
|
||||
|
||||
<h3 id="structs"> 20. structs 提供操作 struct, tag, field 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="structs"> 21. structs 提供操作 struct, tag, field 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/structs"
|
||||
@@ -1449,33 +1783,35 @@ 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>
|
||||
<h3 id="strutil"> 22. strutil 包含字符串处理的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/strutil"
|
||||
@@ -1597,8 +1933,39 @@ 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](https://go.dev/play/p/gD52SZHr4Kp)]
|
||||
- **<big>Ellipsis</big>** : 将字符串截断到指定长度,并在末尾添加省略号。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Ellipsis)]
|
||||
[[play](https://go.dev/play/p/i1vbdQiQVRR)]
|
||||
- **<big>Shuffle</big>** : 打乱给定字符串中的字符顺序。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Shuffle)]
|
||||
[[play](https://go.dev/play/p/iStFwBwyGY7)]
|
||||
- **<big>Rotate</big>** : 按指定的字符数旋转字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Rotate)]
|
||||
[[play](https://go.dev/play/p/Kf03iOeT5bd)]
|
||||
- **<big>TemplateReplace</big>** : 将模板字符串中的占位符替换为map中的相应值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#TemplateReplace)]
|
||||
[[play](https://go.dev/play/p/cXSuFvyZqv9)]
|
||||
- **<big>RegexMatchAllGroups</big>** : 使用正则表达式匹配字符串中的所有子组并返回结果。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#RegexMatchAllGroups)]
|
||||
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
|
||||
- **<big>ExtractContent</big>** : 提取两个标记之间的内容。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#ExtractContent)]
|
||||
[[play](https://go.dev/play/p/Ay9UIk7Rum9)]
|
||||
- **<big>FindAllOccurrences</big>** : 返回子字符串在字符串中所有出现的位置。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#FindAllOccurrences)]
|
||||
[[play](todo)]
|
||||
|
||||
<h3 id="system"> 22. system 包含 os, runtime, shell command 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
<h3 id="system"> 23. system 包含 os, runtime, shell command 的相关函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/system"
|
||||
@@ -1633,8 +2000,22 @@ 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](https://go.dev/play/p/5GVol6ryS_X)]
|
||||
- **<big>StopProcess</big>** : 停止进程。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StopProcess)]
|
||||
[[play](https://go.dev/play/p/jJZhRYGGcmD)]
|
||||
- **<big>KillProcess</big>** : 杀掉进程。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#KillProcess)]
|
||||
[[play](https://go.dev/play/p/XKmvV-ExBWa)]
|
||||
- **<big>GetProcessInfo</big>** : 根据进程id获取进程信息。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)]
|
||||
[[play](https://go.dev/play/p/NQDVywEYYx7)]
|
||||
|
||||
<h3 id="tuple"> 23. Tuple 包实现一个元组数据类型。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
|
||||
<h3 id="tuple"> 24. Tuple 包实现一个元组数据类型。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/tuple"
|
||||
@@ -1751,7 +2132,7 @@ import "github.com/duke-git/lancet/v2/tuple"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/tuple.md#Unzip10)]
|
||||
[[play](https://go.dev/play/p/-taQB6Wfre_z)]
|
||||
|
||||
<h3 id="validator"> 24. validator 验证器包,包含常用字符串格式验证函数。 <a href="#index">回到目录</a></h3>
|
||||
<h3 id="validator"> 25. validator 验证器包,包含常用字符串格式验证函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/validator"
|
||||
@@ -1795,7 +2176,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsCreditCard</big>** : 验证字符串是否是信用卡号码。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsCreditCard)]
|
||||
[[play](https://go.dev/play/p/sNwwL6B0-v4)]
|
||||
- **<big>IsDns</big>** : 验证字符串是否是有效 dns。
|
||||
- **<big>IsDns</big>** : 验证字符串是否是有效dns。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsDns)]
|
||||
[[play](https://go.dev/play/p/jlYApVLLGTZ)]
|
||||
- **<big>IsEmail</big>** : 验证字符串是否是有效电子邮件地址。
|
||||
@@ -1831,12 +2212,15 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsIp</big>** : 验证字符串是否是 ip 地址。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIp)]
|
||||
[[play](https://go.dev/play/p/FgcplDvmxoD)]
|
||||
- **<big>IsIpV4</big>** : 验证字符串是否是 ipv4 地址。
|
||||
- **<big>IsIpV4</big>** : 验证字符串是否是ipv4地址。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIpV4)]
|
||||
[[play](https://go.dev/play/p/zBGT99EjaIu)]
|
||||
- **<big>IsIpV6</big>** : 验证字符串是否是 ipv6 地址。
|
||||
- **<big>IsIpV6</big>** : 验证字符串是否是ipv6地址。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIpV6)]
|
||||
[[play](https://go.dev/play/p/AHA0r0AzIdC)]
|
||||
- **<big>IsIpPort</big>** : 检查字符串是否是ip:port格式。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsIpPort)]
|
||||
[[play](todo)]
|
||||
- **<big>IsStrongPassword</big>** : 验证字符串是否是强密码:(字母+数字+特殊字符)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsStrongPassword)]
|
||||
[[play](https://go.dev/play/p/QHdVcSQ3uDg)]
|
||||
@@ -1849,10 +2233,10 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<big>IsZeroValue</big>** : 判断传入的参数值是否为零值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsZeroValue)]
|
||||
[[play](https://go.dev/play/p/UMrwaDCi_t4)]
|
||||
- **<big>IsGBK</big>** : 检查数据编码是否为 gbk(汉字内部代码扩展规范)。
|
||||
- **<big>IsGBK</big>** : 检查数据编码是否为gbk(汉字内部代码扩展规范)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsGBK)]
|
||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
|
||||
- **<big>IsASCII</big>** : 验证字符串全部为ASCII字符。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/validator.md#IsASCII)]
|
||||
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
|
||||
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
||||
@@ -1867,13 +2251,13 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
- **<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/en/api/packages/validator.md#IsJWT)]
|
||||
- **<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 卡号。
|
||||
- **<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 卡号。
|
||||
- **<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 卡号。
|
||||
@@ -1886,7 +2270,7 @@ import "github.com/duke-git/lancet/v2/validator"
|
||||
[[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>
|
||||
<h3 id="xerror"> 26. xerror 包实现一些错误处理函数。 <a href="#index">回到目录</a></h3>
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/xerror"
|
||||
@@ -1909,53 +2293,46 @@ import "github.com/duke-git/lancet/v2/xerror"
|
||||
- **<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)
|
||||
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
|
||||
- **<big>XError_With</big>** : 添加与 XError 对象的键和值。
|
||||
- **<big>XError_With</big>** : 添加与XError对象的键和值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_With)]
|
||||
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||
- **<big>XError_Id</big>** : 设置 XError 对象的 id。
|
||||
- **<big>XError_Id</big>** : 设置XError对象的id。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Id)]
|
||||
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||
- **<big>XError_Is</big>** : 检查目标 error 是否为 XError,两个错误中的 error.id 是否匹配。
|
||||
- **<big>XError_Is</big>** : 检查目标error是否为XError,两个错误中的error.id是否匹配。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Is)]
|
||||
[[play](https://go.dev/play/p/X6HBlsy58U9)]
|
||||
- **<big>XError_Values</big>** : 返回由 With 设置的键和值的映射。将合并所有 XError 键和值。
|
||||
- **<big>XError_Values</big>** : 返回由With设置的键和值的映射。将合并所有XError键和值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Values)]
|
||||
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
|
||||
- **<big>XError_StackTrace</big>** : 返回与 pkg/error 兼容的堆栈信息。
|
||||
- **<big>XError_StackTrace</big>** : 返回与pkg/error兼容的堆栈信息。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_StackTrace)]
|
||||
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
|
||||
- **<big>XError_Info</big>** : 返回可打印的 XError 对象信息。
|
||||
- **<big>XError_Info</big>** : 返回可打印的XError对象信息。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Info)]
|
||||
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
|
||||
- **<big>XError_Error</big>** : 实现标准库的 error 接口。
|
||||
- **<big>XError_Error</big>** : 实现标准库的error接口。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#XError_Error)]
|
||||
[[play](https://go.dev/play/p/w4oWZts7q7f)]
|
||||
- **<big>TryUnwrap</big>** : 检查 error, 如果 err 为 nil 则展开,则它返回一个有效值,如果 err 不是 nil 则 Unwrap 使用 err 发生 panic。
|
||||
- **<big>TryUnwrap</big>** : 检查error, 如果err为nil则展开,则它返回一个有效值,如果err不是nil则Unwrap使用err发生panic。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#TryUnwrap)]
|
||||
[[play](https://go.dev/play/p/acyZVkNZEeW)]
|
||||
- **<big>TryCatch</big>** : 简单实现的java风格异常处理(try-catch-finally)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/xerror.md#TryCatch)]
|
||||
[[play](https://go.dev/play/p/D5Mdb0mRj0P)]
|
||||
|
||||
## 如何贡献代码
|
||||
|
||||
#### [贡献代码指南](./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](https://www.golancet.cn/)官网的维护和云服务器的费用支付。或者当我写代码困倦时,给我买杯 ☕️。_
|
||||
#### [代码贡献指南](./CONTRIBUTION.zh-CN.md)
|
||||
|
||||
## 贡献者
|
||||
|
||||
感谢所有为 lancet 贡献过代码的人!
|
||||
感谢所有为lancet贡献过代码的人!
|
||||
|
||||
<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)
|
||||
@@ -44,7 +44,7 @@ func (l *LRUCache[K, V]) Get(key K) (V, bool) {
|
||||
|
||||
node, ok := l.cache[key]
|
||||
if ok {
|
||||
l.moveToHead(node)
|
||||
l.moveToTail(node)
|
||||
return node.value, true
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func (l *LRUCache[K, V]) Put(key K, value V) {
|
||||
}
|
||||
} else {
|
||||
node.value = value
|
||||
l.moveToHead(node)
|
||||
l.moveToTail(node)
|
||||
}
|
||||
l.length = len(l.cache)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool {
|
||||
delete(l.cache, key)
|
||||
return true
|
||||
}
|
||||
|
||||
l.length = len(l.cache)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
|
||||
return node.key
|
||||
}
|
||||
|
||||
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
|
||||
func (l *LRUCache[K, V]) moveToTail(node *lruNode[K, V]) {
|
||||
if l.tail == node {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
func TestLRUCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestLRUCache")
|
||||
assert := internal.NewAssert(t, "TestLRUCache")
|
||||
|
||||
cache := NewLRUCache[int, int](3)
|
||||
|
||||
@@ -16,19 +16,19 @@ func TestLRUCache(t *testing.T) {
|
||||
cache.Put(2, 2)
|
||||
cache.Put(3, 3)
|
||||
|
||||
asssert.Equal(3, cache.Len())
|
||||
assert.Equal(3, cache.Len())
|
||||
|
||||
v, ok := cache.Get(1)
|
||||
asssert.Equal(true, ok)
|
||||
asssert.Equal(1, v)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(1, v)
|
||||
|
||||
v, ok = cache.Get(2)
|
||||
asssert.Equal(true, ok)
|
||||
asssert.Equal(2, v)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(2, v)
|
||||
|
||||
ok = cache.Delete(2)
|
||||
asssert.Equal(true, ok)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
_, ok = cache.Get(2)
|
||||
asssert.Equal(false, ok)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -8,34 +8,34 @@ import (
|
||||
|
||||
func TestLinearSearch(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestLinearSearch")
|
||||
assert := internal.NewAssert(t, "TestLinearSearch")
|
||||
|
||||
numbers := []int{3, 4, 5, 3, 2, 1}
|
||||
equalFunc := func(a, b int) bool {
|
||||
return a == b
|
||||
}
|
||||
|
||||
asssert.Equal(0, LinearSearch(numbers, 3, equalFunc))
|
||||
asssert.Equal(-1, LinearSearch(numbers, 6, equalFunc))
|
||||
assert.Equal(0, LinearSearch(numbers, 3, equalFunc))
|
||||
assert.Equal(-1, LinearSearch(numbers, 6, equalFunc))
|
||||
}
|
||||
|
||||
func TestBinarySearch(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBinarySearch")
|
||||
assert := internal.NewAssert(t, "TestBinarySearch")
|
||||
|
||||
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
|
||||
asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
assert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
assert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
}
|
||||
|
||||
func TestBinaryIterativeSearch(t *testing.T) {
|
||||
asssert := internal.NewAssert(t, "TestBinaryIterativeSearch")
|
||||
assert := internal.NewAssert(t, "TestBinaryIterativeSearch")
|
||||
|
||||
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
comparator := &intComparator{}
|
||||
|
||||
asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
assert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
|
||||
assert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -47,7 +47,7 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
|
||||
func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||
assert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -62,23 +62,23 @@ func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestBubbleSortForIntSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
||||
assert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
||||
|
||||
numbers := []int{2, 1, 5, 3, 6, 4}
|
||||
comparator := &intComparator{}
|
||||
BubbleSort(numbers, comparator)
|
||||
|
||||
asssert.Equal([]int{1, 2, 3, 4, 5, 6}, numbers)
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, numbers)
|
||||
}
|
||||
|
||||
func TestInsertionSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestInsertionSort")
|
||||
assert := internal.NewAssert(t, "TestInsertionSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -93,12 +93,12 @@ func TestInsertionSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestSelectionSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestSelectionSort")
|
||||
assert := internal.NewAssert(t, "TestSelectionSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -113,12 +113,12 @@ func TestSelectionSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestShellSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestShellSort")
|
||||
assert := internal.NewAssert(t, "TestShellSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -133,12 +133,12 @@ func TestShellSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestQuickSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestQuickSort")
|
||||
assert := internal.NewAssert(t, "TestQuickSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -153,12 +153,12 @@ func TestQuickSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestHeapSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestHeapSort")
|
||||
assert := internal.NewAssert(t, "TestHeapSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -173,12 +173,12 @@ func TestHeapSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestMergeSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestMergeSort")
|
||||
assert := internal.NewAssert(t, "TestMergeSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -193,12 +193,12 @@ func TestMergeSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", peoples)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestCountSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestCountSort")
|
||||
assert := internal.NewAssert(t, "TestCountSort")
|
||||
|
||||
peoples := []people{
|
||||
{Name: "a", Age: 20},
|
||||
@@ -213,5 +213,5 @@ func TestCountSort(t *testing.T) {
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
asssert.Equal(expected, actual)
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package compare
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
@@ -24,6 +25,13 @@ func compareValue(operator string, left, right any) bool {
|
||||
|
||||
case reflect.Struct, reflect.Slice, reflect.Map:
|
||||
return compareRefValue(operator, left, right, leftType.Kind())
|
||||
|
||||
case reflect.Ptr:
|
||||
if leftVal, ok := left.(*big.Int); ok {
|
||||
if rightVal, ok := right.(*big.Int); ok {
|
||||
return compareBigInt(operator, leftVal, rightVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -155,169 +163,129 @@ func compareBasicValue(operator string, leftValue, rightValue any) bool {
|
||||
}
|
||||
|
||||
switch leftVal := leftValue.(type) {
|
||||
case json.Number:
|
||||
if left, err := leftVal.Float64(); err == nil {
|
||||
switch rightVal := rightValue.(type) {
|
||||
case json.Number:
|
||||
if right, err := rightVal.Float64(); err == nil {
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if left < right {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if left > right {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if left <= right {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if left >= right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
right, err := convertor.ToFloat(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if left < right {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if left > right {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if left <= right {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if left >= right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
left, err := convertor.ToBigInt(leftValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
right, err := convertor.ToBigInt(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return compareBigInt(operator, left, right)
|
||||
|
||||
case float32, float64:
|
||||
left, err := convertor.ToFloat(leftValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
switch rightVal := rightValue.(type) {
|
||||
case json.Number:
|
||||
if right, err := rightVal.Float64(); err == nil {
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if left < right {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if left > right {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if left <= right {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if left >= right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
right, err := convertor.ToFloat(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if left < right {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if left > right {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if left <= right {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if left >= right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
right, err := convertor.ToFloat(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return compareFloats(operator, left, right)
|
||||
|
||||
case string:
|
||||
left := leftVal
|
||||
switch right := rightValue.(type) {
|
||||
case string:
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if left < right {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if left > right {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if left <= right {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if left >= right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return compareStrings(operator, left, right)
|
||||
}
|
||||
|
||||
case bool:
|
||||
left := leftVal
|
||||
switch right := rightValue.(type) {
|
||||
case bool:
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return compareBools(operator, left, right)
|
||||
}
|
||||
|
||||
case json.Number:
|
||||
if left, err := leftVal.Float64(); err == nil {
|
||||
switch rightVal := rightValue.(type) {
|
||||
case json.Number:
|
||||
if right, err := rightVal.Float64(); err == nil {
|
||||
return compareFloats(operator, left, right)
|
||||
}
|
||||
case float32, float64:
|
||||
right, err := convertor.ToFloat(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return compareFloats(operator, left, right)
|
||||
|
||||
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
right, err := convertor.ToBigInt(rightValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
left, err := convertor.ToBigInt(left)
|
||||
return compareBigInt(operator, left, right)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// compareBigInt compares two big.Int values based on the operator
|
||||
func compareBigInt(operator string, left, right *big.Int) bool {
|
||||
switch operator {
|
||||
case equal:
|
||||
return left.Cmp(right) == 0
|
||||
case lessThan:
|
||||
return left.Cmp(right) < 0
|
||||
case greaterThan:
|
||||
return left.Cmp(right) > 0
|
||||
case lessOrEqual:
|
||||
return left.Cmp(right) <= 0
|
||||
case greaterOrEqual:
|
||||
return left.Cmp(right) >= 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// compareFloats compares two float64 values based on the operator
|
||||
func compareFloats(operator string, left, right float64) bool {
|
||||
switch operator {
|
||||
case equal:
|
||||
return left == right
|
||||
case lessThan:
|
||||
return left < right
|
||||
case greaterThan:
|
||||
return left > right
|
||||
case lessOrEqual:
|
||||
return left <= right
|
||||
case greaterOrEqual:
|
||||
return left >= right
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// compareStrings compares two string values based on the operator
|
||||
func compareStrings(operator string, left, right string) bool {
|
||||
switch operator {
|
||||
case equal:
|
||||
return left == right
|
||||
case lessThan:
|
||||
return left < right
|
||||
case greaterThan:
|
||||
return left > right
|
||||
case lessOrEqual:
|
||||
return left <= right
|
||||
case greaterOrEqual:
|
||||
return left >= right
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// compareBools compares two boolean values based on the operator
|
||||
func compareBools(operator string, left, right bool) bool {
|
||||
switch operator {
|
||||
case equal:
|
||||
return left == right
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package compare
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -11,146 +13,191 @@ func TestEqual(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
assert.Equal(true, Equal(1, 1))
|
||||
assert.Equal(true, Equal(int64(1), int64(1)))
|
||||
assert.Equal(true, Equal("a", "a"))
|
||||
assert.Equal(true, Equal(true, true))
|
||||
assert.Equal(true, Equal([]int{1, 2, 3}, []int{1, 2, 3}))
|
||||
assert.Equal(true, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}))
|
||||
|
||||
assert.Equal(false, Equal(1, 2))
|
||||
assert.Equal(false, Equal(1, int64(1)))
|
||||
assert.Equal(false, Equal("a", "b"))
|
||||
assert.Equal(false, Equal(true, false))
|
||||
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"}))
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
time3 := time1.Add(time.Second)
|
||||
|
||||
assert.Equal(false, Equal(time1, time2))
|
||||
assert.Equal(true, Equal(time2, time3))
|
||||
|
||||
st1 := struct {
|
||||
A string
|
||||
B string
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
A: "a",
|
||||
B: "b",
|
||||
{1, 1, true},
|
||||
{int64(1), int64(1), true},
|
||||
{"a", "a", true},
|
||||
{true, true, true},
|
||||
{[]int{1, 2, 3}, []int{1, 2, 3}, true},
|
||||
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}, true},
|
||||
{1, 2, false},
|
||||
{1, int64(1), false},
|
||||
{"a", "b", false},
|
||||
{true, false, false},
|
||||
{[]int{1, 2}, []int{1, 2, 3}, false},
|
||||
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}, false},
|
||||
// {time.Now(), time.Now(), true},
|
||||
// {time.Now(), time.Now().Add(time.Second), false},
|
||||
{[]byte("hello"), []byte("hello"), true},
|
||||
{[]byte("hello"), []byte("world"), false},
|
||||
{json.Number("123"), json.Number("123"), true},
|
||||
{json.Number("123"), json.Number("124"), false},
|
||||
|
||||
{big.NewInt(123), big.NewInt(123), true},
|
||||
}
|
||||
|
||||
st2 := struct {
|
||||
A string
|
||||
B string
|
||||
}{
|
||||
A: "a",
|
||||
B: "b",
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, Equal(tt.left, tt.right))
|
||||
}
|
||||
|
||||
st3 := struct {
|
||||
A string
|
||||
B string
|
||||
}{
|
||||
A: "a1",
|
||||
B: "b",
|
||||
}
|
||||
|
||||
assert.Equal(true, Equal(st1, st2))
|
||||
assert.Equal(false, Equal(st1, st3))
|
||||
}
|
||||
|
||||
func TestEqualValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestEqualValue")
|
||||
|
||||
assert.Equal(true, EqualValue(1, 1))
|
||||
assert.Equal(true, EqualValue(int(1), int64(1)))
|
||||
assert.Equal(true, EqualValue(1, "1"))
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
{1, 1, true},
|
||||
{int64(1), int64(1), true},
|
||||
{"a", "a", true},
|
||||
{true, true, true},
|
||||
{[]int{1, 2, 3}, []int{1, 2, 3}, true},
|
||||
{map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}, true},
|
||||
{1, 2, false},
|
||||
{1, int64(1), true},
|
||||
{"a", "b", false},
|
||||
{true, false, false},
|
||||
{[]int{1, 2}, []int{1, 2, 3}, false},
|
||||
}
|
||||
|
||||
assert.Equal(false, EqualValue(1, "2"))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, EqualValue(tt.left, tt.right))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLessThan(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestLessThan")
|
||||
|
||||
assert.Equal(true, LessThan(1, 2))
|
||||
assert.Equal(true, LessThan(1.1, 2.2))
|
||||
assert.Equal(true, LessThan("a", "b"))
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
{1, 2, true},
|
||||
{1.1, 2.2, true},
|
||||
{"a", "b", true},
|
||||
{time.Now(), time.Now().Add(time.Second), true},
|
||||
{[]byte("hello1"), []byte("hello2"), true},
|
||||
{json.Number("123"), json.Number("124"), true},
|
||||
{645680099112988673, 645680099112988675, true},
|
||||
{1, 1, false},
|
||||
{1, int64(1), false},
|
||||
}
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
assert.Equal(true, LessThan(time1, time2))
|
||||
|
||||
assert.Equal(false, LessThan(1, 1))
|
||||
assert.Equal(false, LessThan(1, int64(1)))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, LessThan(tt.left, tt.right))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGreaterThan(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestGreaterThan")
|
||||
|
||||
assert.Equal(true, GreaterThan(2, 1))
|
||||
assert.Equal(true, GreaterThan(2.2, 1.1))
|
||||
assert.Equal(true, GreaterThan("b", "a"))
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
{2, 1, true},
|
||||
{2.2, 1.1, true},
|
||||
{"b", "a", true},
|
||||
{time.Now().Add(time.Second), time.Now(), true},
|
||||
{[]byte("hello2"), []byte("hello1"), true},
|
||||
{json.Number("124"), json.Number("123"), true},
|
||||
{645680099112988675, 645680099112988673, true},
|
||||
{1, 1, false},
|
||||
{1, int64(1), false},
|
||||
}
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
assert.Equal(true, GreaterThan(time2, time1))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, GreaterThan(tt.left, tt.right))
|
||||
}
|
||||
|
||||
assert.Equal(false, GreaterThan(1, 2))
|
||||
assert.Equal(false, GreaterThan(int64(2), 1))
|
||||
assert.Equal(false, GreaterThan("b", "c"))
|
||||
}
|
||||
|
||||
func TestLessOrEqual(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestLessOrEqual")
|
||||
|
||||
assert.Equal(true, LessOrEqual(1, 2))
|
||||
assert.Equal(true, LessOrEqual(1, 1))
|
||||
assert.Equal(true, LessOrEqual(1.1, 2.2))
|
||||
assert.Equal(true, LessOrEqual("a", "b"))
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
{1, 2, true},
|
||||
{1, 1, true},
|
||||
{1.1, 2.2, true},
|
||||
{"a", "b", true},
|
||||
{time.Now(), time.Now().Add(time.Second), true},
|
||||
{[]byte("hello1"), []byte("hello2"), true},
|
||||
{json.Number("123"), json.Number("124"), true},
|
||||
{645680099112988673, 645680099112988675, true},
|
||||
{2, 1, false},
|
||||
{1, int64(2), false},
|
||||
}
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
assert.Equal(true, LessOrEqual(time1, time2))
|
||||
|
||||
assert.Equal(false, LessOrEqual(2, 1))
|
||||
assert.Equal(false, LessOrEqual(1, int64(2)))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, LessOrEqual(tt.left, tt.right))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGreaterOrEqual(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestGreaterThan")
|
||||
|
||||
assert.Equal(true, GreaterOrEqual(2, 1))
|
||||
assert.Equal(true, GreaterOrEqual(1, 1))
|
||||
assert.Equal(true, GreaterOrEqual(2.2, 1.1))
|
||||
assert.Equal(true, GreaterOrEqual("b", "b"))
|
||||
tests := []struct {
|
||||
left any
|
||||
right any
|
||||
want bool
|
||||
}{
|
||||
{2, 1, true},
|
||||
{1, 1, true},
|
||||
{2.2, 1.1, true},
|
||||
{"b", "b", true},
|
||||
{time.Now().Add(time.Second), time.Now(), true},
|
||||
{[]byte("hello2"), []byte("hello1"), true},
|
||||
{json.Number("124"), json.Number("123"), true},
|
||||
{645680099112988675, 645680099112988673, true},
|
||||
{1, 2, false},
|
||||
{int64(2), 1, false},
|
||||
{"b", "c", false},
|
||||
}
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
assert.Equal(true, GreaterOrEqual(time2, time1))
|
||||
|
||||
assert.Equal(false, GreaterOrEqual(1, 2))
|
||||
assert.Equal(false, GreaterOrEqual(int64(2), 1))
|
||||
assert.Equal(false, GreaterOrEqual("b", "c"))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, GreaterOrEqual(tt.left, tt.right))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInDelta(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestInDelta")
|
||||
|
||||
assert.Equal(true, InDelta(1, 1, 0))
|
||||
assert.Equal(false, InDelta(1, 2, 0))
|
||||
tests := []struct {
|
||||
left float64
|
||||
right float64
|
||||
delta float64
|
||||
want bool
|
||||
}{
|
||||
{1, 1, 0, true},
|
||||
{1, 2, 0, false},
|
||||
{2.0 / 3.0, 0.66667, 0.001, true},
|
||||
{2.0 / 3.0, 0.0, 0.001, false},
|
||||
{float64(74.96) - float64(20.48), 54.48, 0, false},
|
||||
{float64(74.96) - float64(20.48), 54.48, 1e-14, true},
|
||||
{float64(float32(80.45)), float64(80.45), 0, false},
|
||||
{float64(float32(80.45)), float64(80.45), 1e-5, true},
|
||||
}
|
||||
|
||||
assert.Equal(true, InDelta(2.0/3.0, 0.66667, 0.001))
|
||||
assert.Equal(false, InDelta(2.0/3.0, 0.0, 0.001))
|
||||
|
||||
assert.Equal(false, InDelta(float64(74.96)-float64(20.48), 54.48, 0))
|
||||
assert.Equal(true, InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14))
|
||||
assert.Equal(false, InDelta(float64(float32(80.45)), float64(80.45), 0))
|
||||
assert.Equal(true, InDelta(float64(float32(80.45)), float64(80.45), 1e-5))
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.want, InDelta(tt.left, tt.right, tt.delta))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,10 +157,10 @@ func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
||||
// Play: https://go.dev/play/p/qmWSy1NVF-Y
|
||||
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T {
|
||||
valStream := make(chan T)
|
||||
|
||||
go func() {
|
||||
defer close(valStream)
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
defer wg.Wait()
|
||||
for {
|
||||
var stream <-chan T
|
||||
select {
|
||||
@@ -169,19 +169,22 @@ func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-c
|
||||
return
|
||||
}
|
||||
stream = maybeStream
|
||||
wg.Add(1)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
for val := range c.OrDone(ctx, stream) {
|
||||
select {
|
||||
case valStream <- val:
|
||||
case <-ctx.Done():
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for val := range c.OrDone(ctx, stream) {
|
||||
select {
|
||||
case valStream <- val:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}()
|
||||
|
||||
return valStream
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,8 @@ func ExampleChannel_Tee() {
|
||||
func ExampleChannel_Bridge() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
m1 := make(map[int]int)
|
||||
m2 := make(map[int]int)
|
||||
c := NewChannel[int]()
|
||||
genVals := func() <-chan <-chan int {
|
||||
out := make(chan (<-chan int))
|
||||
@@ -177,6 +178,7 @@ func ExampleChannel_Bridge() {
|
||||
for i := 1; i <= 5; i++ {
|
||||
stream := make(chan int, 1)
|
||||
stream <- i
|
||||
m1[i]++
|
||||
close(stream)
|
||||
out <- stream
|
||||
}
|
||||
@@ -185,12 +187,15 @@ func ExampleChannel_Bridge() {
|
||||
}
|
||||
|
||||
for v := range c.Bridge(ctx, genVals()) {
|
||||
fmt.Println(v)
|
||||
m2[v]++
|
||||
}
|
||||
for k, v := range m1 {
|
||||
fmt.Println(m2[k] == v)
|
||||
}
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 3
|
||||
// 4
|
||||
// 5
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
@@ -169,7 +169,8 @@ func TestTee(t *testing.T) {
|
||||
func TestBridge(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestBridge")
|
||||
|
||||
m1 := make(map[int]int)
|
||||
m2 := make(map[int]int)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
@@ -181,6 +182,7 @@ func TestBridge(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
stream := make(chan int, 1)
|
||||
stream <- i
|
||||
m1[i]++
|
||||
close(stream)
|
||||
chanStream <- stream
|
||||
}
|
||||
@@ -188,9 +190,11 @@ func TestBridge(t *testing.T) {
|
||||
return chanStream
|
||||
}
|
||||
|
||||
index := 0
|
||||
for val := range c.Bridge(ctx, genVals()) {
|
||||
assert.Equal(index, val)
|
||||
index++
|
||||
m2[val]++
|
||||
}
|
||||
|
||||
for k, v := range m1 {
|
||||
assert.Equal(m2[k], v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -76,10 +72,17 @@ func Nand[T, U any](a T, b U) bool {
|
||||
|
||||
// TernaryOperator checks the value of param `isTrue`, if true return ifValue else return elseValue.
|
||||
// Play: https://go.dev/play/p/ElllPZY0guT
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U {
|
||||
func Ternary[T, U any](isTrue T, ifValue U, elseValue U) U {
|
||||
if Bool(isTrue) {
|
||||
return ifValue
|
||||
} else {
|
||||
return elseValue
|
||||
}
|
||||
}
|
||||
|
||||
// TernaryOperator checks the value of param `isTrue`, if true return ifValue else return elseValue.
|
||||
// Play: https://go.dev/play/p/ElllPZY0guT
|
||||
// Deprecated: Use Ternary instead.
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U {
|
||||
return Ternary(isTrue, ifValue, elseValue)
|
||||
}
|
||||
|
||||
@@ -148,13 +148,13 @@ func ExampleNand() {
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleTernaryOperator() {
|
||||
func ExampleTernary() {
|
||||
conditionTrue := 2 > 1
|
||||
result1 := TernaryOperator(conditionTrue, 0, 1)
|
||||
result1 := Ternary(conditionTrue, 0, 1)
|
||||
fmt.Println(result1)
|
||||
|
||||
conditionFalse := 2 > 3
|
||||
result2 := TernaryOperator(conditionFalse, 0, 1)
|
||||
result2 := Ternary(conditionFalse, 0, 1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
|
||||
@@ -124,13 +124,13 @@ func TestNand(t *testing.T) {
|
||||
assert.Equal(false, Nand(1, 1))
|
||||
}
|
||||
|
||||
func TestTernaryOperator(t *testing.T) {
|
||||
func TestTernary(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TernaryOperator")
|
||||
assert := internal.NewAssert(t, "TestTernary")
|
||||
|
||||
trueValue := "1"
|
||||
falseValue := "0"
|
||||
|
||||
assert.Equal(trueValue, TernaryOperator(true, trueValue, falseValue))
|
||||
assert.Equal(trueValue, Ternary(true, trueValue, falseValue))
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -73,7 +75,7 @@ func ToBytes(value any) ([]byte, error) {
|
||||
// ToChar convert string to char slice.
|
||||
// Play: https://go.dev/play/p/JJ1SvbFkVdM
|
||||
func ToChar(s string) []string {
|
||||
c := make([]string, 0)
|
||||
c := make([]string, 0, len(s))
|
||||
if len(s) == 0 {
|
||||
c = append(c, "")
|
||||
}
|
||||
@@ -106,6 +108,13 @@ func ToString(value any) string {
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
rv := reflect.ValueOf(value)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
if rv.IsNil() {
|
||||
return ""
|
||||
}
|
||||
return ToString(rv.Elem().Interface())
|
||||
}
|
||||
|
||||
switch val := value.(type) {
|
||||
case float32:
|
||||
@@ -141,12 +150,8 @@ func ToString(value any) string {
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
|
||||
// todo: maybe we should't supprt other type conversion
|
||||
// v := reflect.ValueOf(value)
|
||||
// log.Panicf("Unsupported data type: %s ", v.String())
|
||||
// return ""
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,3 +399,124 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
// ToBigInt converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int
|
||||
// Play: https://go.dev/play/p/X3itkCxwB_x
|
||||
func ToBigInt[T any](v T) (*big.Int, error) {
|
||||
result := new(big.Int)
|
||||
|
||||
switch v := any(v).(type) {
|
||||
case int:
|
||||
result.SetInt64(int64(v)) // Convert to int64 for big.Int
|
||||
case int8:
|
||||
result.SetInt64(int64(v))
|
||||
case int16:
|
||||
result.SetInt64(int64(v))
|
||||
case int32:
|
||||
result.SetInt64(int64(v))
|
||||
case int64:
|
||||
result.SetInt64(v)
|
||||
case uint:
|
||||
result.SetUint64(uint64(v)) // Convert to uint64 for big.Int
|
||||
case uint8:
|
||||
result.SetUint64(uint64(v))
|
||||
case uint16:
|
||||
result.SetUint64(uint64(v))
|
||||
case uint32:
|
||||
result.SetUint64(uint64(v))
|
||||
case uint64:
|
||||
result.SetUint64(v)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type: %T", v)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package convertor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -391,3 +392,191 @@ 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
|
||||
}
|
||||
|
||||
func ExampleToBigInt() {
|
||||
n := 9876543210
|
||||
bigInt, _ := ToBigInt(n)
|
||||
|
||||
fmt.Println(bigInt)
|
||||
// Output:
|
||||
// 9876543210
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package convertor
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
@@ -137,13 +142,24 @@ func TestToString(t *testing.T) {
|
||||
}
|
||||
aStruct := TestStruct{Name: "TestStruct"}
|
||||
|
||||
i32Val := int32(123)
|
||||
i64Val := int64(123)
|
||||
iZeroVal := 0
|
||||
fVal := 12.3
|
||||
sVal := "abc"
|
||||
var iNilPointer *int
|
||||
var sNilPointer *string
|
||||
|
||||
cases := []any{
|
||||
"", nil,
|
||||
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||
float64(12.3), float32(12.3),
|
||||
true, false,
|
||||
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111}}
|
||||
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111},
|
||||
&i32Val, &i64Val, &fVal, &sVal, &aStruct, iNilPointer, sNilPointer,
|
||||
&iZeroVal,
|
||||
}
|
||||
|
||||
expected := []string{
|
||||
"", "",
|
||||
@@ -152,6 +168,8 @@ func TestToString(t *testing.T) {
|
||||
"12.3", "12.3",
|
||||
"true", "false",
|
||||
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello",
|
||||
"123", "123", "12.3", "abc", "{\"Name\":\"TestStruct\"}", "", "",
|
||||
"0",
|
||||
}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
@@ -461,3 +479,359 @@ 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))
|
||||
}
|
||||
|
||||
func TestToBigInt(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestToBigInt")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input any
|
||||
want *big.Int
|
||||
hasErr bool
|
||||
}{
|
||||
{
|
||||
name: "int",
|
||||
input: 42,
|
||||
want: big.NewInt(42),
|
||||
},
|
||||
{
|
||||
name: "int8",
|
||||
input: int8(127),
|
||||
want: big.NewInt(127),
|
||||
},
|
||||
{
|
||||
name: "int16",
|
||||
input: int16(32000),
|
||||
want: big.NewInt(32000),
|
||||
},
|
||||
{
|
||||
name: "int32",
|
||||
input: int32(123456),
|
||||
want: big.NewInt(123456),
|
||||
},
|
||||
{
|
||||
name: "int64",
|
||||
input: int64(987654321),
|
||||
want: big.NewInt(987654321),
|
||||
},
|
||||
{
|
||||
name: "uint",
|
||||
input: uint(987654321),
|
||||
want: big.NewInt(987654321),
|
||||
},
|
||||
{
|
||||
name: "uint8",
|
||||
input: uint8(255),
|
||||
want: big.NewInt(255),
|
||||
},
|
||||
{
|
||||
name: "uint16",
|
||||
input: uint16(65535),
|
||||
want: big.NewInt(65535),
|
||||
},
|
||||
{
|
||||
name: "uint32",
|
||||
input: uint32(4294967295),
|
||||
want: big.NewInt(4294967295),
|
||||
},
|
||||
{
|
||||
name: "uint64",
|
||||
input: uint64(18446744073709551615),
|
||||
want: new(big.Int).SetUint64(18446744073709551615),
|
||||
},
|
||||
{
|
||||
name: "unsupported type",
|
||||
input: 3.14, // Unsupported type
|
||||
hasErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ToBigInt(tt.input)
|
||||
if (err != nil) != tt.hasErr {
|
||||
t.Errorf("ToBigInt() error = %v, hasErr %v", err, tt.hasErr)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,20 @@ package cryptor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||||
@@ -76,6 +80,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())
|
||||
|
||||
@@ -95,6 +104,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]
|
||||
@@ -111,6 +125,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())
|
||||
@@ -126,6 +145,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)
|
||||
@@ -148,6 +172,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")
|
||||
}
|
||||
@@ -167,6 +196,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)
|
||||
@@ -189,6 +223,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)
|
||||
@@ -209,6 +248,56 @@ func AesOfbDecrypt(data, key []byte) []byte {
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// AesGcmEncrypt encrypt data with key use AES GCM algorithm
|
||||
// Play: https://go.dev/play/p/rUt0-DmsPCs
|
||||
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: https://go.dev/play/p/rUt0-DmsPCs
|
||||
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
|
||||
@@ -255,6 +344,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())
|
||||
|
||||
@@ -275,6 +369,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]
|
||||
@@ -291,6 +390,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())
|
||||
@@ -306,6 +410,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)
|
||||
@@ -327,6 +436,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")
|
||||
@@ -341,9 +455,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)
|
||||
@@ -365,6 +484,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)
|
||||
@@ -441,7 +565,7 @@ func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
||||
}
|
||||
|
||||
// RsaEncrypt encrypt data with ras algorithm.
|
||||
// Play: https://go.dev/play/p/rDqTT01SPkZ
|
||||
// Play: https://go.dev/play/p/7_zo6mrx-eX
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
|
||||
file, err := os.Open(pubKeyFileName)
|
||||
if err != nil {
|
||||
@@ -471,11 +595,12 @@ func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return cipherText
|
||||
}
|
||||
|
||||
// RsaDecrypt decrypt data with ras algorithm.
|
||||
// Play: https://go.dev/play/p/rDqTT01SPkZ
|
||||
// Play: https://go.dev/play/p/7_zo6mrx-eX
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
||||
file, err := os.Open(privateKeyFileName)
|
||||
if err != nil {
|
||||
@@ -504,6 +629,7 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return plainText
|
||||
}
|
||||
|
||||
@@ -535,3 +661,149 @@ func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte
|
||||
|
||||
return decryptedBytes, nil
|
||||
}
|
||||
|
||||
// RsaSign signs the data with RSA.
|
||||
// Play: https://go.dev/play/p/qhsbf8BJ6Mf
|
||||
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error) {
|
||||
privateKey, err := loadRasPrivateKey(privateKeyFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hashed, err := hashData(hash, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed)
|
||||
}
|
||||
|
||||
// RsaVerifySign verifies the signature of the data with RSA.
|
||||
// Play: https://go.dev/play/p/qhsbf8BJ6Mf
|
||||
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error {
|
||||
publicKey, err := loadRsaPublicKey(pubKeyFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hashed, err := hashData(hash, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rsa.VerifyPKCS1v15(publicKey, hash, hashed, signature)
|
||||
}
|
||||
|
||||
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
|
||||
func loadRsaPublicKey(filename string) (*rsa.PublicKey, error) {
|
||||
pubKeyData, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(pubKeyData)
|
||||
if block == nil {
|
||||
return nil, errors.New("failed to decode PEM block containing the public key")
|
||||
}
|
||||
|
||||
var pubKey *rsa.PublicKey
|
||||
blockType := strings.ToUpper(block.Type)
|
||||
|
||||
if blockType == "RSA PUBLIC KEY" {
|
||||
pubKey, err = x509.ParsePKCS1PublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
key, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
pubKey, ok = key.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to parse RSA private key")
|
||||
}
|
||||
}
|
||||
} else if blockType == "PUBLIC KEY" {
|
||||
key, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
pubKey, ok = key.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to parse RSA private key")
|
||||
}
|
||||
|
||||
} else {
|
||||
return nil, errors.New("unsupported key type")
|
||||
}
|
||||
|
||||
return pubKey, nil
|
||||
}
|
||||
|
||||
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
|
||||
func loadRasPrivateKey(filename string) (*rsa.PrivateKey, error) {
|
||||
priKeyData, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(priKeyData)
|
||||
if block == nil {
|
||||
return nil, errors.New("failed to decode PEM block containing the private key")
|
||||
}
|
||||
|
||||
var privateKey *rsa.PrivateKey
|
||||
blockType := strings.ToUpper(block.Type)
|
||||
|
||||
// PKCS#1 format
|
||||
if blockType == "RSA PRIVATE KEY" {
|
||||
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if blockType == "PRIVATE KEY" { // PKCS#8 format
|
||||
priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ok bool
|
||||
privateKey, ok = priKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to parse RSA private key")
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("unsupported key type")
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
// hashData returns the hash value of the data, using the specified hash function
|
||||
func hashData(hash crypto.Hash, data []byte) ([]byte, error) {
|
||||
if !hash.Available() {
|
||||
return nil, errors.New("unsupported hash algorithm")
|
||||
}
|
||||
|
||||
var hashed []byte
|
||||
|
||||
switch hash {
|
||||
case crypto.SHA224:
|
||||
h := sha256.Sum224(data)
|
||||
hashed = h[:]
|
||||
case crypto.SHA256:
|
||||
h := sha256.Sum256(data)
|
||||
hashed = h[:]
|
||||
case crypto.SHA384:
|
||||
h := sha512.Sum384(data)
|
||||
hashed = h[:]
|
||||
case crypto.SHA512:
|
||||
h := sha512.Sum512(data)
|
||||
hashed = h[:]
|
||||
default:
|
||||
return nil, errors.New("unsupported hash algorithm")
|
||||
}
|
||||
|
||||
return hashed, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@@ -129,6 +130,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"
|
||||
@@ -256,7 +285,7 @@ func ExampleDesOfbDecrypt() {
|
||||
|
||||
func ExampleGenerateRsaKey() {
|
||||
// Create ras private and public pem file
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -269,14 +298,14 @@ func ExampleGenerateRsaKey() {
|
||||
|
||||
func ExampleRsaEncrypt() {
|
||||
// Create ras private and public pem file
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := RsaEncrypt(data, "rsa_public_example.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private_example.pem")
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
@@ -286,14 +315,14 @@ func ExampleRsaEncrypt() {
|
||||
|
||||
func ExampleRsaDecrypt() {
|
||||
// Create ras private and public pem file
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := RsaEncrypt(data, "rsa_public_example.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private_example.pem")
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
@@ -508,3 +537,49 @@ func ExampleRsaEncryptOAEP() {
|
||||
// Output:
|
||||
// hello world
|
||||
}
|
||||
|
||||
func ExampleRsaSign() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private_example.pem"
|
||||
publicKey := "./rsa_public_example.pem"
|
||||
|
||||
signature, err := RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("ok")
|
||||
|
||||
// Output:
|
||||
// ok
|
||||
}
|
||||
|
||||
func ExampleRsaVerifySign() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private_example.pem"
|
||||
publicKey := "./rsa_public_example.pem"
|
||||
|
||||
signature, err := RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("ok")
|
||||
|
||||
// Output:
|
||||
// ok
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
@@ -139,13 +140,13 @@ func TestDesOfbEncrypt(t *testing.T) {
|
||||
func TestRsaEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
err := GenerateRsaKey(4096, "./rsa_private_example.pem", "./rsa_public_example.pem")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
encrypted := RsaEncrypt(data, "./rsa_public_example.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "./rsa_private_example.pem")
|
||||
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
assert.Equal(string(data), string(decrypted))
|
||||
@@ -168,3 +169,66 @@ func TestRsaEncryptOAEP(t *testing.T) {
|
||||
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))
|
||||
}
|
||||
|
||||
func TestRsaSignAndVerify(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
t.Run("RSA Sign and Verify", func(t *testing.T) {
|
||||
privateKey := "./rsa_private_example.pem"
|
||||
publicKey := "./rsa_public_example.pem"
|
||||
|
||||
signature, err := RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
t.Fatalf("RsaSign failed: %v", err)
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
t.Fatalf("RsaVerifySign failed: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RSA Sign and Verify Invalid Signature", func(t *testing.T) {
|
||||
publicKey := "./rsa_public_example.pem"
|
||||
|
||||
invalidSig := []byte("InvalidSignature")
|
||||
|
||||
err := RsaVerifySign(hash, data, invalidSig, publicKey)
|
||||
if err == nil {
|
||||
t.Fatalf("RsaVerifySign failed: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RSA Sign and Verify With Different Hash", func(t *testing.T) {
|
||||
publicKey := "./rsa_public_example.pem"
|
||||
privateKey := "./rsa_private_example.pem"
|
||||
hashSign := crypto.SHA256
|
||||
hashVerify := crypto.SHA512
|
||||
|
||||
signature, err := RsaSign(hashSign, data, privateKey)
|
||||
if err != nil {
|
||||
t.Fatalf("RsaSign failed: %v", err)
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hashVerify, data, signature, publicKey)
|
||||
if err == nil {
|
||||
t.Fatalf("RsaVerifySign failed: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
51
cryptor/rsa_private.pem
Normal file
51
cryptor/rsa_private.pem
Normal file
@@ -0,0 +1,51 @@
|
||||
-----BEGIN rsa private key-----
|
||||
MIIJKAIBAAKCAgEA5IqWfYbW1NlTDWE2plFWqD6CTquA0Ar/1E66lY8OMtrdpxTm
|
||||
chirmoISWN0BD7r2tV9T/kHs44Sy3raAfkR5ixYF5FRkb63FdIAtoynsxS6MEE26
|
||||
fgWuDAa1xwNt+t/uivnpfJk25htpBNkKGT8ii0TPPLn1N15hMHenT6PzWVjGjQxW
|
||||
cp4dUA4gXTDuqaeu7Oy7Ku2yP90/ra+cjTV8DnBJ9enQhAfu1LivJO3FgmXeuC3u
|
||||
qhhM3t9ZbNy7tvJI5PXDCaS8iesBvCp5carTSXWLpFEgvIhXQIsXtxezKAP3gRd8
|
||||
r5JPQI9FZlxyUcyf+Htkn2A4qyKhFElnP1z9j0YLFhL/gQMdtNIY7yhSb29PyuCG
|
||||
7noz25swrfxbA7ZVppM0J19JNhlpqmusBKLBNqN+KMD8EDli7NLX17S9Dj2pQF9I
|
||||
8fVXPEhkdTb67rr7y3OUANKjh0Opnt3JLoj9u1X7BfCeUSR/qq3E8RFPeyxvP1tc
|
||||
5QVqKBG6UPBo8nLQqdzJhUd8a1YEfXIUbdHLs2q5WVFu2MDavIp634+fzfcIFRoB
|
||||
tdxf5aCdxLaLocsA/aLLyL1pK6K0rpdrSUtcEBMST26qIlU0Ht+SQtaMdE2gyjkM
|
||||
M5RpLh1q/gpow+0j3zu6f5tDsu3qwgjLIx78YCTGUuCpsVMzFK4tahYSPNkCAwEA
|
||||
AQKCAgEAuXz97X2uCW0lqjtXhp+HrN+nFUC/OJtkziTj7RUBmibnNX+SFdKOHMYr
|
||||
K/KbtO+y4rwvSLKrGHIQVxBas6DR4SALwij4p2erVgXehIo3gEZqKaVckoH7pAki
|
||||
KhdPgQmU6zkw1w7nbtWaY/Pf7WO/nrdHV+s56ilwykyi/9F6Ze7Wn43+7+ICuoHs
|
||||
pJZdblcJc4Qj2RC41nq0/zwD3NwnBvT+IlgWA8MIhaArjtZospAJtwSYq3czlMRE
|
||||
KUXyGOcGYMZS+RW6bFnPu6/hh271M67ymne6ESq7XkhGBDV5FCY8EItGiJ1AM47U
|
||||
7eJkap2gzKUhovUOqV9eyz9UTComJETl2kmcjpZeaxrZZxtPap23IzBu6PJoPuDg
|
||||
hgzRWh3BrkakLdq6Km2z+jDFEQhWeHsksozuKzln5USx9wovb9LDKKFSpKm4vzW+
|
||||
7YVLZnH4Z1m4wvWQJShvZur7kkM7aNfK+xcS81OBMtqKerjWhdHqfMRVvLvtG/ev
|
||||
ftPTwRy+u02w+FoYcassTS+lW+Pnhj0ZuOewsWoNvgWg1TpPEDBkY4UJOYQPkTrS
|
||||
bixTBVI3teSjMXmjEAif+BG2LBCl7pFY5SW9Jk6eRvmxt9rEly13C+4tcBHEJnXu
|
||||
eVUMurRuB/9BAKgj4qGHPQlG455mKHQzWJxJXBpRurh+U478xm0CggEBAOgduMra
|
||||
tPDhyhy01iIAzYsh0PW9p11AcCoJkDUE/5IUf03fVt3WKdSNauHZBKTulqaCHkvz
|
||||
+pjmSwPr4JdJKcJzwk5ncResFBYF177JmYXzJzwpIPRQFNP34heaUd9cVsFckddV
|
||||
G3jR7c1vD33VElexUM94BubZFEqF2lO3/y0sLwhd7prKhwy6mctJyvyDFk02psDc
|
||||
6XzBG/sMiZ6meWA1sP4QIM6+sYdZ9ihvTNWGb1+TGojvgOHCEQ3Hv9u/qwdkzFKj
|
||||
qo25pRMV4VNMQUvYIywSB7K5c0w1ccfOINzB8kgqpHhpimAHqZw9ix4H98YmvaXS
|
||||
rr0LP8ES9xVvelcCggEBAPwOs7pWvm/R3RAXZ8Erk9x68Fsn8wzoofsGP/BG5QCC
|
||||
r1fDJr9aJAVggXOVNDktWRKkN7Cnib+Z7ymL5br3FfYPy945cF2e8nkx2ri0VveF
|
||||
glkPCFLb3lF3iLKD8nJNtiv1rpu2v4Dj09+SzQYSIF3h55BaZGUCHLskR7Mhdd74
|
||||
iTBzPaQ3NC+n0xrv8o1EXjy9w/nBt07sZojrf82Ae3mIbEFYdEHUVDaCZKKeBT4b
|
||||
9W8Q5aAt56DIkSkaBAZZZhzbfxollmeKiwJ32+finR7LZ1Fj2cTHia19Ef85U8bE
|
||||
Ow7E2cTDZkqaqgi+pFescl518DQ47PCeXfnFP0g65E8CggEAUApHubO3J0VE06dM
|
||||
G8eZGTwc+VBf0RkyVFyd3JqPoojs6SZ1puN94yysyZpzLoiTbHF8DwbfyC/JeF2z
|
||||
QZfaDZKrUyv6ZIZTGtEC92g/R2B0jBtGoNiohft5fFgbmWEXDXBlXhKb+YqybN+6
|
||||
QNLjk1eynQgvoRUEGTqU8b+F/8a3pTP23muuLCaAeAhHNdHiM9f/oovK+9j/VA+b
|
||||
uRiAzDtXgBSBq6k4QIs2BfVzUkIcT6HDSasFD1RDWzQhJZ6vVEpe5rRHUL3OfYlS
|
||||
/M1TytqKLl09SFUIvCPFy3d5/4XljRsfQeJq8/hQdW8HdOCcgTjEttSyqr+hSWvH
|
||||
xh192wKCAQB0uSY3u2XTCH9zrTMJ/HErn+7gd76REsW4JmvDjEEOHHawkJnH8SlP
|
||||
KCKqcMTPWZWvEUcM0njytolPVw6ap0OPQD9reHP1lt64iwK7mB/R3gy/yztSi6kH
|
||||
VvCBoqLKlfwvnUUvrNBAEsER/rxc/FXqw+tlKMbnE7RUYXeml28rQzLcsfEws7PC
|
||||
Adi717QeATQWstYnObL2pHjTHSOA+ee0Hx3qoNith3M8DuQlfkH1QiNFPLDpnXhv
|
||||
N5IpU3fbrNihsm/InvFon3rCONkoKAQUt6LvyOqWusSiB5Im+9g06rhinXwvJ0Ge
|
||||
eMMW65nVU/FelwUWWeo3f08LlHE6tLL3AoIBABcc549sTCMhBmQS9prESurzhPVk
|
||||
HCFYlR/GdlfNmRtTYssk25xaG+tiaEzXi7DXBq20TGNOATgoX7l9EWIRXkDuR6hS
|
||||
aRXyn+CVU3y2dhpGZBf+EUWP0u9TNSJ/RFO0ViAriL5J9kjF9hFvG36B9kRSiMrn
|
||||
mCp9NCdtRYOHjzkvbY5uRMqP8H4/nAXNMA+odPnOPDUOIcH2ztaFOtQgZxa9x/eS
|
||||
eGmnJ/V/rLvS04uVw5d7juJstEspnM4MxPHSFEDN7NG13bN+c1jTY1/85icIeRBi
|
||||
nP47M2kDQ6RrEdgYfPbdlx1wGdTUIeAm3duptTiwpwa5Q2Js22TMJYRTnbM=
|
||||
-----END rsa private key-----
|
||||
51
cryptor/rsa_private_example.pem
Normal file
51
cryptor/rsa_private_example.pem
Normal file
@@ -0,0 +1,51 @@
|
||||
-----BEGIN rsa private key-----
|
||||
MIIJKAIBAAKCAgEA0HaqqGWnNqwRVKoJUUjYiH/dwkSK61La4RGYkvDfcuo9pDgc
|
||||
zHVhFUb/MYWeb3bAlFAGcZLYSBh6WAGxbeMjSkaLroaXnafhKZ2oXXUy8CzyYxZw
|
||||
pLCDgJLG7Pf0jer3STZW93ZT8UJixbKwbqD6b8fkpMANwCYrTlXDWBuZVaEKuQNn
|
||||
C4XufQis4fwRxRgfrZuLMvuQVtnyYmssmnp8JHovYkr87giDjEgvlrC84Lez32Zh
|
||||
EhORRu5NGEDeZ1OewbkXGyQtbcBQYNAxgnOcO44MTTPhEdz4/A0xwzEe+yIOxWIA
|
||||
WuEM2rclXpZBW/MEK41gZ3C04KcX5R0KRdj2PTTH7vJ33yRC4hKtWetwMvsUrewr
|
||||
RKVcUgaeFykDAlgIDoSWvG0nzb70AWSoNcj7krLlwEc2WLGy/kCYWppnfYKafEJX
|
||||
pgblHrDFKlWvte68yrvGdCsWRLQ2uUF0xokQIg4u2bApyWNroxEtjHwUp1VeJuZB
|
||||
Qkfg+vIW+t3moQpMtlhy4aai/oGIxI5TIB82nv8TPVczjHmmE3hwL6nZ5OfbFyWp
|
||||
RFvKLtXcaAKMi2HqOLRkQhqjjJUCO9Wyhu1BkX8RAeKLl3S7gRyhuOB5JNUGEpQ3
|
||||
89MdbUX5S12Qp1xTDS+otbC8tYS1gu0OOOWowxbuF5+Ci2SYgSHv/3zXKoMCAwEA
|
||||
AQKCAgBASCdt0BLVABBEDD7dStpClTNbwWkZEa6e8p8ayJ4OwH6LkiYHQjbSqdbt
|
||||
fWeStYrC8T5bbU22RZ4MX1FIMl9iewh9o9FC806yV4RgdVBk0WdY+MV5c1jJn/kp
|
||||
f3hw/sCMWe5NVrah0bfFgMl5A7jWGUy/JN3Yn6yA9l9LXw9UYVl+Hbd7zSvycGdn
|
||||
NCSCo2K5VRqCeSJUNdbRVH0nkZeQZAESjU8bU5LFAklybUOBBAS6YcaTHWeR+M/b
|
||||
J72tHRL6Z8nhO7Gqg0AF6o0pzd6iWrYeZF4F9R7uEl+C8jW8eQ8W/JZhb75X/1vN
|
||||
pAW5heGGUI0muJF+KOhsZR0S1slvHbCSvwaNBQi8HEbOEPa7wVzsrGLfc+re5ysF
|
||||
X2n5GL4qBwNdMHrADnMWWVa9LEUSr3XmXfpmNDctmdv1ekWpJ44G/qrjKOuimtfk
|
||||
t9haDjhN5lx3V05k18kb53tYAdi3CqrT4syiibtqZLvTRam/yoFJgSOczO5WxNNk
|
||||
xnhnEdr/FQcFQhzuQ6gU196SBi8Bqjz1t0cNozNu3wvp8Fu0G8Rr9gjYnH8m5xXz
|
||||
xb9xevR7X/swfxd+/KUqoenYdU5ZFJpDRCmUMDKWR/3Q7s4SRxMN0+c/uBSaih3J
|
||||
I9I8urHG6mFW2qWQZTvuostmb7vVHaefx0RZOhX0efJVMZPwiQKCAQEA8BUXRw9k
|
||||
Ms3tqmBMVM4sMcPgsffJxjAJUdunUgEpaBAqrDQmZ6uBjAYq7iTzLgJJuLI1o1sv
|
||||
HtEWuGLHRRJpdoEamGweJE/o28OH2MBiiL2ezfRIHsg8RRr6os6KvlKevty6m7d9
|
||||
hAvpS6XvZGK2eCSooL6zZ8XTgnDw+Hw8Q4i+dazjb5dDRRL97eHHUqzcYH5vIsAE
|
||||
EBaNXMKrhf/NyVWCJBVRHg8PZZjGXcrj8ZMx+ejDR0AL5BXUaAX3fYnQyJf6QzrD
|
||||
t5aNDoU6vPO77CLkqBavTePTToiVeTIMZP5yHZFQuPWtP/y67e0csNA6ezwpWEh4
|
||||
4MnpLWzC2YRZ/wKCAQEA3kjpB3977IHFw90Xn8TQu3/SzBMUBqdj5yo6gPBijKNf
|
||||
4mZ1shUp6vZkFOHbAmoafjqCzOO18tW4ci+UWAQgdXQWXwsQDUM+fZsr/5Z9LoIN
|
||||
TYuq98Yh/rjKABxkFdMmkLmykuAblDRwVeMf3e4x6/55hAkwvESBRdfnSjjoNmEM
|
||||
MRVW4v5meDv0W4NS1eyohWPe/IoR09dSsmMhz311b7btBxc97NNqDD4SdxmASnOZ
|
||||
qsE2QxRHRFjpTvytpZH/lTQH6IYdh9REZgX7uvmlmTQwqLy6wX5T/oEzVPRhXgh9
|
||||
rgbPPJuoZwWF+fXipJ8c+laQ/sdzDKCxEEhRZr7HfQKCAQBKflDVtLnjZbA78Fte
|
||||
6QYffubGcdtCyn7pzl0RfdjKOFH1Us0j17x/pR5G/GIUQZN8YpdwE4gAaOJC3it0
|
||||
jCz7Hz4QU2Pa4oyfPAF3yOIKCcQvpX+HRZwl2SQxxiKYwWwOTtD8JiglA8kktt0b
|
||||
6eEyUDWegu2J4oEpdT/f6jSMw+5M9xMu+eFemnD+EdNWHNrYegKj5q6cC1Nbl+++
|
||||
yUuiEA0sgwzDZeriHFBYo+6sc37LS2TkQ8QsxnU8vbU4V73XsAhwOdimq2kjO0Wp
|
||||
gXsq3vzSBw/n/CwBrzGqBFSCNc1UzVUdvuU9+H5L+wmu9z1eJaGyifIv1ZariJbB
|
||||
BWcjAoIBACWRJPEDdqot9IJ5pzh1RuGpZLLgto25VIUI+gI4ni8unVHiBxolwYPY
|
||||
SGnPEfiCfh+/O8Ps6B82R4nkyKlnaSTwjadac0gKiVEpHHKBuH5XtG/anvZpIe2u
|
||||
xVTnd3LI0Me82pVAEuklQ6cAT65uRzmfNGJAO2BWI5LuPkSpAXXPSQQymxCZ9i9z
|
||||
0oR02VcWPBTvIAyGOSUYSv2jC1/J0EMlI0IDh4+y20VeaDiAstHiX6IgLU+A6dp/
|
||||
PE8BHUfSOOO6e2us3ujJ0xV7BWRANOCDlYWu/9EbzI5Cv64n7xy5SqRSukt/8yIW
|
||||
KOJpz/gKfBdC8hZdFvCXZ9Vco4U90PECggEBAIwy5zuWqSaJ8kom7kMZj+JYfhVz
|
||||
rdozFil1CkmWcw4E+rNcq8bKVTa9Er6/3nBTXfKX+4sYzMzbFr6xjFyrPA62wjiT
|
||||
2MRdHu9iB+Rtxn83Ilnh+Aqu/8bPFQUlYFr7nefy2t1aL76diQnsBu4xHOtEMgSv
|
||||
F6d/pDFRC+PZN0B7glrz870jRaw9LNcuIBVoKN07hGBwD76EEZhCrn6eLqMI8srH
|
||||
YESDPUR/wl/PV8ZrA/hNRvjp44PYiLMYRDSQw8kpbLMMc0QgQCvhfMbYVvGteTmG
|
||||
qdCFyy2x70wSh6Rfzb7WEWl15I4yfBTddXkJX82S+MrZu/Xq4FDtng594h0=
|
||||
-----END rsa private key-----
|
||||
14
cryptor/rsa_public.pem
Normal file
14
cryptor/rsa_public.pem
Normal file
@@ -0,0 +1,14 @@
|
||||
-----BEGIN rsa public key-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5IqWfYbW1NlTDWE2plFW
|
||||
qD6CTquA0Ar/1E66lY8OMtrdpxTmchirmoISWN0BD7r2tV9T/kHs44Sy3raAfkR5
|
||||
ixYF5FRkb63FdIAtoynsxS6MEE26fgWuDAa1xwNt+t/uivnpfJk25htpBNkKGT8i
|
||||
i0TPPLn1N15hMHenT6PzWVjGjQxWcp4dUA4gXTDuqaeu7Oy7Ku2yP90/ra+cjTV8
|
||||
DnBJ9enQhAfu1LivJO3FgmXeuC3uqhhM3t9ZbNy7tvJI5PXDCaS8iesBvCp5carT
|
||||
SXWLpFEgvIhXQIsXtxezKAP3gRd8r5JPQI9FZlxyUcyf+Htkn2A4qyKhFElnP1z9
|
||||
j0YLFhL/gQMdtNIY7yhSb29PyuCG7noz25swrfxbA7ZVppM0J19JNhlpqmusBKLB
|
||||
NqN+KMD8EDli7NLX17S9Dj2pQF9I8fVXPEhkdTb67rr7y3OUANKjh0Opnt3JLoj9
|
||||
u1X7BfCeUSR/qq3E8RFPeyxvP1tc5QVqKBG6UPBo8nLQqdzJhUd8a1YEfXIUbdHL
|
||||
s2q5WVFu2MDavIp634+fzfcIFRoBtdxf5aCdxLaLocsA/aLLyL1pK6K0rpdrSUtc
|
||||
EBMST26qIlU0Ht+SQtaMdE2gyjkMM5RpLh1q/gpow+0j3zu6f5tDsu3qwgjLIx78
|
||||
YCTGUuCpsVMzFK4tahYSPNkCAwEAAQ==
|
||||
-----END rsa public key-----
|
||||
14
cryptor/rsa_public_example.pem
Normal file
14
cryptor/rsa_public_example.pem
Normal file
@@ -0,0 +1,14 @@
|
||||
-----BEGIN rsa public key-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0HaqqGWnNqwRVKoJUUjY
|
||||
iH/dwkSK61La4RGYkvDfcuo9pDgczHVhFUb/MYWeb3bAlFAGcZLYSBh6WAGxbeMj
|
||||
SkaLroaXnafhKZ2oXXUy8CzyYxZwpLCDgJLG7Pf0jer3STZW93ZT8UJixbKwbqD6
|
||||
b8fkpMANwCYrTlXDWBuZVaEKuQNnC4XufQis4fwRxRgfrZuLMvuQVtnyYmssmnp8
|
||||
JHovYkr87giDjEgvlrC84Lez32ZhEhORRu5NGEDeZ1OewbkXGyQtbcBQYNAxgnOc
|
||||
O44MTTPhEdz4/A0xwzEe+yIOxWIAWuEM2rclXpZBW/MEK41gZ3C04KcX5R0KRdj2
|
||||
PTTH7vJ33yRC4hKtWetwMvsUrewrRKVcUgaeFykDAlgIDoSWvG0nzb70AWSoNcj7
|
||||
krLlwEc2WLGy/kCYWppnfYKafEJXpgblHrDFKlWvte68yrvGdCsWRLQ2uUF0xokQ
|
||||
Ig4u2bApyWNroxEtjHwUp1VeJuZBQkfg+vIW+t3moQpMtlhy4aai/oGIxI5TIB82
|
||||
nv8TPVczjHmmE3hwL6nZ5OfbFyWpRFvKLtXcaAKMi2HqOLRkQhqjjJUCO9Wyhu1B
|
||||
kX8RAeKLl3S7gRyhuOB5JNUGEpQ389MdbUX5S12Qp1xTDS+otbC8tYS1gu0OOOWo
|
||||
wxbuF5+Ci2SYgSHv/3zXKoMCAwEAAQ==
|
||||
-----END rsa public key-----
|
||||
@@ -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,
|
||||
|
||||
@@ -209,7 +209,7 @@ func (dl *DoublyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all doubly linklist node value
|
||||
func (dl *DoublyLink[T]) Values() []T {
|
||||
result := []T{}
|
||||
result := make([]T, 0, dl.length)
|
||||
current := dl.Head
|
||||
for current != nil {
|
||||
result = append(result, current.Value)
|
||||
|
||||
@@ -212,7 +212,7 @@ func (sl *SinglyLink[T]) Size() int {
|
||||
|
||||
// Values return slice of all singly linklist node value
|
||||
func (sl *SinglyLink[T]) Values() []T {
|
||||
result := []T{}
|
||||
result := make([]T, 0, sl.length)
|
||||
current := sl.Head
|
||||
for current != nil {
|
||||
result = append(result, current.Value)
|
||||
|
||||
@@ -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()
|
||||
}()
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
|
||||
|
||||
// Data return slice of queue data
|
||||
func (q *ArrayQueue[T]) Data() []T {
|
||||
items := []T{}
|
||||
items := make([]T, 0, q.tail-q.head)
|
||||
for i := q.head; i < q.tail; i++ {
|
||||
items = append(items, q.data[i])
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func NewLinkedQueue[T any]() *LinkedQueue[T] {
|
||||
|
||||
// Data return slice of queue data
|
||||
func (q *LinkedQueue[T]) Data() []T {
|
||||
res := []T{}
|
||||
res := make([]T, 0, q.length)
|
||||
current := q.head
|
||||
|
||||
for current != nil {
|
||||
|
||||
@@ -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},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func NewLinkedStack[T any]() *LinkedStack[T] {
|
||||
|
||||
// Data return stack data
|
||||
func (s *LinkedStack[T]) Data() []T {
|
||||
res := []T{}
|
||||
res := make([]T, 0, s.length)
|
||||
current := s.top
|
||||
|
||||
for current != nil {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -100,12 +100,6 @@ func TestBSTree_Delete(t *testing.T) {
|
||||
|
||||
acturl1 := bstree.InOrderTraverse()
|
||||
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
||||
|
||||
//todo
|
||||
// bstree.DeletetNode(6, comparator)
|
||||
// bstree.Print()
|
||||
// acturl2 := bstree.InOrderTraverse()
|
||||
// assert.Equal([]int{2, 5, 7}, acturl2)
|
||||
}
|
||||
|
||||
func TestBSTree_Depth(t *testing.T) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel i
|
||||
|
||||
printSpaces(firstSpaces)
|
||||
|
||||
newNodes := []*datastructure.TreeNode[T]{}
|
||||
newNodes := make([]*datastructure.TreeNode[T], 0, len(nodes)*2)
|
||||
for _, node := range nodes {
|
||||
if node != nil {
|
||||
fmt.Printf("%v", node.Value)
|
||||
@@ -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"
|
||||
)
|
||||
@@ -63,28 +64,95 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// AddMinute add or sub minute to the time.
|
||||
// AddMinute add or sub minutes to the time.
|
||||
// Play: https://go.dev/play/p/nT1heB1KUUK
|
||||
func AddMinute(t time.Time, minute int64) time.Time {
|
||||
return t.Add(time.Minute * time.Duration(minute))
|
||||
func AddMinute(t time.Time, minutes int64) time.Time {
|
||||
return t.Add(time.Minute * time.Duration(minutes))
|
||||
}
|
||||
|
||||
// AddHour add or sub hour to the time.
|
||||
// AddHour add or sub hours to the time.
|
||||
// Play: https://go.dev/play/p/rcMjd7OCsi5
|
||||
func AddHour(t time.Time, hour int64) time.Time {
|
||||
return t.Add(time.Hour * time.Duration(hour))
|
||||
func AddHour(t time.Time, hours int64) time.Time {
|
||||
return t.Add(time.Hour * time.Duration(hours))
|
||||
}
|
||||
|
||||
// AddDay add or sub day to the time.
|
||||
// AddDay add or sub days to the time.
|
||||
// Play: https://go.dev/play/p/dIGbs_uTdFa
|
||||
func AddDay(t time.Time, day int64) time.Time {
|
||||
return t.Add(24 * time.Hour * time.Duration(day))
|
||||
func AddDay(t time.Time, days int64) time.Time {
|
||||
return t.Add(24 * time.Hour * time.Duration(days))
|
||||
}
|
||||
|
||||
// AddWeek add or sub weeks to the time.
|
||||
// play: todo
|
||||
func AddWeek(t time.Time, weeks int64) time.Time {
|
||||
return t.Add(7 * 24 * time.Hour * time.Duration(weeks))
|
||||
}
|
||||
|
||||
// AddMonth add or sub months to the time.
|
||||
// Play: todo
|
||||
func AddMonth(t time.Time, months int64) time.Time {
|
||||
return t.AddDate(0, int(months), 0)
|
||||
}
|
||||
|
||||
// AddYear add or sub year to the time.
|
||||
// Play: https://go.dev/play/p/MqW2ujnBx10
|
||||
func AddYear(t time.Time, year int64) time.Time {
|
||||
return t.Add(365 * 24 * time.Hour * time.Duration(year))
|
||||
return t.AddDate(int(year), 0, 0)
|
||||
}
|
||||
|
||||
// AddDaySafe add or sub days to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddDaySafe(t time.Time, days int) time.Time {
|
||||
t = t.AddDate(0, 0, days)
|
||||
year, month, day := t.Date()
|
||||
|
||||
lastDayOfMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, t.Location()).Day()
|
||||
|
||||
if day > lastDayOfMonth {
|
||||
t = time.Date(year, month, lastDayOfMonth, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// AddMonthSafe add or sub months to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddMonthSafe(t time.Time, months int) time.Time {
|
||||
year := t.Year()
|
||||
month := int(t.Month()) + months
|
||||
|
||||
for month > 12 {
|
||||
month -= 12
|
||||
year++
|
||||
}
|
||||
for month < 1 {
|
||||
month += 12
|
||||
year--
|
||||
}
|
||||
|
||||
daysInMonth := time.Date(year, time.Month(month+1), 0, 0, 0, 0, 0, time.UTC).Day()
|
||||
|
||||
day := t.Day()
|
||||
if day > daysInMonth {
|
||||
day = daysInMonth
|
||||
}
|
||||
|
||||
return time.Date(year, time.Month(month), day, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
// AddYearSafe add or sub years to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddYearSafe(t time.Time, years int) time.Time {
|
||||
year, month, day := t.Date()
|
||||
year += years
|
||||
|
||||
if month == time.February && day == 29 {
|
||||
if !IsLeapYear(year) {
|
||||
day = 28
|
||||
}
|
||||
}
|
||||
|
||||
return time.Date(year, month, day, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
// GetNowDate return format yyyy-mm-dd of current date.
|
||||
@@ -381,3 +449,111 @@ 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: https://go.dev/play/p/QBSEdfXHPTp
|
||||
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: https://go.dev/play/p/qD6qGb3TbOy
|
||||
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: https://go.dev/play/p/6kHBpAxD9ZC
|
||||
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
|
||||
}
|
||||
|
||||
// Min returns the earliest time among the given times.
|
||||
// Play: https://go.dev/play/p/MCIDvHNOGGb
|
||||
func Min(t1 time.Time, times ...time.Time) time.Time {
|
||||
minTime := t1
|
||||
|
||||
for _, t := range times {
|
||||
if t.Before(minTime) {
|
||||
minTime = t
|
||||
}
|
||||
}
|
||||
|
||||
return minTime
|
||||
}
|
||||
|
||||
// Max returns the latest time among the given times.
|
||||
// Play: https://go.dev/play/p/9m6JMk1LB7-
|
||||
func Max(t1 time.Time, times ...time.Time) time.Time {
|
||||
maxTime := t1
|
||||
|
||||
for _, t := range times {
|
||||
if t.After(maxTime) {
|
||||
maxTime = t
|
||||
}
|
||||
}
|
||||
|
||||
return maxTime
|
||||
}
|
||||
|
||||
// MaxMin returns the latest and earliest time among the given times.
|
||||
// Play: https://go.dev/play/p/rbW51cDtM_2
|
||||
func MaxMin(t1 time.Time, times ...time.Time) (maxTime time.Time, minTime time.Time) {
|
||||
maxTime = t1
|
||||
minTime = t1
|
||||
|
||||
for _, t := range times {
|
||||
if t.Before(minTime) {
|
||||
minTime = t
|
||||
}
|
||||
|
||||
if t.After(maxTime) {
|
||||
maxTime = t
|
||||
}
|
||||
}
|
||||
|
||||
return maxTime, minTime
|
||||
}
|
||||
|
||||
@@ -7,71 +7,141 @@ import (
|
||||
)
|
||||
|
||||
func ExampleAddDay() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
tomorrow := AddDay(now, 1)
|
||||
diff1 := tomorrow.Sub(now)
|
||||
after1Day := AddDay(date, 1)
|
||||
before1Day := AddDay(date, -1)
|
||||
|
||||
yesterday := AddDay(now, -1)
|
||||
diff2 := yesterday.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after1Day.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before1Day.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 24h0m0s
|
||||
// -24h0m0s
|
||||
// 2021-01-02 00:00:00
|
||||
// 2020-12-31 00:00:00
|
||||
}
|
||||
|
||||
func ExampleAddWeek() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Weeks := AddWeek(date, 2)
|
||||
before2Weeks := AddWeek(date, -2)
|
||||
|
||||
fmt.Println(after2Weeks.Format("2006-01-02"))
|
||||
fmt.Println(before2Weeks.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-01-15
|
||||
// 2020-12-18
|
||||
}
|
||||
|
||||
func ExampleAddMonth() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Months := AddMonth(date, 2)
|
||||
before2Months := AddMonth(date, -2)
|
||||
|
||||
fmt.Println(after2Months.Format("2006-01-02"))
|
||||
fmt.Println(before2Months.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-03-01
|
||||
// 2020-11-01
|
||||
}
|
||||
|
||||
func ExampleAddHour() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Hours := AddHour(now, 2)
|
||||
diff1 := after2Hours.Sub(now)
|
||||
after2Hours := AddHour(date, 2)
|
||||
before2Hours := AddHour(date, -2)
|
||||
|
||||
before2Hours := AddHour(now, -2)
|
||||
diff2 := before2Hours.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Hours.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Hours.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2h0m0s
|
||||
// -2h0m0s
|
||||
// 2021-01-01 02:00:00
|
||||
// 2020-12-31 22:00:00
|
||||
}
|
||||
|
||||
func ExampleAddMinute() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Minutes := AddMinute(now, 2)
|
||||
diff1 := after2Minutes.Sub(now)
|
||||
after2Minutes := AddMinute(date, 2)
|
||||
before2Minutes := AddMinute(date, -2)
|
||||
|
||||
before2Minutes := AddMinute(now, -2)
|
||||
diff2 := before2Minutes.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Minutes.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Minutes.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2m0s
|
||||
// -2m0s
|
||||
// 2021-01-01 00:02:00
|
||||
// 2020-12-31 23:58:00
|
||||
}
|
||||
|
||||
func ExampleAddYear() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after1Year := AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
after2Years := AddYear(date, 2)
|
||||
before2Years := AddYear(date, -2)
|
||||
|
||||
before1Year := AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Years.Format("2006-01-02"))
|
||||
fmt.Println(before2Years.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
// 2023-01-01
|
||||
// 2019-01-01
|
||||
}
|
||||
|
||||
func ExampleAddDaySafe() {
|
||||
leapYearDate1, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result1 := AddDaySafe(leapYearDate1, 1)
|
||||
|
||||
leapYearDate2, _ := time.Parse("2006-01-02", "2024-03-01")
|
||||
result2 := AddDaySafe(leapYearDate2, -1)
|
||||
|
||||
nonLeapYearDate1, _ := time.Parse("2006-01-02", "2025-02-28")
|
||||
result3 := AddDaySafe(nonLeapYearDate1, 1)
|
||||
|
||||
nonLeaYearDate2, _ := time.Parse("2006-01-02", "2025-03-01")
|
||||
result4 := AddDaySafe(nonLeaYearDate2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
fmt.Println(result3.Format("2006-01-02"))
|
||||
fmt.Println(result4.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2024-03-01
|
||||
// 2024-02-29
|
||||
// 2025-03-01
|
||||
// 2025-02-28
|
||||
}
|
||||
|
||||
func ExampleAddMonthSafe() {
|
||||
date1, _ := time.Parse("2006-01-02", "2025-01-31")
|
||||
result1 := AddMonthSafe(date1, 1)
|
||||
|
||||
date2, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result2 := AddMonthSafe(date2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2025-02-28
|
||||
// 2024-01-29
|
||||
}
|
||||
|
||||
func ExampleAddYearSafe() {
|
||||
date, _ := time.Parse("2006-01-02", "2020-02-29")
|
||||
|
||||
result1 := AddYearSafe(date, 1)
|
||||
result2 := AddYearSafe(date, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-02-28
|
||||
// 2019-02-28
|
||||
}
|
||||
|
||||
func ExampleGetNowDate() {
|
||||
@@ -408,3 +478,61 @@ 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>
|
||||
}
|
||||
|
||||
func ExampleMin() {
|
||||
result := Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
|
||||
func ExampleMax() {
|
||||
result := Max(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 2024-09-02 00:00:00 +0000 UTC
|
||||
}
|
||||
|
||||
func ExampleMaxMin() {
|
||||
max, min := MaxMin(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 3, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(max)
|
||||
fmt.Println(min)
|
||||
|
||||
// Output:
|
||||
// 2024-09-03 00:00:00 +0000 UTC
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
|
||||
@@ -9,78 +9,427 @@ import (
|
||||
|
||||
func TestAddYear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
now := time.Now()
|
||||
after2Years := AddYear(now, 1)
|
||||
diff1 := after2Years.Sub(now)
|
||||
assert.Equal(float64(8760), diff1.Hours())
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
years int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: 1,
|
||||
expected: "2022-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: -1,
|
||||
expected: "2020-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: 0,
|
||||
expected: "2021-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: 2,
|
||||
expected: "2023-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: 3,
|
||||
expected: "2024-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
years: 4,
|
||||
expected: "2025-01-01 00:00:00",
|
||||
},
|
||||
}
|
||||
|
||||
before2Years := AddYear(now, -1)
|
||||
diff2 := before2Years.Sub(now)
|
||||
assert.Equal(float64(-8760), diff2.Hours())
|
||||
}
|
||||
|
||||
func TestBetweenSeconds(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBetweenSeconds")
|
||||
|
||||
today := time.Now()
|
||||
tomorrow := AddDay(today, 1)
|
||||
yesterday := AddDay(today, -1)
|
||||
|
||||
result1 := BetweenSeconds(today, tomorrow)
|
||||
result2 := BetweenSeconds(today, yesterday)
|
||||
|
||||
assert.Equal(int64(86400), result1)
|
||||
assert.Equal(int64(-86400), result2)
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", tt.inputDate)
|
||||
result := AddYear(date, int64(tt.years))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddDay(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
now := time.Now()
|
||||
after2Days := AddDay(now, 2)
|
||||
diff1 := after2Days.Sub(now)
|
||||
assert.Equal(float64(48), diff1.Hours())
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
days int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: 1,
|
||||
expected: "2021-01-02 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: -1,
|
||||
expected: "2020-12-31 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: 0,
|
||||
expected: "2021-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: 2,
|
||||
expected: "2021-01-03 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: 3,
|
||||
expected: "2021-01-04 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
days: 4,
|
||||
expected: "2021-01-05 00:00:00",
|
||||
},
|
||||
}
|
||||
|
||||
before2Days := AddDay(now, -2)
|
||||
diff2 := before2Days.Sub(now)
|
||||
assert.Equal(float64(-48), diff2.Hours())
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", tt.inputDate)
|
||||
result := AddDay(date, int64(tt.days))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddHour(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddHour")
|
||||
|
||||
now := time.Now()
|
||||
after2Hours := AddHour(now, 2)
|
||||
diff1 := after2Hours.Sub(now)
|
||||
assert.Equal(float64(2), diff1.Hours())
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
hours int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 1,
|
||||
expected: "2021-01-01 01:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: -1,
|
||||
expected: "2020-12-31 23:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 0,
|
||||
expected: "2021-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 24,
|
||||
expected: "2021-01-02 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 25,
|
||||
expected: "2021-01-02 01:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 48,
|
||||
expected: "2021-01-03 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
hours: 49,
|
||||
expected: "2021-01-03 01:00:00",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", tt.inputDate)
|
||||
result := AddHour(date, int64(tt.hours))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
|
||||
before2Hours := AddHour(now, -2)
|
||||
diff2 := before2Hours.Sub(now)
|
||||
assert.Equal(float64(-2), diff2.Hours())
|
||||
}
|
||||
|
||||
func TestAddMinute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddMinute")
|
||||
|
||||
now := time.Now()
|
||||
after2Minutes := AddMinute(now, 2)
|
||||
diff1 := after2Minutes.Sub(now)
|
||||
assert.Equal(float64(2), diff1.Minutes())
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
minutes int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 1,
|
||||
expected: "2021-01-01 00:01:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: -1,
|
||||
expected: "2020-12-31 23:59:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 0,
|
||||
expected: "2021-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 60,
|
||||
expected: "2021-01-01 01:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 61,
|
||||
expected: "2021-01-01 01:01:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 1440,
|
||||
expected: "2021-01-02 00:00:00",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01 00:00:00",
|
||||
minutes: 1441,
|
||||
expected: "2021-01-02 00:01:00",
|
||||
},
|
||||
}
|
||||
|
||||
before2Minutes := AddMinute(now, -2)
|
||||
diff2 := before2Minutes.Sub(now)
|
||||
assert.Equal(float64(-2), diff2.Minutes())
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", tt.inputDate)
|
||||
result := AddMinute(date, int64(tt.minutes))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddWeek(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddWeek")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
weeks int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: 1,
|
||||
expected: "2021-01-08",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: -1,
|
||||
expected: "2020-12-25",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: 0,
|
||||
expected: "2021-01-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: 52,
|
||||
expected: "2021-12-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: 53,
|
||||
expected: "2022-01-07",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
weeks: 104,
|
||||
expected: "2022-12-30",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddWeek(date, int64(tt.weeks))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMonth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddMonth")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
months int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: 1,
|
||||
expected: "2021-02-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: -1,
|
||||
expected: "2020-12-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: 0,
|
||||
expected: "2021-01-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: 12,
|
||||
expected: "2022-01-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: 13,
|
||||
expected: "2022-02-01",
|
||||
},
|
||||
{
|
||||
inputDate: "2021-01-01",
|
||||
months: 24,
|
||||
expected: "2023-01-01",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddMonth(date, int64(tt.months))
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAddDaySafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddDaySafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
days int
|
||||
expected string
|
||||
}{
|
||||
{"2025-01-31", 10, "2025-02-10"},
|
||||
{"2025-01-01", 30, "2025-01-31"},
|
||||
{"2025-01-31", 1, "2025-02-01"},
|
||||
{"2025-02-28", 1, "2025-03-01"},
|
||||
{"2024-02-29", 1, "2024-03-01"},
|
||||
{"2024-02-29", 365, "2025-02-28"},
|
||||
|
||||
{"2025-01-31", -10, "2025-01-21"},
|
||||
{"2025-01-01", -30, "2024-12-02"},
|
||||
{"2025-02-01", -1, "2025-01-31"},
|
||||
{"2025-03-01", -1, "2025-02-28"},
|
||||
{"2024-03-01", -1, "2024-02-29"},
|
||||
|
||||
{"2025-01-31", -31, "2024-12-31"},
|
||||
{"2025-12-31", 1, "2026-01-01"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddDaySafe(date, tt.days)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMonthSafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddMonthSafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
months int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: 1,
|
||||
expected: "2025-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: -1,
|
||||
expected: "2024-12-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-12-31",
|
||||
months: 1,
|
||||
expected: "2026-01-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: -1,
|
||||
expected: "2024-12-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2024-02-29",
|
||||
months: 1,
|
||||
expected: "2024-03-29",
|
||||
},
|
||||
{
|
||||
inputDate: "2024-02-29",
|
||||
months: -1,
|
||||
expected: "2024-01-29",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddMonthSafe(date, tt.months)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAddYearSafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddYearSafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
years int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: 1,
|
||||
expected: "2021-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: 2,
|
||||
expected: "2022-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: -1,
|
||||
expected: "2019-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: -2,
|
||||
expected: "2018-02-28",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddYearSafe(date, tt.years)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNowDate(t *testing.T) {
|
||||
@@ -410,3 +759,187 @@ 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")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestMin(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMin")
|
||||
|
||||
zeroTime := time.Time{}
|
||||
now := time.Now()
|
||||
oneMinuteAgo := now.Add(-time.Minute)
|
||||
oneMinuteAfter := now.Add(time.Minute)
|
||||
|
||||
assert.Equal(zeroTime, Min(zeroTime, now, oneMinuteAgo, oneMinuteAfter))
|
||||
|
||||
assert.Equal(zeroTime, Min(now, zeroTime))
|
||||
|
||||
assert.Equal(oneMinuteAgo, Min(oneMinuteAgo, now, oneMinuteAfter))
|
||||
}
|
||||
|
||||
func TestMax(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMax")
|
||||
|
||||
zeroTime := time.Time{}
|
||||
now := time.Now()
|
||||
oneMinuteAgo := now.Add(-time.Minute)
|
||||
oneMinuteAfter := now.Add(time.Minute)
|
||||
|
||||
assert.Equal(oneMinuteAfter, Max(zeroTime, now, oneMinuteAgo, oneMinuteAfter))
|
||||
|
||||
assert.Equal(now, Max(now, zeroTime))
|
||||
|
||||
assert.Equal(oneMinuteAfter, Max(oneMinuteAgo, now, oneMinuteAfter))
|
||||
}
|
||||
|
||||
func TestMaxMin(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMinMax")
|
||||
|
||||
zeroTime := time.Time{}
|
||||
now := time.Now()
|
||||
oneMinuteAgo := now.Add(-time.Minute)
|
||||
oneMinuteAfter := now.Add(time.Minute)
|
||||
|
||||
max, min := MaxMin(zeroTime, now, oneMinuteAgo, oneMinuteAfter)
|
||||
assert.Equal(zeroTime, min)
|
||||
assert.Equal(oneMinuteAfter, max)
|
||||
|
||||
max, min = MaxMin(now, zeroTime)
|
||||
assert.Equal(zeroTime, min)
|
||||
assert.Equal(now, max)
|
||||
|
||||
max, min = MaxMin(oneMinuteAgo, now, oneMinuteAfter)
|
||||
assert.Equal(oneMinuteAgo, min)
|
||||
assert.Equal(oneMinuteAfter, max)
|
||||
}
|
||||
|
||||
func TestBetweenSeconds(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBetweenSeconds")
|
||||
|
||||
today := time.Now()
|
||||
tomorrow := AddDay(today, 1)
|
||||
yesterday := AddDay(today, -1)
|
||||
|
||||
result1 := BetweenSeconds(today, tomorrow)
|
||||
result2 := BetweenSeconds(today, yesterday)
|
||||
|
||||
assert.Equal(int64(86400), result1)
|
||||
assert.Equal(int64(-86400), result2)
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -27,7 +27,8 @@ import (
|
||||
- [Nor](#Nor)
|
||||
- [Xnor](#Xnor)
|
||||
- [Nand](#Nand)
|
||||
- [TernaryOperator](#TernaryOperator)
|
||||
- [Ternary](#Ternary)
|
||||
- [TernaryOperator<sup>deprecated</sup>](#TernaryOperator)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -257,9 +258,45 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Ternary">Ternary</span>
|
||||
<p>三元运算符。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Ternary[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||
```
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conditionTrue := 2 > 1
|
||||
result1 := condition.Ternary(conditionTrue, 0, 1)
|
||||
|
||||
conditionFalse := 2 > 3
|
||||
result2 := condition.Ternary(conditionFalse, 0, 1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TernaryOperator">TernaryOperator</span>
|
||||
<p>三元运算符</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`Ternary`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
|
||||
@@ -43,6 +43,11 @@ import (
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
- [ToStdBase64](#ToStdBase64)
|
||||
- [ToUrlBase64](#ToUrlBase64)
|
||||
- [ToRawStdBase64](#ToRawStdBase64)
|
||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||
- [ToBigInt](#ToBigInt)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -368,7 +373,7 @@ import (
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result, err := ToJson(aMap)
|
||||
result, err := convertor.ToJson(aMap)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("%v", err)
|
||||
@@ -876,3 +881,302 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToBigInt">ToBigInt</span>
|
||||
|
||||
<p>将整数值转换为bigInt。</p>
|
||||
|
||||
<b>函数签名:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/X3itkCxwB_x)</span></b>
|
||||
|
||||
```go
|
||||
func ToBigInt[T any](v T) (*big.Int, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
n := 9876543210
|
||||
bigInt, _ := convertor.ToBigInt(n)
|
||||
|
||||
fmt.Println(bigInt)
|
||||
// Output:
|
||||
// 9876543210
|
||||
}
|
||||
```
|
||||
@@ -32,6 +32,8 @@ import (
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [AesGcmEncrypt](#AesGcmEncrypt)
|
||||
- [AesGcmDecrypt](#AesGcmDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
@@ -68,6 +70,9 @@ import (
|
||||
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
|
||||
- [RsaEncryptOAEP](#RsaEncryptOAEP)
|
||||
- [RsaDecryptOAEP](#RsaDecryptOAEP)
|
||||
- [RsaSign](#RsaSign)
|
||||
- [RsaVerifySign](#RsaVerifySign)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -379,6 +384,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;">[运行](https://go.dev/play/p/rUt0-DmsPCs)</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;">[运行](https://go.dev/play/p/rUt0-DmsPCs)</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>
|
||||
@@ -1363,7 +1436,7 @@ func main() {
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7_zo6mrx-eX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1400,7 +1473,7 @@ func main() {
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7_zo6mrx-eX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1537,3 +1610,81 @@ func main() {
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaSign">RsaSign</span>
|
||||
|
||||
<p>应用RSA算法签名数据。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qhsbf8BJ6Mf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private.pem"
|
||||
publicKey := "./rsa_public.pem"
|
||||
|
||||
signature, err := cryptor.RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = cryptor.RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaVerifySign">RsaVerifySign</span>
|
||||
|
||||
<p>验证数据的签名是否符合RSA算法。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qhsbf8BJ6Mf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private.pem"
|
||||
publicKey := "./rsa_public.pem"
|
||||
|
||||
signature, err := cryptor.RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = cryptor.RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -23,9 +23,14 @@ import (
|
||||
## 目录
|
||||
|
||||
- [AddDay](#AddDay)
|
||||
- [AddWeek](#AddWeek)
|
||||
- [AddMonth](#AddMonth)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [AddYear](#AddYear)
|
||||
- [AddDaySafe](#AddDaySafe)
|
||||
- [AddMonthSafe](#AddMonthSafe)
|
||||
- [AddYearSafe](#AddYearSafe)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
@@ -64,6 +69,12 @@ import (
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
- [TrackFuncTime](#TrackFuncTime)
|
||||
- [DaysBetween](#DaysBetween)
|
||||
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||
- [Min](#Min)
|
||||
- [Max](#Max)
|
||||
- [MaxMin](#MaxMin)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -103,7 +114,7 @@ import (
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time
|
||||
func AddDay(t time.Time, days int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dIGbs_uTdFa)</span></b>
|
||||
@@ -118,20 +129,89 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
tomorrow := datetime.AddDay(now, 1)
|
||||
diff1 := tomorrow.Sub(now)
|
||||
after1Day := datetime.AddDay(date, 1)
|
||||
before1Day := datetime.AddDay(date, -1)
|
||||
|
||||
yesterday := datetime.AddDay(now, -1)
|
||||
diff2 := yesterday.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after1Day.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before1Day.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 24h0m0s
|
||||
// -24h0m0s
|
||||
// 2021-01-02 00:00:00
|
||||
// 2020-12-31 00:00:00
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddWeek">AddWeek</span>
|
||||
|
||||
<p>将日期加/减星期数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddWeek(t time.Time, weeks int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Weeks := datetime.AddWeek(date, 2)
|
||||
before2Weeks := datetime.AddWeek(date, -2)
|
||||
|
||||
fmt.Println(after2Weeks.Format("2006-01-02"))
|
||||
fmt.Println(before2Weeks.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-01-15
|
||||
// 2020-12-18
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMonth">AddMonth</span>
|
||||
|
||||
<p>将日期加/减月数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddMonth(t time.Time, months int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Months := datetime.AddMonth(date, 2)
|
||||
before2Months := datetime.AddMonth(date, -2)
|
||||
|
||||
fmt.Println(after2Months.Format("2006-01-02"))
|
||||
fmt.Println(before2Months.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-03-01
|
||||
// 2020-11-01
|
||||
}
|
||||
```
|
||||
|
||||
@@ -142,7 +222,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddHour(t time.Time, hour int64) time.Time
|
||||
func AddHour(t time.Time, hours int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rcMjd7OCsi5)</span></b>
|
||||
@@ -157,20 +237,17 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Hours := datetime.AddHour(now, 2)
|
||||
diff1 := after2Hours.Sub(now)
|
||||
after2Hours := datetime.AddHour(date, 2)
|
||||
before2Hours := datetime.AddHour(date, -2)
|
||||
|
||||
before2Hours := datetime.AddHour(now, -2)
|
||||
diff2 := before2Hours.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Hours.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Hours.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2h0m0s
|
||||
// -2h0m0s
|
||||
// 2021-01-01 02:00:00
|
||||
// 2020-12-31 22:00:00
|
||||
}
|
||||
```
|
||||
|
||||
@@ -181,7 +258,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddMinute(t time.Time, minute int64) time.Time
|
||||
func AddMinute(t time.Time, minutes int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nT1heB1KUUK)</span></b>
|
||||
@@ -196,20 +273,17 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Minutes := datetime.AddMinute(now, 2)
|
||||
diff1 := after2Minutes.Sub(now)
|
||||
after2Minutes := datetime.AddMinute(date, 2)
|
||||
before2Minutes := datetime.AddMinute(date, -2)
|
||||
|
||||
before2Minutes := datetime.AddMinute(now, -2)
|
||||
diff2 := before2Minutes.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Minutes.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Minutes.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2m0s
|
||||
// -2m0s
|
||||
// 2021-01-01 00:02:00
|
||||
// 2020-12-31 23:58:00
|
||||
}
|
||||
```
|
||||
|
||||
@@ -220,7 +294,7 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddYear(t time.Time, year int64) time.Time
|
||||
func AddYear(t time.Time, years int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MqW2ujnBx10)</span></b>
|
||||
@@ -235,20 +309,137 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
after2Years := AddYear(date, 2)
|
||||
before2Years := AddYear(date, -2)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Years.Format("2006-01-02"))
|
||||
fmt.Println(before2Years.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
// 2023-01-01
|
||||
// 2019-01-01
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddDaySafe">AddDaySafe</span>
|
||||
|
||||
<p>增加/减少指定的天数,并确保日期是有效日期。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddDaySafe(t time.Time, days int) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
leapYearDate1, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result1 := datetime.AddDaySafe(leapYearDate1, 1)
|
||||
|
||||
leapYearDate2, _ := time.Parse("2006-01-02", "2024-03-01")
|
||||
result2 := datetime.AddDaySafe(leapYearDate2, -1)
|
||||
|
||||
nonLeapYearDate1, _ := time.Parse("2006-01-02", "2025-02-28")
|
||||
result3 := datetime.AddDaySafe(nonLeapYearDate1, 1)
|
||||
|
||||
nonLeaYearDate2, _ := time.Parse("2006-01-02", "2025-03-01")
|
||||
result4 := datetime.AddDaySafe(nonLeaYearDate2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
fmt.Println(result3.Format("2006-01-02"))
|
||||
fmt.Println(result4.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2024-03-01
|
||||
// 2024-02-29
|
||||
// 2025-03-01
|
||||
// 2025-02-28
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMonthSafe">AddMonthSafe</span>
|
||||
|
||||
<p>增加/减少指定的月份,并确保日期是有效日期。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddMonthSafe(t time.Time, months int) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1, _ := time.Parse("2006-01-02", "2025-01-31")
|
||||
result1 := datetime.AddMonthSafe(date1, 1)
|
||||
|
||||
date2, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result2 := datetime.AddMonthSafe(date2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2025-02-28
|
||||
// 2024-01-29
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddYearSafe">AddYearSafe</span>
|
||||
|
||||
<p>增加/减少指定的年份,并确保日期是有效日期。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddYearSafe(t time.Time, years int) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2020-02-29")
|
||||
|
||||
result1 := datetime.AddYearSafe(date, 1)
|
||||
result2 := datetime.AddYearSafe(date, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-02-28
|
||||
// 2019-02-28
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1334,7 +1525,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 +1655,199 @@ 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;">[运行](https://go.dev/play/p/QBSEdfXHPTp)</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;">[运行](https://go.dev/play/p/qD6qGb3TbOy)</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;">[运行](https://go.dev/play/p/6kHBpAxD9ZC)</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>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
|
||||
<p>返回最早时间。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Min(t1 time.Time, times ...time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MCIDvHNOGGb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
minTime := datetime.Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(minTime)
|
||||
|
||||
// Output:
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>返回最晚时间。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Max(t1 time.Time, times ...time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9m6JMk1LB7-)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
maxTime := datetime.Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(maxTime)
|
||||
|
||||
// Output:
|
||||
// 2024-09-02 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MaxMin">MaxMin</span>
|
||||
|
||||
<p>返回最早和最晚时间。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MaxMin(t1 time.Time, times ...time.Time) (maxTime time.Time, minTime time.Time)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rbW51cDtM_2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
max, min := datetime.MaxMin(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 3, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(max)
|
||||
fmt.Println(min)
|
||||
|
||||
// Output:
|
||||
// 2024-09-03 00:00:00 +0000 UTC
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
401
docs/api/packages/eventbus.md
Normal file
401
docs/api/packages/eventbus.md
Normal file
@@ -0,0 +1,401 @@
|
||||
# EventBus
|
||||
|
||||
EventbBus是一个事件总线,用于在应用程序中处理事件。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/eventbus/eventbus.go](https://github.com/duke-git/lancet/blob/main/eventbus/eventbus.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewEventBus](#NewEventBus)
|
||||
- [Subscribe](#Subscribe)
|
||||
- [Unsubscribe](#Unsubscribe)
|
||||
- [Publish](#Publish)
|
||||
- [ClearListeners](#ClearListeners)
|
||||
- [ClearListenersByTopic](#ClearListenersByTopic)
|
||||
- [GetListenersCount](#GetListenersCount)
|
||||
- [GetAllListenersCount](#GetAllListenersCount)
|
||||
- [GetEvents](#GetEvents)
|
||||
- [SetErrorHandler](#SetErrorHandler)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="NewEventBus">NewEventBus</span>
|
||||
|
||||
<p>创建EventBus实例。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewEventBus[T any]() *EventBus[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Subscribe">Subscribe</span>
|
||||
|
||||
<p>订阅具有特定事件主题和监听函数的事件。支持异步,事件优先级,事件过滤器。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Subscribe(topic string, listener func(eventData T), async bool, priority int, filter func(eventData T) bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
filter := func(eventData int) bool {
|
||||
return eventData == 1
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, filter)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 2})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Unsubscribe">Unsubscribe</span>
|
||||
|
||||
<p>取消订阅具有特定事件主题的事件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Unsubscribe(topic string, listener func(eventData T))
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.Unsubscribe("event1", listener)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Publish">Publish</span>
|
||||
|
||||
<p>发布一个带有特定事件主题和数据负载的事件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Publish(event Event[T])
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {
|
||||
fmt.Println(eventData)
|
||||
}, false, 0, nil)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ClearListeners">ClearListeners</span>
|
||||
|
||||
<p>清空所有事件监听器。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) ClearListeners()
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.ClearListeners()
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ClearListenersByTopic">ClearListenersByTopic</span>
|
||||
|
||||
<p>清空特定事件监听器。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) ClearListenersByTopic(topic string)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.ClearListenersByTopic("event1")
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetListenersCount">GetListenersCount</span>
|
||||
|
||||
<p>获取特定事件的监听器数量。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetListenersCount(topic string) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
count := eb.GetListenersCount("event1")
|
||||
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetAllListenersCount">GetAllListenersCount</span>
|
||||
|
||||
<p>获取所有事件的监听器数量。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetAllListenersCount() int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
count := eb.GetAllListenersCount()
|
||||
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetEvents">GetEvents</span>
|
||||
|
||||
<p>获取所有事件的topic。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetEvents() []string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
events := eb.GetEvents()
|
||||
|
||||
for _, event := range events {
|
||||
fmt.Println(event)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// event1
|
||||
// event2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SetErrorHandler">SetErrorHandler</span>
|
||||
|
||||
<p>设置事件的错误处理函数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) SetErrorHandler(handler func(err error))
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.SetErrorHandler(func(err error) {
|
||||
fmt.Println(err)
|
||||
})
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {
|
||||
panic("error")
|
||||
}, false, 0, nil)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
// Output:
|
||||
// error
|
||||
}
|
||||
```
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [CopyDir](#CopyDir)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -45,9 +46,13 @@ import (
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
- [ReadFile](#ReadFile)
|
||||
- [ChunkRead](#ChunkRead)
|
||||
- [ParallelChunkRead](#ParallelChunkRead)
|
||||
- [GetExeOrDllVersion](#GetExeOrDllVersion)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -161,6 +166,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>
|
||||
@@ -527,7 +560,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.UnZip("./test.zip", "./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -669,7 +702,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>
|
||||
@@ -701,7 +734,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>
|
||||
@@ -743,6 +776,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>
|
||||
@@ -872,9 +958,153 @@ func main() {
|
||||
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
|
||||
}
|
||||
```
|
||||
### <span id="GetExeOrDllVersion">GetExeOrDllVersion</span>
|
||||
|
||||
<p>返回exe,dll文件版本号(仅Window平台).</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetExeOrDllVersion(filePath string) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iLRrDBhE38E)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := fileutil.GetExeOrDllVersion(`C:\Program Files\Tencent\WeChat\WeChat.exe`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(v)
|
||||
// Output:
|
||||
// 3.9.10.19
|
||||
}
|
||||
```
|
||||
@@ -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;">[运行](https://go.dev/play/p/-dGFrYn_1Zi)</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;">[运行](https://go.dev/play/p/HpoMov-tJSN)</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
@@ -33,7 +33,11 @@ import (
|
||||
- [Percent](#Percent)
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
- [T运行cRound](#T运行cRound)
|
||||
- [CeilToFloat](#CeilToFloat)
|
||||
- [CeilToString](#CeilToString)
|
||||
- [FloorToFloat](#FloorToFloat)
|
||||
- [FloorToString](#FloorToString)
|
||||
- [Range](#Range)
|
||||
- [RangeWithStep](#RangeWithStep)
|
||||
- [AngleToRadian](#AngleToRadian)
|
||||
@@ -47,6 +51,11 @@ import (
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
- [Abs](#Abs)
|
||||
- [Div](#Div)
|
||||
- [Variance](#Variance)
|
||||
- [StdDev](#StdDev)
|
||||
- [Permutation](#Permutation)
|
||||
- [Combination](#Combination)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -59,7 +68,7 @@ import (
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
|
||||
@@ -82,7 +91,7 @@ func main() {
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1.5
|
||||
// 1.3
|
||||
}
|
||||
```
|
||||
@@ -392,7 +401,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 +437,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>
|
||||
@@ -457,14 +466,14 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TruncRound">TruncRound</span>
|
||||
### <span id="T运行cRound">T运行cRound</span>
|
||||
|
||||
<p>截短n位小数(不进行四舍五入)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
func T运行cRound[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>
|
||||
@@ -478,9 +487,9 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.TruncRound(0.124, 2)
|
||||
result2 := mathutil.TruncRound(0.125, 2)
|
||||
result3 := mathutil.TruncRound(0.125, 3)
|
||||
result1 := mathutil.T运行cRound(0.124, 2)
|
||||
result2 := mathutil.T运行cRound(0.125, 2)
|
||||
result3 := mathutil.T运行cRound(0.125, 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -493,6 +502,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>
|
||||
@@ -896,8 +1049,8 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Log(8, 2)
|
||||
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
|
||||
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
|
||||
result2 := mathutil.T运行cRound(mathutil.Log(5, 2), 2)
|
||||
result3 := mathutil.T运行cRound(mathutil.Log(27, 3), 0)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -965,16 +1118,184 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Variance">Variance</span>
|
||||
|
||||
<p>计算方差。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Variance[T constraints.Float | constraints.Integer](numbers []T) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[示例](https://go.dev/play/p/uHuV4YgXf8F)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Variance([]int{1, 2, 3, 4, 5})
|
||||
result2 := mathutil.Variance([]float64{1.1, 2.2, 3.3, 4.4, 5.5})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
// 2.42
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StdDev">StdDev</span>
|
||||
|
||||
<p>计算标准差。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StdDev[T constraints.Float | constraints.Integer](numbers []T) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FkNZDXvHD2l)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.TruncRound(mathutil.StdDev([]int{1, 2, 3, 4, 5}), 2)
|
||||
result2 := mathutil.TruncRound(mathutil.StdDev([]float64{1.1, 2.2, 3.3, 4.4, 5.5}), 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1.41
|
||||
// 1.55
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Permutation">Permutation</span>
|
||||
|
||||
<p>计算排列数P(n, k)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Permutation(n, k uint) uint
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MgobwH_FOxj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Permutation(5, 3)
|
||||
result2 := mathutil.Permutation(5, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 60
|
||||
// 120
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Combination">Combination</span>
|
||||
|
||||
<p>计算组合数C(n, k)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Combination(n, k uint) uint
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ENFQRDQUFi9)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Combination(5, 3)
|
||||
result2 := mathutil.Combination(5, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 10
|
||||
// 1
|
||||
}
|
||||
```
|
||||
@@ -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,15 +25,23 @@ 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)
|
||||
- [RandNumberOfLength](#RandNumberOfLength)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -117,6 +125,62 @@ 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;">[运行](https://go.dev/play/p/UrkWueF6yYo)</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;">[运行](https://go.dev/play/p/68UikN9d6VT)</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>
|
||||
@@ -223,7 +287,7 @@ func main() {
|
||||
|
||||
### <span id="RandSymbolChar">RandSymbolChar</span>
|
||||
|
||||
<p>生成给定长度的随机符号字符串. 符号字符包括: !@#$%^&*()_+-=[]{}|;':\",./<>?。</p>
|
||||
<p>生成给定长度的随机符号字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -231,7 +295,7 @@ func main() {
|
||||
func RandSymbolChar(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Im6ZJxAykOm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -243,7 +307,7 @@ import (
|
||||
|
||||
func main() {
|
||||
randStr := random.RandSymbolChar(6)
|
||||
fmt.Println(randStr) //@#(_")
|
||||
fmt.Println(randStr) // 随机特殊字符字符串,例如: @#(_")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -276,14 +340,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>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GATTQ5xTEG8)</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 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>
|
||||
@@ -304,7 +394,7 @@ func main() {
|
||||
|
||||
### <span id="RandFloat">RandFloat</span>
|
||||
|
||||
<p>生成随机float64数字,可以指定范围和精度。</p>
|
||||
<p>生成一个随机float64数值,可以指定精度。数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -312,7 +402,7 @@ func main() {
|
||||
func RandFloat(min, max float64, precision int) float64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zbD_tuobJtr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -330,7 +420,7 @@ func main() {
|
||||
|
||||
### <span id="RandFloats">RandFloats</span>
|
||||
|
||||
<p>生成随机float64数字切片,指定长度,范围和精度.</p>
|
||||
<p>生成一个特定长度的随机float64切片,可以指定数值精度。数值范围[min, max)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -338,7 +428,7 @@ func main() {
|
||||
func RandFloats(n int, min, max float64, precision int) []float64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/I3yndUQ-rhh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -352,4 +442,110 @@ 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;">[运行](https://go.dev/play/p/2_-PiDv3tGn)</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;">[运行](https://go.dev/play/p/to6BLc26wBv)</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;">[运行](https://go.dev/play/p/o-VSjPjnILI)</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)
|
||||
}
|
||||
```
|
||||
### <span id="RandNumberOfLength">RandNumberOfLength</span>
|
||||
|
||||
<p>生成指定长度的随机数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandNumberOfLength(len int) int
|
||||
```
|
||||
|
||||
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oyZbuV7bu7b)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
i := random.RandNumberOfLength(2)
|
||||
fmt.Println(i) // 21 (random number of length 2)
|
||||
}
|
||||
```
|
||||
@@ -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)
|
||||
@@ -42,7 +44,9 @@ import (
|
||||
- [Every](#Every)
|
||||
- [Equal](#Equal)
|
||||
- [EqualWith](#EqualWith)
|
||||
- [EqualUnordered](#EqualUnordered)
|
||||
- [Filter](#Filter)
|
||||
- [FilterConcurrent](#FilterConcurrent)
|
||||
- [Find<sup>deprecated</sup>](#Find)
|
||||
- [FindBy](#FindBy)
|
||||
- [FindLast<sup>deprecated</sup>](#FindLast)
|
||||
@@ -50,6 +54,7 @@ import (
|
||||
- [Flatten](#Flatten)
|
||||
- [FlattenDeep](#FlattenDeep)
|
||||
- [ForEach](#ForEach)
|
||||
- [ForEachConcurrent](#ForEachConcurrent)
|
||||
- [ForEachWithBreak](#ForEachWithBreak)
|
||||
- [GroupBy](#GroupBy)
|
||||
- [GroupWith](#GroupWith)
|
||||
@@ -60,17 +65,21 @@ import (
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [Map](#Map)
|
||||
- [MapConcurrent](#MapConcurrent)
|
||||
- [FilterMap](#FilterMap)
|
||||
- [FlatMap](#FlatMap)
|
||||
- [Merge](#Merge)
|
||||
- [Reverse](#Reverse)
|
||||
- [ReverseCopy](#ReverseCopy)
|
||||
- [Reduce<sup>deprecated</sup>](#Reduce)
|
||||
- [ReduceConcurrent](#ReduceConcurrent)
|
||||
- [ReduceBy](#ReduceBy)
|
||||
- [ReduceRight](#ReduceRight)
|
||||
- [Replace](#Replace)
|
||||
- [ReplaceAll](#ReplaceAll)
|
||||
- [Repeat](#Repeat)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [ShuffleCopy](#ShuffleCopy)
|
||||
- [IsAscending](#IsAscending)
|
||||
- [IsDescending](#IsDescending)
|
||||
- [IsSorted](#IsSorted)
|
||||
@@ -85,6 +94,9 @@ import (
|
||||
- [ToSlicePointer](#ToSlicePointer)
|
||||
- [Unique](#Unique)
|
||||
- [UniqueBy](#UniqueBy)
|
||||
- [UniqueByComparator](#UniqueByComparator)
|
||||
- [UniqueByField](#UniqueByField)
|
||||
- [UniqueByConcurrent](#UniqueByConcurrent)
|
||||
- [Union](#Union)
|
||||
- [UnionBy](#UnionBy)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
@@ -92,6 +104,14 @@ import (
|
||||
- [KeyBy](#KeyBy)
|
||||
- [Join](#Join)
|
||||
- [Partition](#Partition)
|
||||
- [SetToDefaultIf](#SetToDefaultIf)
|
||||
- [Break](#Break)
|
||||
- [RightPadding](#RightPadding)
|
||||
- [LeftPadding](#LeftPadding)
|
||||
- [Frequency](#Frequency)
|
||||
- [JoinFunc](#JoinFunc)
|
||||
- [ConcatBy](#ConcatBy)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -317,12 +337,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 +536,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 +553,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]
|
||||
// []
|
||||
|
||||
}
|
||||
```
|
||||
@@ -809,6 +877,37 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EqualUnordered">EqualUnordered</span>
|
||||
|
||||
<p>检查两个切片是否相等,元素数量相同,值相等,不考虑元素顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EqualUnordered[T comparable](slice1, slice2 []T) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := slice.EqualUnordered([]int{1, 2, 3}, []int{3, 2, 1})
|
||||
result2 := slice.EqualUnordered([]int{1, 2, 3}, []int{4, 5, 6})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
|
||||
<p>返回切片中通过predicate函数真值测试的所有元素</p>
|
||||
@@ -843,10 +942,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;">[运行](https://go.dev/play/p/t_pkwerIRVx)</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 +1050,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast(废弃:使用 FindLastBy)</span>
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`FindLastBy`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1082,6 +1219,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;">[运行](https://go.dev/play/p/kT4XW7DKVoV)</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 +1364,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 +1395,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="InterfaceSlice">InterfaceSlice(已弃用: 使用 go1.18+泛型代替)</span>
|
||||
### <span id="InterfaceSlice">InterfaceSlice</span>
|
||||
|
||||
<p>将值转换为接口切片</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用go1.18+泛型代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1387,7 +1565,7 @@ func main() {
|
||||
|
||||
### <span id="Map">Map</span>
|
||||
|
||||
<p>对slice中的每个元素执行map函数以创建一个新切片</p>
|
||||
<p>对slice中的每个元素执行map函数以创建一个新切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1419,6 +1597,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;">[运行](https://go.dev/play/p/H1ehfPkPen0)</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 +1703,8 @@ func main() {
|
||||
|
||||
<p>合并多个切片(不会消除重复元素).</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`Concat`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -1550,9 +1762,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReverseCopy">ReverseCopy</span>
|
||||
|
||||
<p>反转切片中的元素顺序, 不改变原slice。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReverseCopy[T any](slice []T) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
strs := []string{"a", "b", "c", "d"}
|
||||
|
||||
reversedStrs := slice.ReverseCopy(strs)
|
||||
|
||||
fmt.Println(reversedStrs)
|
||||
fmt.Println(strs)
|
||||
|
||||
// Output:
|
||||
// [d c b a]
|
||||
// [a b c d]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Reduce">Reduce</span>
|
||||
|
||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果(废弃:建议使用ReduceBy)</p>
|
||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果。</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用`ReduceBy`代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1584,6 +1830,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;">[运行](https://go.dev/play/p/Tjwe6OtaG07)</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>
|
||||
@@ -1750,7 +2028,7 @@ func main() {
|
||||
|
||||
### <span id="Shuffle">Shuffle</span>
|
||||
|
||||
<p>随机打乱切片中的元素顺序</p>
|
||||
<p>随机打乱切片中的元素顺序。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1777,6 +2055,37 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ShuffleCopy">ShuffleCopy</span>
|
||||
|
||||
<p>随机打乱切片中的元素顺序, 不改变原切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ShuffleCopy[T any](slice []T) []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}
|
||||
result := slice.ShuffleCopy(nums)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(nums)
|
||||
|
||||
// Output:
|
||||
// [3 1 5 4 2] (random order)
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsAscending">IsAscending</span>
|
||||
|
||||
<p>检查切片元素是否按升序排列。</p>
|
||||
@@ -2078,10 +2387,12 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StringSlice">StringSlice(已弃用: 使用 go1.18+泛型代替)</span>
|
||||
### <span id="StringSlice">StringSlice</span>
|
||||
|
||||
<p>将接口切片转换为字符串切片</p>
|
||||
|
||||
> ⚠️ 本函数已弃用,使用go1.18+泛型代替。
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
@@ -2230,15 +2541,15 @@ 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>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GY7JE4yikrl)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -2255,7 +2566,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>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rwSacr-ZHsR)</span></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>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wXZ7LcYRMGL)</span></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}]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2475,18 +2893,18 @@ 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]]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2501,7 +2919,7 @@ func main() {
|
||||
func Random[T any](slice []T) (val T, idx int)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](TODO)</span></b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UzpGQptWppw)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -2510,13 +2928,237 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
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
|
||||
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;">[运行](https://go.dev/play/p/CW3UVNdUZOq)</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]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="JoinFunc">JoinFunc</span>
|
||||
|
||||
<p>将切片元素用给定的分隔符连接成一个单一的字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func JoinFunc[T any](slice []T, sep string, transform func(T) T) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/55ib3SB5fM2)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := slice.JoinFunc([]string{"a", "b", "c"}, ", ", func(s string) string {
|
||||
return strings.ToUpper(s)
|
||||
})
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// A, B, C
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcatBy">ConcatBy</span>
|
||||
|
||||
<p>将切片中的元素连接成一个值,使用指定的分隔符和连接器函数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ConcatBy[T any](slice []T, sep T, connector func(T, T) T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6QcUpcY4UMW)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
|
||||
people := []Person{
|
||||
{Name: "Alice", Age: 30},
|
||||
{Name: "Bob", Age: 25},
|
||||
{Name: "Charlie", Age: 35},
|
||||
}
|
||||
|
||||
sep := Person{Name: " | ", Age: 0}
|
||||
|
||||
personConnector := func(a, b Person) Person {
|
||||
return Person{Name: a.Name + b.Name, Age: a.Age + b.Age}
|
||||
}
|
||||
|
||||
result := slice.ConcatBy(people, sep, personConnector)
|
||||
|
||||
fmt.Println(result.Name)
|
||||
fmt.Println(result.Age)
|
||||
|
||||
// Output:
|
||||
// Alice | Bob | Charlie
|
||||
// 90
|
||||
}
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# Stream
|
||||
|
||||
Stream 流,该包仅验证简单 stream 实现,功能有限。
|
||||
Stream流,该包仅验证简单stream实现,功能有限。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -48,6 +48,8 @@ import (
|
||||
- [NoneMatch](#NoneMatch)
|
||||
- [Count](#Count)
|
||||
- [ToSlice](#ToSlice)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -938,3 +940,69 @@ func main() {
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IndexOf">IndexOf</span>
|
||||
|
||||
<p>返回在stream中找到值的第一个匹配项的索引,如果找不到值,则返回-1。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Stream[T]) IndexOf(target T, equal func(a, b T) bool) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tBV5Nc-XDX2)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.FromSlice([]int{1, 2, 3, 2})
|
||||
|
||||
result1 := s.IndexOf(0, func(a, b int) bool { return a == b })
|
||||
result2 := s.IndexOf(2, func(a, b int) bool { return a == b })
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// -1
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LastIndexOf">LastIndexOf</span>
|
||||
|
||||
<p>返回在stream中找到值的最后一个匹配项的索引,如果找不到值,则返回-1。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Stream[T]) LastIndexOf(target T, equal func(a, b T) bool) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CjeoNw2eac_G)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.FromSlice([]int{1, 2, 3, 2})
|
||||
|
||||
result1 := s.LastIndexOf(0, func(a, b int) bool { return a == b })
|
||||
result2 := s.LastIndexOf(2, func(a, b int) bool { return a == b })
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// -1
|
||||
// 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
|
||||
}
|
||||
```
|
||||
@@ -60,6 +60,17 @@ import (
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
- [SubInBetween](#SubInBetween)
|
||||
- [HammingDistance](#HammingDistance)
|
||||
- [Concat](#Concat)
|
||||
- [Ellipsis](#Ellipsis)
|
||||
- [Shuffle](#Shuffle)
|
||||
- [Rotate](#Rotate)
|
||||
- [TemplateReplace](#TemplateReplace)
|
||||
- [RegexMatchAllGroups](#RegexMatchAllGroups)
|
||||
- [ExtractContent](#ExtractContent)
|
||||
- [FindAllOccurrences](#FindAllOccurrences)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1096,10 +1107,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsNotBlank("")
|
||||
result2 := strutil.IsNotBlank(" ")
|
||||
result2 := strutil.IsNotBlank(" ")
|
||||
result3 := strutil.IsNotBlank("\t\v\f\n")
|
||||
result4 := strutil.IsNotBlank(" 中文")
|
||||
result5 := strutil.IsNotBlank(" world ")
|
||||
result5 := strutil.IsNotBlank(" world ")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
@@ -1462,3 +1473,319 @@ 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;">[运行](https://go.dev/play/p/gD52SZHr4Kp)</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;">[运行](https://go.dev/play/p/i1vbdQiQVRR)</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;">[运行](https://go.dev/play/p/iStFwBwyGY7)</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;">[运行](https://go.dev/play/p/Kf03iOeT5bd)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Rotate("Hello", 0)
|
||||
result2 := strutil.Rotate("Hello", 1)
|
||||
result3 := strutil.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;">[运行](https://go.dev/play/p/cXSuFvyZqv9)</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;">[运行](https://go.dev/play/p/JZiu0RXpgN-)</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]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ExtractContent">ExtractContent</span>
|
||||
|
||||
<p>提取两个标记之间的内容。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ExtractContent(s, start, end string) []string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ay9UIk7Rum9)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
html := `<span>content1</span>aa<span>content2</span>bb<span>content1</span>`
|
||||
|
||||
result := strutil.ExtractContent(html, "<span>", "</span>")
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [content1 content2 content1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindAllOccurrences">FindAllOccurrences</span>
|
||||
|
||||
<p>返回子字符串在字符串中所有出现的位置。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FindAllOccurrences(str, substr string) []int
|
||||
```
|
||||
|
||||
<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.FindAllOccurrences("ababab", "ab")
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// [0 2 4]
|
||||
}
|
||||
```
|
||||
@@ -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">[运行](https://go.dev/play/p/5GVol6ryS_X)</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">[运行](https://go.dev/play/p/jJZhRYGGcmD)</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">[运行](https://go.dev/play/p/XKmvV-ExBWa)</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">[运行](https://go.dev/play/p/NQDVywEYYx7)</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)
|
||||
}
|
||||
```
|
||||
@@ -49,6 +49,7 @@ import (
|
||||
- [IsIp](#IsIp)
|
||||
- [IsIpV4](#IsIpV4)
|
||||
- [IsIpV6](#IsIpV6)
|
||||
- [IsIpPort](#IsIpPort)
|
||||
- [IsStrongPassword](#IsStrongPassword)
|
||||
- [IsUrl](#IsUrl)
|
||||
- [IsWeakPassword](#IsWeakPassword)
|
||||
@@ -990,6 +991,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsIpPort">IsIpPort</span>
|
||||
|
||||
<p>检查字符串是否是ip:port格式。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsIpPort(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := validator.IsIpPort("127.0.0.1:8080")
|
||||
result2 := validator.IsIpPort("[0:0:0:0:0:0:0:1]:8080")
|
||||
result3 := validator.IsIpPort(":8080")
|
||||
result4 := validator.IsIpPort("::0:0:0:0:")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsStrongPassword">IsStrongPassword</span>
|
||||
|
||||
<p>验证字符串是否是强密码:(alpha(lower+upper) + number + special chars(!@#$%^&*()?><))。</p>
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
- [XError_Info](#XError_Info)
|
||||
- [XError_Error](#XError_Error)
|
||||
- [TryUnwrap](#TryUnwrap)
|
||||
- [TryCatch](#TryCatch)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -167,12 +168,12 @@ import (
|
||||
|
||||
func main() {
|
||||
err1 := xerror.New("error").With("level", "high")
|
||||
err2 := err1.Wrap(errors.New("invalid username"))
|
||||
err2 := err1.Wrap(errors.New("invalid username"))
|
||||
|
||||
fmt.Println(err2.Error())
|
||||
fmt.Println(err2.Error())
|
||||
|
||||
// Output:
|
||||
// error: invalid username
|
||||
// Output:
|
||||
// error: invalid username
|
||||
}
|
||||
```
|
||||
|
||||
@@ -489,3 +490,54 @@ func main() {
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TryCatch">TryCatch</span>
|
||||
|
||||
<p>简单实现的java风格异常处理(try-catch-finally)。try catch不符合go错误处理风格,谨慎使用。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NewTryCatch(ctx context.Context) *TryCatch
|
||||
|
||||
func (tc *TryCatch) Try(tryFunc func(ctx context.Context) error) *TryCatch
|
||||
|
||||
func (tc *TryCatch) Catch(catchFunc func(ctx context.Context, err error)) *TryCatch
|
||||
|
||||
func (tc *TryCatch) Finally(finallyFunc func(ctx context.Context)) *TryCatch
|
||||
|
||||
func (tc *TryCatch) Do()
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/D5Mdb0mRj0P)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
|
||||
func main() {
|
||||
calledFinally := false
|
||||
calledCatch := false
|
||||
|
||||
tc := xerror.NewTryCatch(context.Background())
|
||||
|
||||
tc.Try(func(ctx context.Context) error {
|
||||
return errors.New("error in try block")
|
||||
}).Catch(func(ctx context.Context, err error) {
|
||||
calledCatch = true
|
||||
}).Finally(func(ctx context.Context) {
|
||||
calledFinally = true
|
||||
}).Do()
|
||||
|
||||
fmt.Println(calledCatch)
|
||||
fmt.Println(calledFinally)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -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>
|
||||
|
||||
@@ -27,7 +27,8 @@ import (
|
||||
- [Nor](#Nor)
|
||||
- [Xnor](#Xnor)
|
||||
- [Nand](#Nand)
|
||||
- [TernaryOperator](#TernaryOperator)
|
||||
- [Ternary](#Ternary)
|
||||
- [TernaryOperator<sup>deprecated</sup>](#TernaryOperator)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -269,9 +270,45 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="Ternary">Ternary</span>
|
||||
<p>Checks the value of param `isTrue`, if true return ifValue else return elseValue</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Ternary[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||
```
|
||||
<b>Example:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conditionTrue := 2 > 1
|
||||
result1 := condition.Ternary(conditionTrue, 0, 1)
|
||||
|
||||
conditionFalse := 2 > 3
|
||||
result2 := condition.Ternary(conditionFalse, 0, 1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TernaryOperator">TernaryOperator</span>
|
||||
<p>Checks the value of param `isTrue`, if true return ifValue else return elseValue</p>
|
||||
|
||||
> ⚠️ This function is deprecated. use `Ternary` instead.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
@@ -307,4 +344,3 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,11 @@ import (
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
- [ToStdBase64](#ToStdBase64)
|
||||
- [ToUrlBase64](#ToUrlBase64)
|
||||
- [ToRawStdBase64](#ToRawStdBase64)
|
||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||
- [ToBigInt](#ToBigInt)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -368,7 +373,7 @@ import (
|
||||
|
||||
func main() {
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
result, err := ToJson(aMap)
|
||||
result, err := convertor.ToJson(aMap)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("%v", err)
|
||||
@@ -567,6 +572,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="EncodeByte">EncodeByte</span>
|
||||
|
||||
<p>Encode data to byte slice.</p>
|
||||
@@ -632,69 +638,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 +718,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 +783,368 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToBigInt">ToBigInt</span>
|
||||
|
||||
<p>Converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int</p>
|
||||
|
||||
<b>Signature:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/X3itkCxwB_x)</span></b>
|
||||
|
||||
```go
|
||||
func ToBigInt[T any](v T) (*big.Int, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
n := 9876543210
|
||||
bigInt, _ := convertor.ToBigInt(n)
|
||||
|
||||
fmt.Println(bigInt)
|
||||
// Output:
|
||||
// 9876543210
|
||||
}
|
||||
```
|
||||
@@ -32,6 +32,8 @@ import (
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [AesGcmEncrypt](#AesGcmEncrypt)
|
||||
- [AesGcmDecrypt](#AesGcmDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
@@ -68,6 +70,8 @@ import (
|
||||
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
|
||||
- [RsaEncryptOAEP](#RsaEncryptOAEP)
|
||||
- [RsaDecryptOAEP](#RsaDecryptOAEP)
|
||||
- [RsaSign](#RsaSign)
|
||||
- [RsaVerifySign](#RsaVerifySign)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -379,6 +383,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](https://go.dev/play/p/rUt0-DmsPCs)</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](https://go.dev/play/p/rUt0-DmsPCs)</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>
|
||||
@@ -991,13 +1063,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==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1054,10 +1126,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1083,10 +1155,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1112,10 +1184,10 @@ import (
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1198,10 +1270,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1258,10 +1330,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1318,10 +1390,10 @@ import (
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1363,7 +1435,7 @@ func main() {
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7_zo6mrx-eX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1400,7 +1472,7 @@ func main() {
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7_zo6mrx-eX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1537,3 +1609,81 @@ func main() {
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaSign">RsaSign</span>
|
||||
|
||||
<p>Signs the data with RSA algorithm.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/qhsbf8BJ6Mf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private.pem"
|
||||
publicKey := "./rsa_public.pem"
|
||||
|
||||
signature, err := RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RsaVerifySign">RsaVerifySign</span>
|
||||
|
||||
<p>Verifies the signature of the data with RSA algorithm.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/qhsbf8BJ6Mf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := []byte("This is a test data for RSA signing")
|
||||
hash := crypto.SHA256
|
||||
|
||||
privateKey := "./rsa_private.pem"
|
||||
publicKey := "./rsa_public.pem"
|
||||
|
||||
signature, err := RsaSign(hash, data, privateKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = RsaVerifySign(hash, data, signature, publicKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -24,9 +24,14 @@ import (
|
||||
## Index
|
||||
|
||||
- [AddDay](#AddDay)
|
||||
- [AddWeek](#AddWeek)
|
||||
- [AddMonth](#AddMonth)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [AddYear](#AddYear)
|
||||
- [AddDaySafe](#AddDaySafe)
|
||||
- [AddMonthSafe](#AddMonthSafe)
|
||||
- [AddYearSafe](#AddYearSafe)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
@@ -65,6 +70,13 @@ import (
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
- [TrackFuncTime](#TrackFuncTime)
|
||||
- [DaysBetween](#DaysBetween)
|
||||
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||
- [Min](#Min)
|
||||
- [Max](#Max)
|
||||
- [MaxMin](#MaxMin)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -104,7 +116,7 @@ import (
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time
|
||||
func AddDay(t time.Time, days int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/dIGbs_uTdFa)</span></b>
|
||||
@@ -119,20 +131,89 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
tomorrow := datetime.AddDay(now, 1)
|
||||
diff1 := tomorrow.Sub(now)
|
||||
after1Day := datetime.AddDay(date, 1)
|
||||
before1Day := datetime.AddDay(date, -1)
|
||||
|
||||
yesterday := datetime.AddDay(now, -1)
|
||||
diff2 := yesterday.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after1Day.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before1Day.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 24h0m0s
|
||||
// -24h0m0s
|
||||
// 2021-01-02 00:00:00
|
||||
// 2020-12-31 00:00:00
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddWeek">AddWeek</span>
|
||||
|
||||
<p>Add or sub weeks to time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddWeek(t time.Time, weeks int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Weeks := datetime.AddWeek(date, 2)
|
||||
before2Weeks := datetime.AddWeek(date, -2)
|
||||
|
||||
fmt.Println(after2Weeks.Format("2006-01-02"))
|
||||
fmt.Println(before2Weeks.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-01-15
|
||||
// 2020-12-18
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMonth">AddMonth</span>
|
||||
|
||||
<p>Add or sub months to time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddMonth(t time.Time, months int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after2Months := datetime.AddMonth(date, 2)
|
||||
before2Months := datetime.AddMonth(date, -2)
|
||||
|
||||
fmt.Println(after2Months.Format("2006-01-02"))
|
||||
fmt.Println(before2Months.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-03-01
|
||||
// 2020-11-01
|
||||
}
|
||||
```
|
||||
|
||||
@@ -158,20 +239,17 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Hours := datetime.AddHour(now, 2)
|
||||
diff1 := after2Hours.Sub(now)
|
||||
after2Hours := datetime.AddHour(date, 2)
|
||||
before2Hours := datetime.AddHour(date, -2)
|
||||
|
||||
before2Hours := datetime.AddHour(now, -2)
|
||||
diff2 := before2Hours.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Hours.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Hours.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2h0m0s
|
||||
// -2h0m0s
|
||||
// 2021-01-01 02:00:00
|
||||
// 2020-12-31 22:00:00
|
||||
}
|
||||
```
|
||||
|
||||
@@ -197,20 +275,17 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02 15:04:05", "2021-01-01 00:00:00")
|
||||
|
||||
after2Minutes := datetime.AddMinute(now, 2)
|
||||
diff1 := after2Minutes.Sub(now)
|
||||
after2Minutes := datetime.AddMinute(date, 2)
|
||||
before2Minutes := datetime.AddMinute(date, -2)
|
||||
|
||||
before2Minutes := datetime.AddMinute(now, -2)
|
||||
diff2 := before2Minutes.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Minutes.Format("2006-01-02 15:04:05"))
|
||||
fmt.Println(before2Minutes.Format("2006-01-02 15:04:05"))
|
||||
|
||||
// Output:
|
||||
// 2m0s
|
||||
// -2m0s
|
||||
// 2021-01-01 00:02:00
|
||||
// 2020-12-31 23:58:00
|
||||
}
|
||||
```
|
||||
|
||||
@@ -236,20 +311,137 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
date, _ := time.Parse("2006-01-02", "2021-01-01")
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
after2Years := AddYear(date, 2)
|
||||
before2Years := AddYear(date, -2)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(after2Years.Format("2006-01-02"))
|
||||
fmt.Println(before2Years.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
// 2023-01-01
|
||||
// 2019-01-01
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddDaySafe">AddDaySafe</span>
|
||||
|
||||
<p>Add or sub days to the time and ensure that the returned date does not exceed the valid date of the target year and month.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddDaySafe(t time.Time, days int) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
leapYearDate1, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result1 := datetime.AddDaySafe(leapYearDate1, 1)
|
||||
|
||||
leapYearDate2, _ := time.Parse("2006-01-02", "2024-03-01")
|
||||
result2 := datetime.AddDaySafe(leapYearDate2, -1)
|
||||
|
||||
nonLeapYearDate1, _ := time.Parse("2006-01-02", "2025-02-28")
|
||||
result3 := datetime.AddDaySafe(nonLeapYearDate1, 1)
|
||||
|
||||
nonLeaYearDate2, _ := time.Parse("2006-01-02", "2025-03-01")
|
||||
result4 := datetime.AddDaySafe(nonLeaYearDate2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
fmt.Println(result3.Format("2006-01-02"))
|
||||
fmt.Println(result4.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2024-03-01
|
||||
// 2024-02-29
|
||||
// 2025-03-01
|
||||
// 2025-02-28
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddMonthSafe">AddMonthSafe</span>
|
||||
|
||||
<p>Add or sub months to the time and ensure that the returned date does not exceed the valid date of the target year and month.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddMonthSafe(t time.Time, months int) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1, _ := time.Parse("2006-01-02", "2025-01-31")
|
||||
result1 := datetime.AddMonthSafe(date1, 1)
|
||||
|
||||
date2, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result2 := datetime.AddMonthSafe(date2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2025-02-28
|
||||
// 2024-01-29
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddYearSafe">AddYearSafe</span>
|
||||
|
||||
<p>Add or sub years to the time and ensure that the returned date does not exceed the valid date of the target year and month.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddYearSafe(t time.Time, years int) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date, _ := time.Parse("2006-01-02", "2020-02-29")
|
||||
|
||||
result1 := datetime.AddYearSafe(date, 1)
|
||||
result2 := datetime.AddYearSafe(date, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-02-28
|
||||
// 2019-02-28
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1335,7 +1527,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)
|
||||
@@ -1465,3 +1657,198 @@ 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](https://go.dev/play/p/QBSEdfXHPTp)</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](https://go.dev/play/p/qD6qGb3TbOy)</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](https://go.dev/play/p/6kHBpAxD9ZC)</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>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
|
||||
<p>Returns the earliest time among the given times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Min(t1 time.Time, times ...time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/MCIDvHNOGGb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
minTime := datetime.Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(minTime)
|
||||
|
||||
// Output:
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>Returns the latest time among the given times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Max(t1 time.Time, times ...time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/9m6JMk1LB7-)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
maxTime := datetime.Min(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(maxTime)
|
||||
|
||||
// Output:
|
||||
// 2024-09-02 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MaxMin">MaxMin</span>
|
||||
|
||||
<p>Returns the latest and earliest time among the given times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func MaxMin(t1 time.Time, times ...time.Time) (maxTime time.Time, minTime time.Time)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/rbW51cDtM_2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
max, min := datetime.MaxMin(time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 2, 0, 0, 0, 0, time.UTC), time.Date(2024, time.September, 3, 0, 0, 0, 0, time.UTC))
|
||||
|
||||
fmt.Println(max)
|
||||
fmt.Println(min)
|
||||
|
||||
// Output:
|
||||
// 2024-09-03 00:00:00 +0000 UTC
|
||||
// 2024-09-01 00:00:00 +0000 UTC
|
||||
}
|
||||
```
|
||||
401
docs/en/api/packages/eventbus.md
Normal file
401
docs/en/api/packages/eventbus.md
Normal file
@@ -0,0 +1,401 @@
|
||||
# EventBus
|
||||
|
||||
EventBus is an event bus used for handling events within an application.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/eventbus/eventbus.go](https://github.com/duke-git/lancet/blob/main/eventbus/eventbus.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [NewEventBus](#NewEventBus)
|
||||
- [Subscribe](#Subscribe)
|
||||
- [Unsubscribe](#Unsubscribe)
|
||||
- [Publish](#Publish)
|
||||
- [ClearListeners](#ClearListeners)
|
||||
- [ClearListenersByTopic](#ClearListenersByTopic)
|
||||
- [GetListenersCount](#GetListenersCount)
|
||||
- [GetAllListenersCount](#GetAllListenersCount)
|
||||
- [GetEvents](#GetEvents)
|
||||
- [SetErrorHandler](#SetErrorHandler)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="NewEventBus">NewEventBus</span>
|
||||
|
||||
<p>Create an EventBus instance.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NewEventBus[T any]() *EventBus[T]
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Subscribe">Subscribe</span>
|
||||
|
||||
<p>Subscribes to an event with a specific event topic and listener function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Subscribe(topic string, listener func(eventData T), async bool, priority int, filter func(eventData T) bool)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
filter := func(eventData int) bool {
|
||||
return eventData == 1
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, filter)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 2})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Unsubscribe">Unsubscribe</span>
|
||||
|
||||
<p>Unsubscribes from an event with a specific event topic and listener function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Unsubscribe(topic string, listener func(eventData T))
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.Unsubscribe("event1", listener)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Publish">Publish</span>
|
||||
|
||||
<p>Publishes an event with a specific event topic and data payload.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) Publish(event Event[T])
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {
|
||||
fmt.Println(eventData)
|
||||
}, false, 0, nil)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ClearListeners">ClearListeners</span>
|
||||
|
||||
<p>Clears all the listeners.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) ClearListeners()
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.ClearListeners()
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ClearListenersByTopic">ClearListenersByTopic</span>
|
||||
|
||||
<p>Clears all the listeners by topic.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) ClearListenersByTopic(topic string)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
receivedData := 0
|
||||
listener := func(eventData int) {
|
||||
receivedData = eventData
|
||||
}
|
||||
|
||||
eb.Subscribe("event1", listener, false, 0, nil)
|
||||
eb.ClearListenersByTopic("event1")
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
fmt.Println(receivedData)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetListenersCount">GetListenersCount</span>
|
||||
|
||||
<p>Returns the number of listeners for a specific event topic.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetListenersCount(topic string) int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
count := eb.GetListenersCount("event1")
|
||||
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetAllListenersCount">GetAllListenersCount</span>
|
||||
|
||||
<p>Returns the total number of all listeners.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetAllListenersCount() int
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
count := eb.GetAllListenersCount()
|
||||
|
||||
fmt.Println(count)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetEvents">GetEvents</span>
|
||||
|
||||
<p>Returns all the events topics.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) GetEvents() []string
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {}, false, 0, nil)
|
||||
eb.Subscribe("event2", func(eventData int) {}, false, 0, nil)
|
||||
|
||||
events := eb.GetEvents()
|
||||
|
||||
for _, event := range events {
|
||||
fmt.Println(event)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// event1
|
||||
// event2
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SetErrorHandler">SetErrorHandler</span>
|
||||
|
||||
<p>Sets the error handler function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (eb *EventBus[T]) SetErrorHandler(handler func(err error))
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/eventbus"
|
||||
)
|
||||
|
||||
func main() {
|
||||
eb := eventbus.NewEventBus[int]()
|
||||
|
||||
eb.SetErrorHandler(func(err error) {
|
||||
fmt.Println(err)
|
||||
})
|
||||
|
||||
eb.Subscribe("event1", func(eventData int) {
|
||||
panic("error")
|
||||
}, false, 0, nil)
|
||||
|
||||
eb.Publish(Event[int]{Topic: "event1", Payload: 1})
|
||||
|
||||
// Output:
|
||||
// error
|
||||
}
|
||||
```
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [CopyDir](#CopyDir)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
@@ -45,9 +46,13 @@ import (
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
- [ReadFile](#ReadFile)
|
||||
- [ChunkRead](#ChunkRead)
|
||||
- [ParallelChunkRead](#ParallelChunkRead)
|
||||
- [GetExeOrDllVersion](#GetExeOrDllVersion)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -161,6 +166,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>
|
||||
@@ -527,7 +560,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
err := fileutil.UnZip("./test.zip", "./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -669,7 +702,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>
|
||||
@@ -701,7 +734,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>
|
||||
@@ -743,6 +776,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>
|
||||
@@ -878,3 +964,148 @@ func main() {
|
||||
// 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GetExeOrDllVersion">GetExeOrDllVersion</span>
|
||||
|
||||
<p>Get the version of exe or dll file on windows.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GetExeOrDllVersion(filePath string) (string, error)
|
||||
```
|
||||
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/iLRrDBhE38E)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
v, err := fileutil.GetExeOrDllVersion(`C:\Program Files\Tencent\WeChat\WeChat.exe`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(v)
|
||||
|
||||
// Output:
|
||||
// 3.9.10.19
|
||||
}
|
||||
```
|
||||
@@ -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](https://go.dev/play/p/-dGFrYn_1Zi)</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](https://go.dev/play/p/HpoMov-tJSN)</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
|
||||
}
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user