mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 21:02:27 +08:00
Compare commits
335 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdfdeaf496 | ||
|
|
172c44c07a | ||
|
|
534263eb08 | ||
|
|
a25b1ac7e3 | ||
|
|
d84f9777ea | ||
|
|
f9caaf8063 | ||
|
|
f198711d1c | ||
|
|
19378ca4d1 | ||
|
|
71c7733eb0 | ||
|
|
20786c360b | ||
|
|
51fafa110e | ||
|
|
07fc453b74 | ||
|
|
b309044981 | ||
|
|
541e6d4ea3 | ||
|
|
4037b96cc4 | ||
|
|
8e484c4a6f | ||
|
|
dd339563bc | ||
|
|
9567dcc57f | ||
|
|
de104ebeb6 | ||
|
|
eebd95395f | ||
|
|
56265647ff | ||
|
|
756da3719d | ||
|
|
f3008ac7c4 | ||
|
|
c6583d3b83 | ||
|
|
a3d7bac72e | ||
|
|
74b4d53514 | ||
|
|
a08afe0d77 | ||
|
|
ee680aa84c | ||
|
|
caa74064f0 | ||
|
|
abc94c0b26 | ||
|
|
86bcdce07b | ||
|
|
789f5d933d | ||
|
|
156fd2ef5d | ||
|
|
ea036b3a81 | ||
|
|
3daca8b331 | ||
|
|
21a952d2be | ||
|
|
03d331dfb6 | ||
|
|
ef79e1305e | ||
|
|
7c2670d019 | ||
|
|
31f64c0a98 | ||
|
|
28b8986cbe | ||
|
|
b4ff33ce80 | ||
|
|
25fa117712 | ||
|
|
0c9f539e3d | ||
|
|
05bd1afaa6 | ||
|
|
51cb665110 | ||
|
|
47c368e8f2 | ||
|
|
3127360b28 | ||
|
|
5b6def5ff0 | ||
|
|
33d99ad7d4 | ||
|
|
8bd31d39c3 | ||
|
|
a418549525 | ||
|
|
1f849efe1c | ||
|
|
8ad374bb21 | ||
|
|
a69d886565 | ||
|
|
cf58542b4a | ||
|
|
51f166d1d9 | ||
|
|
fbeb031b40 | ||
|
|
095cfc0aab | ||
|
|
e66ab154bc | ||
|
|
91bc1a512c | ||
|
|
8753255026 | ||
|
|
9cf1f13fec | ||
|
|
5d78bae4bb | ||
|
|
27777eecc0 | ||
|
|
1a7e0e8792 | ||
|
|
02b7aa8f33 | ||
|
|
f188d3d08f | ||
|
|
0c924b859e | ||
|
|
c5a5a07462 | ||
|
|
1ff5dd6df0 | ||
|
|
b5f86a488c | ||
|
|
1390b7a964 | ||
|
|
c3e28a9fc0 | ||
|
|
e924429d6e | ||
|
|
7079b1f704 | ||
|
|
40cad365c0 | ||
|
|
6386ab908d | ||
|
|
bb563724c7 | ||
|
|
72924d4486 | ||
|
|
231f8b04b4 | ||
|
|
daa932fee3 | ||
|
|
1b0691f1d5 | ||
|
|
0b6a00bd99 | ||
|
|
4ab98664bb | ||
|
|
31eb5f4d1f | ||
|
|
0ae5d17a06 | ||
|
|
4558d7a3c2 | ||
|
|
4715301240 | ||
|
|
1c58ee23f1 | ||
|
|
2a303d5e4b | ||
|
|
326e7881a6 | ||
|
|
31e8b12674 | ||
|
|
a0431d9435 | ||
|
|
0456b65cc7 | ||
|
|
989b4dd791 | ||
|
|
a76b02fbba | ||
|
|
2d7747738a | ||
|
|
fe0cb04137 | ||
|
|
fe0264f628 | ||
|
|
65396cee32 | ||
|
|
544702b460 | ||
|
|
d8936cdcb5 | ||
|
|
d4b97d6b20 | ||
|
|
5caa14c838 | ||
|
|
0d0848ac67 | ||
|
|
d5334f892f | ||
|
|
36ef5b3bd3 | ||
|
|
6f48b00c88 | ||
|
|
7b744c299e | ||
|
|
154ec56780 | ||
|
|
584aabdf62 | ||
|
|
1b754a6264 | ||
|
|
06a558d797 | ||
|
|
423779d3ff | ||
|
|
78c17a9e7b | ||
|
|
529b9317d0 | ||
|
|
dc838f645b | ||
|
|
7f559c4940 | ||
|
|
acb08dfd90 | ||
|
|
ffe46fd06d | ||
|
|
b419e46b9b | ||
|
|
8fbcdfd515 | ||
|
|
f03f48210c | ||
|
|
742944e2f0 | ||
|
|
c0b491ad78 | ||
|
|
e9abae2a92 | ||
|
|
8229de2f10 | ||
|
|
ab364744b6 | ||
|
|
17ff84fa1f | ||
|
|
bf50baa07d | ||
|
|
7d56da8108 | ||
|
|
16c2df711b | ||
|
|
015f8c3f5c | ||
|
|
ba25701d89 | ||
|
|
a0cb4bb266 | ||
|
|
d6ba7497f9 | ||
|
|
7da931e0a0 | ||
|
|
8f49078eb3 | ||
|
|
3050d93703 | ||
|
|
efcfbfb6a1 | ||
|
|
844b7a2c3b | ||
|
|
c8a536eafc | ||
|
|
0fd268face | ||
|
|
8ced7e887f | ||
|
|
957568ed5c | ||
|
|
fffabd0ffa | ||
|
|
e839af3ef9 | ||
|
|
1650e70d04 | ||
|
|
23382b2b76 | ||
|
|
daa3aa3da2 | ||
|
|
be355a23f3 | ||
|
|
95af83b0cb | ||
|
|
1efdbc0973 | ||
|
|
9b829aa695 | ||
|
|
bfa9091c09 | ||
|
|
c11d63c2e2 | ||
|
|
83832daeb1 | ||
|
|
7311f84772 | ||
|
|
a63d78111e | ||
|
|
e2fc2f1bc9 | ||
|
|
23a0135947 | ||
|
|
013b6457bb | ||
|
|
e08a62b0ba | ||
|
|
850800a233 | ||
|
|
a6a8fd88bc | ||
|
|
2f6ee84443 | ||
|
|
b1c6614549 | ||
|
|
a8761eefb0 | ||
|
|
cbf8cfdffa | ||
|
|
286a187942 | ||
|
|
b787e99528 | ||
|
|
e54c9b2850 | ||
|
|
8944109c4c | ||
|
|
10e3732f32 | ||
|
|
a415597c6b | ||
|
|
69b32fd043 | ||
|
|
75ed359084 | ||
|
|
2c71b6375c | ||
|
|
2894bec80c | ||
|
|
09ec5b97a6 | ||
|
|
46ecb117a5 | ||
|
|
388171e739 | ||
|
|
6fbaf2b005 | ||
|
|
53a91cad71 | ||
|
|
a51a182fb2 | ||
|
|
64982f0c89 | ||
|
|
f38f69ce17 | ||
|
|
a33ea3d013 | ||
|
|
e35462fb14 | ||
|
|
af106a4a8e | ||
|
|
ec7232ec40 | ||
|
|
67c1b54b5a | ||
|
|
e149ae2f72 | ||
|
|
b1fcfce188 | ||
|
|
259dbce85e | ||
|
|
78aa679670 | ||
|
|
3beb769f09 | ||
|
|
8af02ff95b | ||
|
|
ba4485d8c0 | ||
|
|
8a1dd40738 | ||
|
|
85e2806531 | ||
|
|
1616d3d1be | ||
|
|
aa8e0d5c12 | ||
|
|
f05477d9cf | ||
|
|
cd91e16b26 | ||
|
|
9fcf046fb3 | ||
|
|
c3f1bc39d7 | ||
|
|
f5784b0f46 | ||
|
|
c86a8a479d | ||
|
|
e2aeb8ec07 | ||
|
|
654ba15aaf | ||
|
|
945c59896b | ||
|
|
219e31d929 | ||
|
|
82cb86b35c | ||
|
|
f93c561f5d | ||
|
|
4888909208 | ||
|
|
33c8875d14 | ||
|
|
99cb1b13a3 | ||
|
|
42ec189995 | ||
|
|
424c291813 | ||
|
|
4311b9ac66 | ||
|
|
581e338889 | ||
|
|
f399425c2a | ||
|
|
dcdb29334d | ||
|
|
4859f3ca23 | ||
|
|
9f2528842e | ||
|
|
6066d6669f | ||
|
|
e3804e9534 | ||
|
|
2f51397d2c | ||
|
|
11217a11c7 | ||
|
|
fa81ee143e | ||
|
|
62891f20f8 | ||
|
|
5e79eaa9dd | ||
|
|
aaf45012e4 | ||
|
|
48c17ea1ce | ||
|
|
e90283c3f9 | ||
|
|
f82c4a305d | ||
|
|
05997603a9 | ||
|
|
6d5ec807f7 | ||
|
|
f73c7e7e86 | ||
|
|
c137428b9e | ||
|
|
9f68620b37 | ||
|
|
2cdbba56a4 | ||
|
|
01a3b139c0 | ||
|
|
fcb3b97b45 | ||
|
|
52ea64bc33 | ||
|
|
14bc08c6d6 | ||
|
|
47bdd6718a | ||
|
|
18d27604e6 | ||
|
|
66bd339e3a | ||
|
|
04abb7a3ea | ||
|
|
975c303a31 | ||
|
|
3b8dd94a5c | ||
|
|
815791c0b6 | ||
|
|
a12a691ee6 | ||
|
|
247cf89947 | ||
|
|
c3fad62d8c | ||
|
|
a8a96be21b | ||
|
|
8e297769b2 | ||
|
|
98cdf1c040 | ||
|
|
d7976e31a4 | ||
|
|
5b11a8b457 | ||
|
|
d4a16534f2 | ||
|
|
ecf0688788 | ||
|
|
90f9cad1ea | ||
|
|
4a298876e9 | ||
|
|
74474cd9ef | ||
|
|
f23f18457e | ||
|
|
18f01ffd75 | ||
|
|
c53d541a6b | ||
|
|
5b9b4c4344 | ||
|
|
6e7300bbbf | ||
|
|
3685aee02b | ||
|
|
046f3e0bf9 | ||
|
|
c01c9d14b4 | ||
|
|
f198191063 | ||
|
|
8bdd46bda4 | ||
|
|
e29b56c3c3 | ||
|
|
c357fc68c8 | ||
|
|
bc25e7a037 | ||
|
|
217350042b | ||
|
|
e56a8a1ef5 | ||
|
|
6453f755a6 | ||
|
|
027abd6ad5 | ||
|
|
91503b1656 | ||
|
|
e2522cd29b | ||
|
|
da69b77892 | ||
|
|
05772d8d7d | ||
|
|
3b497532f3 | ||
|
|
1cd3be508c | ||
|
|
a41d461910 | ||
|
|
cde5946bf0 | ||
|
|
c28803b25e | ||
|
|
f09e521783 | ||
|
|
0aa41f337d | ||
|
|
48814a720a | ||
|
|
04b79b3dfe | ||
|
|
302007ebdf | ||
|
|
965e5fbcda | ||
|
|
70d0adde42 | ||
|
|
0b80074bb7 | ||
|
|
90945a0399 | ||
|
|
47dccd63af | ||
|
|
4ae7e59829 | ||
|
|
8f0c60cade | ||
|
|
3f6aef1432 | ||
|
|
a714e04470 | ||
|
|
7456621153 | ||
|
|
73ac9825e9 | ||
|
|
930bb9c839 | ||
|
|
3d8f1be212 | ||
|
|
13a4ed59fa | ||
|
|
c799d10ce9 | ||
|
|
5ab322ade2 | ||
|
|
d0ffc61842 | ||
|
|
5e66bc6227 | ||
|
|
7261b281ad | ||
|
|
f79693804b | ||
|
|
534c7a0abc | ||
|
|
4eaff47d38 | ||
|
|
3e019522c7 | ||
|
|
0734f220b3 | ||
|
|
2d2c277090 | ||
|
|
ef1e548dfc | ||
|
|
924589d2da | ||
|
|
77f32f4cc6 | ||
|
|
1755dd249b | ||
|
|
7a25688ec1 | ||
|
|
51a6912eb3 | ||
|
|
28d0428b50 | ||
|
|
6a9eb645bb | ||
|
|
3857b342f6 | ||
|
|
71aa91a58d | ||
|
|
081908bce3 |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
liberapay: Duke_Du
|
||||
patreon: DukeDu
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -6,5 +6,10 @@ fileutil/*.txt
|
||||
fileutil/*.zip
|
||||
fileutil/*.link
|
||||
fileutil/unzip/*
|
||||
fileutil/tempdir/*
|
||||
slice/testdata/*
|
||||
cryptor/*.pem
|
||||
cryptor/*.pem
|
||||
test
|
||||
docs/node_modules
|
||||
docs/.vitepress/cache
|
||||
docs/.vitepress/dist
|
||||
|
||||
37
CONTRIBUTING.en-US.md
Normal file
37
CONTRIBUTING.en-US.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Lancet Contributing Guide
|
||||
|
||||
Hi! Thank you for choosing Lancet.
|
||||
|
||||
Lancet is a powerful, efficient, and reusable util function library of go. It makes Go dev easier by taking the hassle out of working with concurrency, net, math, slice, string, etc.
|
||||
|
||||
We are excited that you are interested in contributing to lancet. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
|
||||
|
||||
## Issue Guidelines
|
||||
|
||||
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly.
|
||||
|
||||
- Before submitting an issue, please check if similar problems have already been issued.
|
||||
|
||||
- Please specify which version of Lancet and Go you are using, and provide OS information. [Go Playground](https://go.dev/play/) is recommended to build a live demo so that your issue can be reproduced clearly.
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
- Fork this repository to your own account. Do not create branches here.
|
||||
|
||||
- Commit info should be formatted as `type(scope): info about commit`. eg. `fix(package): [scrollbar] fix xxx bug`.
|
||||
|
||||
1. type: type must be one of [chore, docs, feat, fix, refactor, release, test].
|
||||
|
||||
2. scope: scope must be one of [package, file, internal].
|
||||
|
||||
3. header: header must not be longer than 72 characters.
|
||||
|
||||
- Rebase before creating a PR to keep commit history clear.
|
||||
|
||||
- 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.
|
||||
|
||||
- If your PR fixes a bug, please provide a description about the related bug.
|
||||
|
||||
- If the PR is for a new feature, make sure to complete the relevant documentation (/lancet/docs/en/api/packages).
|
||||
37
CONTRIBUTING.zh-CN.md
Normal file
37
CONTRIBUTING.zh-CN.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Lancet 贡献指南
|
||||
|
||||
Hi! 首先感谢你使用 Lancet。
|
||||
|
||||
lancet(柳叶刀)是一个功能强大、全面、高效、可复用的go语言工具函数库。它消除了处理并发、网络、数学、切片、字符串等的麻烦,使 Go 开发变得更容易。
|
||||
|
||||
Lancet 的成长离不开大家的支持,如果你愿意为 Lancet 贡献代码或提供建议,请阅读以下内容。
|
||||
|
||||
## Issue 规范
|
||||
|
||||
- issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。
|
||||
|
||||
- 在提交 issue 之前,请搜索相关内容是否已被提出。
|
||||
|
||||
- 请说明 Lancet 和 Go 的版本号,并提供操作系统信息。推荐使用 [Go Playground](https://go.dev/play/) 生成在线 demo,这能够更直观地重现问题。
|
||||
|
||||
## Pull Request 规范
|
||||
|
||||
- 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。
|
||||
|
||||
- commit 信息要以 `type(scope): 描述信息` 的形式填写,例如 `fix(package): [scrollbar] fix xxx bug`。
|
||||
|
||||
1. type: 必须是 chore, docs, feat, fix, refactor, release, test 其中的一个。
|
||||
|
||||
2. scope: 必须是 package, file, internal 其中的一个。
|
||||
|
||||
3. header: 描述信息不要超过 72 个字符。
|
||||
|
||||
- 提交 PR 前请 rebase,确保 commit 记录的整洁。
|
||||
|
||||
- 提交 PR 前请执行单元测试命令:go test -v ./...,确保所有单元测试任务通过。
|
||||
|
||||
- 确保 PR 是提交到 `v2` 分支,而不是 `main` 分支。
|
||||
|
||||
- 如果是修复 bug,请在 PR 中给出描述信息。
|
||||
|
||||
- 如果PR是新功能,确保完成相关文档(/lancet/docs/api/packages)。
|
||||
1714
README_zh-CN.md
1714
README_zh-CN.md
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestLRUCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestLRUCache")
|
||||
|
||||
cache := NewLRUCache[int, int](3)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func TestLinearSearch(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestLinearSearch")
|
||||
|
||||
numbers := []int{3, 4, 5, 3, 2, 1}
|
||||
@@ -19,6 +20,7 @@ func TestLinearSearch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBinarySearch(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBinarySearch")
|
||||
|
||||
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||
|
||||
@@ -46,6 +46,7 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
|
||||
}
|
||||
|
||||
func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||
|
||||
peoples := []people{
|
||||
@@ -65,6 +66,7 @@ func TestBubbleSortForStructSlice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBubbleSortForIntSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
||||
|
||||
numbers := []int{2, 1, 5, 3, 6, 4}
|
||||
@@ -75,6 +77,7 @@ func TestBubbleSortForIntSlice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertionSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestInsertionSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -94,6 +97,7 @@ func TestInsertionSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSelectionSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestSelectionSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -113,6 +117,7 @@ func TestSelectionSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestShellSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestShellSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -132,6 +137,7 @@ func TestShellSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestQuickSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestQuickSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -151,6 +157,7 @@ func TestQuickSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeapSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestHeapSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -170,6 +177,7 @@ func TestHeapSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMergeSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestMergeSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -189,6 +197,7 @@ func TestMergeSort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCountSort(t *testing.T) {
|
||||
t.Parallel()
|
||||
asssert := internal.NewAssert(t, "TestCountSort")
|
||||
|
||||
peoples := []people{
|
||||
@@ -200,7 +209,6 @@ func TestCountSort(t *testing.T) {
|
||||
}
|
||||
comparator := &peopleAgeComparator{}
|
||||
sortedPeopleByAge := CountSort(peoples, comparator)
|
||||
t.Log(sortedPeopleByAge)
|
||||
|
||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||
|
||||
72
compare/compare.go
Normal file
72
compare/compare.go
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package compare provides a lightweight comparison function on any type.
|
||||
// reference: https://github.com/stretchr/testify
|
||||
package compare
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
// operator type
|
||||
const (
|
||||
equal = "eq"
|
||||
lessThan = "lt"
|
||||
greaterThan = "gt"
|
||||
lessOrEqual = "le"
|
||||
greaterOrEqual = "ge"
|
||||
)
|
||||
|
||||
var (
|
||||
timeType = reflect.TypeOf(time.Time{})
|
||||
bytesType = reflect.TypeOf([]byte{})
|
||||
)
|
||||
|
||||
// Equal checks if two values are equal or not. (check both type and value)
|
||||
// Play: https://go.dev/play/p/wmVxR-to4lz
|
||||
func Equal(left, right any) bool {
|
||||
return compareValue(equal, left, right)
|
||||
}
|
||||
|
||||
// EqualValue checks if two values are equal or not. (check value only)
|
||||
// Play: https://go.dev/play/p/fxnna_LLD9u
|
||||
func EqualValue(left, right any) bool {
|
||||
ls, rs := convertor.ToString(left), convertor.ToString(right)
|
||||
return ls == rs
|
||||
}
|
||||
|
||||
// LessThan checks if value `left` less than value `right`.
|
||||
// Play: https://go.dev/play/p/cYh7FQQj0ne
|
||||
func LessThan(left, right any) bool {
|
||||
return compareValue(lessThan, left, right)
|
||||
}
|
||||
|
||||
// GreaterThan checks if value `left` greater than value `right`.
|
||||
// Play: https://go.dev/play/p/9-NYDFZmIMp
|
||||
func GreaterThan(left, right any) bool {
|
||||
return compareValue(greaterThan, left, right)
|
||||
}
|
||||
|
||||
// LessOrEqual checks if value `left` less than or equal to value `right`.
|
||||
// Play: https://go.dev/play/p/e4T_scwoQzp
|
||||
func LessOrEqual(left, right any) bool {
|
||||
return compareValue(lessOrEqual, left, right)
|
||||
}
|
||||
|
||||
// GreaterOrEqual checks if value `left` greater than or equal to value `right`.
|
||||
// Play: https://go.dev/play/p/vx8mP0U8DFk
|
||||
func GreaterOrEqual(left, right any) bool {
|
||||
return compareValue(greaterOrEqual, left, right)
|
||||
}
|
||||
|
||||
// InDelta checks if two values are equal or not within a delta.
|
||||
// Play: https://go.dev/play/p/TuDdcNtMkjo
|
||||
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool {
|
||||
return float64(mathutil.Abs(left-right)) <= delta
|
||||
}
|
||||
196
compare/compare_example_test.go
Normal file
196
compare/compare_example_test.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package compare
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExampleEqual() {
|
||||
result1 := Equal(1, 1)
|
||||
result2 := Equal("1", "1")
|
||||
result3 := Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||
result4 := Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||
|
||||
result5 := Equal(1, "1")
|
||||
result6 := Equal(1, int64(1))
|
||||
result7 := Equal([]int{1, 2}, []int{1, 2, 3})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleEqualValue() {
|
||||
result1 := EqualValue(1, 1)
|
||||
result2 := EqualValue(int(1), int64(1))
|
||||
result3 := EqualValue(1, "1")
|
||||
result4 := EqualValue(1, "2")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleLessThan() {
|
||||
result1 := LessThan(1, 2)
|
||||
result2 := LessThan(1.1, 2.2)
|
||||
result3 := LessThan("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := LessThan(time1, time2)
|
||||
|
||||
result5 := LessThan(2, 1)
|
||||
result6 := LessThan(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleGreaterThan() {
|
||||
result1 := GreaterThan(2, 1)
|
||||
result2 := GreaterThan(2.2, 1.1)
|
||||
result3 := GreaterThan("b", "a")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := GreaterThan(time2, time1)
|
||||
|
||||
result5 := GreaterThan(1, 2)
|
||||
result6 := GreaterThan(int64(2), 1)
|
||||
result7 := GreaterThan("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleLessOrEqual() {
|
||||
result1 := LessOrEqual(1, 1)
|
||||
result2 := LessOrEqual(1.1, 2.2)
|
||||
result3 := LessOrEqual("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := LessOrEqual(time1, time2)
|
||||
|
||||
result5 := LessOrEqual(2, 1)
|
||||
result6 := LessOrEqual(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleGreaterOrEqual() {
|
||||
result1 := GreaterOrEqual(1, 1)
|
||||
result2 := GreaterOrEqual(2.2, 1.1)
|
||||
result3 := GreaterOrEqual("b", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := GreaterOrEqual(time2, time1)
|
||||
|
||||
result5 := GreaterOrEqual(1, 2)
|
||||
result6 := GreaterOrEqual(int64(2), 1)
|
||||
result7 := GreaterOrEqual("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleInDelta() {
|
||||
result1 := InDelta(1, 1, 0)
|
||||
result2 := InDelta(1, 2, 0)
|
||||
|
||||
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
|
||||
result4 := InDelta(2.0/3.0, 0.0, 0.001)
|
||||
|
||||
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
|
||||
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
323
compare/compare_internal.go
Normal file
323
compare/compare_internal.go
Normal file
@@ -0,0 +1,323 @@
|
||||
package compare
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func compareValue(operator string, left, right any) bool {
|
||||
leftType, rightType := reflect.TypeOf(left), reflect.TypeOf(right)
|
||||
|
||||
if leftType.Kind() != rightType.Kind() {
|
||||
return false
|
||||
}
|
||||
|
||||
switch leftType.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64, reflect.Bool, reflect.String:
|
||||
return compareBasicValue(operator, left, right)
|
||||
|
||||
case reflect.Struct, reflect.Slice, reflect.Map:
|
||||
return compareRefValue(operator, left, right, leftType.Kind())
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind) bool {
|
||||
leftVal, rightVal := reflect.ValueOf(leftObj), reflect.ValueOf(rightObj)
|
||||
|
||||
switch kind {
|
||||
case reflect.Struct:
|
||||
|
||||
// compare time
|
||||
if leftVal.CanConvert(timeType) {
|
||||
timeObj1, ok := leftObj.(time.Time)
|
||||
if !ok {
|
||||
timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
|
||||
}
|
||||
|
||||
timeObj2, ok := rightObj.(time.Time)
|
||||
if !ok {
|
||||
timeObj2 = rightVal.Convert(timeType).Interface().(time.Time)
|
||||
}
|
||||
|
||||
return compareBasicValue(operator, timeObj1.UnixNano(), timeObj2.UnixNano())
|
||||
}
|
||||
|
||||
// for other struct type, only process equal operator
|
||||
switch operator {
|
||||
case equal:
|
||||
return objectsAreEqualValues(leftObj, rightObj)
|
||||
}
|
||||
|
||||
case reflect.Slice:
|
||||
// compare []byte
|
||||
if leftVal.CanConvert(bytesType) {
|
||||
bytesObj1, ok := leftObj.([]byte)
|
||||
if !ok {
|
||||
bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
|
||||
}
|
||||
bytesObj2, ok := rightObj.([]byte)
|
||||
if !ok {
|
||||
bytesObj2 = rightVal.Convert(bytesType).Interface().([]byte)
|
||||
}
|
||||
|
||||
switch operator {
|
||||
case equal:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) == 0 {
|
||||
return true
|
||||
}
|
||||
case lessThan:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) == -1 {
|
||||
return true
|
||||
}
|
||||
case greaterThan:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) == 1 {
|
||||
return true
|
||||
}
|
||||
case lessOrEqual:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) <= 0 {
|
||||
return true
|
||||
}
|
||||
case greaterOrEqual:
|
||||
if bytes.Compare(bytesObj1, bytesObj2) >= 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// for other type slice, only process equal operator
|
||||
switch operator {
|
||||
case equal:
|
||||
return reflect.DeepEqual(leftObj, rightObj)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
// only process equal operator
|
||||
switch operator {
|
||||
case equal:
|
||||
return reflect.DeepEqual(leftObj, rightObj)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func objectsAreEqualValues(expected, actual interface{}) bool {
|
||||
if objectsAreEqual(expected, actual) {
|
||||
return true
|
||||
}
|
||||
|
||||
actualType := reflect.TypeOf(actual)
|
||||
if actualType == nil {
|
||||
return false
|
||||
}
|
||||
expectedValue := reflect.ValueOf(expected)
|
||||
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||
// Attempt comparison after type conversion
|
||||
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func objectsAreEqual(expected, actual interface{}) bool {
|
||||
if expected == nil || actual == nil {
|
||||
return expected == actual
|
||||
}
|
||||
|
||||
exp, ok := expected.([]byte)
|
||||
if !ok {
|
||||
return reflect.DeepEqual(expected, actual)
|
||||
}
|
||||
|
||||
act, ok := actual.([]byte)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if exp == nil || act == nil {
|
||||
return exp == nil && act == nil
|
||||
}
|
||||
return bytes.Equal(exp, act)
|
||||
}
|
||||
|
||||
// compareBasic compare basic value: integer, float, string, bool
|
||||
func compareBasicValue(operator string, leftValue, rightValue any) bool {
|
||||
if leftValue == nil && rightValue == nil && operator == equal {
|
||||
return true
|
||||
}
|
||||
|
||||
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 float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case bool:
|
||||
left := leftVal
|
||||
switch right := rightValue.(type) {
|
||||
case bool:
|
||||
switch operator {
|
||||
case equal:
|
||||
if left == right {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
156
compare/compare_test.go
Normal file
156
compare/compare_test.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package compare
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
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
|
||||
}{
|
||||
A: "a",
|
||||
B: "b",
|
||||
}
|
||||
|
||||
st2 := struct {
|
||||
A string
|
||||
B string
|
||||
}{
|
||||
A: "a",
|
||||
B: "b",
|
||||
}
|
||||
|
||||
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"))
|
||||
|
||||
assert.Equal(false, EqualValue(1, "2"))
|
||||
}
|
||||
|
||||
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"))
|
||||
|
||||
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)))
|
||||
}
|
||||
|
||||
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"))
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
assert.Equal(true, GreaterThan(time2, time1))
|
||||
|
||||
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"))
|
||||
|
||||
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)))
|
||||
}
|
||||
|
||||
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"))
|
||||
|
||||
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"))
|
||||
}
|
||||
|
||||
func TestInDelta(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestInDelta")
|
||||
|
||||
assert.Equal(true, InDelta(1, 1, 0))
|
||||
assert.Equal(false, InDelta(1, 2, 0))
|
||||
|
||||
assert.Equal(true, InDelta(2.0/3.0, 0.66667, 0.001))
|
||||
assert.Equal(false, InDelta(2.0/3.0, 0.0, 0.001))
|
||||
|
||||
assert.Equal(false, InDelta(float64(74.96)-float64(20.48), 54.48, 0))
|
||||
assert.Equal(true, InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14))
|
||||
assert.Equal(false, InDelta(float64(float32(80.45)), float64(80.45), 0))
|
||||
assert.Equal(true, InDelta(float64(float32(80.45)), float64(80.45), 1e-5))
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, async.
|
||||
// Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel.
|
||||
package concurrency
|
||||
|
||||
import (
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestGenerate")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -23,6 +24,7 @@ func TestGenerate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRepeat(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestRepeat")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -39,6 +41,7 @@ func TestRepeat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRepeatFn(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestRepeatFn")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -57,6 +60,7 @@ func TestRepeatFn(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTake(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestTake")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -79,6 +83,7 @@ func TestTake(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFanIn(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestFanIn")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -101,6 +106,7 @@ func TestFanIn(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOr(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestOr")
|
||||
|
||||
sig := func(after time.Duration) <-chan any {
|
||||
@@ -127,6 +133,7 @@ func TestOr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOrDone(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestOrDone")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -141,6 +148,7 @@ func TestOrDone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTee(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestTee")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -159,6 +167,7 @@ func TestTee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBridge(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestBridge")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -181,7 +190,6 @@ func TestBridge(t *testing.T) {
|
||||
|
||||
index := 0
|
||||
for val := range c.Bridge(ctx, genVals()) {
|
||||
// t.Logf("%v ", val) //0 1 2 3 4 5 6 7 8 9
|
||||
assert.Equal(index, val)
|
||||
index++
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
type TestStruct struct{}
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBool")
|
||||
|
||||
// bool
|
||||
@@ -63,6 +65,8 @@ func TestBool(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAnd(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAnd")
|
||||
assert.Equal(false, And(0, 1))
|
||||
assert.Equal(false, And(0, ""))
|
||||
@@ -71,6 +75,8 @@ func TestAnd(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOr(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestOr")
|
||||
assert.Equal(false, Or(0, ""))
|
||||
assert.Equal(true, Or(0, 1))
|
||||
@@ -79,6 +85,8 @@ func TestOr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestXor(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestOr")
|
||||
assert.Equal(false, Xor(0, 0))
|
||||
assert.Equal(true, Xor(0, 1))
|
||||
@@ -87,6 +95,8 @@ func TestXor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNor(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestNor")
|
||||
assert.Equal(true, Nor(0, 0))
|
||||
assert.Equal(false, Nor(0, 1))
|
||||
@@ -95,6 +105,8 @@ func TestNor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestXnor(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestXnor")
|
||||
assert.Equal(true, Xnor(0, 0))
|
||||
assert.Equal(false, Xnor(0, 1))
|
||||
@@ -103,6 +115,8 @@ func TestXnor(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNand(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestNand")
|
||||
assert.Equal(true, Nand(0, 0))
|
||||
assert.Equal(true, Nand(0, 1))
|
||||
@@ -111,7 +125,10 @@ func TestNand(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTernaryOperator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TernaryOperator")
|
||||
|
||||
trueValue := "1"
|
||||
falseValue := "0"
|
||||
|
||||
|
||||
@@ -11,11 +11,15 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ToBool convert string to boolean.
|
||||
@@ -235,31 +239,7 @@ func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K
|
||||
// map key is specified same as struct field tag `json` value.
|
||||
// Play: https://go.dev/play/p/KYGYJqNUBOI
|
||||
func StructToMap(value any) (map[string]any, error) {
|
||||
v := reflect.ValueOf(value)
|
||||
t := reflect.TypeOf(value)
|
||||
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
|
||||
}
|
||||
|
||||
result := make(map[string]any)
|
||||
|
||||
fieldNum := t.NumField()
|
||||
pattern := `^[A-Z]`
|
||||
regex := regexp.MustCompile(pattern)
|
||||
for i := 0; i < fieldNum; i++ {
|
||||
name := t.Field(i).Name
|
||||
tag := t.Field(i).Tag.Get("json")
|
||||
if regex.MatchString(name) && tag != "" {
|
||||
//result[name] = v.Field(i).Interface()
|
||||
result[tag] = v.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return structs.ToMap(value)
|
||||
}
|
||||
|
||||
// MapToSlice convert map to slice based on iteratee function.
|
||||
@@ -343,44 +323,74 @@ func DeepClone[T any](src T) T {
|
||||
}
|
||||
|
||||
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
||||
// Play: todo
|
||||
func CopyProperties[T, U any](dst T, src U) (err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = errors.New(fmt.Sprintf("%v", e))
|
||||
}
|
||||
}()
|
||||
|
||||
dstType, dstValue := reflect.TypeOf(dst), reflect.ValueOf(dst)
|
||||
srcType, srcValue := reflect.TypeOf(src), reflect.ValueOf(src)
|
||||
// use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.
|
||||
// Play: https://go.dev/play/p/oZujoB5Sgg5
|
||||
func CopyProperties[T, U any](dst T, src U) error {
|
||||
dstType, srcType := reflect.TypeOf(dst), reflect.TypeOf(src)
|
||||
|
||||
if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
|
||||
return errors.New("CopyProperties: param dst should be struct pointer")
|
||||
return errors.New("CopyProperties: parameter dst should be struct pointer")
|
||||
}
|
||||
|
||||
if srcType.Kind() == reflect.Ptr {
|
||||
srcType, srcValue = srcType.Elem(), srcValue.Elem()
|
||||
srcType = srcType.Elem()
|
||||
}
|
||||
if srcType.Kind() != reflect.Struct {
|
||||
return errors.New("CopyProperties: param src should be a struct or struct pointer")
|
||||
return errors.New("CopyProperties: parameter src should be a struct or struct pointer")
|
||||
}
|
||||
|
||||
dstType, dstValue = dstType.Elem(), dstValue.Elem()
|
||||
|
||||
propertyNums := dstType.NumField()
|
||||
|
||||
for i := 0; i < propertyNums; i++ {
|
||||
property := dstType.Field(i)
|
||||
propertyValue := srcValue.FieldByName(property.Name)
|
||||
|
||||
if !propertyValue.IsValid() || property.Type != propertyValue.Type() {
|
||||
continue
|
||||
}
|
||||
|
||||
if dstValue.Field(i).CanSet() {
|
||||
dstValue.Field(i).Set(propertyValue)
|
||||
}
|
||||
bytes, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CopyProperties: unable to marshal src: %s", err)
|
||||
}
|
||||
err = json.Unmarshal(bytes, dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CopyProperties: unable to unmarshal into dst: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToInterface converts reflect value to its interface type.
|
||||
// Play: https://go.dev/play/p/syqw0-WG7Xd
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool) {
|
||||
if v.IsValid() && v.CanInterface() {
|
||||
return v.Interface(), true
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
return v.Bool(), true
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int(), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint(), true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float(), true
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return v.Complex(), true
|
||||
case reflect.String:
|
||||
return v.String(), true
|
||||
case reflect.Ptr:
|
||||
return ToInterface(v.Elem())
|
||||
case reflect.Interface:
|
||||
return ToInterface(v.Elem())
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
|
||||
// Play: https://go.dev/play/p/9FlIaFLArIL
|
||||
func Utf8ToGbk(bs []byte) ([]byte, error) {
|
||||
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewEncoder())
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// GbkToUtf8 convert GBK encoding data to utf8 encoding data.
|
||||
// Play: https://go.dev/play/p/OphmHCN_9u8
|
||||
func GbkToUtf8(bs []byte) ([]byte, error) {
|
||||
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package convertor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func ExampleToBool() {
|
||||
@@ -255,12 +259,12 @@ func ExampleDecodeByte() {
|
||||
|
||||
func ExampleDeepClone() {
|
||||
type Struct struct {
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
unexported string
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
// unexported string
|
||||
}
|
||||
|
||||
cases := []interface{}{
|
||||
@@ -293,47 +297,97 @@ func ExampleDeepClone() {
|
||||
// 1 false
|
||||
// 0.1 false
|
||||
// map[a:1 b:2] false
|
||||
// &{test 1 0.1 true <nil> } false
|
||||
// &{test 1 0.1 true <nil>} false
|
||||
}
|
||||
|
||||
func ExampleCopyProperties() {
|
||||
type Address struct {
|
||||
Country string
|
||||
ZipCode string
|
||||
type Disk struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type DiskVO struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type Indicator struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int `json:"cpu"`
|
||||
Disk []Disk `json:"disk"`
|
||||
Stop chan bool `json:"-"`
|
||||
}
|
||||
|
||||
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||
type IndicatorVO struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int64 `json:"cpu"`
|
||||
Disk []DiskVO `json:"disk"`
|
||||
}
|
||||
|
||||
employee1 := Employee{}
|
||||
CopyProperties(&employee1, &user)
|
||||
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||
}}
|
||||
|
||||
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||
indicatorVO := IndicatorVO{}
|
||||
|
||||
CopyProperties(&employee2, &user)
|
||||
CopyProperties(&indicatorVO, indicator)
|
||||
|
||||
fmt.Println(employee1)
|
||||
fmt.Println(employee2)
|
||||
fmt.Println(indicatorVO.Id)
|
||||
fmt.Println(indicatorVO.Ip)
|
||||
fmt.Println(len(indicatorVO.Disk))
|
||||
|
||||
// Output:
|
||||
// {user001 10 Admin {CN 001} [a b] 0}
|
||||
// {user001 10 Admin {CN 001} [a b] 500}
|
||||
// 001
|
||||
// 127.0.0.1
|
||||
// 3
|
||||
}
|
||||
|
||||
func ExampleToInterface() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleUtf8ToGbk() {
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, _ := Utf8ToGbk(utf8Data)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(validator.IsGBK(gbkData))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleGbkToUtf8() {
|
||||
gbkData, _ := Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func (c *cloner) cloneArray(v reflect.Value) reflect.Value {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
val := c.clone(v.Index(i))
|
||||
|
||||
if val.IsValid() {
|
||||
if !val.IsValid() {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,16 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func TestToChar(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToChar")
|
||||
|
||||
cases := []string{"", "abc", "1 2#3"}
|
||||
@@ -25,6 +29,8 @@ func TestToChar(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToChannel(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToChannel")
|
||||
|
||||
ch := ToChannel([]int{1, 2, 3})
|
||||
@@ -37,6 +43,8 @@ func TestToChannel(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToBool")
|
||||
|
||||
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
|
||||
@@ -49,6 +57,8 @@ func TestToBool(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToBytes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToBytes")
|
||||
|
||||
cases := []any{
|
||||
@@ -75,6 +85,8 @@ func TestToBytes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToInt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToInt")
|
||||
|
||||
cases := []any{"123", "-123", 123,
|
||||
@@ -91,6 +103,8 @@ func TestToInt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToFloat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToFloat")
|
||||
|
||||
cases := []any{
|
||||
@@ -109,6 +123,8 @@ func TestToFloat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToString")
|
||||
|
||||
aMap := make(map[string]int)
|
||||
@@ -144,6 +160,8 @@ func TestToString(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func TestToJson(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToJson")
|
||||
|
||||
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
@@ -159,6 +177,8 @@ func TestToJson(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToMap")
|
||||
|
||||
type Message struct {
|
||||
@@ -178,23 +198,45 @@ func TestToMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStructToMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestStructToMap")
|
||||
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
age int
|
||||
}
|
||||
p := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
t.Run("StructToMap", func(_ *testing.T) {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
age int
|
||||
}
|
||||
p := People{
|
||||
"test",
|
||||
100,
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
var expected = map[string]any{"name": "test"}
|
||||
assert.Equal(expected, pm)
|
||||
})
|
||||
|
||||
expected := map[string]any{"name": "test"}
|
||||
assert.Equal(expected, pm)
|
||||
t.Run("StructToMapWithJsonAttr", func(_ *testing.T) {
|
||||
type People struct {
|
||||
Name string `json:"name,omitempty"` // json tag with attribute
|
||||
Phone string `json:"phone"` // json tag without attribute
|
||||
Sex string `json:"-"` // ignore
|
||||
age int // no tag
|
||||
}
|
||||
p := People{
|
||||
Phone: "1111",
|
||||
Sex: "male",
|
||||
age: 100,
|
||||
}
|
||||
pm, _ := StructToMap(p)
|
||||
var expected = map[string]any{"phone": "1111"}
|
||||
assert.Equal(expected, pm)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMapToSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMapToSlice")
|
||||
|
||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
@@ -209,6 +251,8 @@ func TestMapToSlice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestColorHexToRGB(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
colorHex := "#003366"
|
||||
r, g, b := ColorHexToRGB(colorHex)
|
||||
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
|
||||
@@ -219,6 +263,8 @@ func TestColorHexToRGB(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestColorRGBToHex(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := 0
|
||||
g := 51
|
||||
b := 102
|
||||
@@ -230,6 +276,8 @@ func TestColorRGBToHex(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToPointer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToPointer")
|
||||
result := ToPointer(123)
|
||||
|
||||
@@ -237,6 +285,8 @@ func TestToPointer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEncodeByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEncodeByte")
|
||||
|
||||
byteData, _ := EncodeByte("abc")
|
||||
@@ -246,6 +296,8 @@ func TestEncodeByte(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDecodeByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDecodeByte")
|
||||
|
||||
var obj string
|
||||
@@ -256,15 +308,17 @@ func TestDecodeByte(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeepClone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// assert := internal.NewAssert(t, "TestDeepClone")
|
||||
|
||||
type Struct struct {
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
unexported string
|
||||
Str string
|
||||
Int int
|
||||
Float float64
|
||||
Bool bool
|
||||
Nil interface{}
|
||||
// unexported string
|
||||
}
|
||||
|
||||
cases := []interface{}{
|
||||
@@ -283,12 +337,12 @@ func TestDeepClone(t *testing.T) {
|
||||
Nil: nil,
|
||||
// unexported: "can't be cloned",
|
||||
},
|
||||
[]interface{}{1, &Struct{Str: "test"}, Struct{Str: "test2"}},
|
||||
}
|
||||
|
||||
for i, item := range cases {
|
||||
cloned := DeepClone(item)
|
||||
|
||||
t.Log(cloned)
|
||||
if &cloned == &item {
|
||||
t.Fatalf("[TestDeepClone case #%d failed]: equal pointer", i)
|
||||
}
|
||||
@@ -300,51 +354,110 @@ func TestDeepClone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCopyProperties(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCopyProperties")
|
||||
|
||||
type Address struct {
|
||||
Country string
|
||||
ZipCode string
|
||||
type Disk struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type DiskVO struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type Indicator struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int `json:"cpu"`
|
||||
Disk []Disk `json:"disk"`
|
||||
Stop chan bool `json:"-"`
|
||||
}
|
||||
|
||||
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||
type IndicatorVO struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int64 `json:"cpu"`
|
||||
Disk []DiskVO `json:"disk"`
|
||||
}
|
||||
|
||||
employee1 := Employee{}
|
||||
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||
}}
|
||||
|
||||
err := CopyProperties(&employee1, &user)
|
||||
indicatorVO := IndicatorVO{}
|
||||
|
||||
err := CopyProperties(&indicatorVO, indicator)
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal("user001", employee1.Name)
|
||||
assert.Equal("Admin", employee1.Role)
|
||||
assert.Equal("CN", employee1.Addr.Country)
|
||||
assert.Equal(0, employee1.salary)
|
||||
|
||||
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||
|
||||
err = CopyProperties(&employee2, &user)
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal("user001", employee2.Name)
|
||||
assert.Equal("Admin", employee2.Role)
|
||||
assert.Equal("CN", employee2.Addr.Country)
|
||||
assert.Equal(500, employee2.salary)
|
||||
assert.Equal("001", indicatorVO.Id)
|
||||
assert.Equal("127.0.0.1", indicatorVO.Ip)
|
||||
assert.Equal(3, len(indicatorVO.Disk))
|
||||
}
|
||||
|
||||
func TestToInterface(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToInterface")
|
||||
|
||||
cases := []reflect.Value{
|
||||
reflect.ValueOf("abc"),
|
||||
reflect.ValueOf(int(0)), reflect.ValueOf(int8(1)), reflect.ValueOf(int16(-1)), reflect.ValueOf(int32(123)), reflect.ValueOf(int64(123)),
|
||||
reflect.ValueOf(uint(123)), reflect.ValueOf(uint8(123)), reflect.ValueOf(uint16(123)), reflect.ValueOf(uint32(123)), reflect.ValueOf(uint64(123)),
|
||||
reflect.ValueOf(float64(12.3)), reflect.ValueOf(float32(12.3)),
|
||||
reflect.ValueOf(true), reflect.ValueOf(false),
|
||||
}
|
||||
|
||||
expected := []interface{}{
|
||||
"abc",
|
||||
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,
|
||||
}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual, _ := ToInterface(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
|
||||
nilVal, ok := ToInterface(reflect.ValueOf(nil))
|
||||
assert.EqualValues(nil, nilVal)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestUtf8ToGbk(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestUtf8ToGbk")
|
||||
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, err := Utf8ToGbk(utf8Data)
|
||||
|
||||
assert.Equal(true, utf8.Valid(utf8Data))
|
||||
assert.Equal(true, validator.IsGBK(gbkData))
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestGbkToUtf8(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := internal.NewAssert(t, "TestGbkToUtf8")
|
||||
|
||||
gbkData, err := Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, err := GbkToUtf8(gbkData)
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal(true, utf8.Valid(utf8Data))
|
||||
assert.Equal("hello", string(utf8Data))
|
||||
}
|
||||
|
||||
108
cryptor/basic.go
108
cryptor/basic.go
@@ -40,6 +40,30 @@ func Md5String(s string) string {
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5StringWithBase64 return the md5 value of string with base64.
|
||||
// Play: https://go.dev/play/p/Lx4gH7Vdr5_y
|
||||
func Md5StringWithBase64(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5Byte return the md5 string of byte slice.
|
||||
// Play: https://go.dev/play/p/suraalH8lyC
|
||||
func Md5Byte(data []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(data)
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5ByteWithBase64 return the md5 string of byte slice with base64.
|
||||
// Play: https://go.dev/play/p/Tcb-Z7LN2ax
|
||||
func Md5ByteWithBase64(data []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(data)
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5File return the md5 value of file.
|
||||
func Md5File(filename string) (string, error) {
|
||||
if fileInfo, err := os.Stat(filename); err != nil {
|
||||
@@ -74,56 +98,112 @@ func Md5File(filename string) (string, error) {
|
||||
|
||||
// HmacMd5 return the hmac hash of string use md5.
|
||||
// Play: https://go.dev/play/p/uef0q1fz53I
|
||||
func HmacMd5(data, key string) string {
|
||||
func HmacMd5(str, key string) string {
|
||||
h := hmac.New(md5.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacMd5WithBase64 return the hmac hash of string use md5 with base64.
|
||||
// https://go.dev/play/p/UY0ng2AefFC
|
||||
func HmacMd5WithBase64(data, key string) string {
|
||||
h := hmac.New(md5.New, []byte(key))
|
||||
h.Write([]byte(data))
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha1 return the hmac hash of string use sha1.
|
||||
// Play: https://go.dev/play/p/1UI4oQ4WXKM
|
||||
func HmacSha1(data, key string) string {
|
||||
func HmacSha1(str, key string) string {
|
||||
h := hmac.New(sha1.New, []byte(key))
|
||||
h.Write([]byte(data))
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha1WithBase64 return the hmac hash of string use sha1 with base64.
|
||||
// Play: https://go.dev/play/p/47JmmGrnF7B
|
||||
func HmacSha1WithBase64(str, key string) string {
|
||||
h := hmac.New(sha1.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha256 return the hmac hash of string use sha256.
|
||||
// Play: https://go.dev/play/p/HhpwXxFhhC0
|
||||
func HmacSha256(data, key string) string {
|
||||
func HmacSha256(str, key string) string {
|
||||
h := hmac.New(sha256.New, []byte(key))
|
||||
h.Write([]byte(data))
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha256WithBase64 return the hmac hash of string use sha256 with base64.
|
||||
// Play: https://go.dev/play/p/EKbkUvPTLwO
|
||||
func HmacSha256WithBase64(str, key string) string {
|
||||
h := hmac.New(sha256.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha512 return the hmac hash of string use sha512.
|
||||
// Play: https://go.dev/play/p/59Od6m4A0Ud
|
||||
func HmacSha512(data, key string) string {
|
||||
func HmacSha512(str, key string) string {
|
||||
h := hmac.New(sha512.New, []byte(key))
|
||||
h.Write([]byte(data))
|
||||
h.Write([]byte(str))
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha512WithBase64 return the hmac hash of string use sha512 with base64.
|
||||
// Play: https://go.dev/play/p/c6dSe3E2ydU
|
||||
func HmacSha512WithBase64(str, key string) string {
|
||||
h := hmac.New(sha512.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
|
||||
// Play: https://go.dev/play/p/_m_uoD1deMT
|
||||
func Sha1(data string) string {
|
||||
func Sha1(str string) string {
|
||||
sha1 := sha1.New()
|
||||
sha1.Write([]byte(data))
|
||||
sha1.Write([]byte(str))
|
||||
return hex.EncodeToString(sha1.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha1WithBase64 return the sha1 value (SHA-1 hash algorithm) of base64 string.
|
||||
// Play: https://go.dev/play/p/fSyx-Gl2l2-
|
||||
func Sha1WithBase64(str string) string {
|
||||
sha1 := sha1.New()
|
||||
sha1.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha1.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha256 return the sha256 value (SHA256 hash algorithm) of string.
|
||||
// Play: https://go.dev/play/p/tU9tfBMIAr1
|
||||
func Sha256(data string) string {
|
||||
func Sha256(str string) string {
|
||||
sha256 := sha256.New()
|
||||
sha256.Write([]byte(data))
|
||||
sha256.Write([]byte(str))
|
||||
return hex.EncodeToString(sha256.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha256WithBase64 return the sha256 value (SHA256 hash algorithm) of base64 string.
|
||||
// Play: https://go.dev/play/p/85IXJHIal1k
|
||||
func Sha256WithBase64(str string) string {
|
||||
sha256 := sha256.New()
|
||||
sha256.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha256.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha512 return the sha512 value (SHA512 hash algorithm) of string.
|
||||
// Play: https://go.dev/play/p/3WsvLYZxsHa
|
||||
func Sha512(data string) string {
|
||||
func Sha512(str string) string {
|
||||
sha512 := sha512.New()
|
||||
sha512.Write([]byte(data))
|
||||
sha512.Write([]byte(str))
|
||||
return hex.EncodeToString(sha512.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha512WithBase64 return the sha512 value (SHA512 hash algorithm) of base64 string.
|
||||
// Play: https://go.dev/play/p/q_fY2rA-k5I
|
||||
func Sha512WithBase64(str string) string {
|
||||
sha512 := sha512.New()
|
||||
sha512.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha512.Sum([]byte("")))
|
||||
}
|
||||
|
||||
@@ -7,21 +7,51 @@ import (
|
||||
)
|
||||
|
||||
func TestBase64StdEncode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBase64StdEncode")
|
||||
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
|
||||
}
|
||||
|
||||
func TestBase64StdDecode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBase64StdDecode")
|
||||
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
|
||||
}
|
||||
|
||||
func TestMd5String(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMd5String")
|
||||
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
|
||||
}
|
||||
|
||||
func TestMd5StringWithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMd5StringWithBase64")
|
||||
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5StringWithBase64("hello"))
|
||||
}
|
||||
|
||||
func TestMd5Byte(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMd5Byte")
|
||||
data := []byte{'a'}
|
||||
assert.Equal("0cc175b9c0f1b6a831c399e269772661", Md5Byte(data))
|
||||
}
|
||||
|
||||
func TestMd5ByteWithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMd5ByteWithBase64")
|
||||
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5ByteWithBase64([]byte("hello")))
|
||||
}
|
||||
|
||||
func TestMd5File(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
fileMd5, err := Md5File("./basic.go")
|
||||
assert := internal.NewAssert(t, "TestMd5File")
|
||||
assert.IsNotNil(fileMd5)
|
||||
@@ -29,11 +59,22 @@ func TestMd5File(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHmacMd5(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacMd5")
|
||||
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
|
||||
}
|
||||
|
||||
func TestHmacMd5WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacMd5WithBase64")
|
||||
assert.Equal("6DQwbquJLYclJdSRinpjmg==", HmacMd5WithBase64("hello", "12345"))
|
||||
}
|
||||
|
||||
func TestHmacSha1(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
hmacSha1 := HmacSha1(s, key)
|
||||
@@ -43,17 +84,45 @@ func TestHmacSha1(t *testing.T) {
|
||||
assert.Equal(expected, hmacSha1)
|
||||
}
|
||||
|
||||
func TestHmacSha256(t *testing.T) {
|
||||
s := "hello world"
|
||||
func TestHmacSha1WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello"
|
||||
key := "12345"
|
||||
hmacSha256 := HmacSha256(s, key)
|
||||
hmacSha1 := HmacSha1WithBase64(s, key)
|
||||
expected := "XGqdsMzLkuNu0DI/0Jt/k23prOA="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha1")
|
||||
assert.Equal(expected, hmacSha1)
|
||||
}
|
||||
|
||||
func TestHmacSha256(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := "hello world"
|
||||
key := "12345"
|
||||
hmacSha256 := HmacSha256(str, key)
|
||||
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha256")
|
||||
assert.Equal(expected, hmacSha256)
|
||||
}
|
||||
|
||||
func TestHmacSha256WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
hms := HmacSha256WithBase64(str, key)
|
||||
expected := "MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha256WithBase64")
|
||||
assert.Equal(expected, hms)
|
||||
}
|
||||
|
||||
func TestHmacSha512(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
hmacSha512 := HmacSha512(s, key)
|
||||
@@ -63,7 +132,21 @@ func TestHmacSha512(t *testing.T) {
|
||||
assert.Equal(expected, hmacSha512)
|
||||
}
|
||||
|
||||
func TestHmacSha512WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
hms := HmacSha512WithBase64(str, key)
|
||||
expected := "3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A=="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha512WithBase64")
|
||||
assert.Equal(expected, hms)
|
||||
}
|
||||
|
||||
func TestSha1(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello world"
|
||||
sha1 := Sha1(s)
|
||||
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
||||
@@ -72,7 +155,19 @@ func TestSha1(t *testing.T) {
|
||||
assert.Equal(expected, sha1)
|
||||
}
|
||||
|
||||
func TestSha1WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := Sha1WithBase64("hello")
|
||||
expected := "qvTGHdzF6KLavt4PO0gs2a6pQ00="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha1WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
func TestSha256(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello world"
|
||||
sha256 := Sha256(s)
|
||||
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
||||
@@ -81,7 +176,19 @@ func TestSha256(t *testing.T) {
|
||||
assert.Equal(expected, sha256)
|
||||
}
|
||||
|
||||
func TestSha256WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := Sha256WithBase64("hello")
|
||||
expected := "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha256WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
func TestSha512(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := "hello world"
|
||||
sha512 := Sha512(s)
|
||||
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
||||
@@ -89,3 +196,13 @@ func TestSha512(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSha512")
|
||||
assert.Equal(expected, sha512)
|
||||
}
|
||||
|
||||
func TestSha512WithBase64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
str := Sha512WithBase64("hello")
|
||||
expected := "m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha512WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
@@ -322,89 +322,165 @@ func ExampleHmacMd5() {
|
||||
key := "12345"
|
||||
|
||||
hms := HmacMd5(str, key)
|
||||
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// e834306eab892d872525d4918a7a639a
|
||||
}
|
||||
|
||||
func ExampleHmacMd5WithBase64() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacMd5WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 6DQwbquJLYclJdSRinpjmg==
|
||||
}
|
||||
|
||||
func ExampleHmacSha1() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacSha1(str, key)
|
||||
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
||||
}
|
||||
|
||||
func ExampleHmacSha1WithBase64() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacSha1WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
|
||||
}
|
||||
|
||||
func ExampleHmacSha256() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacSha256(str, key)
|
||||
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
|
||||
}
|
||||
|
||||
func ExampleHmacSha256WithBase64() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacSha256WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
|
||||
}
|
||||
|
||||
func ExampleHmacSha512() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := HmacSha512(str, key)
|
||||
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
|
||||
}
|
||||
|
||||
func ExampleMd5String() {
|
||||
func ExampleHmacSha512WithBase64() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
md5Str := Md5String(str)
|
||||
hms := HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
}
|
||||
|
||||
func ExampleMd5String() {
|
||||
md5Str := Md5String("hello")
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
|
||||
func ExampleMd5StringWithBase64() {
|
||||
md5Str := Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
|
||||
func ExampleMd5Byte() {
|
||||
md5Str := Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
|
||||
func ExampleMd5ByteWithBase64() {
|
||||
md5Str := Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
|
||||
func ExampleSha1() {
|
||||
str := "hello"
|
||||
|
||||
result := Sha1(str)
|
||||
|
||||
result := Sha1("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
|
||||
}
|
||||
|
||||
func ExampleSha1WithBase64() {
|
||||
result := Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
|
||||
func ExampleSha256() {
|
||||
str := "hello"
|
||||
|
||||
result := Sha256(str)
|
||||
|
||||
result := Sha256("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
|
||||
}
|
||||
|
||||
func ExampleSha256WithBase64() {
|
||||
result := Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
|
||||
func ExampleSha512() {
|
||||
str := "hello"
|
||||
|
||||
result := Sha512(str)
|
||||
|
||||
result := Sha512("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
|
||||
}
|
||||
|
||||
func ExampleSha512WithBase64() {
|
||||
result := Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestAesEcbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
@@ -18,6 +20,8 @@ func TestAesEcbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAesCbcEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
@@ -29,6 +33,8 @@ func TestAesCbcEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAesCtrCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
@@ -40,6 +46,8 @@ func TestAesCtrCrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAesCfbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
@@ -51,6 +59,8 @@ func TestAesCfbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAesOfbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
@@ -62,6 +72,8 @@ func TestAesOfbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDesEcbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
@@ -73,6 +85,8 @@ func TestDesEcbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDesCbcEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
@@ -84,6 +98,8 @@ func TestDesCbcEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDesCtrCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
@@ -95,6 +111,8 @@ func TestDesCtrCrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDesCfbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
@@ -106,6 +124,8 @@ func TestDesCfbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDesOfbEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
@@ -117,6 +137,8 @@ func TestDesOfbEncrypt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRsaEncrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
@@ -1,12 +1,13 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure. hashmap structure.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var defaultMapCapacity uint64 = 1 << 10
|
||||
@@ -17,7 +18,7 @@ type mapNode struct {
|
||||
next *mapNode
|
||||
}
|
||||
|
||||
//HashMap implements a hash map
|
||||
// HashMap implements a hash map
|
||||
type HashMap struct {
|
||||
capacity uint64
|
||||
size uint64
|
||||
@@ -45,13 +46,24 @@ func NewHashMapWithCapacity(size, capacity uint64) *HashMap {
|
||||
func (hm *HashMap) Get(key any) any {
|
||||
hashValue := hm.hash(key)
|
||||
node := hm.table[hashValue]
|
||||
if node != nil {
|
||||
return node.value
|
||||
for node != nil {
|
||||
if reflect.DeepEqual(node.key, key) {
|
||||
return node.value
|
||||
}
|
||||
node = node.next
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOrDefault return the value of given key in hashmap, if not found return default value
|
||||
func (hm *HashMap) GetOrDefault(key any, defaultValue any) any {
|
||||
value := hm.Get(key)
|
||||
if value == nil {
|
||||
return defaultValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// Put new key value in hashmap
|
||||
func (hm *HashMap) Put(key any, value any) {
|
||||
hm.putValue(hm.hash(key), key, value)
|
||||
@@ -90,7 +102,13 @@ func (hm *HashMap) Delete(key any) {
|
||||
// Contains checks if given key is in hashmap or not
|
||||
func (hm *HashMap) Contains(key any) bool {
|
||||
node := hm.table[hm.hash(key)]
|
||||
return node != nil
|
||||
for node != nil {
|
||||
if reflect.DeepEqual(node.key, key) {
|
||||
return true
|
||||
}
|
||||
node = node.next
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Iterate executes iteratee funcation for every key and value pair of hashmap (random order)
|
||||
|
||||
@@ -32,6 +32,8 @@ func TestHashMap_Resize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHashMap_Delete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_Delete")
|
||||
|
||||
hm := NewHashMap()
|
||||
@@ -44,6 +46,8 @@ func TestHashMap_Delete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHashMap_Contains(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_Contains")
|
||||
|
||||
hm := NewHashMap()
|
||||
@@ -54,6 +58,8 @@ func TestHashMap_Contains(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHashMap_KeysValues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_KeysValues")
|
||||
|
||||
hm := NewHashMap()
|
||||
@@ -64,8 +70,38 @@ func TestHashMap_KeysValues(t *testing.T) {
|
||||
|
||||
keys := hm.Keys()
|
||||
values := hm.Values()
|
||||
t.Log(keys, values)
|
||||
|
||||
assert.Equal(3, len(values))
|
||||
assert.Equal(3, len(keys))
|
||||
}
|
||||
|
||||
func TestHashMap_Keys(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_Keys")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
keys := hm.Keys()
|
||||
|
||||
assert.Equal(3, len(keys))
|
||||
}
|
||||
|
||||
func TestHashMap_GetOrDefault(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestHashMap_GetOrDefault")
|
||||
|
||||
hm := NewHashMap()
|
||||
|
||||
hm.Put("a", 1)
|
||||
hm.Put("b", 2)
|
||||
hm.Put("c", 3)
|
||||
|
||||
assert.Equal(1, hm.GetOrDefault("a", 5))
|
||||
assert.Equal(5, hm.GetOrDefault("d", 5))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure. MaxHeap is a binary max heap.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -21,6 +21,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
||||
}
|
||||
|
||||
func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
|
||||
|
||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
||||
@@ -33,6 +35,8 @@ func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMaxHeap_Push(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Push")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
@@ -51,6 +55,8 @@ func TestMaxHeap_Push(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMaxHeap_Pop(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
@@ -70,6 +76,8 @@ func TestMaxHeap_Pop(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMaxHeap_Peek(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
|
||||
|
||||
heap := NewMaxHeap[int](&intComparator{})
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -22,6 +24,8 @@ func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_InsertAtTail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -37,12 +41,12 @@ func TestDoublyLink_InsertAtTail(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_InsertAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
|
||||
link.InsertAt(1, 1) //do nothing
|
||||
|
||||
link.InsertAt(0, 1)
|
||||
link.InsertAt(1, 2)
|
||||
link.InsertAt(2, 4)
|
||||
@@ -55,6 +59,8 @@ func TestDoublyLink_InsertAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -74,6 +80,8 @@ func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -93,6 +101,8 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_DeleteAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -116,6 +126,8 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_Reverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -130,6 +142,8 @@ func TestDoublyLink_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
@@ -149,10 +163,11 @@ func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDoublyLink_Clear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
|
||||
|
||||
link := NewDoublyLink[int]()
|
||||
|
||||
assert.Equal(true, link.IsEmpty())
|
||||
assert.Equal(0, link.Size())
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -22,6 +24,8 @@ func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_InsertAtTail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -37,6 +41,8 @@ func TestSinglyLink_InsertAtTail(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_InsertAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -57,6 +63,8 @@ func TestSinglyLink_InsertAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -78,10 +86,11 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
@@ -96,10 +105,11 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(2)
|
||||
@@ -114,10 +124,11 @@ func TestSinglyLink_DeleteValue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_DeleteAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
|
||||
link.InsertAtTail(1)
|
||||
link.InsertAtTail(2)
|
||||
link.InsertAtTail(3)
|
||||
@@ -136,6 +147,8 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_Reverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -149,6 +162,8 @@ func TestSinglyLink_Reverse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
|
||||
|
||||
link := NewSinglyLink[int]()
|
||||
@@ -163,6 +178,7 @@ func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
||||
link.InsertAtTail(5)
|
||||
link.InsertAtTail(6)
|
||||
link.InsertAtTail(7)
|
||||
|
||||
middle2 := link.GetMiddleNode()
|
||||
assert.Equal(4, middle2.Value)
|
||||
}
|
||||
|
||||
350
datastructure/list/copyonwritelist.go
Normal file
350
datastructure/list/copyonwritelist.go
Normal file
@@ -0,0 +1,350 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type CopyOnWriteList[T any] struct {
|
||||
data []T
|
||||
lock sync.Locker
|
||||
}
|
||||
|
||||
// NewCopyOnWriteList Creates an empty list.
|
||||
func NewCopyOnWriteList[T any](data []T) *CopyOnWriteList[T] {
|
||||
return &CopyOnWriteList[T]{data: data, lock: &sync.RWMutex{}}
|
||||
}
|
||||
|
||||
func (c *CopyOnWriteList[T]) getList() []T {
|
||||
return c.data
|
||||
}
|
||||
func (c *CopyOnWriteList[T]) setList(data []T) {
|
||||
c.data = data
|
||||
}
|
||||
|
||||
// Size returns the number of elements in this list.
|
||||
func (c *CopyOnWriteList[T]) Size() int {
|
||||
return len(c.getList())
|
||||
}
|
||||
|
||||
// IsEmpty returns true if this list contains no elements.
|
||||
func (c *CopyOnWriteList[T]) IsEmpty() bool {
|
||||
return c.Size() == 0
|
||||
}
|
||||
|
||||
// Contain returns true if this list contains the specified element.
|
||||
func (c *CopyOnWriteList[T]) Contain(e T) bool {
|
||||
list := c.getList()
|
||||
return indexOf(e, list, 0, c.Size()) >= 0
|
||||
}
|
||||
|
||||
// ValueOf returns the index of the first occurrence of the specified element in this list, or null if this list does not contain the element.
|
||||
func (c *CopyOnWriteList[T]) ValueOf(index int) (*T, bool) {
|
||||
list := c.getList()
|
||||
if index < 0 || index >= len(c.data) {
|
||||
return nil, false
|
||||
}
|
||||
return get(list, index), true
|
||||
}
|
||||
|
||||
// IndexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
||||
func (c *CopyOnWriteList[T]) IndexOf(e T) int {
|
||||
list := c.getList()
|
||||
return indexOf(e, list, 0, c.Size())
|
||||
}
|
||||
|
||||
// indexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
||||
// start the start position of the search (inclusive)
|
||||
// end the end position of the search (exclusive)
|
||||
func indexOf[T any](o T, e []T, start int, end int) int {
|
||||
if start >= end {
|
||||
return -1
|
||||
}
|
||||
for i := start; i < end; i++ {
|
||||
if reflect.DeepEqual(e[i], o) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// LastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
||||
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int {
|
||||
list := c.getList()
|
||||
return lastIndexOf(e, list, 0, c.Size())
|
||||
}
|
||||
|
||||
// lastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
|
||||
// start the start position of the search (inclusive)
|
||||
// end the end position of the search (exclusive)
|
||||
func lastIndexOf[T any](o T, e []T, start int, end int) int {
|
||||
if start >= end {
|
||||
return -1
|
||||
}
|
||||
for i := end - 1; i >= start; i-- {
|
||||
if reflect.DeepEqual(e[i], o) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// get returns the element at the specified position in this list.
|
||||
func get[T any](o []T, index int) *T {
|
||||
return &o[index]
|
||||
}
|
||||
|
||||
// Get returns the element at the specified position in this list.
|
||||
func (c *CopyOnWriteList[T]) Get(index int) *T {
|
||||
list := c.getList()
|
||||
if index < 0 || index >= len(list) {
|
||||
return nil
|
||||
}
|
||||
return get(list, index)
|
||||
}
|
||||
|
||||
func (c *CopyOnWriteList[T]) set(index int, e T) (oldValue *T) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
list := c.getList()
|
||||
oldValue = get(list, index)
|
||||
|
||||
if reflect.DeepEqual(oldValue, e) {
|
||||
c.setList(list)
|
||||
} else {
|
||||
newList := make([]T, len(list))
|
||||
copy(newList, list)
|
||||
newList[index] = e
|
||||
c.setList(newList)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Set replaces the element at the specified position in this list with the specified element.
|
||||
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool) {
|
||||
list := c.getList()
|
||||
if index < 0 || index >= len(list) {
|
||||
return oldValue, false
|
||||
}
|
||||
return c.set(index, e), true
|
||||
}
|
||||
|
||||
// Add appends the specified element to the end of this list.
|
||||
func (c *CopyOnWriteList[T]) Add(e T) bool {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
newList := make([]T, len(list)+1)
|
||||
copy(newList, list)
|
||||
newList[len(list)] = e
|
||||
c.setList(newList)
|
||||
return true
|
||||
}
|
||||
|
||||
// AddAll appends all the elements in the specified collection to the end of this list
|
||||
func (c *CopyOnWriteList[T]) AddAll(e []T) bool {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
newList := make([]T, len(list)+len(e))
|
||||
copy(newList, list)
|
||||
copy(newList[len(list):], e)
|
||||
c.setList(newList)
|
||||
return true
|
||||
}
|
||||
|
||||
// AddByIndex inserts the specified element at the specified position in this list.
|
||||
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
length := len(list)
|
||||
if index < 0 || index > length {
|
||||
return false
|
||||
}
|
||||
var newList []T
|
||||
var numMove = length - index
|
||||
if numMove == 0 {
|
||||
newList = make([]T, length+1)
|
||||
copy(newList, list)
|
||||
} else {
|
||||
newList = make([]T, length+1)
|
||||
copy(newList, list[:index])
|
||||
copy(newList[index+1:], list[index:])
|
||||
}
|
||||
newList[index] = e
|
||||
c.setList(newList)
|
||||
return true
|
||||
}
|
||||
|
||||
// delete removes the element at the specified position in this list.
|
||||
func (c *CopyOnWriteList[T]) delete(index int) *T {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
length := len(list)
|
||||
|
||||
oldValue := get(list, index)
|
||||
numMove := length - index - 1
|
||||
var newList []T
|
||||
if numMove == 0 {
|
||||
newList = make([]T, length-1)
|
||||
copy(newList, list[:index])
|
||||
} else {
|
||||
newList = make([]T, length-1)
|
||||
copy(newList, list[:index])
|
||||
copy(newList[index:], list[index+1:])
|
||||
}
|
||||
|
||||
c.setList(newList)
|
||||
return oldValue
|
||||
}
|
||||
|
||||
// DeleteAt removes the element at the specified position in this list.
|
||||
func (c *CopyOnWriteList[T]) DeleteAt(index int) (*T, bool) {
|
||||
list := c.getList()
|
||||
if index < 0 || index >= len(list) {
|
||||
return nil, false
|
||||
}
|
||||
return c.delete(index), true
|
||||
}
|
||||
|
||||
// DeleteBy removes the first occurrence of the specified element from this list, if it is present.
|
||||
func (c *CopyOnWriteList[T]) DeleteBy(o T) (*T, bool) {
|
||||
list := c.getList()
|
||||
index := indexOf(o, list, 0, len(list))
|
||||
if index == -1 {
|
||||
return nil, false
|
||||
}
|
||||
return c.delete(index), true
|
||||
}
|
||||
|
||||
// DeleteRange removes from this list all the elements whose index is between fromIndex, inclusive, and toIndex, exclusive.
|
||||
// left close and right open
|
||||
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
length := len(list)
|
||||
if start < 0 || end > length || start > end {
|
||||
return
|
||||
}
|
||||
var newList []T
|
||||
numMove := length - end
|
||||
if numMove == 0 {
|
||||
newList = make([]T, length-(end-start))
|
||||
copy(newList, list[:start])
|
||||
} else {
|
||||
newList = make([]T, length-(end-start))
|
||||
copy(newList, list[:start])
|
||||
copy(newList[start:], list[end:])
|
||||
}
|
||||
c.setList(newList)
|
||||
}
|
||||
|
||||
// DeleteIf removes all the elements of this collection that satisfy the given predicate.
|
||||
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
length := len(list)
|
||||
var newList []T
|
||||
for i := 0; i < length; i++ {
|
||||
if !f(list[i]) {
|
||||
newList = append(newList, list[i])
|
||||
}
|
||||
}
|
||||
c.setList(newList)
|
||||
}
|
||||
|
||||
// Equal returns true if the specified object is equal to this list.
|
||||
func (c *CopyOnWriteList[T]) Equal(other *[]T) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
if c.Size() != len(*other) {
|
||||
return false
|
||||
}
|
||||
list := c.getList()
|
||||
otherList := NewCopyOnWriteList(*other).getList()
|
||||
for i := 0; i < len(list); i++ {
|
||||
if !reflect.DeepEqual(list[i], otherList[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Clear removes all the elements from this list.
|
||||
func (c *CopyOnWriteList[T]) Clear() {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
list = make([]T, 0)
|
||||
c.setList(list)
|
||||
}
|
||||
|
||||
// Merge a tow list to one, change the list
|
||||
func (c *CopyOnWriteList[T]) Merge(other []T) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
list := c.getList()
|
||||
list = append(list, other...)
|
||||
c.setList(list)
|
||||
}
|
||||
|
||||
// ForEach performs the given action for each element of the Iterable until all elements have been processed
|
||||
// or the action throws an exception.
|
||||
func (c *CopyOnWriteList[T]) ForEach(f func(T)) {
|
||||
list := c.getList()
|
||||
for i := 0; i < len(list); i++ {
|
||||
f(list[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Sort sorts this list according to the order induced by the specified Comparator.
|
||||
func (c *CopyOnWriteList[T]) Sort(compare func(o1 T, o2 T) bool) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
list := c.getList()
|
||||
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return compare(list[i], list[j])
|
||||
})
|
||||
|
||||
c.setList(list)
|
||||
}
|
||||
|
||||
func (c *CopyOnWriteList[T]) SubList(start int, end int) (newList []T) {
|
||||
lock := c.lock
|
||||
lock.Lock()
|
||||
list := c.getList()
|
||||
length := len(list)
|
||||
defer lock.Unlock()
|
||||
if start < 0 || end > length || start > end {
|
||||
return []T{}
|
||||
}
|
||||
newList = make([]T, end-start)
|
||||
copy(newList, list[start:end])
|
||||
c.setList(newList)
|
||||
return
|
||||
}
|
||||
235
datastructure/list/copyonwritelist_test.go
Normal file
235
datastructure/list/copyonwritelist_test.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCopyOnWriteList_ValueOf(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
|
||||
of, ok := list.ValueOf(3)
|
||||
assert.Equal(4, *of)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
_, ok = list.ValueOf(6)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Contain(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Contains")
|
||||
assert.Equal(true, list.Contain(3))
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_IsEmpty(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_IsEmpty")
|
||||
assert.Equal(true, list.IsEmpty())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Size(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_size")
|
||||
assert.Equal(5, list.Size())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_GetList(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_GetList")
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Get(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Get")
|
||||
i := list.Get(2)
|
||||
assert.Equal(3, *i)
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Set(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Set")
|
||||
list.Set(2, 6)
|
||||
assert.Equal(6, list.getList()[2])
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.Set(0, 6)
|
||||
assert.Equal(6, list.getList()[0])
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.Set(0, 1)
|
||||
assert.Equal(1, list.getList()[0])
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Add(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Add")
|
||||
list.Add(6)
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_AddAll(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_AddAll")
|
||||
list.AddAll([]int{6, 7, 8})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_AddByIndex(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_AddByIndex")
|
||||
list.AddByIndex(2, 6)
|
||||
assert.Equal([]int{1, 2, 6, 3, 4, 5}, list.getList())
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.AddByIndex(0, 6)
|
||||
assert.Equal([]int{6, 1, 2, 3, 4, 5}, list.getList())
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.AddByIndex(5, 6)
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_DeleteAt2(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByIndex")
|
||||
list.DeleteAt(2)
|
||||
assert.Equal([]int{1, 2, 4, 5}, list.getList())
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.DeleteAt(4)
|
||||
assert.Equal([]int{1, 2, 3, 4}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_RemoveByValue(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByValue")
|
||||
list.DeleteBy(3)
|
||||
assert.Equal([]int{1, 2, 4, 5}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_DeleteRange(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveRange")
|
||||
list.DeleteRange(1, 3)
|
||||
assert.Equal([]int{1, 4, 5}, list.getList())
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
|
||||
list.DeleteRange(0, 5)
|
||||
assert.Equal([]int{}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_LastIndexOf(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_LastIndexOf")
|
||||
assert.Equal(5, list.LastIndexOf(3))
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_DeleteAt(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteAt")
|
||||
list.DeleteAt(2)
|
||||
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_DeleteBy(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteBy")
|
||||
list.DeleteBy(3)
|
||||
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_DeleteIf(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteIf")
|
||||
|
||||
list.DeleteIf(func(i int) bool {
|
||||
return i%2 == 0
|
||||
})
|
||||
|
||||
assert.Equal([]int{1, 3, 5, 3}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Equal(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Equal")
|
||||
|
||||
assert.Equal(true, list.Equal(&[]int{1, 2, 3, 4, 5, 3, 6}))
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_ForEach(t *testing.T) {
|
||||
testList := make([]int, 0)
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_ForEach")
|
||||
|
||||
list.ForEach(func(i int) {
|
||||
testList = append(testList, i)
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6}, testList)
|
||||
|
||||
list.ForEach(func(i int) {
|
||||
list.Add(i)
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6, 1, 2, 3, 4, 5, 3, 6}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Clear(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Clear")
|
||||
|
||||
list.Clear()
|
||||
assert.Equal([]int{}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Merge(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Merge")
|
||||
|
||||
list.Merge([]int{2, 4, 6, 8, 10})
|
||||
assert.Equal([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}, list.getList())
|
||||
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_Sort(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_Sort")
|
||||
|
||||
list.Sort(func(i, j int) bool {
|
||||
return i < j
|
||||
})
|
||||
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, list.getList())
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_IndexOf(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
|
||||
|
||||
assert.Equal(0, list.IndexOf(1))
|
||||
assert.Equal(9, list.IndexOf(10))
|
||||
assert.Equal(-1, list.IndexOf(11))
|
||||
}
|
||||
|
||||
func TestCopyOnWriteList_SubList(t *testing.T) {
|
||||
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
|
||||
assert := internal.NewAssert(t, "CopyOnWriteList_SubList")
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
subList := list.SubList(1, 3)
|
||||
assert.Equal([]int{3, 5}, subList)
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
subList = list.SubList(1, 1)
|
||||
assert.Equal([]int{}, subList)
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
assert.Equal(10, list.Size())
|
||||
subList = list.SubList(1, 10)
|
||||
assert.Equal([]int{3, 5, 7, 9, 2, 4, 6, 8, 10}, subList)
|
||||
|
||||
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
|
||||
subList = list.SubList(11, 1)
|
||||
assert.Equal([]int{}, subList)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure contains some data structure. list is a linear table, implemented with slice.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
@@ -271,7 +271,7 @@ func (l *List[T]) Reverse() {
|
||||
}
|
||||
}
|
||||
|
||||
// Unique remove duplicate items in list.
|
||||
// Unique delete duplicate items in list.
|
||||
func (l *List[T]) Unique() {
|
||||
data := l.data
|
||||
size := len(data)
|
||||
@@ -294,7 +294,7 @@ func (l *List[T]) Unique() {
|
||||
l.data = uniqueData
|
||||
}
|
||||
|
||||
// Union creates a new list contain all element in list l and other, remove duplicate element.
|
||||
// Union creates a new list contain all element in list l and other, delete duplicate element.
|
||||
func (l *List[T]) Union(other *List[T]) *List[T] {
|
||||
result := NewList([]T{})
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestListData(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestListData")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -14,6 +16,8 @@ func TestListData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestValueOf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestValueOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -26,6 +30,8 @@ func TestValueOf(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIndexOf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -37,6 +43,8 @@ func TestIndexOf(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIndexOfFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -48,6 +56,8 @@ func TestIndexOfFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLastIndexOf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
||||
@@ -65,6 +75,8 @@ func TestLastIndexOf(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLastIndexOfFunc(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIndexOf")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
||||
@@ -82,6 +94,8 @@ func TestLastIndexOfFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestContain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestContain")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -90,6 +104,8 @@ func TestContain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestPush")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -99,6 +115,8 @@ func TestPush(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertAtFirst(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestInsertAtFirst")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -108,6 +126,8 @@ func TestInsertAtFirst(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertAtLast(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestInsertAtLast")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -117,6 +137,8 @@ func TestInsertAtLast(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInsertAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestInsertAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -135,6 +157,8 @@ func TestInsertAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPopFirst(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestPopFirst")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -150,6 +174,8 @@ func TestPopFirst(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPopLast(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestPopLast")
|
||||
|
||||
list := NewList([]int{1, 2, 3})
|
||||
@@ -165,6 +191,8 @@ func TestPopLast(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDeleteAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -183,6 +211,8 @@ func TestDeleteAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateAt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestUpdateAt")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -201,6 +231,8 @@ func TestUpdateAt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEqual")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -212,6 +244,8 @@ func TestEqual(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIsEmpty")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -222,6 +256,8 @@ func TestIsEmpty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsClear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIsClear")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -232,6 +268,8 @@ func TestIsClear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestClone")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -241,6 +279,8 @@ func TestClone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestMerge")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -252,6 +292,8 @@ func TestMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSize")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -262,6 +304,8 @@ func TestSize(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCap")
|
||||
|
||||
data := make([]int, 0, 100)
|
||||
@@ -274,6 +318,8 @@ func TestCap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSwap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSwap")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -285,6 +331,8 @@ func TestSwap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestReverse")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -296,6 +344,8 @@ func TestReverse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnique(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestUnique")
|
||||
|
||||
list := NewList([]int{1, 2, 2, 3, 4})
|
||||
@@ -307,6 +357,8 @@ func TestUnique(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestUnion")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -318,6 +370,8 @@ func TestUnion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIntersection(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIntersection")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3, 4})
|
||||
@@ -329,6 +383,8 @@ func TestIntersection(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDifference")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3})
|
||||
@@ -340,6 +396,8 @@ func TestDifference(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSymmetricDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSymmetricDifference")
|
||||
|
||||
list1 := NewList([]int{1, 2, 3})
|
||||
@@ -351,6 +409,8 @@ func TestSymmetricDifference(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSubSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSubSlice")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4, 5, 8})
|
||||
@@ -367,6 +427,8 @@ func BenchmarkSubSlice(b *testing.B) {
|
||||
}
|
||||
|
||||
func TestDeleteIf(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDeleteIf")
|
||||
|
||||
list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
|
||||
@@ -381,10 +443,11 @@ func TestDeleteIf(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestForEach(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
rs := make([]int, 0)
|
||||
list.ForEach(func(i int) {
|
||||
rs = append(rs, i)
|
||||
@@ -394,6 +457,8 @@ func TestForEach(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRetainAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestRetainAll")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -414,6 +479,8 @@ func TestRetainAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDeleteAll")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
@@ -433,10 +500,11 @@ func TestDeleteAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIterator(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIterator")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
iterator := list.Iterator()
|
||||
|
||||
rs := make([]int, 0)
|
||||
@@ -449,14 +517,15 @@ func TestIterator(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListToMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "ListToMap")
|
||||
|
||||
list := NewList([]int{1, 2, 3, 4})
|
||||
|
||||
result := ListToMap(list, func(n int) (int, bool) {
|
||||
return n, n > 1
|
||||
})
|
||||
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
|
||||
|
||||
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
|
||||
assert.Equal(expected, result)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure.
|
||||
package datastructure
|
||||
|
||||
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestArrayQueue_Enqueue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
|
||||
|
||||
queue := NewArrayQueue[int](5)
|
||||
@@ -14,15 +16,16 @@ func TestArrayQueue_Enqueue(t *testing.T) {
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
expected := []int{1, 2, 3}
|
||||
data := queue.Data()
|
||||
size := queue.Size()
|
||||
|
||||
assert.Equal(expected, data)
|
||||
assert.Equal([]int{1, 2, 3}, data)
|
||||
assert.Equal(3, size)
|
||||
}
|
||||
|
||||
func TestArrayQueue_Dequeue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
|
||||
|
||||
queue := NewArrayQueue[int](4)
|
||||
@@ -38,6 +41,8 @@ func TestArrayQueue_Dequeue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayQueue_Front(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Front")
|
||||
|
||||
queue := NewArrayQueue[int](4)
|
||||
@@ -52,6 +57,8 @@ func TestArrayQueue_Front(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayQueue_Back(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Back")
|
||||
|
||||
queue := NewArrayQueue[int](4)
|
||||
@@ -66,6 +73,8 @@ func TestArrayQueue_Back(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayQueue_Contain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
|
||||
|
||||
queue := NewArrayQueue[int](4)
|
||||
@@ -78,6 +87,8 @@ func TestArrayQueue_Contain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayQueue_Clear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
|
||||
|
||||
queue := NewArrayQueue[int](4)
|
||||
@@ -95,6 +106,8 @@ func TestArrayQueue_Clear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestArrayQueue_IsFull(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
|
||||
|
||||
queue := NewArrayQueue[int](3)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestCircularQueue_Enqueue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
@@ -34,6 +36,8 @@ func TestCircularQueue_Enqueue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Dequeue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||
|
||||
queue := NewCircularQueue[int](4)
|
||||
@@ -60,6 +64,8 @@ func TestCircularQueue_Dequeue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Front(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||
|
||||
queue := NewCircularQueue[int](6)
|
||||
@@ -80,6 +86,8 @@ func TestCircularQueue_Front(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Back(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
||||
|
||||
queue := NewCircularQueue[int](3)
|
||||
@@ -103,6 +111,8 @@ func TestCircularQueue_Back(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Contain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||
|
||||
queue := NewCircularQueue[int](2)
|
||||
@@ -114,6 +124,8 @@ func TestCircularQueue_Contain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Clear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
|
||||
|
||||
queue := NewCircularQueue[int](3)
|
||||
@@ -132,6 +144,8 @@ func TestCircularQueue_Clear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCircularQueue_Data(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||
|
||||
queue := NewCircularQueue[int](3)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestLinkedQueue_Enqueue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
@@ -19,6 +21,8 @@ func TestLinkedQueue_Enqueue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Dequeue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
@@ -35,6 +39,8 @@ func TestLinkedQueue_Dequeue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Front(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
@@ -51,6 +57,8 @@ func TestLinkedQueue_Front(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Back(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
@@ -67,6 +75,8 @@ func TestLinkedQueue_Back(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Clear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
@@ -82,10 +92,11 @@ func TestLinkedQueue_Clear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLinkedQueue_Contain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
|
||||
|
||||
queue := NewLinkedQueue[int]()
|
||||
|
||||
queue.Enqueue(1)
|
||||
queue.Enqueue(2)
|
||||
queue.Enqueue(3)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -20,6 +20,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
||||
return 0
|
||||
}
|
||||
func TestPriorityQueue_Enqueue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
|
||||
|
||||
comparator := &intComparator{}
|
||||
@@ -45,6 +47,8 @@ func TestPriorityQueue_Enqueue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPriorityQueue_Dequeue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
|
||||
|
||||
comparator := &intComparator{}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
|
||||
package datastructure
|
||||
|
||||
// Set is a data container, like slice, but element of set is not duplicate
|
||||
// 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
|
||||
@@ -171,3 +175,25 @@ func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
// EachWithBreak iterates over elements of a set and invokes function for each element,
|
||||
// when iteratee return false, will break the for each loop.
|
||||
func (s Set[T]) EachWithBreak(iteratee func(item T) bool) {
|
||||
for _, v := range s.Values() {
|
||||
if !iteratee(v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
return v, false
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestSet_NewSetFromSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
|
||||
|
||||
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
|
||||
@@ -20,17 +22,21 @@ func TestSet_NewSetFromSlice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Add(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Add")
|
||||
|
||||
set := NewSet[int]()
|
||||
set.Add(1, 2, 3)
|
||||
|
||||
expected := NewSet(1, 2, 3)
|
||||
cmpSet := NewSet(1, 2, 3)
|
||||
|
||||
assert.Equal(true, set.Equal(expected))
|
||||
assert.Equal(true, set.Equal(cmpSet))
|
||||
}
|
||||
|
||||
func TestSet_AddIfNotExist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
|
||||
|
||||
set := NewSet[int]()
|
||||
@@ -42,6 +48,8 @@ func TestSet_AddIfNotExist(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
|
||||
|
||||
set := NewSet[int]()
|
||||
@@ -63,6 +71,8 @@ func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Contain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||
|
||||
set := NewSet[int]()
|
||||
@@ -73,6 +83,8 @@ func TestSet_Contain(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_ContainAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
@@ -84,6 +96,8 @@ func TestSet_ContainAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Clone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Clone")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
@@ -94,18 +108,20 @@ func TestSet_Clone(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Delete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Delete")
|
||||
|
||||
set := NewSet[int]()
|
||||
set.Add(1, 2, 3)
|
||||
set.Delete(3)
|
||||
|
||||
expected := NewSet(1, 2)
|
||||
|
||||
assert.Equal(true, set.Equal(expected))
|
||||
assert.Equal(true, set.Equal(NewSet(1, 2)))
|
||||
}
|
||||
|
||||
func TestSet_Equal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Equal")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
@@ -117,6 +133,8 @@ func TestSet_Equal(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Iterate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Iterate")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
@@ -129,6 +147,8 @@ func TestSet_Iterate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_IsEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
||||
|
||||
set := NewSet[int]()
|
||||
@@ -136,6 +156,8 @@ func TestSet_IsEmpty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Size(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Size")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
@@ -143,6 +165,8 @@ func TestSet_Size(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Values(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Values")
|
||||
|
||||
set := NewSet(1, 2, 3)
|
||||
@@ -152,28 +176,33 @@ func TestSet_Values(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Union(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Union")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
expected := NewSet(1, 2, 3, 4, 5)
|
||||
|
||||
unionSet := set1.Union(set2)
|
||||
|
||||
assert.Equal(expected, unionSet)
|
||||
assert.Equal(NewSet(1, 2, 3, 4, 5), unionSet)
|
||||
}
|
||||
|
||||
func TestSet_Intersection(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Intersection")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
expected := NewSet(2, 3)
|
||||
intersectionSet := set1.Intersection(set2)
|
||||
|
||||
assert.Equal(expected, intersectionSet)
|
||||
assert.Equal(NewSet(2, 3), intersectionSet)
|
||||
}
|
||||
|
||||
func TestSet_SymmetricDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
@@ -183,6 +212,8 @@ func TestSet_SymmetricDifference(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSet_Minus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestSet_Minus")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
@@ -192,3 +223,40 @@ func TestSet_Minus(t *testing.T) {
|
||||
assert.Equal(NewSet(1), set1.Minus(set2))
|
||||
assert.Equal(NewSet(4, 5), set2.Minus(set3))
|
||||
}
|
||||
|
||||
func TestEachWithBreak(t *testing.T) {
|
||||
// s := NewSet(1, 2, 3, 4, 5)
|
||||
|
||||
// var sum int
|
||||
|
||||
// s.EachWithBreak(func(n int) bool {
|
||||
// if n > 3 {
|
||||
// return false
|
||||
// }
|
||||
// sum += n
|
||||
// return true
|
||||
// })
|
||||
|
||||
// assert := internal.NewAssert(t, "TestEachWithBreak")
|
||||
// assert.Equal(6, sum)
|
||||
}
|
||||
|
||||
// func TestPop(t *testing.T) {
|
||||
// assert := internal.NewAssert(t, "TestPop")
|
||||
|
||||
// s := NewSet[int]()
|
||||
|
||||
// val, ok := s.Pop()
|
||||
// assert.Equal(0, val)
|
||||
// assert.Equal(false, ok)
|
||||
|
||||
// s.Add(1)
|
||||
// s.Add(2)
|
||||
// s.Add(3)
|
||||
|
||||
// // s = NewSet(1, 2, 3, 4, 5)
|
||||
|
||||
// val, ok = s.Pop()
|
||||
// assert.Equal(3, val)
|
||||
// assert.Equal(true, ok)
|
||||
// }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
|
||||
package datastructure
|
||||
|
||||
import "errors"
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestArrayStack_Push(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Push")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
@@ -14,15 +16,16 @@ func TestArrayStack_Push(t *testing.T) {
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := stack.Data()
|
||||
length := stack.Size()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
assert.Equal([]int{3, 2, 1}, values)
|
||||
assert.Equal(3, length)
|
||||
}
|
||||
|
||||
func TestArrayStack_Pop(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Pop")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
@@ -37,11 +40,12 @@ func TestArrayStack_Pop(t *testing.T) {
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
assert.Equal([]int{2, 1}, stack.Data())
|
||||
}
|
||||
|
||||
func TestArrayStack_Peak(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Peak")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
@@ -56,11 +60,12 @@ func TestArrayStack_Peak(t *testing.T) {
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
assert.Equal([]int{3, 2, 1}, stack.Data())
|
||||
}
|
||||
|
||||
func TestArrayStack_Clear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestArrayStack_Clear")
|
||||
|
||||
stack := NewArrayStack[int]()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestLinkedStack_Push(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Push")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
@@ -14,15 +16,16 @@ func TestLinkedStack_Push(t *testing.T) {
|
||||
stack.Push(2)
|
||||
stack.Push(3)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
values := stack.Data()
|
||||
size := stack.Size()
|
||||
|
||||
assert.Equal(expected, values)
|
||||
assert.Equal([]int{3, 2, 1}, values)
|
||||
assert.Equal(3, size)
|
||||
}
|
||||
|
||||
func TestLinkedStack_Pop(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
@@ -37,12 +40,13 @@ func TestLinkedStack_Pop(t *testing.T) {
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{2, 1}
|
||||
stack.Print()
|
||||
assert.Equal(expected, stack.Data())
|
||||
assert.Equal([]int{2, 1}, stack.Data())
|
||||
}
|
||||
|
||||
func TestLinkedStack_Peak(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
@@ -57,11 +61,12 @@ func TestLinkedStack_Peak(t *testing.T) {
|
||||
assert.IsNil(err)
|
||||
assert.Equal(3, *topItem)
|
||||
|
||||
expected := []int{3, 2, 1}
|
||||
assert.Equal(expected, stack.Data())
|
||||
assert.Equal([]int{3, 2, 1}, stack.Data())
|
||||
}
|
||||
|
||||
func TestLinkedStack_Empty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
|
||||
|
||||
stack := NewLinkedStack[int]()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. BSTree is binary search tree.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -20,16 +20,9 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func TestBSTree_Insert(t *testing.T) {
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
|
||||
bstree.Insert(7)
|
||||
bstree.Insert(5)
|
||||
bstree.Insert(2)
|
||||
bstree.Insert(4)
|
||||
}
|
||||
|
||||
func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -40,11 +33,12 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.PreOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_PostOrderTraverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -55,11 +49,12 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.PostOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_InOrderTraverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -70,11 +65,12 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.InOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -85,11 +81,12 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||
bstree.Insert(4)
|
||||
|
||||
acturl := bstree.LevelOrderTraverse()
|
||||
t.Log(acturl)
|
||||
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
||||
}
|
||||
|
||||
func TestBSTree_Delete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_Delete")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -102,18 +99,18 @@ func TestBSTree_Delete(t *testing.T) {
|
||||
bstree.Delete(4)
|
||||
|
||||
acturl1 := bstree.InOrderTraverse()
|
||||
t.Log(acturl1)
|
||||
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
||||
|
||||
//todo
|
||||
// bstree.DeletetNode(6, comparator)
|
||||
// bstree.Print()
|
||||
// acturl2 := bstree.InOrderTraverse()
|
||||
// t.Log(acturl2)
|
||||
// assert.Equal([]int{2, 5, 7}, acturl2)
|
||||
}
|
||||
|
||||
func TestBSTree_Depth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_Depth")
|
||||
|
||||
bstree := NewBSTree(6, &intComparator{})
|
||||
@@ -127,6 +124,8 @@ func TestBSTree_Depth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBSTree_IsSubTree(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
|
||||
|
||||
superTree := NewBSTree(8, &intComparator{})
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
)
|
||||
|
||||
func TestToUnix(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToUnix")
|
||||
|
||||
tm1 := NewUnixNow()
|
||||
@@ -17,34 +19,37 @@ func TestToUnix(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestToFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToFormat")
|
||||
|
||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||
t.Log("TestToFormat", tm.ToFormat())
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToFormat -> ", tm.ToFormat())
|
||||
}
|
||||
|
||||
func TestToFormatForTpl(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToFormatForTpl")
|
||||
|
||||
_, err := NewFormat("2022/03/18 17:04:05")
|
||||
assert.IsNotNil(err)
|
||||
|
||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||
t.Log("TestToFormatForTpl", tm.ToFormatForTpl("2006/01/02 15:04:05"))
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
|
||||
}
|
||||
|
||||
func TestToIso8601(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToIso8601")
|
||||
|
||||
_, err := NewISO8601("2022-03-18 17:04:05")
|
||||
assert.IsNotNil(err)
|
||||
|
||||
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
t.Log("TestToIso8601", tm.ToIso8601())
|
||||
assert.IsNil(err)
|
||||
|
||||
t.Log("ToIso8601 -> ", tm.ToIso8601())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// Package datetime implements some functions to format date and time.
|
||||
// Note:
|
||||
// 1. `format` param in FormatTimeToStr function should be as flow:
|
||||
// 1. `format` param in FormatTimeToStr function should be as flow (case no sensitive):
|
||||
// "yyyy-mm-dd hh:mm:ss"
|
||||
// "yyyy-mm-dd hh:mm"
|
||||
// "yyyy-mm-dd hh"
|
||||
@@ -18,14 +18,19 @@
|
||||
// "yyyy/mm"
|
||||
// "mm/dd"
|
||||
// "dd/mm/yy hh:mm:ss"
|
||||
// "yyyymmdd"
|
||||
// "mmddyy"
|
||||
// "yyyy"
|
||||
// "yy"
|
||||
// "mm"
|
||||
// "hh:mm:ss"
|
||||
// "hh:mm"
|
||||
// "mm:ss"
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -35,7 +40,7 @@ func init() {
|
||||
timeFormat = map[string]string{
|
||||
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
|
||||
"yyyy-mm-dd hh:mm": "2006-01-02 15:04",
|
||||
"yyyy-mm-dd hh": "2006-01-02 15:04",
|
||||
"yyyy-mm-dd hh": "2006-01-02 15",
|
||||
"yyyy-mm-dd": "2006-01-02",
|
||||
"yyyy-mm": "2006-01",
|
||||
"mm-dd": "01-02",
|
||||
@@ -47,9 +52,13 @@ func init() {
|
||||
"yyyy/mm": "2006/01",
|
||||
"mm/dd": "01/02",
|
||||
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
|
||||
"yyyymmdd": "20060102",
|
||||
"mmddyy": "010206",
|
||||
"yyyy": "2006",
|
||||
"yy": "06",
|
||||
"mm": "01",
|
||||
"hh:mm:ss": "15:04:05",
|
||||
"hh:mm": "15:04",
|
||||
"mm:ss": "04:05",
|
||||
}
|
||||
}
|
||||
@@ -72,6 +81,12 @@ func AddDay(t time.Time, day int64) time.Time {
|
||||
return t.Add(24 * time.Hour * time.Duration(day))
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// GetNowDate return format yyyy-mm-dd of current date.
|
||||
// Play: https://go.dev/play/p/PvfkPpcpBBf
|
||||
func GetNowDate() string {
|
||||
@@ -90,6 +105,18 @@ func GetNowDateTime() string {
|
||||
return time.Now().Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// GetTodayStartTime return the start time of today, format: yyyy-mm-dd 00:00:00.
|
||||
// Play: https://go.dev/play/p/84siyYF7t99
|
||||
func GetTodayStartTime() string {
|
||||
return time.Now().Format("2006-01-02") + " 00:00:00"
|
||||
}
|
||||
|
||||
// GetTodayEndTime return the end time of today, format: yyyy-mm-dd 23:59:59.
|
||||
// Play: https://go.dev/play/p/jjrLnfoqgn3
|
||||
func GetTodayEndTime() string {
|
||||
return time.Now().Format("2006-01-02") + " 23:59:59"
|
||||
}
|
||||
|
||||
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
|
||||
// Play: https://go.dev/play/p/QmL2oIaGE3q
|
||||
func GetZeroHourTimestamp() int64 {
|
||||
@@ -106,19 +133,40 @@ func GetNightTimestamp() int64 {
|
||||
|
||||
// FormatTimeToStr convert time to string.
|
||||
// Play: https://go.dev/play/p/_Ia7M8H_OvE
|
||||
func FormatTimeToStr(t time.Time, format string) string {
|
||||
return t.Format(timeFormat[format])
|
||||
func FormatTimeToStr(t time.Time, format string, timezone ...string) string {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return t.In(loc).Format(tf)
|
||||
}
|
||||
return t.Format(tf)
|
||||
}
|
||||
|
||||
// FormatStrToTime convert string to time.
|
||||
// Play: https://go.dev/play/p/1h9FwdU8ql4
|
||||
func FormatStrToTime(str, format string) (time.Time, error) {
|
||||
v, ok := timeFormat[format]
|
||||
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error) {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return time.Time{}, fmt.Errorf("format %s not found", format)
|
||||
return time.Time{}, fmt.Errorf("format %s not support", format)
|
||||
}
|
||||
|
||||
return time.Parse(v, str)
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return time.ParseInLocation(tf, str, loc)
|
||||
}
|
||||
|
||||
return time.Parse(tf, str)
|
||||
}
|
||||
|
||||
// BeginOfMinute return beginning minute time of day.
|
||||
@@ -218,3 +266,118 @@ func BeginOfYear(t time.Time) time.Time {
|
||||
func EndOfYear(t time.Time) time.Time {
|
||||
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
||||
}
|
||||
|
||||
// IsLeapYear check if param year is leap year or not.
|
||||
// Play: https://go.dev/play/p/xS1eS2ejGew
|
||||
func IsLeapYear(year int) bool {
|
||||
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
||||
}
|
||||
|
||||
// BetweenSeconds returns the number of seconds between two times.
|
||||
// Play: https://go.dev/play/p/n3YDRyfyXJu
|
||||
func BetweenSeconds(t1 time.Time, t2 time.Time) int64 {
|
||||
index := t2.Unix() - t1.Unix()
|
||||
return index
|
||||
}
|
||||
|
||||
// DayOfYear returns which day of the year the parameter date `t` is.
|
||||
// Play: https://go.dev/play/p/0hjqhTwFNlH
|
||||
func DayOfYear(t time.Time) int {
|
||||
y, m, d := t.Date()
|
||||
firstDay := time.Date(y, 1, 1, 0, 0, 0, 0, t.Location())
|
||||
nowDate := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
|
||||
return int(nowDate.Sub(firstDay).Hours() / 24)
|
||||
}
|
||||
|
||||
// IsWeekend checks if passed time is weekend or not.
|
||||
// Play: https://go.dev/play/p/cupRM5aZOIY
|
||||
// Deprecated Use '== Weekday' instead
|
||||
func IsWeekend(t time.Time) bool {
|
||||
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
|
||||
}
|
||||
|
||||
// NowDateOrTime return current datetime with specific format and timezone.
|
||||
// Play: https://go.dev/play/p/EZ-begEjtT0
|
||||
func NowDateOrTime(format string, timezone ...string) string {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return time.Now().In(loc).Format(tf)
|
||||
}
|
||||
|
||||
return time.Now().Format(tf)
|
||||
}
|
||||
|
||||
// Timestamp return current second timestamp.
|
||||
// Play: https://go.dev/play/p/iU5b7Vvjx6x
|
||||
func Timestamp(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// TimestampMilli return current mill second timestamp.
|
||||
// Play: https://go.dev/play/p/4gvEusOTu1T
|
||||
func TimestampMilli(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// TimestampMicro return current micro second timestamp.
|
||||
// Play: https://go.dev/play/p/2maANglKHQE
|
||||
func TimestampMicro(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Microsecond)
|
||||
}
|
||||
|
||||
// TimestampNano return current nano second timestamp.
|
||||
// Play: https://go.dev/play/p/A9Oq_COrcCF
|
||||
func TimestampNano(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return t.UnixNano()
|
||||
}
|
||||
|
||||
@@ -57,6 +57,23 @@ func ExampleAddMinute() {
|
||||
// -2m0s
|
||||
}
|
||||
|
||||
func ExampleAddYear() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
|
||||
func ExampleGetNowDate() {
|
||||
result := GetNowDate()
|
||||
|
||||
@@ -114,15 +131,18 @@ func ExampleFormatTimeToStr() {
|
||||
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
|
||||
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
|
||||
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
|
||||
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 2021-01-02 16:04:08
|
||||
// 2021-01-02
|
||||
// 02-01-21 16:04:08
|
||||
// 2021-01-02 16
|
||||
}
|
||||
|
||||
func ExampleFormatStrToTime() {
|
||||
@@ -321,3 +341,70 @@ func ExampleNewUnixNow() {
|
||||
// // Output:
|
||||
// // 2006-01-02T23:04:05+08:00
|
||||
// }
|
||||
|
||||
func ExampleIsLeapYear() {
|
||||
result1 := IsLeapYear(2000)
|
||||
result2 := IsLeapYear(2001)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleBetweenSeconds() {
|
||||
today := time.Now()
|
||||
tomorrow := AddDay(today, 1)
|
||||
yesterday := AddDay(today, -1)
|
||||
|
||||
result1 := BetweenSeconds(today, tomorrow)
|
||||
result2 := BetweenSeconds(today, yesterday)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 86400
|
||||
// -86400
|
||||
}
|
||||
|
||||
func ExampleDayOfYear() {
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := DayOfYear(date1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := DayOfYear(date2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := DayOfYear(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 31
|
||||
// 1
|
||||
// 0
|
||||
}
|
||||
|
||||
func ExampleIsWeekend() {
|
||||
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||
|
||||
result1 := IsWeekend(date1)
|
||||
result2 := IsWeekend(date2)
|
||||
result3 := IsWeekend(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
@@ -7,7 +7,40 @@ import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
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())
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func TestAddDay(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
now := time.Now()
|
||||
@@ -21,6 +54,8 @@ func TestAddDay(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddHour(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddHour")
|
||||
|
||||
now := time.Now()
|
||||
@@ -34,6 +69,8 @@ func TestAddHour(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddMinute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddMinute")
|
||||
|
||||
now := time.Now()
|
||||
@@ -47,44 +84,77 @@ func TestAddMinute(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetNowDate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGetNowDate")
|
||||
expected := time.Now().Format("2006-01-02")
|
||||
assert.Equal(expected, GetNowDate())
|
||||
}
|
||||
|
||||
func TestGetNowTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGetNowTime")
|
||||
expected := time.Now().Format("15:04:05")
|
||||
assert.Equal(expected, GetNowTime())
|
||||
}
|
||||
|
||||
func TestGetNowDateTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGetNowDateTime")
|
||||
expected := time.Now().Format("2006-01-02 15:04:05")
|
||||
assert.Equal(expected, GetNowDateTime())
|
||||
}
|
||||
|
||||
func TestGetTodayStartTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGetTodayStartTime")
|
||||
expected := time.Now().Format("2006-01-02") + " 00:00:00"
|
||||
assert.Equal(expected, GetTodayStartTime())
|
||||
}
|
||||
|
||||
func TestGetTodayEndTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestGetTodayEndTime")
|
||||
expected := time.Now().Format("2006-01-02") + " 23:59:59"
|
||||
assert.Equal(expected, GetTodayEndTime())
|
||||
}
|
||||
|
||||
func TestFormatTimeToStr(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestFormatTimeToStr")
|
||||
|
||||
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
|
||||
cases := []string{
|
||||
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
|
||||
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
|
||||
"hh:mm:ss", "yyyy/mm"}
|
||||
"hh:mm:ss", "yyyy/mm",
|
||||
"yyyy-mm-dd hh",
|
||||
}
|
||||
|
||||
expected := []string{
|
||||
"2021-01-02 16:04:08", "2021-01-02",
|
||||
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
||||
"16:04:08", "2021/01"}
|
||||
"16:04:08", "2021/01",
|
||||
"2021-01-02 16",
|
||||
}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual := FormatTimeToStr(datetime, cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
|
||||
ds := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss", "EST")
|
||||
t.Log(ds)
|
||||
}
|
||||
|
||||
func TestFormatStrToTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestFormatStrToTime")
|
||||
|
||||
formats := []string{
|
||||
@@ -96,22 +166,28 @@ func TestFormatStrToTime(t *testing.T) {
|
||||
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
|
||||
"yyyy/mm"}
|
||||
|
||||
datetimeStr := []string{
|
||||
expected := []string{
|
||||
"2021-01-02 16:04:08", "2021-01-02",
|
||||
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
||||
"2021/01"}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual, err := FormatStrToTime(datetimeStr[i], cases[i])
|
||||
actual, err := FormatStrToTime(expected[i], cases[i])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
||||
expected, _ := time.Parse(formats[i], expected[i])
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
estTime, err := FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss", "EST")
|
||||
t.Log(estTime)
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestBeginOfMinute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfMinute")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local)
|
||||
@@ -122,6 +198,8 @@ func TestBeginOfMinute(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfMinute(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfMinute")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local)
|
||||
@@ -132,6 +210,8 @@ func TestEndOfMinute(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeginOfHour(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfHour")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local)
|
||||
@@ -142,6 +222,8 @@ func TestBeginOfHour(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfHour(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfHour")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local)
|
||||
@@ -152,6 +234,8 @@ func TestEndOfHour(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeginOfDay(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfDay")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local)
|
||||
@@ -162,6 +246,8 @@ func TestBeginOfDay(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfDay(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfDay")
|
||||
|
||||
expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local)
|
||||
@@ -172,6 +258,8 @@ func TestEndOfDay(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeginOfWeek(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfWeek")
|
||||
|
||||
expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local)
|
||||
@@ -182,6 +270,8 @@ func TestBeginOfWeek(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfWeek(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfWeek")
|
||||
|
||||
expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local)
|
||||
@@ -192,6 +282,8 @@ func TestEndOfWeek(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeginOfMonth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfMonth")
|
||||
|
||||
expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local)
|
||||
@@ -202,6 +294,8 @@ func TestBeginOfMonth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfMonth(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfMonth")
|
||||
|
||||
expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local)
|
||||
@@ -212,6 +306,8 @@ func TestEndOfMonth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBeginOfYear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestBeginOfYear")
|
||||
|
||||
expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local)
|
||||
@@ -222,6 +318,8 @@ func TestBeginOfYear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEndOfYear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfYear")
|
||||
|
||||
expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local)
|
||||
@@ -230,3 +328,85 @@ func TestEndOfYear(t *testing.T) {
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestIsLeapYear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestEndOfYear")
|
||||
|
||||
result1 := IsLeapYear(2000)
|
||||
result2 := IsLeapYear(2001)
|
||||
|
||||
assert.Equal(true, result1)
|
||||
assert.Equal(false, result2)
|
||||
}
|
||||
|
||||
func TestDayOfYear(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestDayOfYear")
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := DayOfYear(date1)
|
||||
assert.Equal(31, result1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := DayOfYear(date2)
|
||||
assert.Equal(1, result2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := DayOfYear(date3)
|
||||
assert.Equal(0, result3)
|
||||
}
|
||||
|
||||
func TestIsWeekend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIsWeekend")
|
||||
|
||||
date := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||
result := IsWeekend(date)
|
||||
assert.Equal(true, result)
|
||||
|
||||
date1 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||
result1 := IsWeekend(date1)
|
||||
assert.Equal(true, result1)
|
||||
|
||||
date2 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||
result2 := IsWeekend(date2)
|
||||
assert.Equal(false, result2)
|
||||
}
|
||||
|
||||
func TestNowDateOrTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
formats := []string{
|
||||
"yyyy-mm-dd hh:mm:ss",
|
||||
"yyyy-mm-dd",
|
||||
"dd-mm-yy hh:mm:ss",
|
||||
"yyyy/mm/dd hh:mm:ss",
|
||||
"hh:mm:ss",
|
||||
"yyyy/mm",
|
||||
"yyyy-mm-dd hh",
|
||||
}
|
||||
|
||||
for i := 0; i < len(formats); i++ {
|
||||
result := NowDateOrTime(formats[i], "UTC")
|
||||
t.Log(result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimestamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ts1 := Timestamp()
|
||||
t.Log(ts1)
|
||||
|
||||
ts2 := TimestampMilli()
|
||||
t.Log(ts2)
|
||||
|
||||
ts3 := TimestampMicro()
|
||||
t.Log(ts3)
|
||||
|
||||
ts4 := TimestampNano()
|
||||
t.Log(ts4)
|
||||
}
|
||||
|
||||
89
docs/.vitepress/common.ts
Normal file
89
docs/.vitepress/common.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { defineConfig, HeadConfig } from 'vitepress'
|
||||
|
||||
export const META_IMAGE = '/lancet_logo.png'
|
||||
export const isProduction = process.env.NETLIFY && process.env.CONTEXT === 'production'
|
||||
|
||||
if (process.env.NETLIFY) {
|
||||
console.log('Netlify build', process.env.CONTEXT)
|
||||
}
|
||||
|
||||
const productionHead: HeadConfig[] = [
|
||||
[
|
||||
'script',
|
||||
{
|
||||
src: 'https://unpkg.com/thesemetrics@latest',
|
||||
async: '',
|
||||
type: 'text/javascript',
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
const rControl = /[\u0000-\u001f]/g
|
||||
const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g
|
||||
const rCombining = /[\u0300-\u036F]/g
|
||||
|
||||
/**
|
||||
* Default slugification function
|
||||
*/
|
||||
export const slugify = (str: string): string =>
|
||||
str
|
||||
.normalize('NFKD')
|
||||
// Remove accents
|
||||
.replace(rCombining, '')
|
||||
// Remove control characters
|
||||
.replace(rControl, '')
|
||||
// Replace special characters
|
||||
.replace(rSpecial, '-')
|
||||
// ensure it doesn't start with a number
|
||||
.replace(/^(\d)/, '_$1')
|
||||
|
||||
export const commonConfig = defineConfig({
|
||||
title: 'Lancet',
|
||||
appearance: true,
|
||||
|
||||
markdown: {
|
||||
theme: {
|
||||
dark: 'dracula-soft',
|
||||
light: 'vitesse-light',
|
||||
},
|
||||
|
||||
attrs: {
|
||||
leftDelimiter: '%{',
|
||||
rightDelimiter: '}%',
|
||||
},
|
||||
|
||||
anchor: {
|
||||
slugify,
|
||||
},
|
||||
},
|
||||
|
||||
head: [
|
||||
// ['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
|
||||
['link', { rel: 'icon', type: 'image/png', href: '/lancet_logo_mini.png' }],
|
||||
['meta', { name: 'theme-color', content: '#5f67ee' }],
|
||||
['meta', { name: 'og:type', content: 'website' }],
|
||||
['meta', { name: 'og:locale', content: 'zh' }],
|
||||
|
||||
...(isProduction ? productionHead : []),
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
logo: { src: '/lancet_logo_mini.png', width: 24, height: 24 },
|
||||
outline: [2, 3],
|
||||
|
||||
search: {
|
||||
provider: 'local',
|
||||
},
|
||||
socialLinks: [
|
||||
{
|
||||
icon: 'github',
|
||||
link: 'https://github.com/duke-git/lancet',
|
||||
},
|
||||
],
|
||||
|
||||
footer: {
|
||||
copyright: 'Copyright © 2023-present Duke Du',
|
||||
message: '备案号: 京ICP备2023022770号',
|
||||
},
|
||||
},
|
||||
})
|
||||
14
docs/.vitepress/config.mts
Normal file
14
docs/.vitepress/config.mts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
import { commonConfig } from './common'
|
||||
import { zhConfig } from './zh'
|
||||
import { enConfig } from './en'
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
...commonConfig,
|
||||
|
||||
locales: {
|
||||
root: { label: '简体中文', lang: 'zh-CN', link: '/', ...zhConfig },
|
||||
en: { label: 'English', lang: 'en-US', link: '/en/', ...enConfig },
|
||||
},
|
||||
})
|
||||
139
docs/.vitepress/en.ts
Normal file
139
docs/.vitepress/en.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
|
||||
|
||||
export const META_URL = 'https://www.golancet.cn/en/'
|
||||
export const META_TITLE = 'Lancet'
|
||||
export const META_DESCRIPTION = 'A powerful util function library of Go'
|
||||
|
||||
export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
|
||||
description: META_DESCRIPTION,
|
||||
|
||||
head: [
|
||||
['meta', { property: 'og:url', content: META_URL }],
|
||||
['meta', { property: 'og:description', content: META_DESCRIPTION }],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/duke-git/lancet/edit/v2/docs/:path',
|
||||
text: 'Suggest changes to this page',
|
||||
},
|
||||
nav: [
|
||||
{
|
||||
text: 'Home',
|
||||
link: '/en/',
|
||||
activeMatch: '^/en/',
|
||||
},
|
||||
{
|
||||
text: 'Guide',
|
||||
link: '/en/guide/introduction',
|
||||
activeMatch: '^/en/guide/',
|
||||
},
|
||||
{ text: 'API', link: '/en/api/overview', activeMatch: '^/en/api/' },
|
||||
{
|
||||
text: 'Links',
|
||||
items: [
|
||||
{
|
||||
text: 'Discussion',
|
||||
link: 'https://github.com/duke-git/lancet/discussions',
|
||||
},
|
||||
{
|
||||
text: 'Changelog',
|
||||
link: 'https://github.com/duke-git/lancet/releases',
|
||||
},
|
||||
{
|
||||
text: 'Contribution',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.en-US.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
'/en/guide/': [
|
||||
{
|
||||
text: 'Introduction',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{
|
||||
text: 'What is Lancet?',
|
||||
link: '/en/guide/introduction',
|
||||
},
|
||||
{
|
||||
text: 'Getting started',
|
||||
link: '/en/guide/getting_started',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Contribute Code',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{
|
||||
text: 'Contribution guide',
|
||||
link: '/en/guide/contribution_guide',
|
||||
},
|
||||
{
|
||||
text: 'Contributors',
|
||||
link: '/en/guide/contributors',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'API Reference',
|
||||
link: '/en/api/overview'
|
||||
},
|
||||
],
|
||||
'/en/api/': [
|
||||
{
|
||||
text: 'Overview',
|
||||
items: [{ text: 'API overview', link: '/en/api/overview' }],
|
||||
},
|
||||
{
|
||||
text: 'Packages',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'algorithm', link: '/en/api/packages/algorithm' },
|
||||
{ text: 'compare', link: '/en/api/packages/compare' },
|
||||
{ text: 'concurrency', link: '/en/api/packages/concurrency' },
|
||||
{ text: 'condition', link: '/en/api/packages/condition' },
|
||||
{ text: 'convertor', link: '/en/api/packages/convertor' },
|
||||
{ text: 'cryptor', link: '/en/api/packages/cryptor' },
|
||||
{
|
||||
text: 'datastructure',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'list', link: '/en/api/packages/datastructure/list' },
|
||||
{ text: 'safelist', link: '/en/api/packages/datastructure/copyonwritelist' },
|
||||
{ text: 'link', link: '/en/api/packages/datastructure/link' },
|
||||
{ text: 'stack', link: '/en/api/packages/datastructure/stack' },
|
||||
{ text: 'queue', link: '/en/api/packages/datastructure/queue' },
|
||||
{ text: 'heap', link: '/en/api/packages/datastructure/heap' },
|
||||
{ text: 'tree', link: '/en/api/packages/datastructure/tree' },
|
||||
{ text: 'set', link: '/en/api/packages/datastructure/set' },
|
||||
{ text: 'hashmap', link: '/en/api/packages/datastructure/hashmap' },
|
||||
],
|
||||
},
|
||||
{ text: 'datetime', link: '/en/api/packages/datetime' },
|
||||
{ text: 'fileutil', link: '/en/api/packages/fileutil' },
|
||||
{ text: 'formatter', link: '/en/api/packages/formatter' },
|
||||
{ text: 'function', link: '/en/api/packages/function' },
|
||||
{ text: 'mathutil', link: '/en/api/packages/mathutil' },
|
||||
{ text: 'maputil', link: '/en/api/packages/maputil' },
|
||||
{ text: 'netutil', link: '/en/api/packages/netutil' },
|
||||
{ text: 'pointer', link: '/en/api/packages/pointer' },
|
||||
{ text: 'random', link: '/en/api/packages/random' },
|
||||
{ text: 'retry', link: '/en/api/packages/retry' },
|
||||
{ text: 'slice', link: '/en/api/packages/slice' },
|
||||
{ text: 'stream', link: '/en/api/packages/stream' },
|
||||
{ text: 'struct', link: '/en/api/packages/struct' },
|
||||
{ text: 'strutil', link: '/en/api/packages/strutil' },
|
||||
{ text: 'system', link: '/en/api/packages/system' },
|
||||
{ text: 'tuple', link: '/en/api/packages/tuple' },
|
||||
{ text: 'validator', link: '/en/api/packages/validator' },
|
||||
{ text: 'xerror', link: '/en/api/packages/xerror' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
152
docs/.vitepress/zh.ts
Normal file
152
docs/.vitepress/zh.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
|
||||
|
||||
export const META_URL = 'https://www.golancet.cn'
|
||||
export const META_TITLE = 'Lancet'
|
||||
export const META_DESCRIPTION = '一个强大的Go语言工具函数库'
|
||||
|
||||
export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
|
||||
description: META_DESCRIPTION,
|
||||
|
||||
head: [
|
||||
['meta', { property: 'og:url', content: META_URL }],
|
||||
['meta', { property: 'og:description', content: META_DESCRIPTION }],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
editLink: {
|
||||
pattern: 'https://github.com/duke-git/lancet/edit/v2/docs/:path',
|
||||
text: '对本页提出修改建议',
|
||||
},
|
||||
outline: {
|
||||
label: '本页内容',
|
||||
},
|
||||
|
||||
docFooter: {
|
||||
prev: '上一页',
|
||||
next: '下一页',
|
||||
},
|
||||
|
||||
nav: [
|
||||
{
|
||||
text: '首页',
|
||||
link: '/',
|
||||
activeMatch: '^/',
|
||||
},
|
||||
{
|
||||
text: '指南',
|
||||
link: '/guide/introduction',
|
||||
activeMatch: '^/guide/',
|
||||
},
|
||||
{ text: 'API', link: '/api/overview', activeMatch: '^/api/' },
|
||||
{
|
||||
text: '相关链接',
|
||||
items: [
|
||||
{
|
||||
text: '论坛',
|
||||
link: 'https://github.com/duke-git/lancet/discussions',
|
||||
},
|
||||
{
|
||||
text: '更新日志',
|
||||
link: 'https://github.com/duke-git/lancet/releases',
|
||||
},
|
||||
{
|
||||
text: '参与贡献',
|
||||
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.zh-CN.md',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
{
|
||||
text: '介绍',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{
|
||||
text: 'Lancet是什么?',
|
||||
link: '/guide/introduction',
|
||||
},
|
||||
{
|
||||
text: '开始',
|
||||
link: '/guide/getting_started',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '贡献代码',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{
|
||||
text: '贡献指南',
|
||||
link: '/guide/contribution_guide',
|
||||
},
|
||||
{
|
||||
text: '贡献者',
|
||||
link: '/guide/contributors',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'API手册',
|
||||
link: '/api/overview'
|
||||
},
|
||||
],
|
||||
|
||||
'/api/': [
|
||||
{
|
||||
text: '概览',
|
||||
items: [{ text: 'API概述', link: '/api/overview' }],
|
||||
},
|
||||
{
|
||||
text: 'API文档',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '算法', link: '/api/packages/algorithm' },
|
||||
{ text: '比较器', link: '/api/packages/compare' },
|
||||
{ text: '并发处理', link: '/api/packages/concurrency' },
|
||||
{ text: '条件判断', link: '/api/packages/condition' },
|
||||
{ text: '类型转换', link: '/api/packages/convertor' },
|
||||
{ text: '加密&解密', link: '/api/packages/cryptor' },
|
||||
{
|
||||
text: '数据结构',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: '线性表', link: '/api/packages/datastructure/list' },
|
||||
{
|
||||
text: '线性表(线程安全)',
|
||||
link: '/api/packages/datastructure/copyonwritelist',
|
||||
},
|
||||
{ text: '链表', link: '/api/packages/datastructure/link' },
|
||||
{ text: '栈', link: '/api/packages/datastructure/stack' },
|
||||
{ text: '队列', link: '/api/packages/datastructure/queue' },
|
||||
{ text: '堆', link: '/api/packages/datastructure/heap' },
|
||||
{ text: '树', link: '/api/packages/datastructure/tree' },
|
||||
{ text: '集合', link: '/api/packages/datastructure/set' },
|
||||
{ text: 'HashMap', link: '/api/packages/datastructure/hashmap' },
|
||||
],
|
||||
},
|
||||
{ text: '日期&时间', link: '/api/packages/datetime' },
|
||||
{ text: '文件', link: '/api/packages/fileutil' },
|
||||
{ text: '格式化工具', link: '/api/packages/formatter' },
|
||||
{ text: '函数', link: '/api/packages/function' },
|
||||
{ text: '数学工具', link: '/api/packages/mathutil' },
|
||||
{ text: 'Map', link: '/api/packages/maputil' },
|
||||
{ text: '网络', link: '/api/packages/netutil' },
|
||||
{ text: '指针', link: '/api/packages/pointer' },
|
||||
{ text: '随机数', link: '/api/packages/random' },
|
||||
{ text: '重试', link: '/api/packages/retry' },
|
||||
{ text: '切片', link: '/api/packages/slice' },
|
||||
{ text: '流', link: '/api/packages/stream' },
|
||||
{ text: '结构体', link: '/api/packages/struct' },
|
||||
{ text: '字符串', link: '/api/packages/strutil' },
|
||||
{ text: '系统', link: '/api/packages/system' },
|
||||
{ text: '元组', link: '/api/packages/tuple' },
|
||||
{ text: '验证器', link: '/api/packages/validator' },
|
||||
{ text: '错误处理', link: '/api/packages/xerror' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
69
docs/api/overview.md
Normal file
69
docs/api/overview.md
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# API概述
|
||||
|
||||
<b>lancet(柳叶刀)是一个功能强大、全面、高效、可复用的go语言工具函数库。包含25个包,超过600个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。</b>
|
||||
|
||||
|
||||
<style>
|
||||
.package-title {
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.package-container {
|
||||
font-size: 16px;
|
||||
border: 1px dashed;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.package-cell {
|
||||
height: 40px;
|
||||
width: 140px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
background: #ecefff;
|
||||
border: 1px solid;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<p class="package-title">lancet功能模块</p>
|
||||
<div class="package-container">
|
||||
<div class="package-cell">algorithm</div>
|
||||
<div class="package-cell">compare</div>
|
||||
<div class="package-cell">concurrency</div>
|
||||
<div class="package-cell">condition</div>
|
||||
<div class="package-cell">convertor</div>
|
||||
<div class="package-cell">cryptor</div>
|
||||
<div class="package-cell">datastructure</div>
|
||||
<div class="package-cell">datetime</div>
|
||||
<div class="package-cell">fileutil</div>
|
||||
<div class="package-cell">formatter</div>
|
||||
<div class="package-cell">function</div>
|
||||
<div class="package-cell">iterator</div>
|
||||
<div class="package-cell">maputil</div>
|
||||
<div class="package-cell">mathutil</div>
|
||||
<div class="package-cell">netutil</div>
|
||||
<div class="package-cell">pointer</div>
|
||||
<div class="package-cell">random</div>
|
||||
<div class="package-cell">retry</div>
|
||||
<div class="package-cell">slice</div>
|
||||
<div class="package-cell">stream</div>
|
||||
<div class="package-cell">structs</div>
|
||||
<div class="package-cell">strutil</div>
|
||||
<div class="package-cell">system</div>
|
||||
<div class="package-cell">tuple</div>
|
||||
<div class="package-cell">validator</div>
|
||||
<div class="package-cell">xerror</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,7 +51,7 @@ import (
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -99,7 +99,7 @@ func main() {
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -162,7 +162,7 @@ func main() {
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -210,7 +210,7 @@ func main() {
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -258,7 +258,7 @@ func main() {
|
||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -306,7 +306,7 @@ func main() {
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -354,7 +354,7 @@ func main() {
|
||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -402,7 +402,7 @@ func main() {
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -451,7 +451,7 @@ func main() {
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -502,7 +502,7 @@ func main() {
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -553,7 +553,7 @@ func main() {
|
||||
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -596,7 +596,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
|
||||
func (l *LRUCache[K, V]) Len() int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/-EZjgOURufP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
375
docs/api/packages/compare.md
Normal file
375
docs/api/packages/compare.md
Normal file
@@ -0,0 +1,375 @@
|
||||
# Compare
|
||||
|
||||
compare包提供几个轻量级的类型比较函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/compare/compare.go](https://github.com/duke-git/lancet/blob/main/compare/compare.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Equal](#Equal)
|
||||
- [EqualValue](#EqualValue)
|
||||
- [LessThan](#LessThan)
|
||||
- [GreaterThan](#GreaterThan)
|
||||
- [LessOrEqual](#LessOrEqual)
|
||||
- [GreaterOrEqual](#GreaterOrEqual)
|
||||
- [InDelta](#InDelta)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
|
||||
<p>检查两个值是否相等(检查类型和值)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Equal(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wmVxR-to4lz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.Equal(1, 1)
|
||||
result2 := compare.Equal("1", "1")
|
||||
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||
|
||||
result5 := compare.Equal(1, "1")
|
||||
result6 := compare.Equal(1, int64(1))
|
||||
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EqualValue">EqualValue</span>
|
||||
|
||||
<p>检查两个值是否相等(只检查值)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EqualValue(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fxnna_LLD9u)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.EqualValue(1, 1)
|
||||
result2 := compare.EqualValue(int(1), int64(1))
|
||||
result3 := compare.EqualValue(1, "1")
|
||||
result4 := compare.EqualValue(1, "2")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LessThan">LessThan</span>
|
||||
|
||||
<p>验证参数`left`的值是否小于参数`right`的值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LessThan(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cYh7FQQj0ne)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.LessThan(1, 2)
|
||||
result2 := compare.LessThan(1.1, 2.2)
|
||||
result3 := compare.LessThan("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.LessThan(time1, time2)
|
||||
|
||||
result5 := compare.LessThan(2, 1)
|
||||
result6 := compare.LessThan(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GreaterThan">GreaterThan</span>
|
||||
|
||||
<p>验证参数`left`的值是否大于参数`right`的值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GreaterThan(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9-NYDFZmIMp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.GreaterThan(2, 1)
|
||||
result2 := compare.GreaterThan(2.2, 1.1)
|
||||
result3 := compare.GreaterThan("b", "a")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.GreaterThan(time2, time1)
|
||||
|
||||
result5 := compare.GreaterThan(1, 2)
|
||||
result6 := compare.GreaterThan(int64(2), 1)
|
||||
result7 := compare.GreaterThan("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LessOrEqual">LessOrEqual</span>
|
||||
|
||||
<p>验证参数`left`的值是否小于或等于参数`right`的值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LessOrEqual(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/e4T_scwoQzp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.LessOrEqual(1, 1)
|
||||
result2 := compare.LessOrEqual(1.1, 2.2)
|
||||
result3 := compare.LessOrEqual("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.LessOrEqual(time1, time2)
|
||||
|
||||
result5 := compare.LessOrEqual(2, 1)
|
||||
result6 := compare.LessOrEqual(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GreaterOrEqual">GreaterOrEqual</span>
|
||||
|
||||
<p>验证参数`left`的值是否大于或参数`right`的值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GreaterOrEqual(left, right any) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vx8mP0U8DFk)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.GreaterOrEqual(1, 1)
|
||||
result2 := compare.GreaterOrEqual(2.2, 1.1)
|
||||
result3 := compare.GreaterOrEqual("b", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.GreaterOrEqual(time2, time1)
|
||||
|
||||
result5 := compare.GreaterOrEqual(1, 2)
|
||||
result6 := compare.GreaterOrEqual(int64(2), 1)
|
||||
result7 := compare.GreaterOrEqual("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="InDelta">InDelta</span>
|
||||
|
||||
<p>检查增量内两个值是否相等。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool
|
||||
```
|
||||
|
||||
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TuDdcNtMkjo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := InDelta(1, 1, 0)
|
||||
result2 := InDelta(1, 2, 0)
|
||||
|
||||
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
|
||||
result4 := InDelta(2.0/3.0, 0.0, 0.001)
|
||||
|
||||
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
|
||||
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -1,15 +1,17 @@
|
||||
# Concurrency
|
||||
并发包包含一些支持并发编程的功能。例如:goroutine, channel, async等。
|
||||
|
||||
并发包包含一些支持并发编程的功能。例如:goroutine, channel 等。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/concurrency"
|
||||
@@ -19,25 +21,28 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
### Channel
|
||||
- [NewChannel](#NewChannel)
|
||||
- [Bridge](#Bridge)
|
||||
- [FanIn](#FanIn)
|
||||
- [Generate](#Generate)
|
||||
- [Or](#Or)
|
||||
- [OrDone](#OrDone)
|
||||
- [Repeat](#Repeat)
|
||||
- [RepeatFn](#RepeatFn)
|
||||
- [Take](#Take)
|
||||
- [Tee](#Tee)
|
||||
|
||||
- [NewChannel](#NewChannel)
|
||||
- [Bridge](#Bridge)
|
||||
- [FanIn](#FanIn)
|
||||
- [Generate](#Generate)
|
||||
- [Or](#Or)
|
||||
- [OrDone](#OrDone)
|
||||
- [Repeat](#Repeat)
|
||||
- [RepeatFn](#RepeatFn)
|
||||
- [Take](#Take)
|
||||
- [Tee](#Tee)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
### Channel
|
||||
|
||||
### <span id="NewChannel">NewChannel</span>
|
||||
|
||||
<p>返回一个Channel指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -46,7 +51,8 @@ import (
|
||||
type Channel[T any] struct
|
||||
func NewChannel[T any]() *Channel[T]
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -70,7 +76,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -122,7 +129,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2VYFMexEvTm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -161,7 +169,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -199,7 +208,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -238,7 +248,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4J1zAWttP85)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -279,7 +290,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Wqz9rwioPww)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -322,7 +334,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -360,7 +373,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -406,7 +420,8 @@ func main() {
|
||||
```go
|
||||
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3TQPKnCirrP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -436,4 +451,4 @@ func main() {
|
||||
// 1
|
||||
// 1
|
||||
}
|
||||
```
|
||||
```
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
## 目录
|
||||
|
||||
- [Bool](#Bool)
|
||||
- [And](#And)
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
## 文档
|
||||
|
||||
### <span id="Bool">Bool</span>
|
||||
<p>返回传入参数的bool值.<br/>
|
||||
@@ -45,7 +45,7 @@ slices和map的length大于0时,返回true,否则返回false<br/>
|
||||
```go
|
||||
func Bool[T any](value T) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -109,7 +109,7 @@ func main() {
|
||||
```go
|
||||
func And[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -135,7 +135,7 @@ func main() {
|
||||
```go
|
||||
func Or[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -161,7 +161,7 @@ func main() {
|
||||
```go
|
||||
func Xor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -187,7 +187,7 @@ func main() {
|
||||
```go
|
||||
func Nor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -213,7 +213,7 @@ func main() {
|
||||
```go
|
||||
func Xnor[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -239,7 +239,7 @@ func main() {
|
||||
```go
|
||||
func Nand[T, U any](a T, b U) bool
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -265,7 +265,7 @@ func main() {
|
||||
```go
|
||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||
```
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -40,7 +40,9 @@ import (
|
||||
- [DecodeByte](#DecodeByte)
|
||||
- [DeepClone](#DeepClone)
|
||||
- [CopyProperties](#CopyProperties)
|
||||
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -56,7 +58,7 @@ import (
|
||||
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/o7_ft-JCJBV)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -87,7 +89,7 @@ func main() {
|
||||
func ColorRGBToHex(red, green, blue int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nzKS2Ro87J1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -120,7 +122,7 @@ func main() {
|
||||
func ToBool(s string) (bool, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ARht2WnGdIN)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -161,7 +163,7 @@ func main() {
|
||||
func ToBytes(data any) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fAMXYFDvOvr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -194,7 +196,7 @@ func main() {
|
||||
func ToChar(s string) []string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JJ1SvbFkVdM)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -230,7 +232,7 @@ func main() {
|
||||
func ToChannel[T any](array []T) <-chan T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hOx_oYZbAnL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -267,7 +269,7 @@ func main() {
|
||||
func ToFloat(value any) (float64, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4YTmPCibqHJ)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -312,7 +314,7 @@ func main() {
|
||||
func ToInt(value any) (int64, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9_h9vIt-QZ_b)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -354,7 +356,7 @@ func main() {
|
||||
func ToJson(value any) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2rLIkMmXWvR)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -389,7 +391,7 @@ func main() {
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tVFy7E-t24l)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -430,7 +432,7 @@ func main() {
|
||||
func ToPointer[T any](value T) *T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ASf_etHNlw1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -459,7 +461,7 @@ func main() {
|
||||
func ToString(value any) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nF1zOOslpQq)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -507,7 +509,7 @@ func main() {
|
||||
func StructToMap(value any) (map[string]any, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KYGYJqNUBOI)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -545,7 +547,7 @@ func main() {
|
||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dmX4Ix5V6Wl)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -575,7 +577,7 @@ func main() {
|
||||
func EncodeByte(data any) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DVmM1G5JfuP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -604,7 +606,7 @@ func main() {
|
||||
func DecodeByte(data []byte, target any) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -640,7 +642,7 @@ func main() {
|
||||
func DeepClone[T any](src T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/j4DP5dquxnk)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -696,7 +698,7 @@ func main() {
|
||||
|
||||
### <span id="CopyProperties">CopyProperties</span>
|
||||
|
||||
<p>拷贝不同结构体之间的同名字段。</p>
|
||||
<p>拷贝不同结构体之间的同名字段。使用json.Marshal序列化,需要设置dst和src struct字段的json tag。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -704,7 +706,7 @@ func main() {
|
||||
func CopyProperties[T, U any](dst T, src U) (err error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oZujoB5Sgg5)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -715,44 +717,162 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Address struct {
|
||||
Country string
|
||||
ZipCode string
|
||||
type Disk struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type DiskVO struct {
|
||||
Name string `json:"name"`
|
||||
Total string `json:"total"`
|
||||
Used string `json:"used"`
|
||||
Percent float64 `json:"percent"`
|
||||
}
|
||||
|
||||
type Employee struct {
|
||||
Name string
|
||||
Age int
|
||||
Role string
|
||||
Addr Address
|
||||
Hobbys []string
|
||||
salary int
|
||||
type Indicator struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int `json:"cpu"`
|
||||
Disk []Disk `json:"disk"`
|
||||
Stop chan bool `json:"-"`
|
||||
}
|
||||
|
||||
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
||||
type IndicatorVO struct {
|
||||
Id string `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
UpTime string `json:"upTime"`
|
||||
LoadAvg string `json:"loadAvg"`
|
||||
Cpu int64 `json:"cpu"`
|
||||
Disk []DiskVO `json:"disk"`
|
||||
}
|
||||
|
||||
employee1 := Employee{}
|
||||
CopyProperties(&employee1, &user)
|
||||
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||
}}
|
||||
|
||||
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
||||
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
||||
indicatorVO := IndicatorVO{}
|
||||
|
||||
CopyProperties(&employee2, &user)
|
||||
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||
|
||||
fmt.Println(employee1)
|
||||
fmt.Println(employee2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(indicatorVO.Id)
|
||||
fmt.Println(indicatorVO.Ip)
|
||||
fmt.Println(len(indicatorVO.Disk))
|
||||
|
||||
// Output:
|
||||
// {user001 10 Admin {CN 001} [a b] 0}
|
||||
// {user001 10 Admin {CN 001} [a b] 500}
|
||||
// 001
|
||||
// 127.0.0.1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### <span id="ToInterface">ToInterface</span>
|
||||
|
||||
<p>将反射值转换成对应的interface类型。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](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>utf8编码转GBK编码。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Utf8ToGbk(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9FlIaFLArIL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(validator.IsGBK(gbkData))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GbkToUtf8">GbkToUtf8</span>
|
||||
|
||||
<p>GBK编码转utf8编码。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GbkToUtf8(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OphmHCN_9u8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := convertor.GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
@@ -1,16 +1,18 @@
|
||||
# Cryptor
|
||||
cryptor加密包支持数据加密和解密,获取md5,hash值。支持base64, md5, hmac, aes, des, rsa。
|
||||
|
||||
cryptor包包含数据加密和解密功能。支持 base64, md5, hmac, hash, aes, des, rsa。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
@@ -20,46 +22,54 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [AesEcbEncrypt](#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha512](#Sha512)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
|
||||
- [AesEcbEncrypt](#AesEcbEncrypt)
|
||||
- [AesEcbDecrypt](#AesEcbDecrypt)
|
||||
- [AesCbcEncrypt](#AesCbcEncrypt)
|
||||
- [AesCbcDecrypt](#AesCbcDecrypt)
|
||||
- [AesCtrCrypt](#AesCtrCrypt)
|
||||
- [AesCfbEncrypt](#AesCfbEncrypt)
|
||||
- [AesCfbDecrypt](#AesCfbDecrypt)
|
||||
- [AesOfbEncrypt](#AesOfbEncrypt)
|
||||
- [AesOfbDecrypt](#AesOfbDecrypt)
|
||||
- [Base64StdEncode](#Base64StdEncode)
|
||||
- [Base64StdDecode](#Base64StdDecode)
|
||||
- [DesEcbEncrypt](#DesEcbEncrypt)
|
||||
- [DesEcbDecrypt](#DesEcbDecrypt)
|
||||
- [DesCbcEncrypt](#DesCbcEncrypt)
|
||||
- [DesCbcDecrypt](#DesCbcDecrypt)
|
||||
- [DesCtrCrypt](#DesCtrCrypt)
|
||||
- [DesCfbEncrypt](#DesCfbEncrypt)
|
||||
- [DesCfbDecrypt](#DesCfbDecrypt)
|
||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||
- [Md5Byte](#Md5Byte)
|
||||
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha1WithBase64](#Sha1WithBase64)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha256WithBase64](#Sha256WithBase64)
|
||||
- [Sha512](#Sha512)
|
||||
- [Sha512WithBase64](#Sha512WithBase64)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
|
||||
|
||||
### <span id="AesEcbEncrypt">AesEcbEncrypt</span>
|
||||
|
||||
<p>使用AES ECB算法模式加密数据. 参数`key`的长度是16, 24 or 32。</p>
|
||||
@@ -69,7 +79,8 @@ import (
|
||||
```go
|
||||
func AesEcbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -102,7 +113,8 @@ func main() {
|
||||
```go
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -135,7 +147,8 @@ func main() {
|
||||
```go
|
||||
func AesCbcEncrypt(data, key []byte) []byte
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOq_g8_lKZD)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -169,7 +182,7 @@ func main() {
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOq_g8_lKZD)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -203,7 +216,7 @@ func main() {
|
||||
func AesCtrCrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/SpaZO0-5Nsp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -237,7 +250,7 @@ func main() {
|
||||
func AesCfbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tfkF10B13kH)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -271,7 +284,7 @@ func main() {
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tfkF10B13kH)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -305,7 +318,7 @@ func main() {
|
||||
func AesOfbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VtHxtkUj-3F)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -328,6 +341,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AesCfbDecrypt">AesOfbDecrypt</span>
|
||||
|
||||
<p>使用AES OFB算法模式解密数据,参数`key`的长度是16, 24 or 32。</p>
|
||||
@@ -338,7 +352,7 @@ func main() {
|
||||
func AesOfbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VtHxtkUj-3F)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -371,7 +385,8 @@ func main() {
|
||||
```go
|
||||
func Base64StdEncode(s string) string
|
||||
```
|
||||
<b>示例:</b>
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VOaUyQUreoK)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -389,6 +404,7 @@ func main() {
|
||||
// aGVsbG8=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Base64StdDecode">Base64StdDecode</span>
|
||||
|
||||
<p>解码base64字符串。</p>
|
||||
@@ -399,7 +415,7 @@ func main() {
|
||||
func Base64StdDecode(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RWQylnJVgIe)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -428,7 +444,7 @@ func main() {
|
||||
func DesEcbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8qivmPeZy4P)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -452,6 +468,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesEcbDecrypt">DesEcbDecrypt</span>
|
||||
|
||||
<p>使用DES ECB算法模式解决密数据,参数`key`的长度是8。</p>
|
||||
@@ -462,7 +479,7 @@ func main() {
|
||||
func DesEcbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8qivmPeZy4P)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -497,7 +514,7 @@ func main() {
|
||||
func DesCbcEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4cC4QvWfe3_1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -531,7 +548,7 @@ func main() {
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4cC4QvWfe3_1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -554,6 +571,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesCtrCrypt">DesCtrCrypt</span>
|
||||
|
||||
<p>使用DES CTR算法模式加密/解密数据,参数`key`的长度是8</p>
|
||||
@@ -564,7 +582,7 @@ func main() {
|
||||
func DesCtrCrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9-T6OjKpcdw)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -598,7 +616,7 @@ func main() {
|
||||
func DesCfbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/y-eNxcFBlxL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -621,6 +639,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesCfbDecrypt">DesCfbDecrypt</span>
|
||||
|
||||
<p>使用DES CFB算法模式解决密数据,参数`key`的长度是8。</p>
|
||||
@@ -631,7 +650,7 @@ func main() {
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/y-eNxcFBlxL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -654,6 +673,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesOfbEncrypt">DesOfbEncrypt</span>
|
||||
|
||||
<p>使用DES OFB算法模式加密数据,参数`key`的长度是8。</p>
|
||||
@@ -664,7 +684,7 @@ func main() {
|
||||
func DesOfbEncrypt(data, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/74KmNadjN1J)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -687,6 +707,7 @@ func main() {
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DesOfbDecrypt">DesOfbDecrypt</span>
|
||||
|
||||
<p>使用DES OFB算法模式解密数据,参数`key`的长度是8。</p>
|
||||
@@ -697,7 +718,7 @@ func main() {
|
||||
func DesOfbDecrypt(encrypted, key []byte) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/74KmNadjN1J)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -728,10 +749,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacMd5(data, key string) string
|
||||
func HmacMd5(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -742,7 +763,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacMd5(str, key)
|
||||
@@ -752,17 +773,50 @@ func main() {
|
||||
// e834306eab892d872525d4918a7a639a
|
||||
}
|
||||
```
|
||||
### <span id="HmacSha1">HmacSha1</span>
|
||||
|
||||
<p>获取字符串sha1 hmac值。</p>
|
||||
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
|
||||
|
||||
<p>获取字符串md5 hmac base64字符串值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha1(data, key string) string
|
||||
func HmacMd5WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UY0ng2AefFC)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacMd5WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 6DQwbquJLYclJdSRinpjmg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha1">HmacSha1</span>
|
||||
|
||||
<p>获取字符串的sha1 hmac值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha1(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1UI4oQ4WXKM)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -783,6 +837,39 @@ func main() {
|
||||
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
|
||||
|
||||
<p>获取字符串的sha1 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha1WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/47JmmGrnF7B)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha1WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256">HmacSha256</span>
|
||||
|
||||
<p>获取字符串sha256 hmac值。</p>
|
||||
@@ -790,10 +877,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256(data, key string) string
|
||||
func HmacSha256(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HhpwXxFhhC0)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -815,6 +902,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
|
||||
|
||||
<p>获取字符串sha256 hmac base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EKbkUvPTLwO)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha256WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha512">HmacSha512</span>
|
||||
|
||||
<p>获取字符串sha512 hmac值。</p>
|
||||
@@ -822,10 +941,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha512(data, key string) string
|
||||
func HmacSha512(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/59Od6m4A0Ud)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -847,6 +966,37 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
|
||||
|
||||
<p>获取字符串sha512 hmac base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha512WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/c6dSe3E2ydU)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5String">Md5String</span>
|
||||
|
||||
@@ -855,10 +1005,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5String(s string) string
|
||||
func Md5String(str string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1bLcVetbTOI)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -879,6 +1029,93 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
|
||||
|
||||
<p>获取字符串md5 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5StringWithBase64(s string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Tcb-Z7LN2ax)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5Byte">Md5Byte</span>
|
||||
|
||||
<p>获取byte slice的md5值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5Byte(data []byte) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/suraalH8lyC)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
|
||||
|
||||
<p>获取byte slice的md5 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5ByteWithBase64(data []byte) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Lx4gH7Vdr5_y)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5File">Md5File</span>
|
||||
|
||||
<p>获取文件md5值。</p>
|
||||
@@ -912,10 +1149,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha1(data string) string
|
||||
func Sha1(str string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_m_uoD1deMT)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -936,6 +1173,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha1WithBase64">Sha1WithBase64</span>
|
||||
|
||||
<p>获取字符串sha1 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha1WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fSyx-Gl2l2-)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256">Sha256</span>
|
||||
|
||||
<p>获取字符串sha256值。</p>
|
||||
@@ -943,10 +1209,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha256(data string) string
|
||||
func Sha256(str string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tU9tfBMIAr1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -967,6 +1233,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256WithBase64">Sha256WithBase64</span>
|
||||
|
||||
<p>获取字符串sha256 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha256WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/85IXJHIal1k)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512">Sha512</span>
|
||||
|
||||
<p>获取字符串sha512值。</p>
|
||||
@@ -974,10 +1269,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha512(data string) string
|
||||
func Sha512(str string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3WsvLYZxsHa)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -998,6 +1293,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512WithBase64">Sha512WithBase64</span>
|
||||
|
||||
<p>获取字符串sha512 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha512WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q_fY2rA-k5I)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateRsaKey">GenerateRsaKey</span>
|
||||
|
||||
<p>在当前目录下创建rsa私钥文件和公钥文件。</p>
|
||||
@@ -1008,7 +1332,7 @@ func main() {
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zutRHrDqs0X)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1036,7 +1360,7 @@ func main() {
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1051,11 +1375,11 @@ func main() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
@@ -1063,7 +1387,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RsaDecrypt">RsaDecrypt</span>
|
||||
|
||||
<p>用私钥文件rsa解密数据。</p>
|
||||
@@ -1074,7 +1397,7 @@ func main() {
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1089,14 +1412,14 @@ func main() {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
data := []byte("hello")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
|
||||
fmt.Println(string(decrypted))
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
```
|
||||
471
docs/api/packages/datastructure/copyonwritelist.md
Normal file
471
docs/api/packages/datastructure/copyonwritelist.md
Normal file
@@ -0,0 +1,471 @@
|
||||
# CopyOnWriteList
|
||||
|
||||
CopyOnWriteList 是一个线程安全的 List 实现,底层使用 go 切片。写入时,会复制一份新的切片,写入完成后,再将新的切片赋值给原来的切片。读取时,直接读取原来的切片。
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go](https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go)
|
||||
|
||||
## 用法
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewCopyOnWriteList](#NewCopyOnWriteList)
|
||||
- [Size](#Size)
|
||||
- [Get](#Get)
|
||||
- [Set](#Set)
|
||||
- [Remove](#Remove)
|
||||
- [IndexOf](#IndexOf)
|
||||
- [LastIndexOf](#LastIndexOf)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Contain](#Contain)
|
||||
- [ValueOf](#ValueOf)
|
||||
- [Add](#Add)
|
||||
- [AddAll](#AddAll)
|
||||
- [AddByIndex](#AddByIndex)
|
||||
- [DeleteAt](#DeleteAt)
|
||||
- [DeleteIf](#DeleteIf)
|
||||
- [DeleteBy](#DeleteBy)
|
||||
- [DeleteRange](#DeleteRange)
|
||||
- [Equal](#Equal)
|
||||
|
||||
## 文档
|
||||
|
||||
### NewCopyOnWriteList
|
||||
|
||||
返回一个具有空切片的 CopyOnWriteList。
|
||||
|
||||
```go
|
||||
type CopyOnWriteList[T any] struct {
|
||||
data []T
|
||||
lock sync.Locker
|
||||
}
|
||||
|
||||
func NewCopyOnWriteList() *CopyOnWriteList
|
||||
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Size
|
||||
|
||||
返回 CopyOnWriteList 的长度。
|
||||
|
||||
```go
|
||||
func (l *CopyOnWriteList[T]) Size() int
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.Size())
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Get
|
||||
|
||||
返回列表中指定位置的元素
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) Get(index int) *T
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.Get(2))
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Set
|
||||
|
||||
将此列表中指定位置的元素替换为指定元素。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.Set(2, 4))
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Remove
|
||||
|
||||
### IndexOf
|
||||
|
||||
返回列表中值的索引,如果没有找到返回-1。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) IndexOf(e T) int
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.IndexOf(1))
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### LastIndexOf
|
||||
|
||||
返回指定元素在此列表中最后出现的索引,如果此列表不包含该元素,则返回-1。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3,1})
|
||||
fmt.Println(l.LastIndexOf(1))
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### IsEmpty
|
||||
|
||||
如果此列表不包含任何元素,则返回 true。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) IsEmpty() bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{})
|
||||
fmt.Println(l.IsEmpty())
|
||||
}
|
||||
```
|
||||
|
||||
### Contain
|
||||
|
||||
判断 CopyOnWriteList 是否包含某个元素
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) Contain(e T) bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.Contain(1))
|
||||
}
|
||||
```
|
||||
|
||||
### ValueOf
|
||||
|
||||
返回列表中索引处的值指针
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) ValueOf(index int) []T
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
fmt.Println(l.ValueOf(2))
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Add
|
||||
|
||||
将指定的元素追加到此列表的末尾。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) Add(e T) bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
l.Add(4)
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### AddAll
|
||||
|
||||
将指定集合中的所有元素追加到此列表的末尾
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) AddAll(e []T) bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
l.AddAll([]int{4,5,6})
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### AddByIndex
|
||||
|
||||
将指定元素插入此列表中的指定位置。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
list.AddByIndex(2, 6)
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### DeleteAt
|
||||
|
||||
移除此列表中指定位置的元素。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) DeleteAt(index int) (oldValue *T, ok bool)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
list.DeleteAt(2)
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
```
|
||||
|
||||
### DeleteIf
|
||||
|
||||
从此列表中删除第一个出现的指定元素(如果该元素存在)。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) (oldValue *T, ok bool)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
list.DeleteIf(func(i int) bool {
|
||||
return i == 2
|
||||
})
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
```
|
||||
|
||||
### DeleteBy
|
||||
|
||||
从此列表中删除第一个出现的指定元素(如果该元素存在)。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) DeleteBy(e T) (*T bool)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3})
|
||||
list.DeleteBy(2)
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
```
|
||||
|
||||
### DeleteRange
|
||||
|
||||
从该列表中删除索引介于 fromIndex(包含)和 toIndex(不包含)之间的所有元素。
|
||||
(左闭右开)。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
|
||||
list.DeleteRange(2, 5)
|
||||
fmt.Println(l.getList())
|
||||
}
|
||||
```
|
||||
|
||||
### Equal
|
||||
|
||||
如果指定的对象等于此列表,则返回 true。
|
||||
|
||||
```go
|
||||
func (c *CopyOnWriteList[T]) Equal(e []T) bool
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```go
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datastructure/list"
|
||||
)
|
||||
|
||||
func main() {
|
||||
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
|
||||
fmt.Println(l.Equal([]int{1,2,3,4,5,6,7,8,9}))
|
||||
}
|
||||
```
|
||||
@@ -38,7 +38,7 @@ import (
|
||||
|
||||
### <span id="NewHashMap">NewHashMap</span>
|
||||
|
||||
<p>新建默认容量(1 << 10)的HashMap指针实例</p>
|
||||
<p>新建默认容量(1 << 10)的HashMap指针实例</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Set
|
||||
Set集合数据结构,类似列表。Set中元素不重复。
|
||||
|
||||
Set 集合数据结构,类似列表。Set 中元素不重复。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法
|
||||
|
||||
```go
|
||||
import (
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
@@ -21,32 +22,31 @@ import (
|
||||
|
||||
## 目录
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [NewSetFromSlice](#NewSetFromSlice)
|
||||
- [Values](#Values)
|
||||
- [Add](#Add)
|
||||
- [AddIfNotExist](#AddIfNotExist)
|
||||
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||
- [Delete](#Delete)
|
||||
- [Contain](#Contain)
|
||||
- [ContainAll](#ContainAll)
|
||||
- [Clone](#Clone)
|
||||
- [Size](#Size)
|
||||
- [Equal](#Equal)
|
||||
- [Iterate](#Iterate)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
|
||||
|
||||
- [NewSet](#NewSet)
|
||||
- [NewSetFromSlice](#NewSetFromSlice)
|
||||
- [Values](#Values)
|
||||
- [Add](#Add)
|
||||
- [AddIfNotExist](#AddIfNotExist)
|
||||
- [AddIfNotExistBy](#AddIfNotExistBy)
|
||||
- [Delete](#Delete)
|
||||
- [Contain](#Contain)
|
||||
- [ContainAll](#ContainAll)
|
||||
- [Clone](#Clone)
|
||||
- [Size](#Size)
|
||||
- [Equal](#Equal)
|
||||
- [Iterate](#Iterate)
|
||||
- [IsEmpty](#IsEmpty)
|
||||
- [Union](#Union)
|
||||
- [Intersection](#Intersection)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Minus](#Minus)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="NewSet">NewSet</span>
|
||||
|
||||
<p>返回Set结构体对象</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -55,6 +55,7 @@ import (
|
||||
type Set[T comparable] map[T]bool
|
||||
func NewSet[T comparable](items ...T) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -71,9 +72,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="NewSetFromSlice">NewSetFromSlice</span>
|
||||
|
||||
<p>基于切片创建集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -81,6 +81,7 @@ func main() {
|
||||
```go
|
||||
func NewSetFromSlice[T comparable](items []T) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -97,9 +98,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
|
||||
<p>获取集合中所有元素的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -107,6 +107,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Values() []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -123,10 +124,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Add">Add</span>
|
||||
|
||||
<p>向集合中添加元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -134,6 +133,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Add(items ...T)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -152,8 +152,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="AddIfNotExist">AddIfNotExist</span>
|
||||
|
||||
<p>如果集合中不存在元素,则添加该元素返回true, 如果集合中存在元素, 不做任何操作,返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -161,6 +161,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) AddIfNotExist(item T) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -176,7 +177,7 @@ func main() {
|
||||
st.Add(1, 2, 3)
|
||||
|
||||
r1 := st.AddIfNotExist(1)
|
||||
r2 := st.AddIfNotExist(4)
|
||||
r2 := st.AddIfNotExist(4)
|
||||
|
||||
fmt.Println(r1) // false
|
||||
fmt.Println(r2) // true
|
||||
@@ -184,8 +185,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="AddIfNotExistBy">AddIfNotExistBy</span>
|
||||
|
||||
<p>根据checker函数判断元素是否在集合中,如果集合中不存在元素且checker返回true,则添加该元素返回true, 否则不做任何操作,返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -193,6 +194,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -207,24 +209,23 @@ func main() {
|
||||
st := set.NewSet[int]()
|
||||
st.Add(1, 2)
|
||||
|
||||
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||
return val%2 != 0
|
||||
})
|
||||
ok := st.AddIfNotExistBy(3, func(val int) bool {
|
||||
return val%2 != 0
|
||||
})
|
||||
fmt.Println(ok) // true
|
||||
|
||||
|
||||
notOk := st.AddIfNotExistBy(4, func(val int) bool {
|
||||
return val%2 != 0
|
||||
})
|
||||
notOk := st.AddIfNotExistBy(4, func(val int) bool {
|
||||
return val%2 != 0
|
||||
})
|
||||
fmt.Println(notOk) // false
|
||||
|
||||
|
||||
fmt.Println(st.Values()) // 1, 2, 3
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Delete">Delete</span>
|
||||
|
||||
<p>删除集合中元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -232,6 +233,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Delete(items ...T)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -251,9 +253,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Contain">Contain</span>
|
||||
|
||||
<p>判断集合是否包含某个值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -261,6 +262,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Contain(item T) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -280,10 +282,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="ContainAll">ContainAll</span>
|
||||
|
||||
<p>判断集合是否包含另一个集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -291,6 +291,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) ContainAll(other Set[T]) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -303,17 +304,16 @@ import (
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
set2 := set.NewSet(1, 2)
|
||||
set3 := set.NewSet(1, 2, 3, 4)
|
||||
|
||||
fmt.Println(set1.ContainAll(set2)) //true
|
||||
fmt.Println(set1.ContainAll(set3)) //false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Size">Size</span>
|
||||
|
||||
<p>获取集合中元素的个数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -321,6 +321,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Size() int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -338,9 +339,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Clone">Clone</span>
|
||||
|
||||
<p>克隆一个集合</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -348,6 +348,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Clone() Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -367,10 +368,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
|
||||
<p>比较两个集合是否相等,包含相同元素为相等</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -378,6 +377,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Equal(other Set[T]) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -398,9 +398,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Iterate">Iterate</span>
|
||||
|
||||
<p>迭代结合,在每个元素上调用函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -408,6 +407,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Iterate(fn func(item T))
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -429,9 +429,45 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EachWithBreak">EachWithBreak</span>
|
||||
|
||||
<p>遍历集合的元素并为每个元素调用iteratee函数,当iteratee函数返回false时,终止遍历。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) EachWithBreak(iteratee func(item T) bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet(1, 2, 3, 4, 5)
|
||||
|
||||
var sum int
|
||||
|
||||
s.EachWithBreak(func(n int) bool {
|
||||
if n > 3 {
|
||||
return false
|
||||
}
|
||||
sum += n
|
||||
return true
|
||||
})
|
||||
|
||||
fmt.Println(sum) //6
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsEmpty">IsEmpty</span>
|
||||
|
||||
<p>判断集合是否为空</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -439,6 +475,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) IsEmpty() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -458,9 +495,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Union">Union</span>
|
||||
|
||||
<p>求两个集合的并集</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -468,6 +504,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Union(other Set[T]) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -487,9 +524,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Intersection">Intersection</span>
|
||||
|
||||
<p>求两个集合的交集</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -497,6 +533,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Intersection(other Set[T]) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -516,8 +553,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||
|
||||
<p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -525,6 +562,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -537,18 +575,15 @@ import (
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set1.SymmetricDifference(set2)
|
||||
|
||||
fmt.Println(set3.Values()) //1,4,5
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
|
||||
<p>创建一个集合,其元素在原始集中但不在比较集中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
@@ -556,6 +591,7 @@ func main() {
|
||||
```go
|
||||
func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
@@ -568,8 +604,8 @@ import (
|
||||
|
||||
func main() {
|
||||
set1 := set.NewSet(1, 2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
set2 := set.NewSet(2, 3, 4, 5)
|
||||
set3 := set.NewSet(2, 3)
|
||||
|
||||
res1 := set1.Minus(set2)
|
||||
fmt.Println(res1.Values()) //1
|
||||
@@ -579,5 +615,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Pop">Pop</span>
|
||||
|
||||
<p>删除并返回集合中的顶部元素</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s Set[T]) Pop() (v T, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
set "github.com/duke-git/lancet/v2/datastructure/set"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := set.NewSet[int]()
|
||||
s.Add(1)
|
||||
s.Add(2)
|
||||
s.Add(3)
|
||||
|
||||
val, ok = s.Pop()
|
||||
|
||||
fmt.Println(val) // 3
|
||||
fmt.Println(ok) // true
|
||||
}
|
||||
```
|
||||
1467
docs/api/packages/datetime.md
Normal file
1467
docs/api/packages/datetime.md
Normal file
File diff suppressed because it is too large
Load Diff
841
docs/api/packages/fileutil.md
Normal file
841
docs/api/packages/fileutil.md
Normal file
@@ -0,0 +1,841 @@
|
||||
# Fileutil
|
||||
|
||||
fileutil 包支持文件基本操作。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [ClearFile](#ClearFile)
|
||||
- [CreateFile](#CreateFile)
|
||||
- [CreateDir](#CreateDir)
|
||||
- [CopyFile](#CopyFile)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [FileMode](#FileMode)
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [ZipAppendEntry](#ZipAppendEntry)
|
||||
- [UnZip](#UnZip)
|
||||
- [IsZipFile](#IsZipFile)
|
||||
- [FileSize](#FileSize)
|
||||
- [MTime](#MTime)
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="ClearFile">ClearFile</span>
|
||||
|
||||
<p>清空文件内容</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ClearFile(path string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/NRZ0ZT-G94H)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ClearFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CreateFile">CreateFile</span>
|
||||
|
||||
<p>创建文件,创建成功返回true, 否则返回false</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CreateFile(path string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lDt8PEsTNKI)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isCreatedSucceed := fileutil.CreateFile("./test.txt")
|
||||
fmt.Println(isCreatedSucceed)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CreateDir">CreateDir</span>
|
||||
|
||||
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CreateDir(absPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qUuCe1OGQnM)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CreateDir("/a/b") // will create folder /a/b
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CopyFile">CopyFile</span>
|
||||
|
||||
<p>拷贝文件,会覆盖原有的文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CopyFile(srcPath string, dstPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Jg9AMJMLrJi)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CurrentPath">CurrentPath</span>
|
||||
|
||||
<p>返回当前位置的绝对路径。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CurrentPath() string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/s74a9iBGcSw)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
absPath := CurrentPath()
|
||||
fmt.Println(absPath)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FileMode">FileMode</span>
|
||||
|
||||
<p>获取文件mode信息</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FileMode(path string) (fs.FileMode, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2l2hI42fA3p)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mode, err := fileutil.FileMode("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(mode)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MiMeType">MiMeType</span>
|
||||
|
||||
<p>获取文件mime类型, 'file'参数的类型必须是string或者*os.File</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MiMeType(file any) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bd5sevSUZNu)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type1 := fileutil.MiMeType("./test.txt")
|
||||
fmt.Println(type1) //text/plain; charset=utf-8
|
||||
|
||||
f, _ := os.Open("./file.go")
|
||||
type2 := fileutil.MiMeType(f)
|
||||
fmt.Println(type2) //text/plain; charset=utf-8
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsExist">IsExist</span>
|
||||
|
||||
<p>判断文件或目录是否存在</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsExist(path string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nKKXt8ZQbmh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileutil.CreateFile("./test.txt")
|
||||
isFileExist := fileutil.IsExist("./test.txt")
|
||||
fmt.Println(isFileExist) //true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsLink">IsLink</span>
|
||||
|
||||
<p>判断文件是否是符号链接</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsLink(path string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TL-b-Kzvf44)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isLinkFile := fileutil.IsLink("./test.txt")
|
||||
fmt.Println(isLinkFile) //false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsDir">IsDir</span>
|
||||
|
||||
<p>判断参数是否是目录</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsDir(path string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WkVwEKqtOWk)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isDir := fileutil.IsDir("./")
|
||||
fmt.Println(isDir) //true
|
||||
|
||||
isDir = fileutil.IsDir("./test.txt")
|
||||
fmt.Println(isDir) //false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ListFileNames">ListFileNames</span>
|
||||
|
||||
<p>返回目录下所有文件名</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ListFileNames(path string) ([]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Tjd7Y07rejl)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fileNames, _ := fileutil.ListFileNames("./")
|
||||
fmt.Println(fileNames)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RemoveFile">RemoveFile</span>
|
||||
|
||||
<p>删除文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveFile(path string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P2y0XW8a1SH)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.RemoveFile("./test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReadFileToString">ReadFileToString</span>
|
||||
|
||||
<p>读取文件内容并返回字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadFileToString(path string) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cmfwp_5SQTp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./test.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
f.WriteString("hello world")
|
||||
|
||||
content, _ := fileutil.ReadFileToString(path)
|
||||
fmt.Println(content) //hello world
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReadFileByLine">ReadFileByLine</span>
|
||||
|
||||
<p>按行读取文件内容,返回字符串切片包含每一行</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadFileByLine(path string)([]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/svJP_7ZrBrD)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
path := "./text.txt"
|
||||
fileutil.CreateFile(path)
|
||||
|
||||
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||
defer f.Close()
|
||||
f.WriteString("hello\nworld")
|
||||
|
||||
contents, _ := fileutil.ReadFileByLine(path)
|
||||
fmt.Println(contents) //[]string{"hello", "world"}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Zip">Zip</span>
|
||||
|
||||
<p>zip压缩文件, fpath参数可以是文件或目录</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Zip(fpath string, destPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/j-3sWBp8ik_P)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ZipAppendEntry">ZipAppendEntry</span>
|
||||
|
||||
<p>通过将单个文件或目录追加到现有的zip文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ZipAppendEntry(fpath string, destPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cxvaT8TRNQp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnZip">UnZip</span>
|
||||
|
||||
<p>zip解压缩文件并保存在目录中</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UnZip(zipFile string, destPath string) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g0w34kS7B8m)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.Zip("./test.zip", "./unzip/test.txt")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsZipFile">IsZipFile</span>
|
||||
|
||||
<p>判断文件是否是zip压缩文件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsZipFile(filepath string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9M0g2j_uF_e)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isZip := fileutil.IsZipFile("./zipfile.zip")
|
||||
fmt.Println(isZip)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FileSize">FileSize</span>
|
||||
|
||||
<p>返回文件字节大小。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FileSize(path string) (int64, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/H9Z05uD-Jjc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
size, err := fileutil.FileSize("./testdata/test.txt")
|
||||
|
||||
fmt.Println(size)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// 20
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MTime">MTime</span>
|
||||
|
||||
<p>返回文件修改时间(unix timestamp).</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MTime(filepath string) (int64, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/s_Tl7lZoAaY)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mtime, err := fileutil.MTime("./testdata/test.txt")
|
||||
|
||||
fmt.Println(mtime)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// 1682391110
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha">Sha</span>
|
||||
|
||||
<p>返回文件sha值,参数`shaType` 应传值为: 1, 256,512.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha(filepath string, shaType ...int) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VfEEcO2MJYf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sha1, err := fileutil.Sha("./testdata/test.txt", 1)
|
||||
sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
|
||||
sha512, _ := fileutil.Sha("./testdata/test.txt", 512)
|
||||
|
||||
fmt.Println(sha1)
|
||||
fmt.Println(sha256)
|
||||
fmt.Println(sha512)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
|
||||
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
|
||||
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReadCsvFile">ReadCsvFile</span>
|
||||
|
||||
<p>读取csv文件内容到切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReadCsvFile(filepath string) ([][]string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
content, err := fileutil.ReadCsvFile("./testdata/test.csv")
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteCsvFile">WriteCsvFile</span>
|
||||
|
||||
<p>向csv文件写入内容。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dAXm58Q5U1o)</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()
|
||||
|
||||
data := [][]string{
|
||||
{"Lili", "22", "female"},
|
||||
{"Jim", "21", "male"},
|
||||
}
|
||||
err := fileutil.WriteCsvFile(fpath, data, false)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadCsvFile(fpath)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// [[Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||
|
||||
<p>将bytes写入文件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteBytesToFile(filepath string, content []byte) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/s7QlDxMj3P8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||
|
||||
<p>将字符串写入文件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteStringToFile(filepath string, content string, append bool) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GhLS6d8lH_g)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
310
docs/api/packages/formatter.md
Normal file
310
docs/api/packages/formatter.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# Formatter
|
||||
|
||||
formatter 格式化器包含一些数据格式化处理方法。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/formatter/byte.go](https://github.com/duke-git/lancet/blob/main/formatter/byte.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Comma](#Comma)
|
||||
- [Pretty](#Pretty)
|
||||
- [PrettyToWriter](#PrettyToWriter)
|
||||
- [DecimalBytes](#DecimalBytes)
|
||||
- [BinaryBytes](#BinaryBytes)
|
||||
- [ParseDecimalBytes](#ParseDecimalBytes)
|
||||
- [ParseBinaryBytes](#ParseBinaryBytes)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Comma">Comma</span>
|
||||
|
||||
<p>用逗号每隔3位分割数字/字符串,支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := formatter.Comma("123", "")
|
||||
result2 := formatter.Comma("12345", "$")
|
||||
result3 := formatter.Comma(1234567, "¥")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// $12,345
|
||||
// ¥1,234,567
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Pretty">Pretty</span>
|
||||
|
||||
<p>返回pretty JSON字符串.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Pretty(v any) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YsciGj3FH2x)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
|
||||
result2, _ := formatter.Pretty(map[string]int{"a": 1})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [
|
||||
// "a",
|
||||
// "b",
|
||||
// "c"
|
||||
// ]
|
||||
// {
|
||||
// "a": 1
|
||||
// }
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="PrettyToWriter">PrettyToWriter</span>
|
||||
|
||||
<p>Pretty encode数据到writer。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func PrettyToWriter(v any, out io.Writer) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/LPLZ3lDi5ma)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Aage uint `json:"age"`
|
||||
}
|
||||
user := User{Name: "King", Aage: 10000}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
err := formatter.PrettyToWriter(user, buf)
|
||||
|
||||
fmt.Println(buf)
|
||||
fmt.Println(err)
|
||||
|
||||
// Output:
|
||||
// {
|
||||
// "name": "King",
|
||||
// "age": 10000
|
||||
// }
|
||||
//
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DecimalBytes">DecimalBytes</span>
|
||||
|
||||
<p>返回十进制标准(以1000为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DecimalBytes(size float64, precision ...int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FPXs1suwRcs)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := formatter.DecimalBytes(1000)
|
||||
result2 := formatter.DecimalBytes(1024)
|
||||
result3 := formatter.DecimalBytes(1234567)
|
||||
result4 := formatter.DecimalBytes(1234567, 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 1KB
|
||||
// 1.024KB
|
||||
// 1.2346MB
|
||||
// 1.235MB
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BinaryBytes">BinaryBytes</span>
|
||||
|
||||
<p>返回binary标准(以1024为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BinaryBytes(size float64, precision ...int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G9oHHMCAZxP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := formatter.BinaryBytes(1024)
|
||||
result2 := formatter.BinaryBytes(1024 * 1024)
|
||||
result3 := formatter.BinaryBytes(1234567)
|
||||
result4 := formatter.BinaryBytes(1234567, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 1KiB
|
||||
// 1MiB
|
||||
// 1.1774MiB
|
||||
// 1.18MiB
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
|
||||
|
||||
<p>将字节单位字符串转换成其所表示的字节数(以1000为基数)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ParseDecimalBytes(size string) (uint64, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Am98ybWjvjj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1, _ := formatter.ParseDecimalBytes("12")
|
||||
result2, _ := formatter.ParseDecimalBytes("12k")
|
||||
result3, _ := formatter.ParseDecimalBytes("12 Kb")
|
||||
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 12
|
||||
// 12000
|
||||
// 12000
|
||||
// 12200
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
|
||||
|
||||
<p>将字节单位字符串转换成其所表示的字节数(以1024为基数)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ParseBinaryBytes(size string) (uint64, error)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/69v1tTT62x8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/formatter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1, _ := formatter.ParseBinaryBytes("12")
|
||||
result2, _ := formatter.ParseBinaryBytes("12ki")
|
||||
result3, _ := formatter.ParseBinaryBytes("12 KiB")
|
||||
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 12
|
||||
// 12288
|
||||
// 12288
|
||||
// 12492
|
||||
}
|
||||
```
|
||||
@@ -47,7 +47,7 @@ import (
|
||||
func After(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -80,7 +80,7 @@ func main() {
|
||||
func Before(n int, fn any) func(args ...any) []reflect.Value
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0HqUDIFZ3IL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -88,7 +88,6 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/function"
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -118,7 +117,7 @@ type CurryFn[T any] func(...T) T
|
||||
func (cf CurryFn[T]) New(val T) func(...T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/5HopfDwANKX)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -157,7 +156,7 @@ func main() {
|
||||
func Compose[T any](fnList ...func(...T) T) func(...T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KKfugD4PKYF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -195,7 +194,7 @@ func main() {
|
||||
func Debounced(fn func(), duration time.Duration) func()
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/absuEGB_GN7)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -245,7 +244,7 @@ func main() {
|
||||
func Delay(delay time.Duration, fn any, args ...any)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ivtc2ZE-Tye)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -277,7 +276,7 @@ func main() {
|
||||
func Schedule(d time.Duration, fn any, args ...any) chan bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hbON-Xeyn5N)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -316,7 +315,7 @@ func main() {
|
||||
func Pipeline[T any](funcs ...func(T) T) func(T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mPdUVvj6HD6)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -361,13 +360,14 @@ type Watcher struct {
|
||||
excuting bool
|
||||
}
|
||||
func NewWatcher() *Watcher
|
||||
func (w *Watcher) Start() //start the watcher
|
||||
func (w *Watcher) Stop() //stop the watcher
|
||||
func (w *Watcher) Reset() //reset the watcher
|
||||
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
|
||||
func (w *Watcher) Start()
|
||||
func (w *Watcher) Stop()
|
||||
func (w *Watcher) Reset()
|
||||
func (w *Watcher) GetElapsedTime() time.Duration
|
||||
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/l2yrOpCLd1I)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
## 目录:
|
||||
|
||||
- [MapTo](#MapTo)
|
||||
- [ForEach](#ForEach)
|
||||
- [Filter](#Filter)
|
||||
- [FilterByKeys](#FilterByKeys)
|
||||
@@ -42,11 +43,77 @@ import (
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [IsDisjoint](#IsDisjoint)
|
||||
- [HasKey](#HasKey)
|
||||
- [NewConcurrentMap](#NewConcurrentMap)
|
||||
- [ConcurrentMap_Get](#ConcurrentMap_Get)
|
||||
- [ConcurrentMap_Set](#ConcurrentMap_Set)
|
||||
- [ConcurrentMap_GetOrSet](#ConcurrentMap_GetOrSet)
|
||||
- [ConcurrentMap_Delete](#ConcurrentMap_Delete)
|
||||
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
|
||||
- [ConcurrentMap_Has](#ConcurrentMap_Has)
|
||||
- [ConcurrentMap_Range](#ConcurrentMap_Range)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API 文档:
|
||||
|
||||
### <span id="MapTo">MapTo</span>
|
||||
|
||||
<p>快速将map或者其他类型映射到结构体或者指定类型。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MapTo(src any, dst any) error
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4K7KBEPgS5M)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type (
|
||||
Person struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Phone string `json:"phone"`
|
||||
Addr Address `json:"address"`
|
||||
}
|
||||
|
||||
Address struct {
|
||||
Street string `json:"street"`
|
||||
Number int `json:"number"`
|
||||
}
|
||||
)
|
||||
|
||||
personInfo := map[string]interface{}{
|
||||
"name": "Nothin",
|
||||
"age": 28,
|
||||
"phone": "123456789",
|
||||
"address": map[string]interface{}{
|
||||
"street": "test",
|
||||
"number": 1,
|
||||
},
|
||||
}
|
||||
|
||||
var p Person
|
||||
err := MapTo(personInfo, &p)
|
||||
|
||||
fmt.Println(err)
|
||||
fmt.Println(p)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// {Nothin 28 123456789 {test 1}}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ForEach">ForEach</span>
|
||||
|
||||
<p>对map中的每对key和value执行iteratee函数</p>
|
||||
@@ -57,7 +124,7 @@ import (
|
||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OaThj6iNVXK)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -80,7 +147,7 @@ func main() {
|
||||
maputil.ForEach(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
|
||||
|
||||
fmt.Println(sum)
|
||||
|
||||
// Output:
|
||||
@@ -98,7 +165,7 @@ func main() {
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fSvF3wxuNG7)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -123,7 +190,7 @@ func main() {
|
||||
maputil.Filter(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
|
||||
|
||||
result := Filter(m, isEven)
|
||||
|
||||
fmt.Println(result)
|
||||
@@ -143,7 +210,7 @@ func main() {
|
||||
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7ov6BJHbVqh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -171,7 +238,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="FilterByValues">FilterByValues</span>
|
||||
|
||||
<p>迭代map, 返回一个新map,其value都是给定的value值。</p>
|
||||
@@ -182,7 +248,7 @@ func main() {
|
||||
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P3-9MdcXegR)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -210,7 +276,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OmitBy">OmitBy</span>
|
||||
|
||||
<p>Filter的反向操作, 迭代map中的每对key和value, 删除符合predicate函数的key, value, 返回新map。</p>
|
||||
@@ -221,7 +286,7 @@ func main() {
|
||||
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YJM4Hj5hNwm)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -252,7 +317,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OmitByKeys">OmitByKeys</span>
|
||||
|
||||
<p>FilterByKeys的反向操作, 迭代map, 返回一个新map,其key不包括给定的key值。</p>
|
||||
@@ -263,7 +327,7 @@ func main() {
|
||||
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jXGrWDBfSRp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -291,7 +355,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="OmitByValues">OmitByValues</span>
|
||||
|
||||
<p>FilterByValues的反向操作, 迭代map, 返回一个新map,其value不包括给定的value值。</p>
|
||||
@@ -302,7 +365,7 @@ func main() {
|
||||
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XB7Y10uw20_U)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -340,7 +403,7 @@ func main() {
|
||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Zld0oj3sjcC)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -395,7 +458,7 @@ func main() {
|
||||
func Keys[K comparable, V any](m map[K]V) []K
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xNB5bTb97Wd)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -416,7 +479,7 @@ func main() {
|
||||
|
||||
keys := maputil.Keys(m)
|
||||
sort.Ints(keys)
|
||||
|
||||
|
||||
fmt.Println(keys)
|
||||
|
||||
// Output:
|
||||
@@ -434,7 +497,7 @@ func main() {
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/H95LENF1uB-)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -453,7 +516,7 @@ func main() {
|
||||
1: "1",
|
||||
3: "2",
|
||||
}
|
||||
|
||||
|
||||
result := maputil.Merge(m1, m2)
|
||||
|
||||
fmt.Println(result)
|
||||
@@ -473,7 +536,7 @@ func main() {
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3u5U9K7YZ9m)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -515,7 +578,7 @@ func main() {
|
||||
func Values[K comparable, V any](m map[K]V) []V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CBKdUc5FTW6)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -552,7 +615,7 @@ func main() {
|
||||
func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hI371iB8Up8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -593,7 +656,7 @@ func main() {
|
||||
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sg9-oRidh8f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -632,7 +695,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="MapKeys">MapKeys</span>
|
||||
|
||||
<p>操作map的每个key,然后转为新的map。</p>
|
||||
@@ -643,7 +705,7 @@ func main() {
|
||||
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8scDxWeBDKd)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -682,7 +744,7 @@ func main() {
|
||||
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g92aY3fc7Iw)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -711,7 +773,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Entry">Entry</span>
|
||||
|
||||
<p>将map转换为键/值对切片。</p>
|
||||
@@ -726,7 +787,7 @@ type Entry[K comparable, V any] struct {
|
||||
func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ltb11LNcElY)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -757,7 +818,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="FromEntries">FromEntries</span>
|
||||
|
||||
<p>基于键/值对的切片创建map。</p>
|
||||
@@ -772,7 +832,7 @@ type Entry[K comparable, V any] struct {
|
||||
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C8L4ul9TVwf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -806,7 +866,7 @@ func main() {
|
||||
func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P6ovfToM3zj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -845,7 +905,7 @@ func main() {
|
||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/N9qgYg_Ho6f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -881,3 +941,415 @@ func main() {
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HasKey">HasKey</span>
|
||||
|
||||
<p>检查map是否包含某个key。用于代替以下样板代码:</p>
|
||||
|
||||
```go
|
||||
_, haskey := amap["baz"];
|
||||
|
||||
if haskey {
|
||||
fmt.Println("map has key baz")
|
||||
}
|
||||
```
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HasKey[K comparable, V any](m map[K]V, key K) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/isZZHOsDhFc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
|
||||
result1 := maputil.HasKey(m, "a")
|
||||
result2 := maputil.HasKey(m, "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NewConcurrentMap">NewConcurrentMap</span>
|
||||
|
||||
<p>ConcurrentMap协程安全的map结构。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
// NewConcurrentMap create a ConcurrentMap with specific shard count.
|
||||
func NewConcurrentMap[K comparable, V any](shardCount int) *ConcurrentMap[K, V]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// create a ConcurrentMap whose key type is string, value type is int
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_Set">ConcurrentMap_Set</span>
|
||||
|
||||
<p>在map中设置key和value。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) Set(key K, value V)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(5)
|
||||
for j := 0; j < 5; j++ {
|
||||
go func(n int) {
|
||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||
fmt.Println(val, ok)
|
||||
wg2.Done()
|
||||
}(j)
|
||||
}
|
||||
wg2.Wait()
|
||||
|
||||
// output: (order may change)
|
||||
// 1 true
|
||||
// 3 true
|
||||
// 2 true
|
||||
// 0 true
|
||||
// 4 true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_Get">ConcurrentMap_Get</span>
|
||||
|
||||
<p>根据key获取value, 如果不存在key,返回零值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) Get(key K) (V, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(5)
|
||||
for j := 0; j < 5; j++ {
|
||||
go func(n int) {
|
||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||
fmt.Println(val, ok)
|
||||
wg2.Done()
|
||||
}(j)
|
||||
}
|
||||
wg2.Wait()
|
||||
|
||||
// output: (order may change)
|
||||
// 1 true
|
||||
// 3 true
|
||||
// 2 true
|
||||
// 0 true
|
||||
// 4 true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_GetOrSet">ConcurrentMap_GetOrSet</span>
|
||||
|
||||
<p>返回键的现有值(如果存在),否则,设置key并返回给定值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) GetOrSet(key K, value V) (actual V, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aDcDApOK01a)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
val, ok := cm.GetOrSet(fmt.Sprintf("%d", n), n)
|
||||
fmt.Println(val, ok)
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// output: (order may change)
|
||||
// 1 false
|
||||
// 3 false
|
||||
// 2 false
|
||||
// 0 false
|
||||
// 4 false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_Delete">ConcurrentMap_Delete</span>
|
||||
|
||||
<p>删除key。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) Delete(key K)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uTIJZYhpVMS)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(5)
|
||||
for j := 0; j < 5; j++ {
|
||||
go func(n int) {
|
||||
cm.Delete(fmt.Sprintf("%d", n))
|
||||
wg2.Done()
|
||||
}(i)
|
||||
}
|
||||
wg2.Wait()
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_GetAndDelete">ConcurrentMap_GetAndDelete</span>
|
||||
|
||||
<p>获取key,然后删除。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) GetAndDelete(key K) (actual V, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZyxeIXSZUiM)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(5)
|
||||
for j := 0; j < 5; j++ {
|
||||
go func(n int) {
|
||||
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
|
||||
fmt.Println(val, ok) //n, true
|
||||
|
||||
_, ok = cm.Get(fmt.Sprintf("%d", n))
|
||||
fmt.Println(val, ok) //false
|
||||
|
||||
wg2.Done()
|
||||
}(j)
|
||||
}
|
||||
wg2.Wait()
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_Has">ConcurrentMap_Has</span>
|
||||
|
||||
<p>验证是否包含key。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) Has(key K) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C8L4ul9TVwf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(5)
|
||||
|
||||
for j := 0; j < 5; j++ {
|
||||
go func(n int) {
|
||||
ok := cm.Has(fmt.Sprintf("%d", n))
|
||||
fmt.Println(ok) // true
|
||||
|
||||
wg2.Done()
|
||||
}(j)
|
||||
}
|
||||
wg2.Wait()
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ConcurrentMap_Range">ConcurrentMap_Range</span>
|
||||
|
||||
<p>为map中每个键和值顺序调用迭代器。 如果iterator返回false,则停止迭代。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (cm *ConcurrentMap[K, V]) Range(iterator func(key K, value V) bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iqcy7P8P0Pr)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cm := maputil.NewConcurrentMap[string, int](100)
|
||||
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(5)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
go func(n int) {
|
||||
cm.Set(fmt.Sprintf("%d", n), n)
|
||||
wg1.Done()
|
||||
}(i)
|
||||
}
|
||||
wg1.Wait()
|
||||
|
||||
|
||||
cm.Range(func(key string, value int) bool {
|
||||
fmt.Println(value)
|
||||
return true
|
||||
})
|
||||
}
|
||||
```
|
||||
980
docs/api/packages/mathutil.md
Normal file
980
docs/api/packages/mathutil.md
Normal file
@@ -0,0 +1,980 @@
|
||||
# Mathutil
|
||||
|
||||
mathutil 包实现了一些数学计算的函数.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Average](#Average)
|
||||
- [Exponent](#Exponent)
|
||||
- [Fibonacci](#Fibonacci)
|
||||
- [Factorial](#Factorial)
|
||||
- [Max](#Max)
|
||||
- [MaxBy](#MaxBy)
|
||||
- [Min](#Min)
|
||||
- [MinBy](#MaxBy)
|
||||
- [Percent](#Percent)
|
||||
- [RoundToFloat](#RoundToFloat)
|
||||
- [RoundToString](#RoundToString)
|
||||
- [TruncRound](#TruncRound)
|
||||
- [Range](#Range)
|
||||
- [RangeWithStep](#RangeWithStep)
|
||||
- [AngleToRadian](#AngleToRadian)
|
||||
- [RadianToAngle](#RadianToAngle)
|
||||
- [PointDistance](#PointDistance)
|
||||
- [IsPrime](#IsPrime)
|
||||
- [GCD](#GCD)
|
||||
- [LCM](#LCM)
|
||||
- [Cos](#Cos)
|
||||
- [Sin](#Sin)
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
- [Abs](#Abs)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Average">Average</span>
|
||||
|
||||
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Average(1, 2)
|
||||
|
||||
avg := mathutil.Average(1.2, 1.4)
|
||||
result2 := mathutil.RoundToFloat(avg, 1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1.3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Exponent">Exponent</span>
|
||||
|
||||
<p>指数计算(x的n次方)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Exponent(x, n int64) int64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Vv7LBwER-pz)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Exponent(10, 0)
|
||||
result2 := mathutil.Exponent(10, 1)
|
||||
result3 := mathutil.Exponent(10, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 10
|
||||
// 100
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Fibonacci">Fibonacci</span>
|
||||
|
||||
<p>计算斐波那契数列的第n个数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Fibonacci(first, second, n int) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IscseUNMuUc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Fibonacci(1, 1, 1)
|
||||
result2 := mathutil.Fibonacci(1, 1, 2)
|
||||
result3 := mathutil.Fibonacci(1, 1, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Factorial">Factorial</span>
|
||||
|
||||
<p>计算阶乘</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Factorial(x uint) uint
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tt6LdOK67Nx)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Factorial(1)
|
||||
result2 := mathutil.Factorial(2)
|
||||
result3 := mathutil.Factorial(3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 6
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>返回参数中的最大数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cN8DHI0rTkH)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Max(1, 2, 3)
|
||||
result2 := mathutil.Max(1.2, 1.4, 1.1, 1.4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 1.4
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MaxBy">MaxBy</span>
|
||||
|
||||
<p>使用给定的比较器函数返回切片的最大值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MaxBy[T any](slice []T, comparator func(T, T) bool) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pbe2MT-7DV2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
|
||||
return len(v1) > len(v2)
|
||||
})
|
||||
|
||||
result2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
|
||||
return len(v1) > len(v2)
|
||||
})
|
||||
|
||||
result3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
|
||||
return len(v1) > len(v2)
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abc
|
||||
// abd
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
|
||||
<p>返回参数中的最小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pbe2MT-7DV2)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Min(1, 2, 3)
|
||||
result2 := mathutil.Min(1.2, 1.4, 1.1, 1.4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1.1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="MinBy">MinBy</span>
|
||||
|
||||
<p>使用给定的比较器函数返回切片的最小值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func MinBy[T any](slice []T, comparator func(T, T) bool) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/N9qgYg_Ho6f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
|
||||
return len(v1) < len(v2)
|
||||
})
|
||||
|
||||
result2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
|
||||
return len(v1) < len(v2)
|
||||
})
|
||||
|
||||
result3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
|
||||
return len(v1) < len(v2)
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// a
|
||||
// ab
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Percent">Percent</span>
|
||||
|
||||
<p>计算百分比,保留n位小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Percent(val, total float64, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/s0NdFCtwuyd)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Percent(1, 2, 2)
|
||||
result2 := mathutil.Percent(0.1, 0.3, 2)
|
||||
result3 := mathutil.Percent(-30305, 408420, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 50
|
||||
// 33.33
|
||||
// -7.42
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RoundToFloat">RoundToFloat</span>
|
||||
|
||||
<p>四舍五入,保留n位小数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToFloat(x float64, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ghyb528JRJL)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.RoundToFloat(0.124, 2)
|
||||
result2 := mathutil.RoundToFloat(0.125, 2)
|
||||
result3 := mathutil.RoundToFloat(0.125, 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.12
|
||||
// 0.13
|
||||
// 0.125
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RoundToString">RoundToString</span>
|
||||
|
||||
<p>四舍五入,保留n位小数,返回字符串</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RoundToString(x float64, n int) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kZwpBRAcllO)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.RoundToString(0.124, 2)
|
||||
result2 := mathutil.RoundToString(0.125, 2)
|
||||
result3 := mathutil.RoundToString(0.125, 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.12
|
||||
// 0.13
|
||||
// 0.125
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TruncRound">TruncRound</span>
|
||||
|
||||
<p>截短n位小数(不进行四舍五入)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TruncRound(x float64, n int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aumarSHIGzP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.TruncRound(0.124, 2)
|
||||
result2 := mathutil.TruncRound(0.125, 2)
|
||||
result3 := mathutil.TruncRound(0.125, 3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.12
|
||||
// 0.12
|
||||
// 0.125
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Range">Range</span>
|
||||
|
||||
<p>根据指定的起始值和数量,创建一个数字切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Range[T constraints.Integer | constraints.Float](start T, count int) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9ke2opxa8ZP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Range(1, 4)
|
||||
result2 := mathutil.Range(1, -4)
|
||||
result3 := mathutil.Range(-4, 4)
|
||||
result4 := mathutil.Range(1.0, 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4]
|
||||
// [1 2 3 4]
|
||||
// [-4 -3 -2 -1]
|
||||
// [1 2 3 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RangeWithStep">RangeWithStep</span>
|
||||
|
||||
<p>根据指定的起始值,结束值,步长,创建一个数字切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/akLWz0EqOSM)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.RangeWithStep(1, 4, 1)
|
||||
result2 := mathutil.RangeWithStep(1, -1, 0)
|
||||
result3 := mathutil.RangeWithStep(-4, 1, 2)
|
||||
result4 := mathutil.RangeWithStep(1.0, 4.0, 1.1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
// []
|
||||
// [-4 -2 0]
|
||||
// [1 2.1 3.2]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AngleToRadian">AngleToRadian</span>
|
||||
|
||||
<p>将角度值转为弧度值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AngleToRadian(angle float64) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CIvlICqrHql)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.AngleToRadian(45)
|
||||
result2 := mathutil.AngleToRadian(90)
|
||||
result3 := mathutil.AngleToRadian(180)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.7853981633974483
|
||||
// 1.5707963267948966
|
||||
// 3.141592653589793
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RadianToAngle">RadianToAngle</span>
|
||||
|
||||
<p>将弧度值转为角度值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RadianToAngle(radian float64) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dQtmOTUOMgi)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.RadianToAngle(math.Pi)
|
||||
result2 := mathutil.RadianToAngle(math.Pi / 2)
|
||||
result3 := mathutil.RadianToAngle(math.Pi / 4)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 180
|
||||
// 90
|
||||
// 45
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="PointDistance">PointDistance</span>
|
||||
|
||||
<p>计算两个坐标点的距离</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func PointDistance(x1, y1, x2, y2 float64) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RrG4JIaziM8)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.PointDistance(1, 1, 4, 5)
|
||||
|
||||
fmt.Println(result1)
|
||||
|
||||
// Output:
|
||||
// 5
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsPrime">IsPrime</span>
|
||||
|
||||
<p>判断质数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsPrime(n int) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rdd8UTHZJ7u)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.IsPrime(-1)
|
||||
result2 := mathutil.IsPrime(0)
|
||||
result3 := mathutil.IsPrime(1)
|
||||
result4 := mathutil.IsPrime(2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GCD">GCD</span>
|
||||
|
||||
<p>计算最大公约数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GCD[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CiEceLSoAKB)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.GCD(1, 1)
|
||||
result2 := mathutil.GCD(1, -1)
|
||||
result3 := mathutil.GCD(-1, 1)
|
||||
result4 := mathutil.GCD(-1, -1)
|
||||
result5 := mathutil.GCD(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1
|
||||
// -1
|
||||
// -1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LCM">LCM</span>
|
||||
|
||||
<p>计算最小公倍数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LCM[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EjcZxfY7G_g)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.LCM(1, 1)
|
||||
result2 := mathutil.LCM(1, 2)
|
||||
result3 := mathutil.LCM(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 18
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Cos">Cos</span>
|
||||
|
||||
<p>计算弧度的余弦值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Cos(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Sm89LoIfvFq)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Cos(0)
|
||||
result2 := mathutil.Cos(90)
|
||||
result3 := mathutil.Cos(180)
|
||||
result4 := mathutil.Cos(math.Pi)
|
||||
result5 := mathutil.Cos(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// -0.447
|
||||
// -0.598
|
||||
// -1
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sin">Sin</span>
|
||||
|
||||
<p>计算弧度的正弦值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sin(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TWMQlMywDsP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sin(0)
|
||||
result2 := mathutil.Sin(90)
|
||||
result3 := mathutil.Sin(180)
|
||||
result4 := mathutil.Sin(math.Pi)
|
||||
result5 := mathutil.Sin(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 0.894
|
||||
// -0.801
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Log">Log</span>
|
||||
|
||||
<p>计算以base为底n的对数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Log(n, base float64) float64
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_d4bi8oyhat)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Log(8, 2)
|
||||
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
|
||||
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 2.32
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sum">Sum</span>
|
||||
|
||||
<p>求传入参数之和。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1To2ImAMJA7)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sum(1, 2)
|
||||
result2 := mathutil.Sum(0.1, float64(1))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 1.1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Abs">Abs</span>
|
||||
|
||||
<p>求绝对值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Abs[T constraints.Integer | constraints.Float](x T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fsyBh1Os-1d)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := Abs(-1)
|
||||
result2 := Abs(-0.1)
|
||||
result3 := Abs(float32(0.2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 0.1
|
||||
// 0.2
|
||||
}
|
||||
```
|
||||
@@ -44,6 +44,10 @@ import (
|
||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||
- [ParseHttpResponse](#ParseHttpResponse)
|
||||
- [DownloadFile](#DownloadFile)
|
||||
- [UploadFile](#UploadFile)
|
||||
- [IsPingConnected](#IsPingConnected)
|
||||
- [IsTelnetConnected](#IsTelnetConnected)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -59,7 +63,7 @@ import (
|
||||
func ConvertMapToQueryString(param map[string]any) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jnNt_qoSnRi)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -94,7 +98,7 @@ func main() {
|
||||
func EncodeUrl(urlStr string) (string, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bsZ6BRC4uKI)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -129,7 +133,7 @@ func main() {
|
||||
func GetInternalIp() string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fxnna_LLD9u)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -161,7 +165,7 @@ func main() {
|
||||
func GetIps() []string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/NUFfcEmukx1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -191,7 +195,7 @@ func main() {
|
||||
func GetMacAddrs() []string {
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rq9UUBS_Xp1)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -235,7 +239,7 @@ type PublicIpInfo struct {
|
||||
}
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YDxIfozsRHR)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -265,7 +269,7 @@ func main() {
|
||||
func GetRequestPublicIp(req *http.Request) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kxU-YDc_eBo)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -303,7 +307,7 @@ func main() {
|
||||
func IsPublicIP(IP net.IP) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nmktSQpJZnn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -340,7 +344,7 @@ func main() {
|
||||
func IsInternalIP(IP net.IP) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sYGhXbgO4Cb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -384,7 +388,7 @@ type HttpRequest struct {
|
||||
}
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -441,7 +445,7 @@ func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
|
||||
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -472,7 +476,7 @@ func main() {
|
||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -526,7 +530,7 @@ func main() {
|
||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -580,7 +584,7 @@ func main() {
|
||||
func StructToUrlValues(targetStruct any) url.Values
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pFqMkM40w9z)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -592,27 +596,35 @@ import (
|
||||
|
||||
func main() {
|
||||
type TodoQuery struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Id int `json:"id"`
|
||||
UserId int `json:"userId"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Status string
|
||||
}
|
||||
todoQuery := TodoQuery{
|
||||
Id: 1,
|
||||
Name: "Test",
|
||||
item := TodoQuery{
|
||||
Id: 1,
|
||||
UserId: 123,
|
||||
Name: "test",
|
||||
Status: "completed",
|
||||
}
|
||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
||||
queryValues := netutil.StructToUrlValues(item)
|
||||
|
||||
fmt.Println(todoValues.Get("id"))
|
||||
fmt.Println(todoValues.Get("userId"))
|
||||
fmt.Println(todoValues.Get("name"))
|
||||
fmt.Println(todoValues.Get("status"))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// Test
|
||||
// 123
|
||||
// test
|
||||
//
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
|
||||
<p>发送http get请求</p>
|
||||
<p>发送http get请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -652,9 +664,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
|
||||
<p>发送http post请求</p>
|
||||
<p>发送http post请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -682,16 +694,14 @@ import (
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, "TestAddToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -701,9 +711,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
|
||||
<p>发送http put请求</p>
|
||||
<p>发送http put请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -751,9 +761,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
|
||||
<p>发送http delete请求</p>
|
||||
<p>发送http delete请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -790,9 +800,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
|
||||
<p>发送http patch请求</p>
|
||||
<p>发送http patch请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -890,3 +900,124 @@ func main() {
|
||||
fmt.Println(toDoResp)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DownloadFile">DownloadFile</span>
|
||||
|
||||
<p>从指定的server地址下载文件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DownloadFile(filepath string, url string) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := netutil.DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UploadFile">UploadFile</span>
|
||||
|
||||
<p>将文件上传指定的server地址。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func UploadFile(filepath string, server string) (bool, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ok, err := netutil.UploadFile("./a.jpg", "http://www.xxx.com/bucket/test")
|
||||
|
||||
fmt.Println(ok)
|
||||
fmt.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsPingConnected">IsPingConnected</span>
|
||||
|
||||
<p>检查能否ping通主机。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsPingConnected(host string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q8OzTijsA87)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := netutil.IsPingConnected("www.baidu.com")
|
||||
result2 := netutil.IsPingConnected("www.!@#&&&.com")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsTelnetConnected">IsTelnetConnected</span>
|
||||
|
||||
<p>检查能否telnet到主机。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsTelnetConnected(host string, port string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yiLCGtQv_ZG)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := netutil.IsTelnetConnected("www.baidu.com", "80")
|
||||
result2 := netutil.IsTelnetConnected("www.baidu.com", "123")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
227
docs/api/packages/pointer.md
Normal file
227
docs/api/packages/pointer.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Pointer
|
||||
|
||||
pointer 包支持一些指针类型的操作。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/pointer/pointer.go](https://github.com/duke-git/lancet/blob/main/pointer/pointer.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Of](#Of)
|
||||
- [Unwrap](#Unwrap)
|
||||
- [ExtractPointer](#ExtractPointer)
|
||||
- [UnwarpOr](#UnwarpOr)
|
||||
- [UnwarpOrDefault](#UnwarpOrDefault)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Of">Of</span>
|
||||
|
||||
<p>返回传入参数的指针值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Of[T any](v T) *T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := pointer.Of(123)
|
||||
result2 := pointer.Of("abc")
|
||||
|
||||
fmt.Println(*result1)
|
||||
fmt.Println(*result2)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
|
||||
<p>返回传入指针指向的值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Unwrap[T any](p *T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cgeu3g7cjWb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 123
|
||||
b := "abc"
|
||||
|
||||
result1 := pointer.Unwrap(&a)
|
||||
result2 := pointer.Unwrap(&b)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ExtractPointer">ExtractPointer</span>
|
||||
|
||||
<p>返回传入interface的底层值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ExtractPointer(value any) any
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/D7HFjeWU2ZP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 1
|
||||
b := &a
|
||||
c := &b
|
||||
d := &c
|
||||
|
||||
result := pointer.ExtractPointer(d)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnwarpOr">UnwarpOr</span>
|
||||
|
||||
<p>返回指针的值,如果指针为零值,则返回fallback。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
UnwarpOr[T any](p *T, fallback T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mmNaLC38W8C)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 123
|
||||
b := "abc"
|
||||
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOr(&a, 456)
|
||||
result2 := pointer.UnwarpOr(&b, "abc")
|
||||
result3 := pointer.UnwarpOr(c, 456)
|
||||
result4 := pointer.UnwarpOr(d, "def")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
// 456
|
||||
// def
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
|
||||
|
||||
<p>返回指针的值,如果指针为零值,则返回相应零值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
UnwarpOrDefault[T any](p *T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZnGIHf8_o4E)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/pointer"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := 123
|
||||
b := "abc"
|
||||
|
||||
var c *int
|
||||
var d *string
|
||||
|
||||
result1 := pointer.UnwarpOrDefault(&a)
|
||||
result2 := pointer.UnwarpOrDefault(&b)
|
||||
result3 := pointer.UnwarpOrDefault(c)
|
||||
result4 := pointer.UnwarpOrDefault(d)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
// 0
|
||||
//
|
||||
}
|
||||
```
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -45,7 +46,7 @@ import (
|
||||
func RandBytes(length int) []byte
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EkiLESeXf8d)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -71,7 +72,7 @@ func main() {
|
||||
func RandInt(min, max int) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pXyyAAI5YxD)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -97,7 +98,7 @@ func main() {
|
||||
func RandString(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/W2xvRUXA7Mi)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -123,7 +124,7 @@ func main() {
|
||||
func RandUpper(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/29QfOh0DVuh)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -149,7 +150,7 @@ func main() {
|
||||
func RandLower(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XJtZ471cmtI)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -175,7 +176,7 @@ func main() {
|
||||
func RandNumeral(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g4JWVpHsJcf)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -201,7 +202,7 @@ func main() {
|
||||
func RandNumeralOrLetter(length int) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/19CEQvpx2jD)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -227,7 +228,7 @@ func main() {
|
||||
func UUIdV4() (string, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_Z9SFmr28ft)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -245,3 +246,29 @@ func main() {
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>生成一个不重复的长度为n的随机int切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(n, min, max int) []int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uBkRSOz73Ec)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := random.RandUniqueIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
@@ -30,7 +30,8 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Document 文档
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Context">Context</span>
|
||||
|
||||
@@ -42,7 +43,7 @@ import (
|
||||
func Context(ctx context.Context)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xnAOOXv9GkS)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -89,7 +90,7 @@ func main() {
|
||||
type RetryFunc func() error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -135,7 +136,7 @@ func main() {
|
||||
func RetryTimes(n uint)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ssfVeU2SwLO)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -178,7 +179,7 @@ func main() {
|
||||
func RetryDuration(d time.Duration)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -224,7 +225,7 @@ func main() {
|
||||
func Retry(retryFunc RetryFunc, opts ...Option) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
File diff suppressed because it is too large
Load Diff
940
docs/api/packages/stream.md
Normal file
940
docs/api/packages/stream.md
Normal file
@@ -0,0 +1,940 @@
|
||||
# Stream
|
||||
|
||||
Stream 流,该包仅验证简单 stream 实现,功能有限。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
|
||||
- [Of](#Of)
|
||||
- [FromSlice](#FromSlice)
|
||||
- [FromChannel](#FromChannel)
|
||||
- [FromRange](#FromRange)
|
||||
- [Generate](#Generate)
|
||||
- [Concat](#Concat)
|
||||
- [Distinct](#Distinct)
|
||||
- [Filter](#Filter)
|
||||
- [Map](#Map)
|
||||
- [Peek](#Peek)
|
||||
- [Skip](#Skip)
|
||||
- [Limit](#Limit)
|
||||
- [Reverse](#Reverse)
|
||||
- [Range](#Range)
|
||||
- [Sorted](#Sorted)
|
||||
- [ForEach](#ForEach)
|
||||
- [Reduce](#Reduce)
|
||||
- [FindFirst](#FindFirst)
|
||||
- [FindLast](#FindLast)
|
||||
- [Max](#Max)
|
||||
- [Min](#Min)
|
||||
- [AllMatch](#AllMatch)
|
||||
- [AnyMatch](#AnyMatch)
|
||||
- [NoneMatch](#NoneMatch)
|
||||
- [Count](#Count)
|
||||
- [ToSlice](#ToSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="Of">Of</span>
|
||||
|
||||
<p>创建元素为指定值的stream。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Of[T any](elems ...T) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jI6_iZZuVFE)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.Of(1, 2, 3)
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FromSlice">FromSlice</span>
|
||||
|
||||
<p>从切片创建stream。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FromSlice[T any](source []T) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wywTO0XZtI4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FromChannel">FromChannel</span>
|
||||
|
||||
<p>从通道创建stream。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FromChannel[T any](source <-chan T) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9TZYugGMhXZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ch := make(chan int)
|
||||
go func() {
|
||||
for i := 1; i < 4; i++ {
|
||||
ch <- i
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
||||
s := stream.FromChannel(ch)
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FromRange">FromRange</span>
|
||||
|
||||
<p>指定一个范围创建stream, 范围两端点值都包括在内。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9Ex1-zcg-B-)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.FromRange(1, 5, 1)
|
||||
|
||||
data := s.ToSlice()
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4 5]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Generate">Generate</span>
|
||||
|
||||
<p>创建一个stream,其中每个元素都由提供的生成器函数生成</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rkOWL1yA3j9)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
n := 0
|
||||
max := 4
|
||||
|
||||
generator := func() func() (int, bool) {
|
||||
return func() (int, bool) {
|
||||
n++
|
||||
return n, n < max
|
||||
}
|
||||
}
|
||||
|
||||
s := stream.Generate(generator)
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Concat">Concat</span>
|
||||
|
||||
<p>创建一个延迟连接stream,其元素是第一个stream的所有元素,后跟第二个stream的全部元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Concat[T any](a, b stream[T]) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HM4OlYk_OUC)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||
s2 := stream.FromSlice([]int{4, 5, 6})
|
||||
|
||||
s := Concat(s1, s2)
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4 5 6]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Distinct">Distinct</span>
|
||||
|
||||
<p>创建并返回一个stream,用于删除重复的项。 <b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Distinct() stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eGkOSrm64cB)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||
distinct := original.Distinct()
|
||||
|
||||
data1 := original.ToSlice()
|
||||
data2 := distinct.ToSlice()
|
||||
|
||||
fmt.Println(data1)
|
||||
fmt.Println(data2)
|
||||
|
||||
// Output:
|
||||
// [1 2 2 3 3 3]
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
|
||||
<p>返回一个通过判定函数的stream <b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MFlSANo-buc)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
|
||||
|
||||
isEven := func(n int) bool {
|
||||
return n%2 == 0
|
||||
}
|
||||
|
||||
even := original.Filter(isEven)
|
||||
|
||||
fmt.Println(even.ToSlice())
|
||||
|
||||
// Output:
|
||||
// [2 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Map">Map</span>
|
||||
|
||||
<p>返回一个stream,该stream由将给定函数应用于源stream元素的元素组成。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Map(mapper func(item T) T) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OtNQUImdYko)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
addOne := func(n int) int {
|
||||
return n + 1
|
||||
}
|
||||
|
||||
increament := original.Map(addOne)
|
||||
|
||||
fmt.Println(increament.ToSlice())
|
||||
|
||||
// Output:
|
||||
// [2 3 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Peek">Peek</span>
|
||||
|
||||
<p>返回一个由源stream的元素组成的stream,并在从生成的stream中消耗元素时对每个元素执行所提供的操作。 <b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Peek(consumer func(item T)) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/u1VNzHs6cb2)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
data := []string{}
|
||||
peekStream := original.Peek(func(n int) {
|
||||
data = append(data, fmt.Sprint("value", n))
|
||||
})
|
||||
|
||||
fmt.Println(original.ToSlice())
|
||||
fmt.Println(peekStream.ToSlice())
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
// [1 2 3]
|
||||
// [value1 value2 value3]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Skip">Skip</span>
|
||||
|
||||
<p>在丢弃stream的前n个元素后,返回由源stream的其余元素组成的stream。如果此stream包含的元素少于n个,则将返回一个空stream。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Skip(n int) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fNdHbqjahum)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||
|
||||
s1 := original.Skip(-1)
|
||||
s2 := original.Skip(0)
|
||||
s3 := original.Skip(1)
|
||||
s4 := original.Skip(5)
|
||||
|
||||
fmt.Println(s1.ToSlice())
|
||||
fmt.Println(s2.ToSlice())
|
||||
fmt.Println(s3.ToSlice())
|
||||
fmt.Println(s4.ToSlice())
|
||||
|
||||
// Output:
|
||||
// [1 2 3 4]
|
||||
// [1 2 3 4]
|
||||
// [2 3 4]
|
||||
// []
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Limit">Limit</span>
|
||||
|
||||
<p>返回由源stream的元素组成的stream,该stream被截断为长度不超过maxSize。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Limit(maxSize int) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qsO4aniDcGf)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||
|
||||
s1 := original.Limit(-1)
|
||||
s2 := original.Limit(0)
|
||||
s3 := original.Limit(1)
|
||||
s4 := original.Limit(5)
|
||||
|
||||
fmt.Println(s1.ToSlice())
|
||||
fmt.Println(s2.ToSlice())
|
||||
fmt.Println(s3.ToSlice())
|
||||
fmt.Println(s4.ToSlice())
|
||||
|
||||
// Output:
|
||||
// []
|
||||
// []
|
||||
// [1]
|
||||
// [1 2 3 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Reverse">Reverse</span>
|
||||
|
||||
<p>返回元素与源stream的顺序相反的stream。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Reverse() stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/A8_zkJnLHm4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
reverse := original.Reverse()
|
||||
|
||||
fmt.Println(reverse.ToSlice())
|
||||
|
||||
// Output:
|
||||
// [3 2 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Range">Range</span>
|
||||
|
||||
<p>返回一个stream,该stream的元素在从源stream的开始(包含)到结束(排除)的范围内。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Range(start, end int) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/indZY5V2f4j)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
s1 := original.Range(0, 0)
|
||||
s2 := original.Range(0, 1)
|
||||
s3 := original.Range(0, 3)
|
||||
s4 := original.Range(1, 2)
|
||||
|
||||
fmt.Println(s1.ToSlice())
|
||||
fmt.Println(s2.ToSlice())
|
||||
fmt.Println(s3.ToSlice())
|
||||
fmt.Println(s4.ToSlice())
|
||||
|
||||
// Output:
|
||||
// []
|
||||
// [1]
|
||||
// [1 2 3]
|
||||
// [2]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sorted">Sorted</span>
|
||||
|
||||
<p>返回一个stream,该stream由源stream的元素组成,并根据提供的less函数进行排序。<b>支持链式操作</b></p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XXtng5uonFj)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||
|
||||
fmt.Println(original.ToSlice())
|
||||
fmt.Println(sorted.ToSlice())
|
||||
|
||||
// Output:
|
||||
// [4 2 1 3]
|
||||
// [1 2 3 4]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ForEach">ForEach</span>
|
||||
|
||||
<p>对stream的每个元素执行一个操作。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) ForEach(action func(item T))
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Dsm0fPqcidk)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result := 0
|
||||
original.ForEach(func(item int) {
|
||||
result += item
|
||||
})
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 6
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Reduce">Reduce</span>
|
||||
|
||||
<p>使用关联累加函数对stream的元素执行reduce操作,并reduce操作结果(如果有)。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6uzZjq_DJLU)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result := original.Reduce(0, func(a, b int) int {
|
||||
return a + b
|
||||
})
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 6
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindFirst">FindFirst</span>
|
||||
|
||||
<p>返回此stream的第一个元素和true,如果stream为空,则返回零值和false。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) FindFirst() (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9xEf0-6C1e3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result, ok := original.FindFirst()
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>返回此stream最后一个元素和true,如果stream为空,则返回零值和false。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) FindLast() (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WZD2rDAW-2h)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{3, 2, 1})
|
||||
|
||||
result, ok := original.FindLast()
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fm-1KOPtGzn)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||
|
||||
fmt.Println(max)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Min">Min</span>
|
||||
|
||||
<p>根据提供的less函数返回stream的最小元素。less函数: a < b</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vZfIDgGNRe_0)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||
|
||||
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||
|
||||
fmt.Println(min)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AllMatch">AllMatch</span>
|
||||
|
||||
<p>判断stream的所有元素是否全部匹配指定判定函数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/V5TBpVRs-Cx)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result1 := original.AllMatch(func(item int) bool {
|
||||
return item > 0
|
||||
})
|
||||
|
||||
result2 := original.AllMatch(func(item int) bool {
|
||||
return item > 1
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AnyMatch">AnyMatch</span>
|
||||
|
||||
<p>判断stream是否包含匹配指定判定函数的元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/PTCnWn4OxSn)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result1 := original.AnyMatch(func(item int) bool {
|
||||
return item > 1
|
||||
})
|
||||
|
||||
result2 := original.AnyMatch(func(item int) bool {
|
||||
return item > 3
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NoneMatch">NoneMatch</span>
|
||||
|
||||
<p>判断stream的元素是否全部不匹配指定的判定函数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iWS64pL1oo3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{1, 2, 3})
|
||||
|
||||
result1 := original.NoneMatch(func(item int) bool {
|
||||
return item > 3
|
||||
})
|
||||
|
||||
result2 := original.NoneMatch(func(item int) bool {
|
||||
return item > 1
|
||||
})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Count">Count</span>
|
||||
|
||||
<p>返回stream中元素的数量。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) Count() int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/r3koY6y_Xo-)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||
s2 := stream.FromSlice([]int{})
|
||||
|
||||
fmt.Println(s1.Count())
|
||||
fmt.Println(s2.Count())
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToSlice">ToSlice</span>
|
||||
|
||||
<p>返回stream中的元素切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) ToSlice() []T
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jI6_iZZuVFE)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := stream.Of(1, 2, 3)
|
||||
|
||||
data := s.ToSlice()
|
||||
|
||||
fmt.Println(data)
|
||||
|
||||
// Output:
|
||||
// [1 2 3]
|
||||
}
|
||||
```
|
||||
534
docs/api/packages/struct.md
Normal file
534
docs/api/packages/struct.md
Normal file
@@ -0,0 +1,534 @@
|
||||
# Structs
|
||||
|
||||
structs 包封装了一个抽象的`Struct`结构体,提供了操作`struct`的相关函数
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/structs/struct.go](https://github.com/duke-git/lancet/blob/main/structs/struct.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/structs/field.go](https://github.com/duke-git/lancet/blob/main/structs/field.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录:
|
||||
|
||||
- [New](#New)
|
||||
- [ToMap](#ToMap)
|
||||
- [Fields](#Fields)
|
||||
- [Field](#Field)
|
||||
- [IsStruct](#IsStruct)
|
||||
- [Tag](#Tag)
|
||||
- [Name](#Name)
|
||||
- [Value](#Value)
|
||||
- [Kind](#Kind)
|
||||
- [IsEmbedded](#IsEmbedded)
|
||||
- [IsExported](#IsExported)
|
||||
- [IsZero](#IsZero)
|
||||
- [IsSlice](#IsSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API 文档:
|
||||
|
||||
### <span id="New">New</span>
|
||||
|
||||
<p>`Struct`结构体的构造函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func New(value any, tagName ...string) *Struct
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
// to do something
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToMap">ToMap</span>
|
||||
|
||||
<p>将一个合法的struct对象转换为map[string]any</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *Struct) ToMap() (map[string]any, error)
|
||||
```
|
||||
|
||||
<b>除此之外,提供一个便捷的静态方法 ToMap</b>
|
||||
|
||||
```go
|
||||
func ToMap(v any) (map[string]any, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s1 := structs.New(p1)
|
||||
m1, _ := s1.ToMap()
|
||||
|
||||
fmt.Println(m1)
|
||||
|
||||
// 如果不需要Struct更多的方法,可以直接使用ToMap
|
||||
m2, _ := structs.ToMap(p1)
|
||||
|
||||
fmt.Println(m2)
|
||||
|
||||
// Output:
|
||||
// map[name:11]
|
||||
// map[name:11]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Fields">Fields</span>
|
||||
|
||||
<p>获取一个struct对象的属性列表</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *Struct) Fields() []*Field
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
fields := s.Fields()
|
||||
|
||||
fmt.Println(len(fields))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Field">Field</span>
|
||||
|
||||
<p>根据属性名获取一个struct对象的属性</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *Struct) Field(name string) *Field
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
f := s.Field("Name")
|
||||
|
||||
fmt.Println(f.Value())
|
||||
|
||||
// Output:
|
||||
// 11
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsStruct">IsStruct</span>
|
||||
|
||||
<p>判断是否为一个合法的struct对象</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s *Struct) IsStruct() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
|
||||
fmt.Println(s.IsStruct())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Tag">Tag</span>
|
||||
|
||||
<p>获取`Field`的`Tag`,默认的tag key是json</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) Tag() *Tag
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
tag := n.Tag()
|
||||
|
||||
fmt.Println(tag.Name)
|
||||
|
||||
// Output:
|
||||
// name
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Value">Value</span>
|
||||
|
||||
<p>获取`Field`属性的值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) Value() any
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
|
||||
fmt.Println(n.Value())
|
||||
|
||||
// Output:
|
||||
// 111
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsEmbedded">IsEmbedded</span>
|
||||
|
||||
<p>判断属性是否为嵌入</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsEmbedded() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
}
|
||||
type Child struct {
|
||||
Parent
|
||||
Age int
|
||||
}
|
||||
c1 := &Child{}
|
||||
c1.Name = "111"
|
||||
c1.Age = 11
|
||||
|
||||
s := structs.New(c1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsEmbedded())
|
||||
fmt.Println(a.IsEmbedded())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsExported">IsExported</span>
|
||||
|
||||
<p>判断属性是否导出</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsExported() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
p1 := &Parent{Name: "11", age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("age")
|
||||
|
||||
fmt.Println(n.IsExported())
|
||||
fmt.Println(a.IsExported())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsZero">IsZero</span>
|
||||
|
||||
<p>判断属性是否为零值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsZero() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsZero())
|
||||
fmt.Println(a.IsZero())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Name">Name</span>
|
||||
|
||||
<p>获取属性名</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) Name() string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Name())
|
||||
fmt.Println(a.Name())
|
||||
|
||||
// Output:
|
||||
// Name
|
||||
// Age
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Kind">Kind</span>
|
||||
|
||||
<p>获取属性Kind</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) Kind() reflect.Kind
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Kind())
|
||||
fmt.Println(a.Kind())
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// int
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsSlice">IsSlice</span>
|
||||
|
||||
<p>判断属性是否是切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (f *Field) IsSlice() bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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)
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(a.IsSlice())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -45,10 +45,24 @@ import (
|
||||
- [Unwrap](#Unwrap)
|
||||
- [SplitWords](#SplitWords)
|
||||
- [WordCount](#WordCount)
|
||||
- [RemoveNonPrintable](#RemoveNonPrintable)
|
||||
- [StringToBytes](#StringToBytes)
|
||||
- [BytesToString](#BytesToString)
|
||||
- [IsBlank](#IsBlank)
|
||||
- [HasPrefixAny](#HasPrefixAny)
|
||||
- [HasSuffixAny](#HasSuffixAny)
|
||||
- [IndexOffset](#IndexOffset)
|
||||
- [ReplaceWithMap](#ReplaceWithMap)
|
||||
- [Trim](#Trim)
|
||||
- [SplitAndTrim](#SplitAndTrim)
|
||||
- [HideString](#HideString)
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation 文档
|
||||
## 文档
|
||||
|
||||
### <span id="After">After</span>
|
||||
|
||||
@@ -60,7 +74,7 @@ import (
|
||||
func After(s, char string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RbCOQqCDA7m)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -100,7 +114,7 @@ func main() {
|
||||
func AfterLast(s, char string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1TegARrb8Yn)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -140,7 +154,7 @@ func main() {
|
||||
func Before(s, char string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JAWTZDS4F5w)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -177,7 +191,7 @@ func main() {
|
||||
func BeforeLast(s, char string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pJfXXAoG_Te)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -214,7 +228,7 @@ func main() {
|
||||
func CamelCase(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9eXP3tn2tUy)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -249,7 +263,7 @@ func main() {
|
||||
func KebabCase(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dcZM9Oahw-Y)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -284,7 +298,7 @@ func main() {
|
||||
func UpperKebabCase(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zDyKNneyQXk)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -319,7 +333,7 @@ func main() {
|
||||
func Capitalize(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2OAjgbmAqHZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -354,7 +368,7 @@ func main() {
|
||||
func IsString(v any) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOgq7oF9ERm)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -394,7 +408,7 @@ func main() {
|
||||
func LowerFirst(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CbzAyZmtJwL)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -428,7 +442,7 @@ func main() {
|
||||
func UpperFirst(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sBbBxRbs8MM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -462,7 +476,7 @@ func main() {
|
||||
func Pad(source string, size int, padStr string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/NzImQq-VF8q)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -507,7 +521,7 @@ func main() {
|
||||
func PadEnd(source string, size int, padStr string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9xP8rN0vz--)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -553,7 +567,7 @@ func main() {
|
||||
func PadStart(source string, size int, padStr string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xpTfzArDfvT)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -599,7 +613,7 @@ func main() {
|
||||
func Reverse(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/adfwalJiecD)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -630,7 +644,7 @@ func main() {
|
||||
func SnakeCase(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tgzQG11qBuN)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -662,10 +676,10 @@ func main() {
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SnakeCase(s string) string
|
||||
func UpperSnakeCase(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4COPHpnLx38)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -700,7 +714,7 @@ func main() {
|
||||
func SplitEx(s, sep string, removeEmptyString bool) []string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Us-ySSbWh-3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -741,7 +755,7 @@ func main() {
|
||||
func Substring(s string, offset int, length uint) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q3sM6ehnPDp)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -784,7 +798,7 @@ func main() {
|
||||
func Wrap(str string, wrapWith string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KoZOlZDDt9y)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -811,7 +825,7 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Wrap">Wrap</span>
|
||||
### <span id="Unwrap">Unwrap</span>
|
||||
|
||||
<p>用另一个字符串解开包裹一个字符串。</p>
|
||||
|
||||
@@ -821,7 +835,7 @@ func main() {
|
||||
func Unwrap(str string, wrapToken string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ec2q4BzCpG-)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -861,7 +875,7 @@ func main() {
|
||||
func SplitWords(s string) []string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KLiX4WiysMM)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -894,7 +908,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="WordCount">WordCount</span>
|
||||
|
||||
<p>返回有意义单词的数量,只支持字母字符单词。</p>
|
||||
@@ -905,7 +918,7 @@ func main() {
|
||||
func WordCount(s string) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bj7_odx3vRf)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -936,4 +949,476 @@ func main() {
|
||||
// 0
|
||||
// 0
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### <span id="RemoveNonPrintable">RemoveNonPrintable</span>
|
||||
|
||||
<p>删除字符串中不可打印的字符。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveNonPrintable(str string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/og47F5x_jTZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.RemoveNonPrintable("hello\u00a0 \u200bworld\n")
|
||||
result2 := strutil.RemoveNonPrintable("你好😄")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
// 你好😄
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="StringToBytes">StringToBytes</span>
|
||||
|
||||
<p>在不分配内存的情况下将字符串转换为字节片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func StringToBytes(str string) (b []byte)
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7OyFBrf9AxA)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.StringToBytes("abc")
|
||||
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// [97 98 99]
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BytesToString">BytesToString</span>
|
||||
|
||||
<p>在不分配内存的情况下将字节切片转换为字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BytesToString(bytes []byte) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6c68HRvJecH)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
bytes := []byte{'a', 'b', 'c'}
|
||||
result := strutil.BytesToString(bytes)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsBlank">IsBlank</span>
|
||||
|
||||
<p>检查字符串是否为空格或空。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsBlank(str string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6zXRH_c0Qd3)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsBlank("")
|
||||
result2 := strutil.IsBlank("\t\v\f\n")
|
||||
result3 := strutil.IsBlank(" 中文")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HasPrefixAny">HasPrefixAny</span>
|
||||
|
||||
<p>检查字符串是否以指定字符串数组中的任何一个开头。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HasPrefixAny(str string, prefixes []string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8UUTl2C5slo)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
||||
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HasSuffixAny">HasSuffixAny</span>
|
||||
|
||||
<p>检查字符串是否以指定字符串数组中的任何一个结尾。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HasSuffixAny(str string, suffixes []string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sKWpCQdOVkx)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
||||
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IndexOffset">IndexOffset</span>
|
||||
|
||||
<p>将字符串偏移idxFrom后,返回字符串中第一个 substr 实例的索引,如果字符串中不存在 substr,则返回 -1。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IndexOffset(str string, substr string, idxFrom int) int
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qZo4lV2fomB)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "foo bar hello world"
|
||||
|
||||
result1 := strutil.IndexOffset(str, "o", 5)
|
||||
result2 := strutil.IndexOffset(str, "o", 0)
|
||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||
result5 := strutil.IndexOffset(str, "f", -1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 12
|
||||
// 1
|
||||
// 18
|
||||
// -1
|
||||
// -1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReplaceWithMap">ReplaceWithMap</span>
|
||||
|
||||
<p>返回`str`的副本,以无序的方式被map替换,区分大小写。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReplaceWithMap(str string, replaces map[string]string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/h3t7CNj2Vvu)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Trim">Trim</span>
|
||||
|
||||
<p>从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Trim(str string, characterMask ...string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Y0ilP0NRV3j)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SplitAndTrim">SplitAndTrim</span>
|
||||
|
||||
<p>将字符串str按字符串delimiter拆分为一个切片,并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SplitAndTrim(str, delimiter string, characterMask ...string) []string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZNL6o4SkYQ7)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HideString">HideString</span>
|
||||
|
||||
<p>使用参数`replaceChar`隐藏源字符串中的一些字符。替换范围是 origin[start : end]。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HideString(origin string, start, end int, replaceChar string) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pzbaIVCTreZ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "13242658976"
|
||||
|
||||
result1 := strutil.HideString(str, 3, 3, "*")
|
||||
result2 := strutil.HideString(str, 3, 4, "*")
|
||||
result3 := strutil.HideString(str, 3, 7, "*")
|
||||
result4 := strutil.HideString(str, 7, 11, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAll">ContainsAll</span>
|
||||
|
||||
<p>判断字符串是否包括全部给定的子字符串切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainsAll(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KECtK2Os4zq)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAny">ContainsAny</span>
|
||||
|
||||
<p>判断字符串是否包括给定的子字符串切片中任意一个子字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainsAny(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dZGSSMB3LXE)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
|
||||
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
|
||||
|
||||
<p>删除字符串中的空格,当设置repalceAll为true时,删除全部空格,为false时,替换多个空格为1个空格。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveWhiteSpace(str string, repalceAll bool) string
|
||||
```
|
||||
|
||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HzLC9vsTwkf)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " hello \r\n \t world"
|
||||
|
||||
result1 := strutil.RemoveWhiteSpace(str, true)
|
||||
result2 := strutil.RemoveWhiteSpace(str, false)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// helloworld
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
@@ -34,19 +34,19 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation 文档
|
||||
## 文档
|
||||
|
||||
### <span id="IsWindows">IsWindows</span>
|
||||
|
||||
<p>检查当前操作系统是否是windows</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsWindows() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zIflQgZNuxD)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -64,13 +64,13 @@ func main() {
|
||||
|
||||
<p>检查当前操作系统是否是linux</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zIflQgZNuxD)</span></b>
|
||||
|
||||
```go
|
||||
func IsLinux() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -88,13 +88,13 @@ func main() {
|
||||
|
||||
<p>检查当前操作系统是否是macos</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsMac() bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Mg4Hjtyq7Zc)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -112,13 +112,13 @@ func main() {
|
||||
|
||||
<p>获取key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetOsEnv(key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/D88OYVCyjO-)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -142,13 +142,13 @@ func main() {
|
||||
|
||||
<p>设置由key命名的环境变量的值</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SetOsEnv(key, value string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/D88OYVCyjO-)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -172,13 +172,13 @@ func main() {
|
||||
|
||||
<p>删除单个环境变量</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveOsEnv(key string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/fqyq4b3xUFQ)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -210,13 +210,13 @@ func main() {
|
||||
|
||||
<p>获取key命名的环境变量值并与compareEnv进行比较</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func CompareOsEnv(key, comparedEnv string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/BciHrKYOHbp)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -243,13 +243,16 @@ func main() {
|
||||
|
||||
<p>执行shell命令,返回命令的stdout和stderr字符串,如果出现错误,则返回错误。参数`command`是一个完整的命令字符串,如ls-a(linux),dir(windows),ping 127.0.0.1。在linux中,使用/bin/bash-c执行命令,在windows中,使用powershell.exe执行命令。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
||||
type (
|
||||
Option func(*exec.Cmd)
|
||||
)
|
||||
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/n-2fLyZef-4)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
@@ -289,7 +292,7 @@ func main() {
|
||||
func GetOsBits() int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ml-_XH3gJbW)</span></b>
|
||||
|
||||
```go
|
||||
import (
|
||||
1198
docs/api/packages/tuple.md
Normal file
1198
docs/api/packages/tuple.md
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@ import (
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
|
||||
## 文档
|
||||
|
||||
### <span id="New">New</span>
|
||||
@@ -58,7 +59,7 @@ type XError struct {
|
||||
func New(format string, args ...any) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/w4oWZts7q7f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -87,7 +88,7 @@ func main() {
|
||||
func Wrap(cause error, message ...any) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/5385qT2dCi4)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -118,7 +119,7 @@ func main() {
|
||||
func Unwrap(err error) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/LKMLep723tu)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -153,24 +154,25 @@ func main() {
|
||||
func (e *XError) Wrap(cause error) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/RpjJ5u5sc97)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"github.com/duke-git/lancet/v2/xerror"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := xerror.New("wrong password")
|
||||
wrapErr := xerror.Wrap(err, "error")
|
||||
err1 := xerror.New("error").With("level", "high")
|
||||
err2 := err1.Wrap(errors.New("invalid username"))
|
||||
|
||||
fmt.Println(wrapErr.Error())
|
||||
fmt.Println(err2.Error())
|
||||
|
||||
// Output:
|
||||
// error: wrong password
|
||||
// Output:
|
||||
// error: invalid username
|
||||
}
|
||||
```
|
||||
|
||||
@@ -184,7 +186,7 @@ func main() {
|
||||
func (e *XError) Unwrap() error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/VUXJ8BST4c6)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -217,7 +219,7 @@ func main() {
|
||||
func (e *XError) With(key string, value any) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ow8UISXX_Dp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -249,7 +251,7 @@ func main() {
|
||||
func (e *XError) Id(id string) *XError
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/X6HBlsy58U9)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -286,7 +288,7 @@ func main() {
|
||||
func (e *XError) Is(target error) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/X6HBlsy58U9)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -323,7 +325,7 @@ func main() {
|
||||
func (e *XError) Values() map[string]any
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ow8UISXX_Dp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -356,7 +358,7 @@ func main() {
|
||||
func (e *XError) StackTrace() StackTrace
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/6FAvSQpa7pc)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -390,7 +392,7 @@ func main() {
|
||||
func (e *XError) Info() *errInfo
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/1ZX0ME1F-Jb)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -430,7 +432,7 @@ func main() {
|
||||
func (e *XError) Error() string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/w4oWZts7q7f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -459,7 +461,7 @@ func main() {
|
||||
func TryUnwrap[T any](val T, err error) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/acyZVkNZEeW)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
File diff suppressed because it is too large
Load Diff
70
docs/en/api/overview.md
Normal file
70
docs/en/api/overview.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# API Overview
|
||||
|
||||
<b>Lancet (Lancet) is a powerful, comprehensive, efficient and reusable go language tool function library. Contains 25 packages, more than 600 utility functions. Functions cover string processing, slice processing, network, concurrency, encryption and decryption, file processing, time/date, stream processing, iterators, and more.</b>
|
||||
|
||||
|
||||
<style>
|
||||
.package-title {
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.package-container {
|
||||
font-size: 16px;
|
||||
border: 1px dashed;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.package-cell {
|
||||
height: 40px;
|
||||
width: 140px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 40px;
|
||||
background: #ecefff;
|
||||
border: 1px solid;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<p class="package-title">Lancet function module</p>
|
||||
<div class="package-container">
|
||||
<div class="package-cell">algorithm</div>
|
||||
<div class="package-cell">compare</div>
|
||||
<div class="package-cell">concurrency</div>
|
||||
<div class="package-cell">condition</div>
|
||||
<div class="package-cell">convertor</div>
|
||||
<div class="package-cell">cryptor</div>
|
||||
<div class="package-cell">datastructure</div>
|
||||
<div class="package-cell">datetime</div>
|
||||
<div class="package-cell">fileutil</div>
|
||||
<div class="package-cell">formatter</div>
|
||||
<div class="package-cell">function</div>
|
||||
<div class="package-cell">iterator</div>
|
||||
<div class="package-cell">maputil</div>
|
||||
<div class="package-cell">mathutil</div>
|
||||
<div class="package-cell">netutil</div>
|
||||
<div class="package-cell">pointer</div>
|
||||
<div class="package-cell">random</div>
|
||||
<div class="package-cell">retry</div>
|
||||
<div class="package-cell">slice</div>
|
||||
<div class="package-cell">stream</div>
|
||||
<div class="package-cell">structs</div>
|
||||
<div class="package-cell">strutil</div>
|
||||
<div class="package-cell">system</div>
|
||||
<div class="package-cell">tuple</div>
|
||||
<div class="package-cell">validator</div>
|
||||
<div class="package-cell">xerror</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ import (
|
||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -99,7 +99,7 @@ func main() {
|
||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -162,7 +162,7 @@ func main() {
|
||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -210,7 +210,7 @@ func main() {
|
||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -258,7 +258,7 @@ func main() {
|
||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -306,7 +306,7 @@ func main() {
|
||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -354,7 +354,7 @@ func main() {
|
||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -402,7 +402,7 @@ func main() {
|
||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -451,7 +451,7 @@ func main() {
|
||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -502,7 +502,7 @@ func main() {
|
||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -553,7 +553,7 @@ func main() {
|
||||
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -596,7 +596,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
|
||||
func (l *LRUCache[K, V]) Len() int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
374
docs/en/api/packages/compare.md
Normal file
374
docs/en/api/packages/compare.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# Compare
|
||||
|
||||
Package compare provides a lightweight comparison function on any type.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/compare/compare.go](https://github.com/duke-git/lancet/blob/main/compare/compare.go)
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Usage:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/condition"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
|
||||
- [Equal](#Equal)
|
||||
- [EqualValue](#EqualValue)
|
||||
- [LessThan](#LessThan)
|
||||
- [GreaterThan](#GreaterThan)
|
||||
- [LessOrEqual](#LessOrEqual)
|
||||
- [GreaterOrEqual](#GreaterOrEqual)
|
||||
- [InDelta](#InDelta)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
### <span id="Equal">Equal</span>
|
||||
|
||||
<p>Checks if two values are equal or not. (check both type and value)</p>
|
||||
|
||||
<b>Signature: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/wmVxR-to4lz)</span></b>
|
||||
|
||||
```go
|
||||
func Equal(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.Equal(1, 1)
|
||||
result2 := compare.Equal("1", "1")
|
||||
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||
|
||||
result5 := compare.Equal(1, "1")
|
||||
result6 := compare.Equal(1, int64(1))
|
||||
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="EqualValue">EqualValue</span>
|
||||
|
||||
<p>Checks if two values are equal or not. (check value only)</p>
|
||||
|
||||
<b>Signature: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/fxnna_LLD9u)</span></b>
|
||||
|
||||
```go
|
||||
func EqualValue(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.EqualValue(1, 1)
|
||||
result2 := compare.EqualValue(int(1), int64(1))
|
||||
result3 := compare.EqualValue(1, "1")
|
||||
result4 := compare.EqualValue(1, "2")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LessThan">LessThan</span>
|
||||
|
||||
<p>Checks if value `left` less than value `right`.</p>
|
||||
|
||||
<b>Signature: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/cYh7FQQj0ne)</span></b>
|
||||
|
||||
```go
|
||||
func LessThan(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.LessThan(1, 2)
|
||||
result2 := compare.LessThan(1.1, 2.2)
|
||||
result3 := compare.LessThan("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.LessThan(time1, time2)
|
||||
|
||||
result5 := compare.LessThan(2, 1)
|
||||
result6 := compare.LessThan(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GreaterThan">GreaterThan</span>
|
||||
|
||||
<p>Checks if value `left` greater than value `right`.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GreaterThan(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/9-NYDFZmIMp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.GreaterThan(2, 1)
|
||||
result2 := compare.GreaterThan(2.2, 1.1)
|
||||
result3 := compare.GreaterThan("b", "a")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.GreaterThan(time2, time1)
|
||||
|
||||
result5 := compare.GreaterThan(1, 2)
|
||||
result6 := compare.GreaterThan(int64(2), 1)
|
||||
result7 := compare.GreaterThan("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LessOrEqual">LessOrEqual</span>
|
||||
|
||||
<p>Checks if value `left` less than or equal than value `right`.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LessOrEqual(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/e4T_scwoQzp)</span></b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.LessOrEqual(1, 1)
|
||||
result2 := compare.LessOrEqual(1.1, 2.2)
|
||||
result3 := compare.LessOrEqual("a", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.LessOrEqual(time1, time2)
|
||||
|
||||
result5 := compare.LessOrEqual(2, 1)
|
||||
result6 := compare.LessOrEqual(1, int64(2))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GreaterOrEqual">GreaterOrEqual</span>
|
||||
|
||||
<p>Checks if value `left` less greater or equal than value `right`.</p>
|
||||
|
||||
<b>Signature: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/vx8mP0U8DFk)</span></b>
|
||||
|
||||
```go
|
||||
func GreaterOrEqual(left, right any) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := compare.GreaterOrEqual(1, 1)
|
||||
result2 := compare.GreaterOrEqual(2.2, 1.1)
|
||||
result3 := compare.GreaterOrEqual("b", "b")
|
||||
|
||||
time1 := time.Now()
|
||||
time2 := time1.Add(time.Second)
|
||||
result4 := compare.GreaterOrEqual(time2, time1)
|
||||
|
||||
result5 := compare.GreaterOrEqual(1, 2)
|
||||
result6 := compare.GreaterOrEqual(int64(2), 1)
|
||||
result7 := compare.GreaterOrEqual("b", "c")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
fmt.Println(result7)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="InDelta">InDelta</span>
|
||||
|
||||
<p>Checks if two values are equal or not within a delta.</p>
|
||||
|
||||
<b>Signature: <span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/TuDdcNtMkjo)</span></b>
|
||||
|
||||
```go
|
||||
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/compare"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := InDelta(1, 1, 0)
|
||||
result2 := InDelta(1, 2, 0)
|
||||
|
||||
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
|
||||
result4 := InDelta(2.0/3.0, 0.0, 0.001)
|
||||
|
||||
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
|
||||
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
// true
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user