mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
339 Commits
v2.1.14
...
51f166d1d9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
66efe61834 | ||
|
|
94f7f3e0e5 | ||
|
|
9d2c9806d1 | ||
|
|
e523d4af6e | ||
|
|
f3801bcd8f | ||
|
|
5767aad303 | ||
|
|
f7aaa1ed2a | ||
|
|
ef19a414bc | ||
|
|
65704dea06 | ||
|
|
5eac358bb0 | ||
|
|
8e36ef5cef | ||
|
|
21b0d2ec0e | ||
|
|
32ca975204 | ||
|
|
ec740e442c | ||
|
|
ed98ad53ec | ||
|
|
af7b9d2710 | ||
|
|
f08b368001 | ||
|
|
be8a0558f8 | ||
|
|
46de539e22 | ||
|
|
36fb3abe9e | ||
|
|
fee8d325b7 | ||
|
|
8784be1583 | ||
|
|
84cd68de7f | ||
|
|
a774c060ce | ||
|
|
730f061b95 | ||
|
|
2eb08f3404 | ||
|
|
4c1496b648 | ||
|
|
c2ae784f27 | ||
|
|
e71cecefea | ||
|
|
572e53aa14 | ||
|
|
ca9ecb9c8a | ||
|
|
8bf0786abe | ||
|
|
61cb8395e3 | ||
|
|
dde8a41daf | ||
|
|
d7518e01af | ||
|
|
be9fa7acaa | ||
|
|
2629a731cc | ||
|
|
54c7f90b7f | ||
|
|
770bc88b88 | ||
|
|
4cc1722f81 | ||
|
|
d0260b2841 | ||
|
|
57bd64cae7 | ||
|
|
c383719496 | ||
|
|
4b196a72b1 | ||
|
|
888381a06c | ||
|
|
a554eb7ef4 | ||
|
|
26ff90122b | ||
|
|
75b27c6540 | ||
|
|
a7e77fa98d | ||
|
|
abf392117a | ||
|
|
d231d9f572 | ||
|
|
97447d058e | ||
|
|
040e112aa6 | ||
|
|
afb021b4b5 | ||
|
|
5075774000 | ||
|
|
6bba44dc50 | ||
|
|
422022c74d | ||
|
|
87fcf97e2d | ||
|
|
05d1f348d4 | ||
|
|
6f2f1f3004 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -6,5 +6,9 @@ fileutil/*.txt
|
|||||||
fileutil/*.zip
|
fileutil/*.zip
|
||||||
fileutil/*.link
|
fileutil/*.link
|
||||||
fileutil/unzip/*
|
fileutil/unzip/*
|
||||||
|
fileutil/tempdir/*
|
||||||
slice/testdata/*
|
slice/testdata/*
|
||||||
cryptor/*.pem
|
cryptor/*.pem
|
||||||
|
test
|
||||||
|
docs/node_modules
|
||||||
|
docs/.vitepress/cache
|
||||||
1028
README_zh-CN.md
1028
README_zh-CN.md
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLRUCache(t *testing.T) {
|
func TestLRUCache(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestLRUCache")
|
asssert := internal.NewAssert(t, "TestLRUCache")
|
||||||
|
|
||||||
cache := NewLRUCache[int, int](3)
|
cache := NewLRUCache[int, int](3)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLinearSearch(t *testing.T) {
|
func TestLinearSearch(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestLinearSearch")
|
asssert := internal.NewAssert(t, "TestLinearSearch")
|
||||||
|
|
||||||
numbers := []int{3, 4, 5, 3, 2, 1}
|
numbers := []int{3, 4, 5, 3, 2, 1}
|
||||||
@@ -19,6 +20,7 @@ func TestLinearSearch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBinarySearch(t *testing.T) {
|
func TestBinarySearch(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestBinarySearch")
|
asssert := internal.NewAssert(t, "TestBinarySearch")
|
||||||
|
|
||||||
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
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) {
|
func TestBubbleSortForStructSlice(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -65,6 +66,7 @@ func TestBubbleSortForStructSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBubbleSortForIntSlice(t *testing.T) {
|
func TestBubbleSortForIntSlice(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
|
||||||
|
|
||||||
numbers := []int{2, 1, 5, 3, 6, 4}
|
numbers := []int{2, 1, 5, 3, 6, 4}
|
||||||
@@ -75,6 +77,7 @@ func TestBubbleSortForIntSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInsertionSort(t *testing.T) {
|
func TestInsertionSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestInsertionSort")
|
asssert := internal.NewAssert(t, "TestInsertionSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -94,6 +97,7 @@ func TestInsertionSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSelectionSort(t *testing.T) {
|
func TestSelectionSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestSelectionSort")
|
asssert := internal.NewAssert(t, "TestSelectionSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -113,6 +117,7 @@ func TestSelectionSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShellSort(t *testing.T) {
|
func TestShellSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestShellSort")
|
asssert := internal.NewAssert(t, "TestShellSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -132,6 +137,7 @@ func TestShellSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestQuickSort(t *testing.T) {
|
func TestQuickSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestQuickSort")
|
asssert := internal.NewAssert(t, "TestQuickSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -151,6 +157,7 @@ func TestQuickSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHeapSort(t *testing.T) {
|
func TestHeapSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestHeapSort")
|
asssert := internal.NewAssert(t, "TestHeapSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -170,6 +177,7 @@ func TestHeapSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMergeSort(t *testing.T) {
|
func TestMergeSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestMergeSort")
|
asssert := internal.NewAssert(t, "TestMergeSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -189,6 +197,7 @@ func TestMergeSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCountSort(t *testing.T) {
|
func TestCountSort(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
asssert := internal.NewAssert(t, "TestCountSort")
|
asssert := internal.NewAssert(t, "TestCountSort")
|
||||||
|
|
||||||
peoples := []people{
|
peoples := []people{
|
||||||
@@ -200,7 +209,6 @@ func TestCountSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
comparator := &peopleAgeComparator{}
|
comparator := &peopleAgeComparator{}
|
||||||
sortedPeopleByAge := CountSort(peoples, comparator)
|
sortedPeopleByAge := CountSort(peoples, comparator)
|
||||||
t.Log(sortedPeopleByAge)
|
|
||||||
|
|
||||||
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
|
||||||
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
actual := fmt.Sprintf("%v", sortedPeopleByAge)
|
||||||
|
|||||||
71
compare/compare.go
Normal file
71
compare/compare.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// 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.
|
||||||
|
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.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// 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
|
package concurrency
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerate(t *testing.T) {
|
func TestGenerate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestGenerate")
|
assert := internal.NewAssert(t, "TestGenerate")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -23,6 +24,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRepeat(t *testing.T) {
|
func TestRepeat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestRepeat")
|
assert := internal.NewAssert(t, "TestRepeat")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -39,6 +41,7 @@ func TestRepeat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRepeatFn(t *testing.T) {
|
func TestRepeatFn(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestRepeatFn")
|
assert := internal.NewAssert(t, "TestRepeatFn")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -57,6 +60,7 @@ func TestRepeatFn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTake(t *testing.T) {
|
func TestTake(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestTake")
|
assert := internal.NewAssert(t, "TestTake")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -79,6 +83,7 @@ func TestTake(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFanIn(t *testing.T) {
|
func TestFanIn(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestFanIn")
|
assert := internal.NewAssert(t, "TestFanIn")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -101,6 +106,7 @@ func TestFanIn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOr(t *testing.T) {
|
func TestOr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestOr")
|
assert := internal.NewAssert(t, "TestOr")
|
||||||
|
|
||||||
sig := func(after time.Duration) <-chan any {
|
sig := func(after time.Duration) <-chan any {
|
||||||
@@ -127,6 +133,7 @@ func TestOr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOrDone(t *testing.T) {
|
func TestOrDone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestOrDone")
|
assert := internal.NewAssert(t, "TestOrDone")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -141,6 +148,7 @@ func TestOrDone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTee(t *testing.T) {
|
func TestTee(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestTee")
|
assert := internal.NewAssert(t, "TestTee")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -159,6 +167,7 @@ func TestTee(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBridge(t *testing.T) {
|
func TestBridge(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestBridge")
|
assert := internal.NewAssert(t, "TestBridge")
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
@@ -181,7 +190,6 @@ func TestBridge(t *testing.T) {
|
|||||||
|
|
||||||
index := 0
|
index := 0
|
||||||
for val := range c.Bridge(ctx, genVals()) {
|
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)
|
assert.Equal(index, val)
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
type TestStruct struct{}
|
type TestStruct struct{}
|
||||||
|
|
||||||
func TestBool(t *testing.T) {
|
func TestBool(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBool")
|
assert := internal.NewAssert(t, "TestBool")
|
||||||
|
|
||||||
// bool
|
// bool
|
||||||
@@ -63,6 +65,8 @@ func TestBool(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAnd(t *testing.T) {
|
func TestAnd(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestAnd")
|
assert := internal.NewAssert(t, "TestAnd")
|
||||||
assert.Equal(false, And(0, 1))
|
assert.Equal(false, And(0, 1))
|
||||||
assert.Equal(false, And(0, ""))
|
assert.Equal(false, And(0, ""))
|
||||||
@@ -71,6 +75,8 @@ func TestAnd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOr(t *testing.T) {
|
func TestOr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestOr")
|
assert := internal.NewAssert(t, "TestOr")
|
||||||
assert.Equal(false, Or(0, ""))
|
assert.Equal(false, Or(0, ""))
|
||||||
assert.Equal(true, Or(0, 1))
|
assert.Equal(true, Or(0, 1))
|
||||||
@@ -79,6 +85,8 @@ func TestOr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestXor(t *testing.T) {
|
func TestXor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestOr")
|
assert := internal.NewAssert(t, "TestOr")
|
||||||
assert.Equal(false, Xor(0, 0))
|
assert.Equal(false, Xor(0, 0))
|
||||||
assert.Equal(true, Xor(0, 1))
|
assert.Equal(true, Xor(0, 1))
|
||||||
@@ -87,6 +95,8 @@ func TestXor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNor(t *testing.T) {
|
func TestNor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestNor")
|
assert := internal.NewAssert(t, "TestNor")
|
||||||
assert.Equal(true, Nor(0, 0))
|
assert.Equal(true, Nor(0, 0))
|
||||||
assert.Equal(false, Nor(0, 1))
|
assert.Equal(false, Nor(0, 1))
|
||||||
@@ -95,6 +105,8 @@ func TestNor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestXnor(t *testing.T) {
|
func TestXnor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestXnor")
|
assert := internal.NewAssert(t, "TestXnor")
|
||||||
assert.Equal(true, Xnor(0, 0))
|
assert.Equal(true, Xnor(0, 0))
|
||||||
assert.Equal(false, Xnor(0, 1))
|
assert.Equal(false, Xnor(0, 1))
|
||||||
@@ -103,6 +115,8 @@ func TestXnor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNand(t *testing.T) {
|
func TestNand(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestNand")
|
assert := internal.NewAssert(t, "TestNand")
|
||||||
assert.Equal(true, Nand(0, 0))
|
assert.Equal(true, Nand(0, 0))
|
||||||
assert.Equal(true, Nand(0, 1))
|
assert.Equal(true, Nand(0, 1))
|
||||||
@@ -111,7 +125,10 @@ func TestNand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTernaryOperator(t *testing.T) {
|
func TestTernaryOperator(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TernaryOperator")
|
assert := internal.NewAssert(t, "TernaryOperator")
|
||||||
|
|
||||||
trueValue := "1"
|
trueValue := "1"
|
||||||
falseValue := "0"
|
falseValue := "0"
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,17 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/structs"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
"golang.org/x/text/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToBool convert string to boolean.
|
// ToBool convert string to boolean.
|
||||||
@@ -234,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.
|
// map key is specified same as struct field tag `json` value.
|
||||||
// Play: https://go.dev/play/p/KYGYJqNUBOI
|
// Play: https://go.dev/play/p/KYGYJqNUBOI
|
||||||
func StructToMap(value any) (map[string]any, error) {
|
func StructToMap(value any) (map[string]any, error) {
|
||||||
v := reflect.ValueOf(value)
|
return structs.ToMap(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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapToSlice convert map to slice based on iteratee function.
|
// MapToSlice convert map to slice based on iteratee function.
|
||||||
@@ -324,3 +305,92 @@ func DecodeByte(data []byte, target any) error {
|
|||||||
decoder := gob.NewDecoder(buffer)
|
decoder := gob.NewDecoder(buffer)
|
||||||
return decoder.Decode(target)
|
return decoder.Decode(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepClone creates a deep copy of passed item.
|
||||||
|
// can't clone unexported field of struct
|
||||||
|
// Play: https://go.dev/play/p/j4DP5dquxnk
|
||||||
|
func DeepClone[T any](src T) T {
|
||||||
|
c := cloner{
|
||||||
|
ptrs: map[reflect.Type]map[uintptr]reflect.Value{},
|
||||||
|
}
|
||||||
|
result := c.clone(reflect.ValueOf(src))
|
||||||
|
if result.Kind() == reflect.Invalid {
|
||||||
|
var zeroValue T
|
||||||
|
return zeroValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Interface().(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
||||||
|
// 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: parameter dst should be struct pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcType.Kind() == reflect.Ptr {
|
||||||
|
srcType = srcType.Elem()
|
||||||
|
}
|
||||||
|
if srcType.Kind() != reflect.Struct {
|
||||||
|
return errors.New("CopyProperties: parameter src should be a struct or struct pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleToBool() {
|
func ExampleToBool() {
|
||||||
@@ -252,3 +256,138 @@ func ExampleDecodeByte() {
|
|||||||
// Output:
|
// Output:
|
||||||
// abc
|
// abc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleDeepClone() {
|
||||||
|
type Struct struct {
|
||||||
|
Str string
|
||||||
|
Int int
|
||||||
|
Float float64
|
||||||
|
Bool bool
|
||||||
|
Nil interface{}
|
||||||
|
// unexported string
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []interface{}{
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
},
|
||||||
|
&Struct{
|
||||||
|
Str: "test",
|
||||||
|
Int: 1,
|
||||||
|
Float: 0.1,
|
||||||
|
Bool: true,
|
||||||
|
Nil: nil,
|
||||||
|
// unexported: "can't be cloned",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range cases {
|
||||||
|
cloned := DeepClone(item)
|
||||||
|
|
||||||
|
isPointerEqual := &cloned == &item
|
||||||
|
fmt.Println(cloned, isPointerEqual)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true false
|
||||||
|
// 1 false
|
||||||
|
// 0.1 false
|
||||||
|
// map[a:1 b:2] false
|
||||||
|
// &{test 1 0.1 true <nil>} false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleCopyProperties() {
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
fmt.Println(indicatorVO.Id)
|
||||||
|
fmt.Println(indicatorVO.Ip)
|
||||||
|
fmt.Println(len(indicatorVO.Disk))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|||||||
216
convertor/convertor_internal.go
Normal file
216
convertor/convertor_internal.go
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
// Copyright 2023 dudaodong@gmail.com. All rights reserved.
|
||||||
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
|
// Package convertor implements some functions to convert data.
|
||||||
|
package convertor
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type cloner struct {
|
||||||
|
ptrs map[reflect.Type]map[uintptr]reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone return a duplicate of passed item.
|
||||||
|
func (c *cloner) clone(v reflect.Value) reflect.Value {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Invalid:
|
||||||
|
return reflect.ValueOf(nil)
|
||||||
|
|
||||||
|
// bool
|
||||||
|
case reflect.Bool:
|
||||||
|
return reflect.ValueOf(v.Bool())
|
||||||
|
|
||||||
|
//int
|
||||||
|
case reflect.Int:
|
||||||
|
return reflect.ValueOf(int(v.Int()))
|
||||||
|
case reflect.Int8:
|
||||||
|
return reflect.ValueOf(int8(v.Int()))
|
||||||
|
case reflect.Int16:
|
||||||
|
return reflect.ValueOf(int16(v.Int()))
|
||||||
|
case reflect.Int32:
|
||||||
|
return reflect.ValueOf(int32(v.Int()))
|
||||||
|
case reflect.Int64:
|
||||||
|
return reflect.ValueOf(v.Int())
|
||||||
|
|
||||||
|
// uint
|
||||||
|
case reflect.Uint:
|
||||||
|
return reflect.ValueOf(uint(v.Uint()))
|
||||||
|
case reflect.Uint8:
|
||||||
|
return reflect.ValueOf(uint8(v.Uint()))
|
||||||
|
case reflect.Uint16:
|
||||||
|
return reflect.ValueOf(uint16(v.Uint()))
|
||||||
|
case reflect.Uint32:
|
||||||
|
return reflect.ValueOf(uint32(v.Uint()))
|
||||||
|
case reflect.Uint64:
|
||||||
|
return reflect.ValueOf(v.Uint())
|
||||||
|
|
||||||
|
// float
|
||||||
|
case reflect.Float32:
|
||||||
|
return reflect.ValueOf(float32(v.Float()))
|
||||||
|
case reflect.Float64:
|
||||||
|
return reflect.ValueOf(v.Float())
|
||||||
|
|
||||||
|
// complex
|
||||||
|
case reflect.Complex64:
|
||||||
|
return reflect.ValueOf(complex64(v.Complex()))
|
||||||
|
case reflect.Complex128:
|
||||||
|
return reflect.ValueOf(v.Complex())
|
||||||
|
|
||||||
|
// string
|
||||||
|
case reflect.String:
|
||||||
|
return reflect.ValueOf(v.String())
|
||||||
|
|
||||||
|
// array
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
return c.cloneArray(v)
|
||||||
|
|
||||||
|
// map
|
||||||
|
case reflect.Map:
|
||||||
|
return c.cloneMap(v)
|
||||||
|
|
||||||
|
// Ptr
|
||||||
|
case reflect.Ptr:
|
||||||
|
return c.clonePtr(v)
|
||||||
|
|
||||||
|
// struct
|
||||||
|
case reflect.Struct:
|
||||||
|
return c.cloneStruct(v)
|
||||||
|
|
||||||
|
// func
|
||||||
|
case reflect.Func:
|
||||||
|
return v
|
||||||
|
|
||||||
|
// interface
|
||||||
|
case reflect.Interface:
|
||||||
|
return c.clone(v.Elem())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.Zero(v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cloner) cloneArray(v reflect.Value) reflect.Value {
|
||||||
|
if v.IsNil() {
|
||||||
|
return reflect.Zero(v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
arr := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
|
||||||
|
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
val := c.clone(v.Index(i))
|
||||||
|
|
||||||
|
if val.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
item := arr.Index(i)
|
||||||
|
if !item.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Set(val.Convert(item.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cloner) cloneMap(v reflect.Value) reflect.Value {
|
||||||
|
if v.IsNil() {
|
||||||
|
return reflect.Zero(v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
clonedMap := reflect.MakeMap(v.Type())
|
||||||
|
|
||||||
|
for _, key := range v.MapKeys() {
|
||||||
|
value := v.MapIndex(key)
|
||||||
|
clonedKey := c.clone(key)
|
||||||
|
clonedValue := c.clone(value)
|
||||||
|
|
||||||
|
if !isNillable(clonedKey) || !clonedKey.IsNil() {
|
||||||
|
clonedKey = clonedKey.Convert(key.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNillable(clonedValue) || !clonedValue.IsNil()) && clonedValue.IsValid() {
|
||||||
|
clonedValue = clonedValue.Convert(value.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !clonedValue.IsValid() {
|
||||||
|
clonedValue = reflect.Zero(clonedMap.Type().Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
clonedMap.SetMapIndex(clonedKey, clonedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return clonedMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNillable(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Chan, reflect.Interface, reflect.Ptr, reflect.Func:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cloner) clonePtr(v reflect.Value) reflect.Value {
|
||||||
|
if v.IsNil() {
|
||||||
|
return reflect.Zero(v.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
var newVal reflect.Value
|
||||||
|
|
||||||
|
if v.Elem().CanAddr() {
|
||||||
|
ptrs, exists := c.ptrs[v.Type()]
|
||||||
|
if exists {
|
||||||
|
if newVal, exists := ptrs[v.Elem().UnsafeAddr()]; exists {
|
||||||
|
return newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newVal = c.clone(v.Elem())
|
||||||
|
|
||||||
|
if v.Elem().CanAddr() {
|
||||||
|
ptrs, exists := c.ptrs[v.Type()]
|
||||||
|
if exists {
|
||||||
|
if newVal, exists := ptrs[v.Elem().UnsafeAddr()]; exists {
|
||||||
|
return newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clonedPtr := reflect.New(newVal.Type())
|
||||||
|
clonedPtr.Elem().Set(newVal)
|
||||||
|
|
||||||
|
return clonedPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cloner) cloneStruct(v reflect.Value) reflect.Value {
|
||||||
|
clonedStructPtr := reflect.New(v.Type())
|
||||||
|
clonedStruct := clonedStructPtr.Elem()
|
||||||
|
|
||||||
|
if v.CanAddr() {
|
||||||
|
ptrs := c.ptrs[clonedStructPtr.Type()]
|
||||||
|
if ptrs == nil {
|
||||||
|
ptrs = make(map[uintptr]reflect.Value)
|
||||||
|
c.ptrs[clonedStructPtr.Type()] = ptrs
|
||||||
|
}
|
||||||
|
ptrs[v.UnsafeAddr()] = clonedStructPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
newStructValue := clonedStruct.Field(i)
|
||||||
|
if !newStructValue.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
clonedVal := c.clone(v.Field(i))
|
||||||
|
if !clonedVal.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newStructValue.Set(clonedVal.Convert(newStructValue.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return clonedStruct
|
||||||
|
}
|
||||||
@@ -2,14 +2,19 @@ package convertor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
"github.com/duke-git/lancet/v2/slice"
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToChar(t *testing.T) {
|
func TestToChar(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToChar")
|
assert := internal.NewAssert(t, "TestToChar")
|
||||||
|
|
||||||
cases := []string{"", "abc", "1 2#3"}
|
cases := []string{"", "abc", "1 2#3"}
|
||||||
@@ -24,6 +29,8 @@ func TestToChar(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToChannel(t *testing.T) {
|
func TestToChannel(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToChannel")
|
assert := internal.NewAssert(t, "TestToChannel")
|
||||||
|
|
||||||
ch := ToChannel([]int{1, 2, 3})
|
ch := ToChannel([]int{1, 2, 3})
|
||||||
@@ -36,6 +43,8 @@ func TestToChannel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToBool(t *testing.T) {
|
func TestToBool(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToBool")
|
assert := internal.NewAssert(t, "TestToBool")
|
||||||
|
|
||||||
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
|
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
|
||||||
@@ -48,6 +57,8 @@ func TestToBool(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToBytes(t *testing.T) {
|
func TestToBytes(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToBytes")
|
assert := internal.NewAssert(t, "TestToBytes")
|
||||||
|
|
||||||
cases := []any{
|
cases := []any{
|
||||||
@@ -74,6 +85,8 @@ func TestToBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToInt(t *testing.T) {
|
func TestToInt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToInt")
|
assert := internal.NewAssert(t, "TestToInt")
|
||||||
|
|
||||||
cases := []any{"123", "-123", 123,
|
cases := []any{"123", "-123", 123,
|
||||||
@@ -90,6 +103,8 @@ func TestToInt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToFloat(t *testing.T) {
|
func TestToFloat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToFloat")
|
assert := internal.NewAssert(t, "TestToFloat")
|
||||||
|
|
||||||
cases := []any{
|
cases := []any{
|
||||||
@@ -108,6 +123,8 @@ func TestToFloat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToString(t *testing.T) {
|
func TestToString(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToString")
|
assert := internal.NewAssert(t, "TestToString")
|
||||||
|
|
||||||
aMap := make(map[string]int)
|
aMap := make(map[string]int)
|
||||||
@@ -143,6 +160,8 @@ func TestToString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestToJson(t *testing.T) {
|
func TestToJson(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToJson")
|
assert := internal.NewAssert(t, "TestToJson")
|
||||||
|
|
||||||
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
|
||||||
@@ -158,6 +177,8 @@ func TestToJson(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToMap(t *testing.T) {
|
func TestToMap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToMap")
|
assert := internal.NewAssert(t, "TestToMap")
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
@@ -177,23 +198,45 @@ func TestToMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStructToMap(t *testing.T) {
|
func TestStructToMap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestStructToMap")
|
assert := internal.NewAssert(t, "TestStructToMap")
|
||||||
|
|
||||||
type People struct {
|
t.Run("StructToMap", func(_ *testing.T) {
|
||||||
Name string `json:"name"`
|
type People struct {
|
||||||
age int
|
Name string `json:"name"`
|
||||||
}
|
age int
|
||||||
p := People{
|
}
|
||||||
"test",
|
p := People{
|
||||||
100,
|
"test",
|
||||||
}
|
100,
|
||||||
pm, _ := StructToMap(p)
|
}
|
||||||
|
pm, _ := StructToMap(p)
|
||||||
|
var expected = map[string]any{"name": "test"}
|
||||||
|
assert.Equal(expected, pm)
|
||||||
|
})
|
||||||
|
|
||||||
expected := map[string]any{"name": "test"}
|
t.Run("StructToMapWithJsonAttr", func(_ *testing.T) {
|
||||||
assert.Equal(expected, pm)
|
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) {
|
func TestMapToSlice(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMapToSlice")
|
assert := internal.NewAssert(t, "TestMapToSlice")
|
||||||
|
|
||||||
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
|
||||||
@@ -208,6 +251,8 @@ func TestMapToSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestColorHexToRGB(t *testing.T) {
|
func TestColorHexToRGB(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
colorHex := "#003366"
|
colorHex := "#003366"
|
||||||
r, g, b := ColorHexToRGB(colorHex)
|
r, g, b := ColorHexToRGB(colorHex)
|
||||||
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
|
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
|
||||||
@@ -218,6 +263,8 @@ func TestColorHexToRGB(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestColorRGBToHex(t *testing.T) {
|
func TestColorRGBToHex(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
r := 0
|
r := 0
|
||||||
g := 51
|
g := 51
|
||||||
b := 102
|
b := 102
|
||||||
@@ -229,6 +276,8 @@ func TestColorRGBToHex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToPointer(t *testing.T) {
|
func TestToPointer(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToPointer")
|
assert := internal.NewAssert(t, "TestToPointer")
|
||||||
result := ToPointer(123)
|
result := ToPointer(123)
|
||||||
|
|
||||||
@@ -236,6 +285,8 @@ func TestToPointer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEncodeByte(t *testing.T) {
|
func TestEncodeByte(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEncodeByte")
|
assert := internal.NewAssert(t, "TestEncodeByte")
|
||||||
|
|
||||||
byteData, _ := EncodeByte("abc")
|
byteData, _ := EncodeByte("abc")
|
||||||
@@ -245,6 +296,8 @@ func TestEncodeByte(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDecodeByte(t *testing.T) {
|
func TestDecodeByte(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDecodeByte")
|
assert := internal.NewAssert(t, "TestDecodeByte")
|
||||||
|
|
||||||
var obj string
|
var obj string
|
||||||
@@ -253,3 +306,157 @@ func TestDecodeByte(t *testing.T) {
|
|||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal("abc", obj)
|
assert.Equal("abc", obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []interface{}{
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
},
|
||||||
|
&Struct{
|
||||||
|
Str: "test",
|
||||||
|
Int: 1,
|
||||||
|
Float: 0.1,
|
||||||
|
Bool: true,
|
||||||
|
Nil: nil,
|
||||||
|
// unexported: "can't be cloned",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, item := range cases {
|
||||||
|
cloned := DeepClone(item)
|
||||||
|
|
||||||
|
if &cloned == &item {
|
||||||
|
t.Fatalf("[TestDeepClone case #%d failed]: equal pointer", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(item, cloned) {
|
||||||
|
t.Fatalf("[TestDeepClone case #%d failed] unequal objects", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyProperties(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestCopyProperties")
|
||||||
|
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
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))
|
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.
|
// Md5File return the md5 value of file.
|
||||||
func Md5File(filename string) (string, error) {
|
func Md5File(filename string) (string, error) {
|
||||||
if fileInfo, err := os.Stat(filename); err != nil {
|
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.
|
// HmacMd5 return the hmac hash of string use md5.
|
||||||
// Play: https://go.dev/play/p/uef0q1fz53I
|
// 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.
|
||||||
|
// todo
|
||||||
|
func HmacMd5WithBase64(data, key string) string {
|
||||||
h := hmac.New(md5.New, []byte(key))
|
h := hmac.New(md5.New, []byte(key))
|
||||||
h.Write([]byte(data))
|
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.
|
// HmacSha1 return the hmac hash of string use sha1.
|
||||||
// Play: https://go.dev/play/p/1UI4oQ4WXKM
|
// 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 := hmac.New(sha1.New, []byte(key))
|
||||||
h.Write([]byte(data))
|
h.Write([]byte(str))
|
||||||
return hex.EncodeToString(h.Sum([]byte("")))
|
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.
|
// HmacSha256 return the hmac hash of string use sha256.
|
||||||
// Play: https://go.dev/play/p/HhpwXxFhhC0
|
// 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 := hmac.New(sha256.New, []byte(key))
|
||||||
h.Write([]byte(data))
|
h.Write([]byte(str))
|
||||||
return hex.EncodeToString(h.Sum([]byte("")))
|
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.
|
// HmacSha512 return the hmac hash of string use sha512.
|
||||||
// Play: https://go.dev/play/p/59Od6m4A0Ud
|
// 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 := hmac.New(sha512.New, []byte(key))
|
||||||
h.Write([]byte(data))
|
h.Write([]byte(str))
|
||||||
return hex.EncodeToString(h.Sum([]byte("")))
|
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.
|
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
|
||||||
// Play: https://go.dev/play/p/_m_uoD1deMT
|
// Play: https://go.dev/play/p/_m_uoD1deMT
|
||||||
func Sha1(data string) string {
|
func Sha1(str string) string {
|
||||||
sha1 := sha1.New()
|
sha1 := sha1.New()
|
||||||
sha1.Write([]byte(data))
|
sha1.Write([]byte(str))
|
||||||
return hex.EncodeToString(sha1.Sum([]byte("")))
|
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.
|
// Sha256 return the sha256 value (SHA256 hash algorithm) of string.
|
||||||
// Play: https://go.dev/play/p/tU9tfBMIAr1
|
// Play: https://go.dev/play/p/tU9tfBMIAr1
|
||||||
func Sha256(data string) string {
|
func Sha256(str string) string {
|
||||||
sha256 := sha256.New()
|
sha256 := sha256.New()
|
||||||
sha256.Write([]byte(data))
|
sha256.Write([]byte(str))
|
||||||
return hex.EncodeToString(sha256.Sum([]byte("")))
|
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.
|
// Sha512 return the sha512 value (SHA512 hash algorithm) of string.
|
||||||
// Play: https://go.dev/play/p/3WsvLYZxsHa
|
// Play: https://go.dev/play/p/3WsvLYZxsHa
|
||||||
func Sha512(data string) string {
|
func Sha512(str string) string {
|
||||||
sha512 := sha512.New()
|
sha512 := sha512.New()
|
||||||
sha512.Write([]byte(data))
|
sha512.Write([]byte(str))
|
||||||
return hex.EncodeToString(sha512.Sum([]byte("")))
|
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) {
|
func TestBase64StdEncode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBase64StdEncode")
|
assert := internal.NewAssert(t, "TestBase64StdEncode")
|
||||||
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
|
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBase64StdDecode(t *testing.T) {
|
func TestBase64StdDecode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBase64StdDecode")
|
assert := internal.NewAssert(t, "TestBase64StdDecode")
|
||||||
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
|
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMd5String(t *testing.T) {
|
func TestMd5String(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMd5String")
|
assert := internal.NewAssert(t, "TestMd5String")
|
||||||
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
|
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) {
|
func TestMd5File(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
fileMd5, err := Md5File("./basic.go")
|
fileMd5, err := Md5File("./basic.go")
|
||||||
assert := internal.NewAssert(t, "TestMd5File")
|
assert := internal.NewAssert(t, "TestMd5File")
|
||||||
assert.IsNotNil(fileMd5)
|
assert.IsNotNil(fileMd5)
|
||||||
@@ -29,11 +59,22 @@ func TestMd5File(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHmacMd5(t *testing.T) {
|
func TestHmacMd5(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestHmacMd5")
|
assert := internal.NewAssert(t, "TestHmacMd5")
|
||||||
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
|
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) {
|
func TestHmacSha1(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s := "hello world"
|
s := "hello world"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
hmacSha1 := HmacSha1(s, key)
|
hmacSha1 := HmacSha1(s, key)
|
||||||
@@ -43,17 +84,45 @@ func TestHmacSha1(t *testing.T) {
|
|||||||
assert.Equal(expected, hmacSha1)
|
assert.Equal(expected, hmacSha1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHmacSha256(t *testing.T) {
|
func TestHmacSha1WithBase64(t *testing.T) {
|
||||||
s := "hello world"
|
t.Parallel()
|
||||||
|
|
||||||
|
s := "hello"
|
||||||
key := "12345"
|
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"
|
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestHmacSha256")
|
assert := internal.NewAssert(t, "TestHmacSha256")
|
||||||
assert.Equal(expected, hmacSha256)
|
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) {
|
func TestHmacSha512(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s := "hello world"
|
s := "hello world"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
hmacSha512 := HmacSha512(s, key)
|
hmacSha512 := HmacSha512(s, key)
|
||||||
@@ -63,7 +132,21 @@ func TestHmacSha512(t *testing.T) {
|
|||||||
assert.Equal(expected, hmacSha512)
|
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) {
|
func TestSha1(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s := "hello world"
|
s := "hello world"
|
||||||
sha1 := Sha1(s)
|
sha1 := Sha1(s)
|
||||||
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
|
||||||
@@ -72,7 +155,19 @@ func TestSha1(t *testing.T) {
|
|||||||
assert.Equal(expected, sha1)
|
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) {
|
func TestSha256(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s := "hello world"
|
s := "hello world"
|
||||||
sha256 := Sha256(s)
|
sha256 := Sha256(s)
|
||||||
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
|
||||||
@@ -81,7 +176,19 @@ func TestSha256(t *testing.T) {
|
|||||||
assert.Equal(expected, sha256)
|
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) {
|
func TestSha512(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
s := "hello world"
|
s := "hello world"
|
||||||
sha512 := Sha512(s)
|
sha512 := Sha512(s)
|
||||||
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
|
||||||
@@ -89,3 +196,13 @@ func TestSha512(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestSha512")
|
assert := internal.NewAssert(t, "TestSha512")
|
||||||
assert.Equal(expected, sha512)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ import (
|
|||||||
// len(key) should be 16, 24 or 32.
|
// len(key) should be 16, 24 or 32.
|
||||||
// Play: https://go.dev/play/p/jT5irszHx-j
|
// Play: https://go.dev/play/p/jT5irszHx-j
|
||||||
func AesEcbEncrypt(data, key []byte) []byte {
|
func AesEcbEncrypt(data, key []byte) []byte {
|
||||||
|
size := len(key)
|
||||||
|
if size != 16 && size != 24 && size != 32 {
|
||||||
|
panic("key length shoud be 16 or 24 or 32")
|
||||||
|
}
|
||||||
|
|
||||||
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||||||
plain := make([]byte, length*aes.BlockSize)
|
plain := make([]byte, length*aes.BlockSize)
|
||||||
|
|
||||||
@@ -34,7 +39,7 @@ func AesEcbEncrypt(data, key []byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encrypted := make([]byte, len(plain))
|
encrypted := make([]byte, len(plain))
|
||||||
cipher, _ := aes.NewCipher(generateAesKey(key))
|
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||||
|
|
||||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||||
@@ -47,7 +52,11 @@ func AesEcbEncrypt(data, key []byte) []byte {
|
|||||||
// len(key) should be 16, 24 or 32.
|
// len(key) should be 16, 24 or 32.
|
||||||
// Play: https://go.dev/play/p/jT5irszHx-j
|
// Play: https://go.dev/play/p/jT5irszHx-j
|
||||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||||
cipher, _ := aes.NewCipher(generateAesKey(key))
|
size := len(key)
|
||||||
|
if size != 16 && size != 24 && size != 32 {
|
||||||
|
panic("key length shoud be 16 or 24 or 32")
|
||||||
|
}
|
||||||
|
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||||
decrypted := make([]byte, len(encrypted))
|
decrypted := make([]byte, len(encrypted))
|
||||||
|
|
||||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||||
@@ -322,89 +322,165 @@ func ExampleHmacMd5() {
|
|||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := HmacMd5(str, key)
|
hms := HmacMd5(str, key)
|
||||||
|
|
||||||
fmt.Println(hms)
|
fmt.Println(hms)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// e834306eab892d872525d4918a7a639a
|
// e834306eab892d872525d4918a7a639a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleHmacMd5WithBase64() {
|
||||||
|
str := "hello"
|
||||||
|
key := "12345"
|
||||||
|
|
||||||
|
hms := HmacMd5WithBase64(str, key)
|
||||||
|
fmt.Println(hms)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6DQwbquJLYclJdSRinpjmg==
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleHmacSha1() {
|
func ExampleHmacSha1() {
|
||||||
str := "hello"
|
str := "hello"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := HmacSha1(str, key)
|
hms := HmacSha1(str, key)
|
||||||
|
|
||||||
fmt.Println(hms)
|
fmt.Println(hms)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleHmacSha1WithBase64() {
|
||||||
|
str := "hello"
|
||||||
|
key := "12345"
|
||||||
|
|
||||||
|
hms := HmacSha1WithBase64(str, key)
|
||||||
|
fmt.Println(hms)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleHmacSha256() {
|
func ExampleHmacSha256() {
|
||||||
str := "hello"
|
str := "hello"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := HmacSha256(str, key)
|
hms := HmacSha256(str, key)
|
||||||
|
|
||||||
fmt.Println(hms)
|
fmt.Println(hms)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
|
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleHmacSha256WithBase64() {
|
||||||
|
str := "hello"
|
||||||
|
key := "12345"
|
||||||
|
|
||||||
|
hms := HmacSha256WithBase64(str, key)
|
||||||
|
fmt.Println(hms)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleHmacSha512() {
|
func ExampleHmacSha512() {
|
||||||
str := "hello"
|
str := "hello"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := HmacSha512(str, key)
|
hms := HmacSha512(str, key)
|
||||||
|
|
||||||
fmt.Println(hms)
|
fmt.Println(hms)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
|
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleMd5String() {
|
func ExampleHmacSha512WithBase64() {
|
||||||
str := "hello"
|
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)
|
fmt.Println(md5Str)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 5d41402abc4b2a76b9719d911017c592
|
// 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() {
|
func ExampleSha1() {
|
||||||
str := "hello"
|
result := Sha1("hello")
|
||||||
|
|
||||||
result := Sha1(str)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
|
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleSha1WithBase64() {
|
||||||
|
result := Sha1WithBase64("hello")
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleSha256() {
|
func ExampleSha256() {
|
||||||
str := "hello"
|
result := Sha256("hello")
|
||||||
|
|
||||||
result := Sha256(str)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
|
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleSha256WithBase64() {
|
||||||
|
result := Sha256WithBase64("hello")
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleSha512() {
|
func ExampleSha512() {
|
||||||
str := "hello"
|
result := Sha512("hello")
|
||||||
|
|
||||||
result := Sha512(str)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
|
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleSha512WithBase64() {
|
||||||
|
result := Sha512WithBase64("hello")
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package cryptor
|
|||||||
|
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
func generateAesKey(key []byte) []byte {
|
func generateAesKey(key []byte, size int) []byte {
|
||||||
genKey := make([]byte, 16)
|
genKey := make([]byte, size)
|
||||||
copy(genKey, key)
|
copy(genKey, key)
|
||||||
for i := 16; i < len(key); {
|
for i := size; i < len(key); {
|
||||||
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
|
for j := 0; j < size && i < len(key); j, i = j+1, i+1 {
|
||||||
genKey[j] ^= key[i]
|
genKey[j] ^= key[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAesEcbEncrypt(t *testing.T) {
|
func TestAesEcbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefghijklmnop"
|
key := "abcdefghijklmnop"
|
||||||
|
|
||||||
@@ -18,6 +20,8 @@ func TestAesEcbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAesCbcEncrypt(t *testing.T) {
|
func TestAesCbcEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefghijklmnop"
|
key := "abcdefghijklmnop"
|
||||||
|
|
||||||
@@ -29,6 +33,8 @@ func TestAesCbcEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAesCtrCrypt(t *testing.T) {
|
func TestAesCtrCrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefghijklmnop"
|
key := "abcdefghijklmnop"
|
||||||
|
|
||||||
@@ -40,6 +46,8 @@ func TestAesCtrCrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAesCfbEncrypt(t *testing.T) {
|
func TestAesCfbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefghijklmnop"
|
key := "abcdefghijklmnop"
|
||||||
|
|
||||||
@@ -51,6 +59,8 @@ func TestAesCfbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAesOfbEncrypt(t *testing.T) {
|
func TestAesOfbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefghijklmnop"
|
key := "abcdefghijklmnop"
|
||||||
|
|
||||||
@@ -62,6 +72,8 @@ func TestAesOfbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDesEcbEncrypt(t *testing.T) {
|
func TestDesEcbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefgh"
|
key := "abcdefgh"
|
||||||
|
|
||||||
@@ -73,6 +85,8 @@ func TestDesEcbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDesCbcEncrypt(t *testing.T) {
|
func TestDesCbcEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefgh"
|
key := "abcdefgh"
|
||||||
|
|
||||||
@@ -84,6 +98,8 @@ func TestDesCbcEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDesCtrCrypt(t *testing.T) {
|
func TestDesCtrCrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefgh"
|
key := "abcdefgh"
|
||||||
|
|
||||||
@@ -95,6 +111,8 @@ func TestDesCtrCrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDesCfbEncrypt(t *testing.T) {
|
func TestDesCfbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefgh"
|
key := "abcdefgh"
|
||||||
|
|
||||||
@@ -106,6 +124,8 @@ func TestDesCfbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDesOfbEncrypt(t *testing.T) {
|
func TestDesOfbEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
data := "hello world"
|
data := "hello world"
|
||||||
key := "abcdefgh"
|
key := "abcdefgh"
|
||||||
|
|
||||||
@@ -117,6 +137,8 @@ func TestDesOfbEncrypt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRsaEncrypt(t *testing.T) {
|
func TestRsaEncrypt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// 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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultMapCapacity uint64 = 1 << 10
|
var defaultMapCapacity uint64 = 1 << 10
|
||||||
@@ -17,7 +18,7 @@ type mapNode struct {
|
|||||||
next *mapNode
|
next *mapNode
|
||||||
}
|
}
|
||||||
|
|
||||||
//HashMap implements a hash map
|
// HashMap implements a hash map
|
||||||
type HashMap struct {
|
type HashMap struct {
|
||||||
capacity uint64
|
capacity uint64
|
||||||
size uint64
|
size uint64
|
||||||
@@ -45,13 +46,24 @@ func NewHashMapWithCapacity(size, capacity uint64) *HashMap {
|
|||||||
func (hm *HashMap) Get(key any) any {
|
func (hm *HashMap) Get(key any) any {
|
||||||
hashValue := hm.hash(key)
|
hashValue := hm.hash(key)
|
||||||
node := hm.table[hashValue]
|
node := hm.table[hashValue]
|
||||||
if node != nil {
|
for node != nil {
|
||||||
return node.value
|
if reflect.DeepEqual(node.key, key) {
|
||||||
|
return node.value
|
||||||
|
}
|
||||||
|
node = node.next
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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
|
// Put new key value in hashmap
|
||||||
func (hm *HashMap) Put(key any, value any) {
|
func (hm *HashMap) Put(key any, value any) {
|
||||||
hm.putValue(hm.hash(key), key, value)
|
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
|
// Contains checks if given key is in hashmap or not
|
||||||
func (hm *HashMap) Contains(key any) bool {
|
func (hm *HashMap) Contains(key any) bool {
|
||||||
node := hm.table[hm.hash(key)]
|
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)
|
// 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) {
|
func TestHashMap_Delete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestHashMap_Delete")
|
assert := internal.NewAssert(t, "TestHashMap_Delete")
|
||||||
|
|
||||||
hm := NewHashMap()
|
hm := NewHashMap()
|
||||||
@@ -44,6 +46,8 @@ func TestHashMap_Delete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHashMap_Contains(t *testing.T) {
|
func TestHashMap_Contains(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestHashMap_Contains")
|
assert := internal.NewAssert(t, "TestHashMap_Contains")
|
||||||
|
|
||||||
hm := NewHashMap()
|
hm := NewHashMap()
|
||||||
@@ -54,6 +58,8 @@ func TestHashMap_Contains(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHashMap_KeysValues(t *testing.T) {
|
func TestHashMap_KeysValues(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestHashMap_KeysValues")
|
assert := internal.NewAssert(t, "TestHashMap_KeysValues")
|
||||||
|
|
||||||
hm := NewHashMap()
|
hm := NewHashMap()
|
||||||
@@ -64,8 +70,38 @@ func TestHashMap_KeysValues(t *testing.T) {
|
|||||||
|
|
||||||
keys := hm.Keys()
|
keys := hm.Keys()
|
||||||
values := hm.Values()
|
values := hm.Values()
|
||||||
t.Log(keys, values)
|
|
||||||
|
|
||||||
assert.Equal(3, len(values))
|
assert.Equal(3, len(values))
|
||||||
assert.Equal(3, len(keys))
|
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.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// 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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
func TestMaxHeap_BuildMaxHeap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
|
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
|
||||||
|
|
||||||
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
|
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) {
|
func TestMaxHeap_Push(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMaxHeap_Push")
|
assert := internal.NewAssert(t, "TestMaxHeap_Push")
|
||||||
|
|
||||||
heap := NewMaxHeap[int](&intComparator{})
|
heap := NewMaxHeap[int](&intComparator{})
|
||||||
@@ -51,6 +55,8 @@ func TestMaxHeap_Push(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxHeap_Pop(t *testing.T) {
|
func TestMaxHeap_Pop(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
|
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
|
||||||
|
|
||||||
heap := NewMaxHeap[int](&intComparator{})
|
heap := NewMaxHeap[int](&intComparator{})
|
||||||
@@ -70,6 +76,8 @@ func TestMaxHeap_Pop(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMaxHeap_Peek(t *testing.T) {
|
func TestMaxHeap_Peek(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
|
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
|
||||||
|
|
||||||
heap := NewMaxHeap[int](&intComparator{})
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
|
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -22,6 +24,8 @@ func TestDoublyLink_InsertAtFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_InsertAtTail(t *testing.T) {
|
func TestDoublyLink_InsertAtTail(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
|
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -37,12 +41,12 @@ func TestDoublyLink_InsertAtTail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_InsertAt(t *testing.T) {
|
func TestDoublyLink_InsertAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
|
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
|
|
||||||
link.InsertAt(1, 1) //do nothing
|
link.InsertAt(1, 1) //do nothing
|
||||||
|
|
||||||
link.InsertAt(0, 1)
|
link.InsertAt(0, 1)
|
||||||
link.InsertAt(1, 2)
|
link.InsertAt(1, 2)
|
||||||
link.InsertAt(2, 4)
|
link.InsertAt(2, 4)
|
||||||
@@ -55,6 +59,8 @@ func TestDoublyLink_InsertAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -74,6 +80,8 @@ func TestDoublyLink_DeleteAtHead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -93,6 +101,8 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_DeleteAt(t *testing.T) {
|
func TestDoublyLink_DeleteAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -116,6 +126,8 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_Reverse(t *testing.T) {
|
func TestDoublyLink_Reverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
|
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -130,6 +142,8 @@ func TestDoublyLink_Reverse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
|
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
@@ -149,10 +163,11 @@ func TestDoublyLink_GetMiddleNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoublyLink_Clear(t *testing.T) {
|
func TestDoublyLink_Clear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
|
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
|
||||||
|
|
||||||
link := NewDoublyLink[int]()
|
link := NewDoublyLink[int]()
|
||||||
|
|
||||||
assert.Equal(true, link.IsEmpty())
|
assert.Equal(true, link.IsEmpty())
|
||||||
assert.Equal(0, link.Size())
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
|
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -22,6 +24,8 @@ func TestSinglyLink_InsertAtFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_InsertAtTail(t *testing.T) {
|
func TestSinglyLink_InsertAtTail(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
|
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -37,6 +41,8 @@ func TestSinglyLink_InsertAtTail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_InsertAt(t *testing.T) {
|
func TestSinglyLink_InsertAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
|
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -57,6 +63,8 @@ func TestSinglyLink_InsertAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -78,10 +86,11 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
link.InsertAtTail(3)
|
link.InsertAtTail(3)
|
||||||
@@ -96,10 +105,11 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_DeleteValue(t *testing.T) {
|
func TestSinglyLink_DeleteValue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
@@ -114,10 +124,11 @@ func TestSinglyLink_DeleteValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_DeleteAt(t *testing.T) {
|
func TestSinglyLink_DeleteAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
|
|
||||||
link.InsertAtTail(1)
|
link.InsertAtTail(1)
|
||||||
link.InsertAtTail(2)
|
link.InsertAtTail(2)
|
||||||
link.InsertAtTail(3)
|
link.InsertAtTail(3)
|
||||||
@@ -136,6 +147,8 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_Reverse(t *testing.T) {
|
func TestSinglyLink_Reverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
|
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -149,6 +162,8 @@ func TestSinglyLink_Reverse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
|
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
|
||||||
|
|
||||||
link := NewSinglyLink[int]()
|
link := NewSinglyLink[int]()
|
||||||
@@ -163,6 +178,7 @@ func TestSinglyLink_GetMiddleNode(t *testing.T) {
|
|||||||
link.InsertAtTail(5)
|
link.InsertAtTail(5)
|
||||||
link.InsertAtTail(6)
|
link.InsertAtTail(6)
|
||||||
link.InsertAtTail(7)
|
link.InsertAtTail(7)
|
||||||
|
|
||||||
middle2 := link.GetMiddleNode()
|
middle2 := link.GetMiddleNode()
|
||||||
assert.Equal(4, middle2.Value)
|
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.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// 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
|
package datastructure
|
||||||
|
|
||||||
import (
|
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() {
|
func (l *List[T]) Unique() {
|
||||||
data := l.data
|
data := l.data
|
||||||
size := len(data)
|
size := len(data)
|
||||||
@@ -294,7 +294,7 @@ func (l *List[T]) Unique() {
|
|||||||
l.data = uniqueData
|
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] {
|
func (l *List[T]) Union(other *List[T]) *List[T] {
|
||||||
result := NewList([]T{})
|
result := NewList([]T{})
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestListData(t *testing.T) {
|
func TestListData(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestListData")
|
assert := internal.NewAssert(t, "TestListData")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -14,6 +16,8 @@ func TestListData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValueOf(t *testing.T) {
|
func TestValueOf(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestValueOf")
|
assert := internal.NewAssert(t, "TestValueOf")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -26,6 +30,8 @@ func TestValueOf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexOf(t *testing.T) {
|
func TestIndexOf(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIndexOf")
|
assert := internal.NewAssert(t, "TestIndexOf")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -37,6 +43,8 @@ func TestIndexOf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexOfFunc(t *testing.T) {
|
func TestIndexOfFunc(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIndexOf")
|
assert := internal.NewAssert(t, "TestIndexOf")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -48,6 +56,8 @@ func TestIndexOfFunc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLastIndexOf(t *testing.T) {
|
func TestLastIndexOf(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIndexOf")
|
assert := internal.NewAssert(t, "TestIndexOf")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
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) {
|
func TestLastIndexOfFunc(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIndexOf")
|
assert := internal.NewAssert(t, "TestIndexOf")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
|
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) {
|
func TestContain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestContain")
|
assert := internal.NewAssert(t, "TestContain")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -90,6 +104,8 @@ func TestContain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPush(t *testing.T) {
|
func TestPush(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestPush")
|
assert := internal.NewAssert(t, "TestPush")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -99,6 +115,8 @@ func TestPush(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInsertAtFirst(t *testing.T) {
|
func TestInsertAtFirst(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestInsertAtFirst")
|
assert := internal.NewAssert(t, "TestInsertAtFirst")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -108,6 +126,8 @@ func TestInsertAtFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInsertAtLast(t *testing.T) {
|
func TestInsertAtLast(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestInsertAtLast")
|
assert := internal.NewAssert(t, "TestInsertAtLast")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -117,6 +137,8 @@ func TestInsertAtLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInsertAt(t *testing.T) {
|
func TestInsertAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestInsertAt")
|
assert := internal.NewAssert(t, "TestInsertAt")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -135,6 +157,8 @@ func TestInsertAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPopFirst(t *testing.T) {
|
func TestPopFirst(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestPopFirst")
|
assert := internal.NewAssert(t, "TestPopFirst")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -150,6 +174,8 @@ func TestPopFirst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPopLast(t *testing.T) {
|
func TestPopLast(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestPopLast")
|
assert := internal.NewAssert(t, "TestPopLast")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3})
|
list := NewList([]int{1, 2, 3})
|
||||||
@@ -165,6 +191,8 @@ func TestPopLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteAt(t *testing.T) {
|
func TestDeleteAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDeleteAt")
|
assert := internal.NewAssert(t, "TestDeleteAt")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -183,6 +211,8 @@ func TestDeleteAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateAt(t *testing.T) {
|
func TestUpdateAt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestUpdateAt")
|
assert := internal.NewAssert(t, "TestUpdateAt")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -201,6 +231,8 @@ func TestUpdateAt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEqual(t *testing.T) {
|
func TestEqual(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEqual")
|
assert := internal.NewAssert(t, "TestEqual")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -212,6 +244,8 @@ func TestEqual(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIsEmpty(t *testing.T) {
|
func TestIsEmpty(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIsEmpty")
|
assert := internal.NewAssert(t, "TestIsEmpty")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -222,6 +256,8 @@ func TestIsEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIsClear(t *testing.T) {
|
func TestIsClear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIsClear")
|
assert := internal.NewAssert(t, "TestIsClear")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -232,6 +268,8 @@ func TestIsClear(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClone(t *testing.T) {
|
func TestClone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestClone")
|
assert := internal.NewAssert(t, "TestClone")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -241,6 +279,8 @@ func TestClone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
func TestMerge(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestMerge")
|
assert := internal.NewAssert(t, "TestMerge")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -252,6 +292,8 @@ func TestMerge(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSize(t *testing.T) {
|
func TestSize(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSize")
|
assert := internal.NewAssert(t, "TestSize")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -262,6 +304,8 @@ func TestSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCap(t *testing.T) {
|
func TestCap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCap")
|
assert := internal.NewAssert(t, "TestCap")
|
||||||
|
|
||||||
data := make([]int, 0, 100)
|
data := make([]int, 0, 100)
|
||||||
@@ -274,6 +318,8 @@ func TestCap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSwap(t *testing.T) {
|
func TestSwap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSwap")
|
assert := internal.NewAssert(t, "TestSwap")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -285,6 +331,8 @@ func TestSwap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReverse(t *testing.T) {
|
func TestReverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestReverse")
|
assert := internal.NewAssert(t, "TestReverse")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -296,6 +344,8 @@ func TestReverse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnique(t *testing.T) {
|
func TestUnique(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestUnique")
|
assert := internal.NewAssert(t, "TestUnique")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 2, 3, 4})
|
list := NewList([]int{1, 2, 2, 3, 4})
|
||||||
@@ -307,6 +357,8 @@ func TestUnique(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnion(t *testing.T) {
|
func TestUnion(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestUnion")
|
assert := internal.NewAssert(t, "TestUnion")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -318,6 +370,8 @@ func TestUnion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIntersection(t *testing.T) {
|
func TestIntersection(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIntersection")
|
assert := internal.NewAssert(t, "TestIntersection")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3, 4})
|
list1 := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -329,6 +383,8 @@ func TestIntersection(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDifference(t *testing.T) {
|
func TestDifference(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDifference")
|
assert := internal.NewAssert(t, "TestDifference")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3})
|
list1 := NewList([]int{1, 2, 3})
|
||||||
@@ -340,6 +396,8 @@ func TestDifference(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSymmetricDifference(t *testing.T) {
|
func TestSymmetricDifference(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSymmetricDifference")
|
assert := internal.NewAssert(t, "TestSymmetricDifference")
|
||||||
|
|
||||||
list1 := NewList([]int{1, 2, 3})
|
list1 := NewList([]int{1, 2, 3})
|
||||||
@@ -351,6 +409,8 @@ func TestSymmetricDifference(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSubSlice(t *testing.T) {
|
func TestSubSlice(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSubSlice")
|
assert := internal.NewAssert(t, "TestSubSlice")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4, 5, 8})
|
list := NewList([]int{1, 2, 3, 4, 5, 8})
|
||||||
@@ -367,6 +427,8 @@ func BenchmarkSubSlice(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteIf(t *testing.T) {
|
func TestDeleteIf(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDeleteIf")
|
assert := internal.NewAssert(t, "TestDeleteIf")
|
||||||
|
|
||||||
list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
|
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) {
|
func TestForEach(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestForEach")
|
assert := internal.NewAssert(t, "TestForEach")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
rs := make([]int, 0)
|
rs := make([]int, 0)
|
||||||
list.ForEach(func(i int) {
|
list.ForEach(func(i int) {
|
||||||
rs = append(rs, i)
|
rs = append(rs, i)
|
||||||
@@ -394,6 +457,8 @@ func TestForEach(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRetainAll(t *testing.T) {
|
func TestRetainAll(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestRetainAll")
|
assert := internal.NewAssert(t, "TestRetainAll")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -414,6 +479,8 @@ func TestRetainAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteAll(t *testing.T) {
|
func TestDeleteAll(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestDeleteAll")
|
assert := internal.NewAssert(t, "TestDeleteAll")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
@@ -433,10 +500,11 @@ func TestDeleteAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIterator(t *testing.T) {
|
func TestIterator(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIterator")
|
assert := internal.NewAssert(t, "TestIterator")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
iterator := list.Iterator()
|
iterator := list.Iterator()
|
||||||
|
|
||||||
rs := make([]int, 0)
|
rs := make([]int, 0)
|
||||||
@@ -449,14 +517,15 @@ func TestIterator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestListToMap(t *testing.T) {
|
func TestListToMap(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "ListToMap")
|
assert := internal.NewAssert(t, "ListToMap")
|
||||||
|
|
||||||
list := NewList([]int{1, 2, 3, 4})
|
list := NewList([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
result := ListToMap(list, func(n int) (int, bool) {
|
result := ListToMap(list, func(n int) (int, bool) {
|
||||||
return n, n > 1
|
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)
|
assert.Equal(expected, result)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
// Use of this source code is governed by MIT license
|
// 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
|
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.
|
// 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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestArrayQueue_Enqueue(t *testing.T) {
|
func TestArrayQueue_Enqueue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](5)
|
queue := NewArrayQueue[int](5)
|
||||||
@@ -14,15 +16,16 @@ func TestArrayQueue_Enqueue(t *testing.T) {
|
|||||||
queue.Enqueue(2)
|
queue.Enqueue(2)
|
||||||
queue.Enqueue(3)
|
queue.Enqueue(3)
|
||||||
|
|
||||||
expected := []int{1, 2, 3}
|
|
||||||
data := queue.Data()
|
data := queue.Data()
|
||||||
size := queue.Size()
|
size := queue.Size()
|
||||||
|
|
||||||
assert.Equal(expected, data)
|
assert.Equal([]int{1, 2, 3}, data)
|
||||||
assert.Equal(3, size)
|
assert.Equal(3, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_Dequeue(t *testing.T) {
|
func TestArrayQueue_Dequeue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
|
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](4)
|
queue := NewArrayQueue[int](4)
|
||||||
@@ -38,6 +41,8 @@ func TestArrayQueue_Dequeue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_Front(t *testing.T) {
|
func TestArrayQueue_Front(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Front")
|
assert := internal.NewAssert(t, "TestArrayQueue_Front")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](4)
|
queue := NewArrayQueue[int](4)
|
||||||
@@ -52,6 +57,8 @@ func TestArrayQueue_Front(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_Back(t *testing.T) {
|
func TestArrayQueue_Back(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Back")
|
assert := internal.NewAssert(t, "TestArrayQueue_Back")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](4)
|
queue := NewArrayQueue[int](4)
|
||||||
@@ -66,6 +73,8 @@ func TestArrayQueue_Back(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_Contain(t *testing.T) {
|
func TestArrayQueue_Contain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
|
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](4)
|
queue := NewArrayQueue[int](4)
|
||||||
@@ -78,6 +87,8 @@ func TestArrayQueue_Contain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_Clear(t *testing.T) {
|
func TestArrayQueue_Clear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
|
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](4)
|
queue := NewArrayQueue[int](4)
|
||||||
@@ -95,6 +106,8 @@ func TestArrayQueue_Clear(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayQueue_IsFull(t *testing.T) {
|
func TestArrayQueue_IsFull(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
|
assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
|
||||||
|
|
||||||
queue := NewArrayQueue[int](3)
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestCircularQueue_Enqueue(t *testing.T) {
|
func TestCircularQueue_Enqueue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](6)
|
||||||
@@ -34,6 +36,8 @@ func TestCircularQueue_Enqueue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Dequeue(t *testing.T) {
|
func TestCircularQueue_Dequeue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](4)
|
queue := NewCircularQueue[int](4)
|
||||||
@@ -60,6 +64,8 @@ func TestCircularQueue_Dequeue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Front(t *testing.T) {
|
func TestCircularQueue_Front(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
assert := internal.NewAssert(t, "TestCircularQueue_Front")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](6)
|
queue := NewCircularQueue[int](6)
|
||||||
@@ -80,6 +86,8 @@ func TestCircularQueue_Front(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Back(t *testing.T) {
|
func TestCircularQueue_Back(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
assert := internal.NewAssert(t, "TestCircularQueue_Back")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](3)
|
queue := NewCircularQueue[int](3)
|
||||||
@@ -103,6 +111,8 @@ func TestCircularQueue_Back(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Contain(t *testing.T) {
|
func TestCircularQueue_Contain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](2)
|
queue := NewCircularQueue[int](2)
|
||||||
@@ -114,6 +124,8 @@ func TestCircularQueue_Contain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Clear(t *testing.T) {
|
func TestCircularQueue_Clear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
|
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](3)
|
queue := NewCircularQueue[int](3)
|
||||||
@@ -132,6 +144,8 @@ func TestCircularQueue_Clear(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularQueue_Data(t *testing.T) {
|
func TestCircularQueue_Data(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
assert := internal.NewAssert(t, "TestCircularQueue_Data")
|
||||||
|
|
||||||
queue := NewCircularQueue[int](3)
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLinkedQueue_Enqueue(t *testing.T) {
|
func TestLinkedQueue_Enqueue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
@@ -19,6 +21,8 @@ func TestLinkedQueue_Enqueue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedQueue_Dequeue(t *testing.T) {
|
func TestLinkedQueue_Dequeue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
@@ -35,6 +39,8 @@ func TestLinkedQueue_Dequeue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedQueue_Front(t *testing.T) {
|
func TestLinkedQueue_Front(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
|
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
@@ -51,6 +57,8 @@ func TestLinkedQueue_Front(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedQueue_Back(t *testing.T) {
|
func TestLinkedQueue_Back(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
@@ -67,6 +75,8 @@ func TestLinkedQueue_Back(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedQueue_Clear(t *testing.T) {
|
func TestLinkedQueue_Clear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
@@ -82,10 +92,11 @@ func TestLinkedQueue_Clear(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedQueue_Contain(t *testing.T) {
|
func TestLinkedQueue_Contain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
|
assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
|
||||||
|
|
||||||
queue := NewLinkedQueue[int]()
|
queue := NewLinkedQueue[int]()
|
||||||
|
|
||||||
queue.Enqueue(1)
|
queue.Enqueue(1)
|
||||||
queue.Enqueue(2)
|
queue.Enqueue(2)
|
||||||
queue.Enqueue(3)
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
func TestPriorityQueue_Enqueue(t *testing.T) {
|
func TestPriorityQueue_Enqueue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
|
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
|
||||||
|
|
||||||
comparator := &intComparator{}
|
comparator := &intComparator{}
|
||||||
@@ -45,6 +47,8 @@ func TestPriorityQueue_Enqueue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPriorityQueue_Dequeue(t *testing.T) {
|
func TestPriorityQueue_Dequeue(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
|
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
|
||||||
|
|
||||||
comparator := &intComparator{}
|
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
|
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{}
|
type Set[T comparable] map[T]struct{}
|
||||||
|
|
||||||
// NewSet return a instance of set
|
// NewSet return a instance of set
|
||||||
@@ -171,3 +175,25 @@ func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
|
|||||||
|
|
||||||
return set
|
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) {
|
func TestSet_NewSetFromSlice(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
|
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
|
||||||
|
|
||||||
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
|
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
|
||||||
@@ -20,17 +22,21 @@ func TestSet_NewSetFromSlice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Add(t *testing.T) {
|
func TestSet_Add(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Add")
|
assert := internal.NewAssert(t, "TestSet_Add")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
set.Add(1, 2, 3)
|
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) {
|
func TestSet_AddIfNotExist(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
|
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
@@ -42,6 +48,8 @@ func TestSet_AddIfNotExist(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_AddIfNotExistBy(t *testing.T) {
|
func TestSet_AddIfNotExistBy(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
|
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
@@ -63,6 +71,8 @@ func TestSet_AddIfNotExistBy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Contain(t *testing.T) {
|
func TestSet_Contain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Contain")
|
assert := internal.NewAssert(t, "TestSet_Contain")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
@@ -73,6 +83,8 @@ func TestSet_Contain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_ContainAll(t *testing.T) {
|
func TestSet_ContainAll(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
assert := internal.NewAssert(t, "TestSet_ContainAll")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
@@ -84,6 +96,8 @@ func TestSet_ContainAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Clone(t *testing.T) {
|
func TestSet_Clone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Clone")
|
assert := internal.NewAssert(t, "TestSet_Clone")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
@@ -94,18 +108,20 @@ func TestSet_Clone(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Delete(t *testing.T) {
|
func TestSet_Delete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Delete")
|
assert := internal.NewAssert(t, "TestSet_Delete")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
set.Add(1, 2, 3)
|
set.Add(1, 2, 3)
|
||||||
set.Delete(3)
|
set.Delete(3)
|
||||||
|
|
||||||
expected := NewSet(1, 2)
|
assert.Equal(true, set.Equal(NewSet(1, 2)))
|
||||||
|
|
||||||
assert.Equal(true, set.Equal(expected))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Equal(t *testing.T) {
|
func TestSet_Equal(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Equal")
|
assert := internal.NewAssert(t, "TestSet_Equal")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
@@ -117,6 +133,8 @@ func TestSet_Equal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Iterate(t *testing.T) {
|
func TestSet_Iterate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Iterate")
|
assert := internal.NewAssert(t, "TestSet_Iterate")
|
||||||
|
|
||||||
set := NewSet(1, 2, 3)
|
set := NewSet(1, 2, 3)
|
||||||
@@ -129,6 +147,8 @@ func TestSet_Iterate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_IsEmpty(t *testing.T) {
|
func TestSet_IsEmpty(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
assert := internal.NewAssert(t, "TestSet_IsEmpty")
|
||||||
|
|
||||||
set := NewSet[int]()
|
set := NewSet[int]()
|
||||||
@@ -136,6 +156,8 @@ func TestSet_IsEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Size(t *testing.T) {
|
func TestSet_Size(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Size")
|
assert := internal.NewAssert(t, "TestSet_Size")
|
||||||
|
|
||||||
set := NewSet(1, 2, 3)
|
set := NewSet(1, 2, 3)
|
||||||
@@ -143,6 +165,8 @@ func TestSet_Size(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Values(t *testing.T) {
|
func TestSet_Values(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Values")
|
assert := internal.NewAssert(t, "TestSet_Values")
|
||||||
|
|
||||||
set := NewSet(1, 2, 3)
|
set := NewSet(1, 2, 3)
|
||||||
@@ -152,28 +176,33 @@ func TestSet_Values(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Union(t *testing.T) {
|
func TestSet_Union(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Union")
|
assert := internal.NewAssert(t, "TestSet_Union")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
set2 := NewSet(2, 3, 4, 5)
|
set2 := NewSet(2, 3, 4, 5)
|
||||||
expected := NewSet(1, 2, 3, 4, 5)
|
|
||||||
unionSet := set1.Union(set2)
|
unionSet := set1.Union(set2)
|
||||||
|
|
||||||
assert.Equal(expected, unionSet)
|
assert.Equal(NewSet(1, 2, 3, 4, 5), unionSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Intersection(t *testing.T) {
|
func TestSet_Intersection(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Intersection")
|
assert := internal.NewAssert(t, "TestSet_Intersection")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
set2 := NewSet(2, 3, 4, 5)
|
set2 := NewSet(2, 3, 4, 5)
|
||||||
expected := NewSet(2, 3)
|
|
||||||
intersectionSet := set1.Intersection(set2)
|
intersectionSet := set1.Intersection(set2)
|
||||||
|
|
||||||
assert.Equal(expected, intersectionSet)
|
assert.Equal(NewSet(2, 3), intersectionSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_SymmetricDifference(t *testing.T) {
|
func TestSet_SymmetricDifference(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
|
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
set1 := NewSet(1, 2, 3)
|
||||||
@@ -183,6 +212,8 @@ func TestSet_SymmetricDifference(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSet_Minus(t *testing.T) {
|
func TestSet_Minus(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestSet_Minus")
|
assert := internal.NewAssert(t, "TestSet_Minus")
|
||||||
|
|
||||||
set1 := NewSet(1, 2, 3)
|
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(1), set1.Minus(set2))
|
||||||
assert.Equal(NewSet(4, 5), set2.Minus(set3))
|
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
|
package datastructure
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestArrayStack_Push(t *testing.T) {
|
func TestArrayStack_Push(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayStack_Push")
|
assert := internal.NewAssert(t, "TestArrayStack_Push")
|
||||||
|
|
||||||
stack := NewArrayStack[int]()
|
stack := NewArrayStack[int]()
|
||||||
@@ -14,15 +16,16 @@ func TestArrayStack_Push(t *testing.T) {
|
|||||||
stack.Push(2)
|
stack.Push(2)
|
||||||
stack.Push(3)
|
stack.Push(3)
|
||||||
|
|
||||||
expected := []int{3, 2, 1}
|
|
||||||
values := stack.Data()
|
values := stack.Data()
|
||||||
length := stack.Size()
|
length := stack.Size()
|
||||||
|
|
||||||
assert.Equal(expected, values)
|
assert.Equal([]int{3, 2, 1}, values)
|
||||||
assert.Equal(3, length)
|
assert.Equal(3, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayStack_Pop(t *testing.T) {
|
func TestArrayStack_Pop(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayStack_Pop")
|
assert := internal.NewAssert(t, "TestArrayStack_Pop")
|
||||||
|
|
||||||
stack := NewArrayStack[int]()
|
stack := NewArrayStack[int]()
|
||||||
@@ -37,11 +40,12 @@ func TestArrayStack_Pop(t *testing.T) {
|
|||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal(3, *topItem)
|
assert.Equal(3, *topItem)
|
||||||
|
|
||||||
expected := []int{2, 1}
|
assert.Equal([]int{2, 1}, stack.Data())
|
||||||
assert.Equal(expected, stack.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayStack_Peak(t *testing.T) {
|
func TestArrayStack_Peak(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayStack_Peak")
|
assert := internal.NewAssert(t, "TestArrayStack_Peak")
|
||||||
|
|
||||||
stack := NewArrayStack[int]()
|
stack := NewArrayStack[int]()
|
||||||
@@ -56,11 +60,12 @@ func TestArrayStack_Peak(t *testing.T) {
|
|||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal(3, *topItem)
|
assert.Equal(3, *topItem)
|
||||||
|
|
||||||
expected := []int{3, 2, 1}
|
assert.Equal([]int{3, 2, 1}, stack.Data())
|
||||||
assert.Equal(expected, stack.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayStack_Clear(t *testing.T) {
|
func TestArrayStack_Clear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestArrayStack_Clear")
|
assert := internal.NewAssert(t, "TestArrayStack_Clear")
|
||||||
|
|
||||||
stack := NewArrayStack[int]()
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestLinkedStack_Push(t *testing.T) {
|
func TestLinkedStack_Push(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedStack_Push")
|
assert := internal.NewAssert(t, "TestLinkedStack_Push")
|
||||||
|
|
||||||
stack := NewLinkedStack[int]()
|
stack := NewLinkedStack[int]()
|
||||||
@@ -14,15 +16,16 @@ func TestLinkedStack_Push(t *testing.T) {
|
|||||||
stack.Push(2)
|
stack.Push(2)
|
||||||
stack.Push(3)
|
stack.Push(3)
|
||||||
|
|
||||||
expected := []int{3, 2, 1}
|
|
||||||
values := stack.Data()
|
values := stack.Data()
|
||||||
size := stack.Size()
|
size := stack.Size()
|
||||||
|
|
||||||
assert.Equal(expected, values)
|
assert.Equal([]int{3, 2, 1}, values)
|
||||||
assert.Equal(3, size)
|
assert.Equal(3, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedStack_Pop(t *testing.T) {
|
func TestLinkedStack_Pop(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
|
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
|
||||||
|
|
||||||
stack := NewLinkedStack[int]()
|
stack := NewLinkedStack[int]()
|
||||||
@@ -37,12 +40,13 @@ func TestLinkedStack_Pop(t *testing.T) {
|
|||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal(3, *topItem)
|
assert.Equal(3, *topItem)
|
||||||
|
|
||||||
expected := []int{2, 1}
|
|
||||||
stack.Print()
|
stack.Print()
|
||||||
assert.Equal(expected, stack.Data())
|
assert.Equal([]int{2, 1}, stack.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedStack_Peak(t *testing.T) {
|
func TestLinkedStack_Peak(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
|
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
|
||||||
|
|
||||||
stack := NewLinkedStack[int]()
|
stack := NewLinkedStack[int]()
|
||||||
@@ -57,11 +61,12 @@ func TestLinkedStack_Peak(t *testing.T) {
|
|||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal(3, *topItem)
|
assert.Equal(3, *topItem)
|
||||||
|
|
||||||
expected := []int{3, 2, 1}
|
assert.Equal([]int{3, 2, 1}, stack.Data())
|
||||||
assert.Equal(expected, stack.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedStack_Empty(t *testing.T) {
|
func TestLinkedStack_Empty(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
|
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
|
||||||
|
|
||||||
stack := NewLinkedStack[int]()
|
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
|
package datastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -20,16 +20,9 @@ func (c *intComparator) Compare(v1, v2 any) int {
|
|||||||
return 0
|
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) {
|
func TestBSTree_PreOrderTraverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
|
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -40,11 +33,12 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
|
|||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
acturl := bstree.PreOrderTraverse()
|
acturl := bstree.PreOrderTraverse()
|
||||||
t.Log(acturl)
|
|
||||||
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
|
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_PostOrderTraverse(t *testing.T) {
|
func TestBSTree_PostOrderTraverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
|
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -55,11 +49,12 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
|
|||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
acturl := bstree.PostOrderTraverse()
|
acturl := bstree.PostOrderTraverse()
|
||||||
t.Log(acturl)
|
|
||||||
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
|
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_InOrderTraverse(t *testing.T) {
|
func TestBSTree_InOrderTraverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
|
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -70,11 +65,12 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
|
|||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
acturl := bstree.InOrderTraverse()
|
acturl := bstree.InOrderTraverse()
|
||||||
t.Log(acturl)
|
|
||||||
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
|
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
|
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -85,11 +81,12 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
|
|||||||
bstree.Insert(4)
|
bstree.Insert(4)
|
||||||
|
|
||||||
acturl := bstree.LevelOrderTraverse()
|
acturl := bstree.LevelOrderTraverse()
|
||||||
t.Log(acturl)
|
|
||||||
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_Delete(t *testing.T) {
|
func TestBSTree_Delete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_Delete")
|
assert := internal.NewAssert(t, "TestBSTree_Delete")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -102,18 +99,18 @@ func TestBSTree_Delete(t *testing.T) {
|
|||||||
bstree.Delete(4)
|
bstree.Delete(4)
|
||||||
|
|
||||||
acturl1 := bstree.InOrderTraverse()
|
acturl1 := bstree.InOrderTraverse()
|
||||||
t.Log(acturl1)
|
|
||||||
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
assert.Equal([]int{2, 5, 6, 7}, acturl1)
|
||||||
|
|
||||||
//todo
|
//todo
|
||||||
// bstree.DeletetNode(6, comparator)
|
// bstree.DeletetNode(6, comparator)
|
||||||
// bstree.Print()
|
// bstree.Print()
|
||||||
// acturl2 := bstree.InOrderTraverse()
|
// acturl2 := bstree.InOrderTraverse()
|
||||||
// t.Log(acturl2)
|
|
||||||
// assert.Equal([]int{2, 5, 7}, acturl2)
|
// assert.Equal([]int{2, 5, 7}, acturl2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_Depth(t *testing.T) {
|
func TestBSTree_Depth(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_Depth")
|
assert := internal.NewAssert(t, "TestBSTree_Depth")
|
||||||
|
|
||||||
bstree := NewBSTree(6, &intComparator{})
|
bstree := NewBSTree(6, &intComparator{})
|
||||||
@@ -127,6 +124,8 @@ func TestBSTree_Depth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBSTree_IsSubTree(t *testing.T) {
|
func TestBSTree_IsSubTree(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
|
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
|
||||||
|
|
||||||
superTree := NewBSTree(8, &intComparator{})
|
superTree := NewBSTree(8, &intComparator{})
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestToUnix(t *testing.T) {
|
func TestToUnix(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToUnix")
|
assert := internal.NewAssert(t, "TestToUnix")
|
||||||
|
|
||||||
tm1 := NewUnixNow()
|
tm1 := NewUnixNow()
|
||||||
@@ -17,34 +19,37 @@ func TestToUnix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToFormat(t *testing.T) {
|
func TestToFormat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToFormat")
|
assert := internal.NewAssert(t, "TestToFormat")
|
||||||
|
|
||||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||||
|
t.Log("TestToFormat", tm.ToFormat())
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
t.Log("ToFormat -> ", tm.ToFormat())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToFormatForTpl(t *testing.T) {
|
func TestToFormatForTpl(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToFormatForTpl")
|
assert := internal.NewAssert(t, "TestToFormatForTpl")
|
||||||
|
|
||||||
_, err := NewFormat("2022/03/18 17:04:05")
|
_, err := NewFormat("2022/03/18 17:04:05")
|
||||||
assert.IsNotNil(err)
|
assert.IsNotNil(err)
|
||||||
|
|
||||||
tm, err := NewFormat("2022-03-18 17:04:05")
|
tm, err := NewFormat("2022-03-18 17:04:05")
|
||||||
|
t.Log("TestToFormatForTpl", tm.ToFormatForTpl("2006/01/02 15:04:05"))
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToIso8601(t *testing.T) {
|
func TestToIso8601(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestToIso8601")
|
assert := internal.NewAssert(t, "TestToIso8601")
|
||||||
|
|
||||||
_, err := NewISO8601("2022-03-18 17:04:05")
|
_, err := NewISO8601("2022-03-18 17:04:05")
|
||||||
assert.IsNotNil(err)
|
assert.IsNotNil(err)
|
||||||
|
|
||||||
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
|
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
|
||||||
|
t.Log("TestToIso8601", tm.ToIso8601())
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
t.Log("ToIso8601 -> ", tm.ToIso8601())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// Package datetime implements some functions to format date and time.
|
// Package datetime implements some functions to format date and time.
|
||||||
// Note:
|
// 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:ss"
|
||||||
// "yyyy-mm-dd hh:mm"
|
// "yyyy-mm-dd hh:mm"
|
||||||
// "yyyy-mm-dd hh"
|
// "yyyy-mm-dd hh"
|
||||||
@@ -18,14 +18,19 @@
|
|||||||
// "yyyy/mm"
|
// "yyyy/mm"
|
||||||
// "mm/dd"
|
// "mm/dd"
|
||||||
// "dd/mm/yy hh:mm:ss"
|
// "dd/mm/yy hh:mm:ss"
|
||||||
|
// "yyyymmdd"
|
||||||
|
// "mmddyy"
|
||||||
// "yyyy"
|
// "yyyy"
|
||||||
|
// "yy"
|
||||||
// "mm"
|
// "mm"
|
||||||
// "hh:mm:ss"
|
// "hh:mm:ss"
|
||||||
|
// "hh:mm"
|
||||||
// "mm:ss"
|
// "mm:ss"
|
||||||
package datetime
|
package datetime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +40,7 @@ func init() {
|
|||||||
timeFormat = map[string]string{
|
timeFormat = map[string]string{
|
||||||
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
|
"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: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-dd": "2006-01-02",
|
||||||
"yyyy-mm": "2006-01",
|
"yyyy-mm": "2006-01",
|
||||||
"mm-dd": "01-02",
|
"mm-dd": "01-02",
|
||||||
@@ -47,9 +52,13 @@ func init() {
|
|||||||
"yyyy/mm": "2006/01",
|
"yyyy/mm": "2006/01",
|
||||||
"mm/dd": "01/02",
|
"mm/dd": "01/02",
|
||||||
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
|
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
|
||||||
|
"yyyymmdd": "20060102",
|
||||||
|
"mmddyy": "010206",
|
||||||
"yyyy": "2006",
|
"yyyy": "2006",
|
||||||
|
"yy": "06",
|
||||||
"mm": "01",
|
"mm": "01",
|
||||||
"hh:mm:ss": "15:04:05",
|
"hh:mm:ss": "15:04:05",
|
||||||
|
"hh:mm": "15:04",
|
||||||
"mm:ss": "04:05",
|
"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))
|
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.
|
// GetNowDate return format yyyy-mm-dd of current date.
|
||||||
// Play: https://go.dev/play/p/PvfkPpcpBBf
|
// Play: https://go.dev/play/p/PvfkPpcpBBf
|
||||||
func GetNowDate() string {
|
func GetNowDate() string {
|
||||||
@@ -90,6 +105,18 @@ func GetNowDateTime() string {
|
|||||||
return time.Now().Format("2006-01-02 15:04:05")
|
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).
|
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
|
||||||
// Play: https://go.dev/play/p/QmL2oIaGE3q
|
// Play: https://go.dev/play/p/QmL2oIaGE3q
|
||||||
func GetZeroHourTimestamp() int64 {
|
func GetZeroHourTimestamp() int64 {
|
||||||
@@ -106,19 +133,40 @@ func GetNightTimestamp() int64 {
|
|||||||
|
|
||||||
// FormatTimeToStr convert time to string.
|
// FormatTimeToStr convert time to string.
|
||||||
// Play: https://go.dev/play/p/_Ia7M8H_OvE
|
// Play: https://go.dev/play/p/_Ia7M8H_OvE
|
||||||
func FormatTimeToStr(t time.Time, format string) string {
|
func FormatTimeToStr(t time.Time, format string, timezone ...string) string {
|
||||||
return t.Format(timeFormat[format])
|
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.
|
// FormatStrToTime convert string to time.
|
||||||
// Play: https://go.dev/play/p/1h9FwdU8ql4
|
// Play: https://go.dev/play/p/1h9FwdU8ql4
|
||||||
func FormatStrToTime(str, format string) (time.Time, error) {
|
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error) {
|
||||||
v, ok := timeFormat[format]
|
tf, ok := timeFormat[strings.ToLower(format)]
|
||||||
if !ok {
|
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.
|
// 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 {
|
func EndOfYear(t time.Time) time.Time {
|
||||||
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
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
|
// -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() {
|
func ExampleGetNowDate() {
|
||||||
result := GetNowDate()
|
result := GetNowDate()
|
||||||
|
|
||||||
@@ -114,15 +131,18 @@ func ExampleFormatTimeToStr() {
|
|||||||
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
|
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
|
||||||
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
|
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
|
||||||
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
|
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
|
||||||
|
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 2021-01-02 16:04:08
|
// 2021-01-02 16:04:08
|
||||||
// 2021-01-02
|
// 2021-01-02
|
||||||
// 02-01-21 16:04:08
|
// 02-01-21 16:04:08
|
||||||
|
// 2021-01-02 16
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleFormatStrToTime() {
|
func ExampleFormatStrToTime() {
|
||||||
@@ -321,3 +341,70 @@ func ExampleNewUnixNow() {
|
|||||||
// // Output:
|
// // Output:
|
||||||
// // 2006-01-02T23:04:05+08:00
|
// // 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"
|
"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) {
|
func TestAddDay(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestAddDay")
|
assert := internal.NewAssert(t, "TestAddDay")
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -21,6 +54,8 @@ func TestAddDay(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddHour(t *testing.T) {
|
func TestAddHour(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestAddHour")
|
assert := internal.NewAssert(t, "TestAddHour")
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -34,6 +69,8 @@ func TestAddHour(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddMinute(t *testing.T) {
|
func TestAddMinute(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestAddMinute")
|
assert := internal.NewAssert(t, "TestAddMinute")
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -47,44 +84,77 @@ func TestAddMinute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNowDate(t *testing.T) {
|
func TestGetNowDate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestGetNowDate")
|
assert := internal.NewAssert(t, "TestGetNowDate")
|
||||||
expected := time.Now().Format("2006-01-02")
|
expected := time.Now().Format("2006-01-02")
|
||||||
assert.Equal(expected, GetNowDate())
|
assert.Equal(expected, GetNowDate())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNowTime(t *testing.T) {
|
func TestGetNowTime(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestGetNowTime")
|
assert := internal.NewAssert(t, "TestGetNowTime")
|
||||||
expected := time.Now().Format("15:04:05")
|
expected := time.Now().Format("15:04:05")
|
||||||
assert.Equal(expected, GetNowTime())
|
assert.Equal(expected, GetNowTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNowDateTime(t *testing.T) {
|
func TestGetNowDateTime(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestGetNowDateTime")
|
assert := internal.NewAssert(t, "TestGetNowDateTime")
|
||||||
expected := time.Now().Format("2006-01-02 15:04:05")
|
expected := time.Now().Format("2006-01-02 15:04:05")
|
||||||
assert.Equal(expected, GetNowDateTime())
|
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) {
|
func TestFormatTimeToStr(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestFormatTimeToStr")
|
assert := internal.NewAssert(t, "TestFormatTimeToStr")
|
||||||
|
|
||||||
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
|
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
|
||||||
cases := []string{
|
cases := []string{
|
||||||
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
|
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
|
||||||
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
|
"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{
|
expected := []string{
|
||||||
"2021-01-02 16:04:08", "2021-01-02",
|
"2021-01-02 16:04:08", "2021-01-02",
|
||||||
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
"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++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
actual := FormatTimeToStr(datetime, cases[i])
|
actual := FormatTimeToStr(datetime, cases[i])
|
||||||
assert.Equal(expected[i], actual)
|
assert.Equal(expected[i], actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ds := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss", "EST")
|
||||||
|
t.Log(ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormatStrToTime(t *testing.T) {
|
func TestFormatStrToTime(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestFormatStrToTime")
|
assert := internal.NewAssert(t, "TestFormatStrToTime")
|
||||||
|
|
||||||
formats := []string{
|
formats := []string{
|
||||||
@@ -96,22 +166,28 @@ func TestFormatStrToTime(t *testing.T) {
|
|||||||
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
|
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
|
||||||
"yyyy/mm"}
|
"yyyy/mm"}
|
||||||
|
|
||||||
datetimeStr := []string{
|
expected := []string{
|
||||||
"2021-01-02 16:04:08", "2021-01-02",
|
"2021-01-02 16:04:08", "2021-01-02",
|
||||||
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
||||||
"2021/01"}
|
"2021/01"}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
actual, err := FormatStrToTime(datetimeStr[i], cases[i])
|
actual, err := FormatStrToTime(expected[i], cases[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
expected, _ := time.Parse(formats[i], expected[i])
|
||||||
assert.Equal(expected, actual)
|
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) {
|
func TestBeginOfMinute(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfMinute")
|
assert := internal.NewAssert(t, "TestBeginOfMinute")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local)
|
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) {
|
func TestEndOfMinute(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfMinute")
|
assert := internal.NewAssert(t, "TestEndOfMinute")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local)
|
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) {
|
func TestBeginOfHour(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfHour")
|
assert := internal.NewAssert(t, "TestBeginOfHour")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local)
|
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) {
|
func TestEndOfHour(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfHour")
|
assert := internal.NewAssert(t, "TestEndOfHour")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local)
|
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) {
|
func TestBeginOfDay(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfDay")
|
assert := internal.NewAssert(t, "TestBeginOfDay")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local)
|
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) {
|
func TestEndOfDay(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfDay")
|
assert := internal.NewAssert(t, "TestEndOfDay")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local)
|
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) {
|
func TestBeginOfWeek(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfWeek")
|
assert := internal.NewAssert(t, "TestBeginOfWeek")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local)
|
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) {
|
func TestEndOfWeek(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfWeek")
|
assert := internal.NewAssert(t, "TestEndOfWeek")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local)
|
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) {
|
func TestBeginOfMonth(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfMonth")
|
assert := internal.NewAssert(t, "TestBeginOfMonth")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local)
|
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) {
|
func TestEndOfMonth(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfMonth")
|
assert := internal.NewAssert(t, "TestEndOfMonth")
|
||||||
|
|
||||||
expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local)
|
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) {
|
func TestBeginOfYear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestBeginOfYear")
|
assert := internal.NewAssert(t, "TestBeginOfYear")
|
||||||
|
|
||||||
expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local)
|
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) {
|
func TestEndOfYear(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestEndOfYear")
|
assert := internal.NewAssert(t, "TestEndOfYear")
|
||||||
|
|
||||||
expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local)
|
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)
|
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: 'dark',
|
||||||
|
|
||||||
|
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: 'Released under the MIT License.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
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 },
|
||||||
|
},
|
||||||
|
})
|
||||||
75
docs/.vitepress/en.ts
Normal file
75
docs/.vitepress/en.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
|
||||||
|
|
||||||
|
export const META_URL = 'https://lancet.go.dev'
|
||||||
|
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 }],
|
||||||
|
['meta', { property: 'twitter:url', content: META_URL }],
|
||||||
|
['meta', { property: 'twitter:title', content: META_TITLE }],
|
||||||
|
['meta', { property: 'twitter:description', content: META_DESCRIPTION }],
|
||||||
|
],
|
||||||
|
|
||||||
|
themeConfig: {
|
||||||
|
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: 'Releaselog',
|
||||||
|
link: 'https://github.com/duke-git/lancet/releases',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
sidebar: {
|
||||||
|
'/en/': [
|
||||||
|
{
|
||||||
|
text: 'Introduction',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'What is Lancet?',
|
||||||
|
link: '/en/guide/introduction',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'getting started',
|
||||||
|
link: '/en/guide/getting_started',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/en/api/': [
|
||||||
|
{
|
||||||
|
text: 'overview',
|
||||||
|
items: [{ text: 'overview of API', link: '/en/api/overview' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'packages',
|
||||||
|
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' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
85
docs/.vitepress/zh.ts
Normal file
85
docs/.vitepress/zh.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
|
||||||
|
|
||||||
|
export const META_URL = 'https://lancet.go.dev'
|
||||||
|
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 }],
|
||||||
|
['meta', { property: 'twitter:url', content: META_URL }],
|
||||||
|
['meta', { property: 'twitter:title', content: META_TITLE }],
|
||||||
|
['meta', { property: 'twitter:description', content: META_DESCRIPTION }],
|
||||||
|
],
|
||||||
|
|
||||||
|
themeConfig: {
|
||||||
|
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/releases',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
sidebar: {
|
||||||
|
'/': [
|
||||||
|
{
|
||||||
|
text: '介绍',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Lancet是什么?',
|
||||||
|
link: '/guide/introduction',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '开始',
|
||||||
|
link: '/guide/getting_started',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
'/api/': [
|
||||||
|
{
|
||||||
|
text: '概览',
|
||||||
|
items: [{ text: 'API概述', link: '/api/overview' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'API文档',
|
||||||
|
items: [
|
||||||
|
{ text: '算法', link: '/api/packages/algorithm' },
|
||||||
|
{ text: '比较器', link: '/api/packages/compare' },
|
||||||
|
{ text: '并发处理', link: '/api/packages/concurrency' },
|
||||||
|
{ text: '条件判断', link: '/api/packages/condition' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
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>
|
||||||
@@ -39,6 +39,8 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|
||||||
### <span id="BubbleSort">BubbleSort</span>
|
### <span id="BubbleSort">BubbleSort</span>
|
||||||
@@ -51,7 +53,7 @@ import (
|
|||||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -99,7 +101,7 @@ func main() {
|
|||||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -162,7 +164,7 @@ func main() {
|
|||||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -210,7 +212,7 @@ func main() {
|
|||||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -258,7 +260,7 @@ func main() {
|
|||||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -306,7 +308,7 @@ func main() {
|
|||||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -354,7 +356,7 @@ func main() {
|
|||||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -402,7 +404,7 @@ func main() {
|
|||||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -451,7 +453,7 @@ func main() {
|
|||||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -502,7 +504,7 @@ func main() {
|
|||||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -553,7 +555,7 @@ func main() {
|
|||||||
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例: <span class="run-container">[运行](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -596,7 +598,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
|
|||||||
func (l *LRUCache[K, V]) Len() int
|
func (l *LRUCache[K, V]) Len() int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/-EZjgOURufP)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
377
docs/api/packages/compare.md
Normal file
377
docs/api/packages/compare.md
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
# 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>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="../../styles/api_doc.css">
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
### <span id="Equal">Equal</span>
|
||||||
|
|
||||||
|
<p>检查两个值是否相等(检查类型和值)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Equal(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例: <span class="run-container">[运行](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 class="run-container">[运行](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 class="run-container">[运行](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 class="run-container">[运行](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 class="run-container">[运行](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 class="run-container">[运行](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 class="run-container">[运行](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,5 +1,5 @@
|
|||||||
# Concurrency
|
# Concurrency
|
||||||
并发包包含一些支持并发编程的功能。例如:goroutine, channel, async等。
|
并发包包含一些支持并发编程的功能。例如:goroutine, channel等。
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -33,11 +33,15 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|
||||||
|
|
||||||
### Channel
|
### Channel
|
||||||
|
|
||||||
### <span id="NewChannel">NewChannel</span>
|
### <span id="NewChannel">NewChannel</span>
|
||||||
|
|
||||||
<p>返回一个Channel指针实例</p>
|
<p>返回一个Channel指针实例</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
@@ -46,7 +50,7 @@ import (
|
|||||||
type Channel[T any] struct
|
type Channel[T any] struct
|
||||||
func NewChannel[T any]() *Channel[T]
|
func NewChannel[T any]() *Channel[T]
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -70,7 +74,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
|
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -122,7 +126,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
|
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/2VYFMexEvTm)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -161,7 +165,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
|
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -199,7 +203,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
|
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -238,7 +242,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
|
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/4J1zAWttP85)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -279,7 +283,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
|
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/Wqz9rwioPww)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -322,7 +326,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
|
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -360,7 +364,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
|
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -406,7 +410,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/3TQPKnCirrP)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Index
|
## 目录
|
||||||
|
|
||||||
- [Bool](#Bool)
|
- [Bool](#Bool)
|
||||||
- [And](#And)
|
- [And](#And)
|
||||||
@@ -31,7 +31,9 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 目录
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
### <span id="Bool">Bool</span>
|
### <span id="Bool">Bool</span>
|
||||||
<p>返回传入参数的bool值.<br/>
|
<p>返回传入参数的bool值.<br/>
|
||||||
@@ -45,7 +47,7 @@ slices和map的length大于0时,返回true,否则返回false<br/>
|
|||||||
```go
|
```go
|
||||||
func Bool[T any](value T) bool
|
func Bool[T any](value T) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -109,7 +111,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func And[T, U any](a T, b U) bool
|
func And[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -135,7 +137,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Or[T, U any](a T, b U) bool
|
func Or[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -161,7 +163,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Xor[T, U any](a T, b U) bool
|
func Xor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -187,7 +189,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Nor[T, U any](a T, b U) bool
|
func Nor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -213,7 +215,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Xnor[T, U any](a T, b U) bool
|
func Xnor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -239,7 +241,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Nand[T, U any](a T, b U) bool
|
func Nand[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -265,7 +267,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||||
```
|
```
|
||||||
<b>示例:</b>
|
<b>示例:<span class="run-container">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
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>
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ Package algorithm implements some basic algorithm. eg. sort, search.
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -51,7 +53,7 @@ import (
|
|||||||
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -99,7 +101,7 @@ func main() {
|
|||||||
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -162,7 +164,7 @@ func main() {
|
|||||||
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/oXovbkekayS)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -210,7 +212,7 @@ func main() {
|
|||||||
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/3ibkszpJEu3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -258,7 +260,7 @@ func main() {
|
|||||||
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[Run](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -306,7 +308,7 @@ func main() {
|
|||||||
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -354,7 +356,7 @@ func main() {
|
|||||||
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/ydinn9YzUJn)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -402,7 +404,7 @@ func main() {
|
|||||||
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -451,7 +453,7 @@ func main() {
|
|||||||
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/t6MeGiUSN47)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -502,7 +504,7 @@ func main() {
|
|||||||
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -553,7 +555,7 @@ func main() {
|
|||||||
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -596,7 +598,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
|
|||||||
func (l *LRUCache[K, V]) Len() int
|
func (l *LRUCache[K, V]) Len() int
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
376
docs/en/api/packages/compare.md
Normal file
376
docs/en/api/packages/compare.md
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
# 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>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### <span id="Equal">Equal</span>
|
||||||
|
|
||||||
|
<p>Checks if two values are equal or not. (check both type and value)</p>
|
||||||
|
|
||||||
|
<b>Signature: <span class="run-container">[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 class="run-container">[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 class="run-container">[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 class="run-container">[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 class="run-container">[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 class="run-container">[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 class="run-container">[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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Concurrency
|
# Concurrency
|
||||||
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.
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -33,8 +33,9 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Documentation
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
## Channel
|
## Channel
|
||||||
### <span id="NewChannel">NewChannel</span>
|
### <span id="NewChannel">NewChannel</span>
|
||||||
@@ -46,7 +47,7 @@ import (
|
|||||||
type Channel[T any] struct
|
type Channel[T any] struct
|
||||||
func NewChannel[T any]() *Channel[T]
|
func NewChannel[T any]() *Channel[T]
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -70,7 +71,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
|
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -122,7 +123,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
|
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/2VYFMexEvTm)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -156,7 +157,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Create channel, put values into the channel repeatly until cancel the context.</p>
|
<p>Create channel, put values into the channel repeatly until cancel the context.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
|
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
|
||||||
@@ -200,7 +201,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
|
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example: <span class="run-container">[Run](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -233,7 +234,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Create a channel, excutes fn repeatly, and put the result into the channel, until close context.</p>
|
<p>Create a channel, excutes fn repeatly, and put the result into the channel, until close context.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/4J1zAWttP85)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
|
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
|
||||||
@@ -275,7 +276,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
|
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/Wqz9rwioPww)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
|
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
|
||||||
@@ -318,7 +319,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Read a channel into another channel, will close until cancel context.</p>
|
<p>Read a channel into another channel, will close until cancel context.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
|
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
|
||||||
@@ -356,7 +357,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Create a channel whose values are taken from another channel with limit number.</p>
|
<p>Create a channel whose values are taken from another channel with limit number.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
|
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
|
||||||
@@ -402,7 +403,7 @@ func main() {
|
|||||||
|
|
||||||
<p>Split one chanel into two channels, until cancel the context.</p>
|
<p>Split one chanel into two channels, until cancel the context.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature: <span class="run-container">[Run](https://go.dev/play/p/3TQPKnCirrP)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
|
||||||
@@ -31,6 +31,8 @@ import (
|
|||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="/styles/api_doc.css">
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ All other types are truthy if they are not their zero value.</p>
|
|||||||
```go
|
```go
|
||||||
func Bool[T any](value T) bool
|
func Bool[T any](value T) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -111,7 +113,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func And[T, U any](a T, b U) bool
|
func And[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -139,7 +141,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Or[T, U any](a T, b U) bool
|
func Or[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -167,7 +169,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Xor[T, U any](a T, b U) bool
|
func Xor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -195,7 +197,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Nor[T, U any](a T, b U) bool
|
func Nor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -222,7 +224,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Xnor[T, U any](a T, b U) bool
|
func Xnor[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -249,7 +251,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func Nand[T, U any](a T, b U) bool
|
func Nand[T, U any](a T, b U) bool
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -277,7 +279,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
|
||||||
```
|
```
|
||||||
<b>Example:</b>
|
<b>Example:<span class="run-container">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
50
docs/en/guide/getting_started.md
Normal file
50
docs/en/guide/getting_started.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause in v2.x.x all functions was rewriten with generics of go1.18.</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||||
|
```
|
||||||
|
|
||||||
|
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.1. </b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions, just import the strutil package like below:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Here takes the string function `Reverse` (reverse order string) as an example, and the strutil package needs to be imported.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := "hello"
|
||||||
|
rs := strutil.Reverse(s)
|
||||||
|
fmt.Println(rs) //olleh
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## More
|
||||||
|
|
||||||
|
Check out the [APIs]([API](https://lancet.go.dev/api/overview.html)) for details.
|
||||||
18
docs/en/guide/introduction.md
Normal file
18
docs/en/guide/introduction.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# What is lancet?
|
||||||
|
|
||||||
|
<b>Lancet is a powerful, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js. </b>
|
||||||
|
|
||||||
|
|
||||||
|
## Why lancet?
|
||||||
|
|
||||||
|
Lancet makes Go dev easier by taking the hassle out of working with concurrency, net, math, slice, string, etc.
|
||||||
|
Lancet's utility methods are great for:
|
||||||
|
|
||||||
|
- Iterating slice and array.
|
||||||
|
- Manipulating strings.
|
||||||
|
- Work with net and http.
|
||||||
|
- Other tools, eg. random, crypto, stream, retry, etc.
|
||||||
43
docs/en/index.md
Normal file
43
docs/en/index.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
# https://vitepress.dev/reference/default-theme-home-page
|
||||||
|
layout: home
|
||||||
|
|
||||||
|
hero:
|
||||||
|
name: "Lancet"
|
||||||
|
text: "A powerful util function library of Go"
|
||||||
|
tagline: Simple, powerful, and efficient.
|
||||||
|
actions:
|
||||||
|
- theme: brand
|
||||||
|
text: Get Started
|
||||||
|
link: /en/guide/getting_started
|
||||||
|
- theme: alt
|
||||||
|
text: View on GitHub
|
||||||
|
link: https://github.com/duke-git/lancet
|
||||||
|
# - theme: alt
|
||||||
|
# text: API Examples
|
||||||
|
# link: /api-examples
|
||||||
|
image:
|
||||||
|
src: /lancet_logo.png
|
||||||
|
alt: lancet
|
||||||
|
|
||||||
|
features:
|
||||||
|
- title: Powerful
|
||||||
|
icon: 💪
|
||||||
|
details: support 600+ go util functions. eg. string, slice, datetime, net, crypto, concurrency...
|
||||||
|
- title: Modular by design
|
||||||
|
icon: 🏗
|
||||||
|
details: Each module is designed as a package with no coupling between modules.
|
||||||
|
- title: Pure
|
||||||
|
icon: 💅
|
||||||
|
details: Only depends on two kinds of libraries, go standard library and golang.org/x.
|
||||||
|
- title: Simple
|
||||||
|
icon: 👏
|
||||||
|
details: Well structure, test for every exported function.
|
||||||
|
---
|
||||||
|
|
||||||
|
<p style="position:relative; top: -316px;left: 560px;">
|
||||||
|
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||||
|
|
||||||
|
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||||
|
|
||||||
|
</p>
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# Formatter
|
|
||||||
|
|
||||||
formatter contains some functions for data formatting.
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Source:
|
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Usage:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"github.com/duke-git/lancet/v2/formatter"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Index
|
|
||||||
|
|
||||||
- [Comma](#Comma)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
### <span id="Comma">Comma</span>
|
|
||||||
|
|
||||||
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# 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)
|
|
||||||
|
|
||||||
<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)
|
|
||||||
|
|
||||||
<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>示例:</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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
48
docs/guide/getting_started.md
Normal file
48
docs/guide/getting_started.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# 安装
|
||||||
|
|
||||||
|
1. <b>使用 go1.18 及以上版本的用户,建议安装 v2.x.x。 因为 v2.x.x 应用 go1.18 的泛型重写了大部分函数。</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||||
|
```
|
||||||
|
|
||||||
|
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.1。</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||||
|
```
|
||||||
|
|
||||||
|
## 用法
|
||||||
|
|
||||||
|
lancet 是以包的结构组织代码的,使用时需要导入相应的包名。例如:如果使用字符串相关函数,需要导入 strutil 包:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
此处以字符串工具函数 Reverse(逆序字符串)为例,需要导入 strutil 包:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := "hello"
|
||||||
|
rs := strutil.Reverse(s)
|
||||||
|
fmt.Println(rs) //olleh
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## More
|
||||||
|
|
||||||
|
其他特性请参考[API](https://lancet.go.dev/api/overview.html).
|
||||||
18
docs/guide/introduction.md
Normal file
18
docs/guide/introduction.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
outline: deep
|
||||||
|
---
|
||||||
|
|
||||||
|
# lancet是什么?
|
||||||
|
|
||||||
|
<b>lancet(柳叶刀)是一个强大、全面、高效、可复用的go语言工具函数库。lancet受到了java apache common包和lodash.js的启发。 </b>
|
||||||
|
|
||||||
|
|
||||||
|
## 为什么选择lancet?
|
||||||
|
|
||||||
|
Lancet 消除了处理并发、网络、数学、切片、字符串等的麻烦,使 Go 开发变得更容易。
|
||||||
|
Lancet 的实用方法非常适合:
|
||||||
|
|
||||||
|
- 迭代切片和数组。
|
||||||
|
- 操作字符串。
|
||||||
|
- 处理网络和http请求。
|
||||||
|
- 其他工具,例如。 随机、加密、流、重试等。
|
||||||
45
docs/index.md
Normal file
45
docs/index.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
# https://vitepress.dev/reference/default-theme-home-page
|
||||||
|
layout: home
|
||||||
|
|
||||||
|
hero:
|
||||||
|
name: 'Lancet'
|
||||||
|
text: '一个强大的Go语言工具函数库'
|
||||||
|
tagline: '简洁, 强大, 高效'
|
||||||
|
actions:
|
||||||
|
- theme: brand
|
||||||
|
text: 开始使用
|
||||||
|
link: /guide/getting_started
|
||||||
|
- theme: alt
|
||||||
|
text: 在GitHub中查看
|
||||||
|
link: https://github.com/duke-git/lancet
|
||||||
|
|
||||||
|
image:
|
||||||
|
src: /lancet_logo.png
|
||||||
|
alt: lancet
|
||||||
|
|
||||||
|
features:
|
||||||
|
- title: 全面
|
||||||
|
icon: 💪
|
||||||
|
details: 特性丰富,支持600+ go util函数。字符串、切片、日期时间、网络、加密、并发...
|
||||||
|
- title: 模块化设计
|
||||||
|
icon: 🏗
|
||||||
|
details: 每个模块设计成一个包,模块之间无耦合。
|
||||||
|
- title: 纯净
|
||||||
|
icon: 💅
|
||||||
|
details: 只依赖go标准库和golang.org/x。
|
||||||
|
- title: 简洁
|
||||||
|
icon: 👏
|
||||||
|
details: 结构良好,测试每个导出的函数。
|
||||||
|
---
|
||||||
|
|
||||||
|
<p style="position:relative; top: -316px;left: 540px;">
|
||||||
|
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||||
|
|
||||||
|
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||||
|
|
||||||
|
<!-- [](https://github.com/duke-git/lancet)
|
||||||
|
|
||||||
|
[](https://github.com/duke-git/lancet) -->
|
||||||
|
|
||||||
|
</p>
|
||||||
BIN
docs/lancet_logo.png
Normal file
BIN
docs/lancet_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
docs/lancet_logo_mini.png
Normal file
BIN
docs/lancet_logo_mini.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.3 KiB |
383
docs/maputil.md
383
docs/maputil.md
@@ -1,383 +0,0 @@
|
|||||||
# Maputil
|
|
||||||
|
|
||||||
Package maputil includes some functions to manipulate map.
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Source:
|
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Index
|
|
||||||
|
|
||||||
- [ForEach](#ForEach)
|
|
||||||
- [Filter](#Filter)
|
|
||||||
- [Intersect](#Intersect)
|
|
||||||
- [Keys](#Keys)
|
|
||||||
- [Merge](#Merge)
|
|
||||||
- [Minus](#Minus)
|
|
||||||
- [Values](#Values)
|
|
||||||
- [IsDisjoint](#IsDisjoint)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
### <span id="ForEach">ForEach</span>
|
|
||||||
|
|
||||||
<p>Executes iteratee funcation for every key and value pair in map.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
"d": 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
var sum int
|
|
||||||
|
|
||||||
maputil.ForEach(m, func(_ string, value int) {
|
|
||||||
sum += value
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Println(sum)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Filter">Filter</span>
|
|
||||||
|
|
||||||
<p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
"d": 4,
|
|
||||||
"e": 5,
|
|
||||||
}
|
|
||||||
isEven := func(_ string, value int) bool {
|
|
||||||
return value%2 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
maputil.Filter(m, func(_ string, value int) {
|
|
||||||
sum += value
|
|
||||||
})
|
|
||||||
|
|
||||||
result := maputil.Filter(m, isEven)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[b:2 d:4]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Intersect">Intersect</span>
|
|
||||||
|
|
||||||
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 6,
|
|
||||||
"d": 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
m3 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 9,
|
|
||||||
"e": 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
result1 := maputil.Intersect(m1)
|
|
||||||
result2 := maputil.Intersect(m1, m2)
|
|
||||||
result3 := maputil.Intersect(m1, m2, m3)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
fmt.Println(result3)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[a:1 b:2 c:3]
|
|
||||||
// map[a:1 b:2]
|
|
||||||
// map[a:1]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Keys">Keys</span>
|
|
||||||
|
|
||||||
<p>Returns a slice of the map's keys.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Keys[K comparable, V any](m map[K]V) []K
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "a",
|
|
||||||
3: "b",
|
|
||||||
4: "c",
|
|
||||||
5: "d",
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := maputil.Keys(m)
|
|
||||||
sort.Ints(keys)
|
|
||||||
|
|
||||||
fmt.Println(keys)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// [1 2 3 4 5]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
|
||||||
|
|
||||||
<p>Merge maps, next key will overwrite previous key.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "b",
|
|
||||||
}
|
|
||||||
m2 := map[int]string{
|
|
||||||
1: "1",
|
|
||||||
3: "2",
|
|
||||||
}
|
|
||||||
|
|
||||||
result := maputil.Merge(m1, m2)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[1:c 2:b 3:d]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Minus">Minus</span>
|
|
||||||
|
|
||||||
<p>Creates an map of whose key in mapA but not in mapB.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"a": 11,
|
|
||||||
"b": 22,
|
|
||||||
"d": 33,
|
|
||||||
}
|
|
||||||
|
|
||||||
result := maputil.Minus(m1, m2)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[c:3]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Values">Values</span>
|
|
||||||
|
|
||||||
<p>Returns a slice of the map's values.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Values[K comparable, V any](m map[K]V) []V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "a",
|
|
||||||
3: "b",
|
|
||||||
4: "c",
|
|
||||||
5: "d",
|
|
||||||
}
|
|
||||||
|
|
||||||
values := maputil.Values(m)
|
|
||||||
sort.Strings(values)
|
|
||||||
|
|
||||||
fmt.Println(values)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// [a a b c d]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsDisjoint">IsDisjoint</span>
|
|
||||||
|
|
||||||
<p>Checks two maps are disjoint if they have no keys in common</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"d": 22,
|
|
||||||
}
|
|
||||||
|
|
||||||
m3 := map[string]int{
|
|
||||||
"a": 22,
|
|
||||||
}
|
|
||||||
|
|
||||||
result1 := maputil.IsDisjoint(m1, m2)
|
|
||||||
result2 := maputil.IsDisjoint(m1, m3)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// true
|
|
||||||
// false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,381 +0,0 @@
|
|||||||
# Maputil
|
|
||||||
|
|
||||||
maputil 包包括一些操作 map 的函数。
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## 源码:
|
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## 用法:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## 目录:
|
|
||||||
|
|
||||||
- [ForEach](#ForEach)
|
|
||||||
- [Filter](#Filter)
|
|
||||||
- [Intersect](#Intersect)
|
|
||||||
- [Keys](#Keys)
|
|
||||||
- [Merge](#Merge)
|
|
||||||
- [Minus](#Minus)
|
|
||||||
- [Values](#Values)
|
|
||||||
- [IsDisjoint](#IsDisjoint)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## API 文档:
|
|
||||||
|
|
||||||
### <span id="ForEach">ForEach</span>
|
|
||||||
|
|
||||||
<p>对map中的每对key和value执行iteratee函数</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
"d": 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
var sum int
|
|
||||||
|
|
||||||
maputil.ForEach(m, func(_ string, value int) {
|
|
||||||
sum += value
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Println(sum)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Filter">Filter</span>
|
|
||||||
|
|
||||||
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
"d": 4,
|
|
||||||
"e": 5,
|
|
||||||
}
|
|
||||||
isEven := func(_ string, value int) bool {
|
|
||||||
return value%2 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
maputil.Filter(m, func(_ string, value int) {
|
|
||||||
sum += value
|
|
||||||
})
|
|
||||||
|
|
||||||
result := Filter(m, isEven)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[b:2 d:4]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Intersect">Intersect</span>
|
|
||||||
|
|
||||||
<p>多个map的交集操作</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 6,
|
|
||||||
"d": 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
m3 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 9,
|
|
||||||
"e": 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
result1 := maputil.Intersect(m1)
|
|
||||||
result2 := maputil.Intersect(m1, m2)
|
|
||||||
result3 := maputil.Intersect(m1, m2, m3)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
fmt.Println(result3)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[a:1 b:2 c:3]
|
|
||||||
// map[a:1 b:2]
|
|
||||||
// map[a:1]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Keys">Keys</span>
|
|
||||||
|
|
||||||
<p>返回map中所有key的切片</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Keys[K comparable, V any](m map[K]V) []K
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "a",
|
|
||||||
3: "b",
|
|
||||||
4: "c",
|
|
||||||
5: "d",
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := maputil.Keys(m)
|
|
||||||
sort.Ints(keys)
|
|
||||||
|
|
||||||
fmt.Println(keys)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// [1 2 3 4 5]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
|
||||||
|
|
||||||
<p>合并多个maps, 相同的key会被后来的key覆盖</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "b",
|
|
||||||
}
|
|
||||||
m2 := map[int]string{
|
|
||||||
1: "1",
|
|
||||||
3: "2",
|
|
||||||
}
|
|
||||||
|
|
||||||
result := maputil.Merge(m1, m2)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[1:c 2:b 3:d]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Minus">Minus</span>
|
|
||||||
|
|
||||||
<p>返回一个map,其中的key存在于mapA,不存在于mapB.</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"a": 11,
|
|
||||||
"b": 22,
|
|
||||||
"d": 33,
|
|
||||||
}
|
|
||||||
|
|
||||||
result := maputil.Minus(m1, m2)
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// map[c:3]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="Values">Values</span>
|
|
||||||
|
|
||||||
<p>返回map中所有value的切片</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Values[K comparable, V any](m map[K]V) []V
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m := map[int]string{
|
|
||||||
1: "a",
|
|
||||||
2: "a",
|
|
||||||
3: "b",
|
|
||||||
4: "c",
|
|
||||||
5: "d",
|
|
||||||
}
|
|
||||||
|
|
||||||
values := maputil.Values(m)
|
|
||||||
sort.Strings(values)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// [a a b c d]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsDisjoint">IsDisjoint</span>
|
|
||||||
|
|
||||||
<p>验证两个map是否具有不同的key</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/maputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m1 := map[string]int{
|
|
||||||
"a": 1,
|
|
||||||
"b": 2,
|
|
||||||
"c": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
m2 := map[string]int{
|
|
||||||
"d": 22,
|
|
||||||
}
|
|
||||||
|
|
||||||
m3 := map[string]int{
|
|
||||||
"a": 22,
|
|
||||||
}
|
|
||||||
|
|
||||||
result1 := maputil.IsDisjoint(m1, m2)
|
|
||||||
result2 := maputil.IsDisjoint(m1, m3)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// true
|
|
||||||
// false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
478
docs/mathutil.md
478
docs/mathutil.md
@@ -1,478 +0,0 @@
|
|||||||
# Mathutil
|
|
||||||
|
|
||||||
Package mathutil implements some functions for math calculation.
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Source:
|
|
||||||
|
|
||||||
- [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>
|
|
||||||
|
|
||||||
## Example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"github.com/duke-git/lancet/v2/mathutil"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Index
|
|
||||||
|
|
||||||
- [Average](#Average)
|
|
||||||
- [Exponent](#Exponent)
|
|
||||||
- [Fibonacci](#Fibonacci)
|
|
||||||
- [Factorial](#Factorial)
|
|
||||||
- [Max](#Max)
|
|
||||||
- [MaxBy](#MaxBy)
|
|
||||||
- [Min](#Min)
|
|
||||||
- [MinBy](#MaxBy)
|
|
||||||
- [Percent](#Percent)
|
|
||||||
- [RoundToFloat](#RoundToFloat)
|
|
||||||
- [RoundToString](#RoundToString)
|
|
||||||
- [TruncRound](#TruncRound)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
### <span id="Average">Average</span>
|
|
||||||
|
|
||||||
<p>Return average value of numbers. Maybe call RoundToFloat to round result.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Calculate x to the nth power.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Exponent(x, n int64) int64
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Calculate the nth number of fibonacci sequence.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Fibonacci(first, second, n int) int
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Calculate the factorial of x.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Factorial(x uint) uint
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Return max value of numbers.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Max[T constraints.Integer | constraints.Float](numbers ...T) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Return the maximum value of a slice using the given comparator function.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func MaxBy[T any](slice []T, comparator func(T, T) bool) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Return the minimum value of numbers.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Min[T constraints.Integer | constraints.Float](numbers ...T) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Return the minimum value of a slice using the given comparator function.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func MinBy[T any](slice []T, comparator func(T, T) bool) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>calculate the percentage of val to total, retain n decimal places.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Percent(val, total float64, n int) float64
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 0.5
|
|
||||||
// 0.33
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="RoundToFloat">RoundToFloat</span>
|
|
||||||
|
|
||||||
<p>Round float up to n decimal places.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func RoundToFloat(x float64, n int) float64
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Round float up to n decimal places. will return string.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func RoundToString(x float64, n int) string
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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>Round float off n decimal places.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func TruncRound(x float64, n int) float64
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,478 +0,0 @@
|
|||||||
# 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)
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
### <span id="Average">Average</span>
|
|
||||||
|
|
||||||
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) T
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</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>示例:</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>示例:</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>示例:</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>示例:</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>示例:</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>示例:</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>示例:</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>示例:</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)
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// 0.5
|
|
||||||
// 0.33
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="RoundToFloat">RoundToFloat</span>
|
|
||||||
|
|
||||||
<p>四舍五入,保留n位小数</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func RoundToFloat(x float64, n int) float64
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</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>示例:</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>示例:</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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
# Convertor
|
# Convertor
|
||||||
|
|
||||||
Package convertor contains some functions for data type convertion.
|
Package convertor contains some functions for data type convertion.
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Source:
|
## Source:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Usage:
|
## Usage:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
@@ -19,28 +21,35 @@ import (
|
|||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Index
|
## Index
|
||||||
- [ColorHexToRGB](#ColorHexToRGB)
|
|
||||||
- [ColorRGBToHex](#ColorRGBToHex)
|
- [ColorHexToRGB](#ColorHexToRGB)
|
||||||
- [ToBool](#ToBool)
|
- [ColorRGBToHex](#ColorRGBToHex)
|
||||||
- [ToBytes](#ToBytes)
|
- [ToBool](#ToBool)
|
||||||
- [ToChar](#ToChar)
|
- [ToBytes](#ToBytes)
|
||||||
- [ToChannel](#ToChannel)
|
- [ToChar](#ToChar)
|
||||||
- [ToFloat](#ToFloat)
|
- [ToChannel](#ToChannel)
|
||||||
- [ToInt](#ToInt)
|
- [ToFloat](#ToFloat)
|
||||||
- [ToJson](#ToJson)
|
- [ToInt](#ToInt)
|
||||||
- [ToMap](#ToMap)
|
- [ToJson](#ToJson)
|
||||||
- [ToPointer](#ToPointer)
|
- [ToMap](#ToMap)
|
||||||
- [ToString](#ToString)
|
- [ToPointer](#ToPointer)
|
||||||
- [StructToMap](#StructToMap)
|
- [ToString](#ToString)
|
||||||
- [MapToSlice](#MapToSlice)
|
- [StructToMap](#StructToMap)
|
||||||
- [EncodeByte](#EncodeByte)
|
- [MapToSlice](#MapToSlice)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
|
- [DecodeByte](#DecodeByte)
|
||||||
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
- [ToInterface](#ToInterface)
|
||||||
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
||||||
|
|
||||||
<p>Convert color hex to color rgb.</p>
|
<p>Convert color hex to color rgb.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
@@ -48,6 +57,7 @@ import (
|
|||||||
```go
|
```go
|
||||||
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -78,6 +88,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ColorRGBToHex(red, green, blue int) string
|
func ColorRGBToHex(red, green, blue int) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -110,6 +121,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToBool(s string) (bool, error)
|
func ToBool(s string) (bool, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -150,6 +162,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToBytes(data any) ([]byte, error)
|
func ToBytes(data any) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -182,6 +195,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToChar(s string) []string
|
func ToChar(s string) []string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -217,6 +231,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToChannel[T any](array []T) <-chan T
|
func ToChannel[T any](array []T) <-chan T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -253,6 +268,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToFloat(value any) (float64, error)
|
func ToFloat(value any) (float64, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -297,6 +313,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToInt(value any) (int64, error)
|
func ToInt(value any) (int64, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -338,6 +355,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToJson(value any) (string, error)
|
func ToJson(value any) (string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -372,6 +390,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -412,6 +431,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToPointer[T any](value T) *T
|
func ToPointer[T any](value T) *T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -424,8 +444,8 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result := convertor.ToPointer(123)
|
result := convertor.ToPointer(123)
|
||||||
fmt.Println(*result)
|
fmt.Println(*result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 123
|
// 123
|
||||||
}
|
}
|
||||||
@@ -440,6 +460,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToString(value any) string
|
func ToString(value any) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -487,6 +508,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func StructToMap(value any) (map[string]any, error)
|
func StructToMap(value any) (map[string]any, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -524,6 +546,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -544,7 +567,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="EncodeByte">EncodeByte</span>
|
### <span id="EncodeByte">EncodeByte</span>
|
||||||
|
|
||||||
<p>Encode data to byte slice.</p>
|
<p>Encode data to byte slice.</p>
|
||||||
@@ -554,6 +576,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func EncodeByte(data any) ([]byte, error)
|
func EncodeByte(data any) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -582,6 +605,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func DecodeByte(data []byte, target any) error
|
func DecodeByte(data []byte, target any) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -595,15 +619,260 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
var result string
|
var result string
|
||||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||||
|
|
||||||
err := convertor.DecodeByte(byteData, &result)
|
err := convertor.DecodeByte(byteData, &result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// abc
|
// abc
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DeepClone">DeepClone</span>
|
||||||
|
|
||||||
|
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DeepClone[T any](src T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Struct struct {
|
||||||
|
Str string
|
||||||
|
Int int
|
||||||
|
Float float64
|
||||||
|
Bool bool
|
||||||
|
Nil interface{}
|
||||||
|
unexported string
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []interface{}{
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
},
|
||||||
|
&Struct{
|
||||||
|
Str: "test",
|
||||||
|
Int: 1,
|
||||||
|
Float: 0.1,
|
||||||
|
Bool: true,
|
||||||
|
Nil: nil,
|
||||||
|
// unexported: "can't be cloned",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range cases {
|
||||||
|
cloned := convertor.DeepClone(item)
|
||||||
|
|
||||||
|
isPointerEqual := &cloned == &item
|
||||||
|
fmt.Println(cloned, isPointerEqual)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true false
|
||||||
|
// 1 false
|
||||||
|
// 0.1 false
|
||||||
|
// map[a:1 b:2] false
|
||||||
|
// &{test 1 0.1 true <nil> } false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="CopyProperties">CopyProperties</span>
|
||||||
|
|
||||||
|
<p>Copies each field from the source struct into the destination struct. Use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties[T, U any](dst T, src U) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(indicatorVO.Id)
|
||||||
|
fmt.Println(indicatorVO.Ip)
|
||||||
|
fmt.Println(len(indicatorVO.Disk))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 001
|
||||||
|
// 127.0.0.1
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToInterface">ToInterface</span>
|
||||||
|
|
||||||
|
<p>Converts reflect value to its interface type.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
val := reflect.ValueOf("abc")
|
||||||
|
iVal, ok := convertor.ToInterface(val)
|
||||||
|
|
||||||
|
fmt.Printf("%T\n", iVal)
|
||||||
|
fmt.Printf("%v\n", iVal)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// string
|
||||||
|
// abc
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Utf8ToGbk">Utf8ToGbk</span>
|
||||||
|
|
||||||
|
<p>Converts utf8 encoding data to GBK encoding data.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Utf8ToGbk(bs []byte) ([]byte, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>Converts GBK encoding data to utf8 encoding data.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GbkToUtf8(bs []byte) ([]byte, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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,11 +1,12 @@
|
|||||||
# Convertor
|
# Convertor
|
||||||
convertor转换器包支持一些常见的数据类型转换
|
|
||||||
|
convertor 转换器包支持一些常见的数据类型转换
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 源码:
|
## 源码:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
- [https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -21,29 +22,34 @@ import (
|
|||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
- [ColorHexToRGB](#ColorHexToRGB)
|
- [ColorHexToRGB](#ColorHexToRGB)
|
||||||
- [ColorRGBToHex](#ColorRGBToHex)
|
- [ColorRGBToHex](#ColorRGBToHex)
|
||||||
- [ToBool](#ToBool)
|
- [ToBool](#ToBool)
|
||||||
- [ToBytes](#ToBytes)
|
- [ToBytes](#ToBytes)
|
||||||
- [ToChar](#ToChar)
|
- [ToChar](#ToChar)
|
||||||
- [ToChannel](#ToChannel)
|
- [ToChannel](#ToChannel)
|
||||||
- [ToFloat](#ToFloat)
|
- [ToFloat](#ToFloat)
|
||||||
- [ToInt](#ToInt)
|
- [ToInt](#ToInt)
|
||||||
- [ToJson](#ToJson)
|
- [ToJson](#ToJson)
|
||||||
- [ToMap](#ToMap)
|
- [ToMap](#ToMap)
|
||||||
- [ToPointer](#ToPointer)
|
- [ToPointer](#ToPointer)
|
||||||
- [ToString](#ToString)
|
- [ToString](#ToString)
|
||||||
- [StructToMap](#StructToMap)
|
- [StructToMap](#StructToMap)
|
||||||
- [MapToSlice](#MapToSlice)
|
- [MapToSlice](#MapToSlice)
|
||||||
- [EncodeByte](#EncodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [DecodeByte](#DecodeByte)
|
||||||
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
- [ToInterface](#ToInterface)
|
||||||
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|
||||||
|
|
||||||
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
### <span id="ColorHexToRGB">ColorHexToRGB</span>
|
||||||
|
|
||||||
<p>颜色值十六进制转rgb。</p>
|
<p>颜色值十六进制转rgb。</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
@@ -51,6 +57,7 @@ import (
|
|||||||
```go
|
```go
|
||||||
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
func ColorHexToRGB(colorHex string) (red, green, blue int)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -81,6 +88,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ColorRGBToHex(red, green, blue int) string
|
func ColorRGBToHex(red, green, blue int) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -113,6 +121,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToBool(s string) (bool, error)
|
func ToBool(s string) (bool, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -153,6 +162,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToBytes(data any) ([]byte, error)
|
func ToBytes(data any) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -185,6 +195,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToChar(s string) []string
|
func ToChar(s string) []string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -220,6 +231,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToChannel[T any](array []T) <-chan T
|
func ToChannel[T any](array []T) <-chan T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -256,6 +268,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToFloat(value any) (float64, error)
|
func ToFloat(value any) (float64, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -300,6 +313,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToInt(value any) (int64, error)
|
func ToInt(value any) (int64, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -341,6 +355,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToJson(value any) (string, error)
|
func ToJson(value any) (string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -375,6 +390,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -415,6 +431,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToPointer[T any](value T) *T
|
func ToPointer[T any](value T) *T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -427,8 +444,8 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result := convertor.ToPointer(123)
|
result := convertor.ToPointer(123)
|
||||||
fmt.Println(*result)
|
fmt.Println(*result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 123
|
// 123
|
||||||
}
|
}
|
||||||
@@ -443,6 +460,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func ToString(value any) string
|
func ToString(value any) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -490,6 +508,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func StructToMap(value any) (map[string]any, error)
|
func StructToMap(value any) (map[string]any, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -527,6 +546,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -556,6 +576,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func EncodeByte(data any) ([]byte, error)
|
func EncodeByte(data any) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -584,6 +605,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
func DecodeByte(data []byte, target any) error
|
func DecodeByte(data []byte, target any) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -597,15 +619,260 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
var result string
|
var result string
|
||||||
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
byteData := []byte{6, 12, 0, 3, 97, 98, 99}
|
||||||
|
|
||||||
err := convertor.DecodeByte(byteData, &result)
|
err := convertor.DecodeByte(byteData, &result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// abc
|
// abc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="DeepClone">DeepClone</span>
|
||||||
|
|
||||||
|
<p>创建一个传入值的深拷贝, 无法克隆结构体的非导出字段。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DeepClone[T any](src T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Struct struct {
|
||||||
|
Str string
|
||||||
|
Int int
|
||||||
|
Float float64
|
||||||
|
Bool bool
|
||||||
|
Nil interface{}
|
||||||
|
unexported string
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []interface{}{
|
||||||
|
true,
|
||||||
|
1,
|
||||||
|
0.1,
|
||||||
|
map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
},
|
||||||
|
&Struct{
|
||||||
|
Str: "test",
|
||||||
|
Int: 1,
|
||||||
|
Float: 0.1,
|
||||||
|
Bool: true,
|
||||||
|
Nil: nil,
|
||||||
|
// unexported: "can't be cloned",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range cases {
|
||||||
|
cloned := convertor.DeepClone(item)
|
||||||
|
|
||||||
|
isPointerEqual := &cloned == &item
|
||||||
|
fmt.Println(cloned, isPointerEqual)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true false
|
||||||
|
// 1 false
|
||||||
|
// 0.1 false
|
||||||
|
// map[a:1 b:2] false
|
||||||
|
// &{test 1 0.1 true <nil> } false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="CopyProperties">CopyProperties</span>
|
||||||
|
|
||||||
|
<p>拷贝不同结构体之间的同名字段。使用json.Marshal序列化,需要设置dst和src struct字段的json tag。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties[T, U any](dst T, src U) (err error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(indicatorVO.Id)
|
||||||
|
fmt.Println(indicatorVO.Ip)
|
||||||
|
fmt.Println(len(indicatorVO.Disk))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 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>示例:</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>示例:</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>示例:</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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -6,7 +6,7 @@ Package cryptor contains some functions for data encryption and decryption. Supp
|
|||||||
## Source:
|
## Source:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
|
- [https://github.com/duke-git/lancet/blob/main/cryptor/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/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -44,14 +44,24 @@ import (
|
|||||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||||
- [HmacMd5](#HmacMd5)
|
- [HmacMd5](#HmacMd5)
|
||||||
|
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||||
- [HmacSha1](#HmacSha1)
|
- [HmacSha1](#HmacSha1)
|
||||||
|
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||||
- [HmacSha256](#HmacSha256)
|
- [HmacSha256](#HmacSha256)
|
||||||
|
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||||
- [HmacSha512](#HmacSha512)
|
- [HmacSha512](#HmacSha512)
|
||||||
|
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||||
- [Md5String](#Md5String)
|
- [Md5String](#Md5String)
|
||||||
|
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||||
|
- [Md5Byte](#Md5Byte)
|
||||||
|
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||||
- [Md5File](#Md5File)
|
- [Md5File](#Md5File)
|
||||||
- [Sha1](#Sha1)
|
- [Sha1](#Sha1)
|
||||||
|
- [Sha1WithBase64](#Sha1WithBase64)
|
||||||
- [Sha256](#Sha256)
|
- [Sha256](#Sha256)
|
||||||
|
- [Sha256WithBase64](#Sha256WithBase64)
|
||||||
- [Sha512](#Sha512)
|
- [Sha512](#Sha512)
|
||||||
|
- [Sha512WithBase64](#Sha512WithBase64)
|
||||||
- [GenerateRsaKey](#GenerateRsaKey)
|
- [GenerateRsaKey](#GenerateRsaKey)
|
||||||
- [RsaEncrypt](#RsaEncrypt)
|
- [RsaEncrypt](#RsaEncrypt)
|
||||||
- [RsaDecrypt](#RsaDecrypt)
|
- [RsaDecrypt](#RsaDecrypt)
|
||||||
@@ -729,7 +739,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacMd5(data, key string) string
|
func HmacMd5(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -743,7 +753,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
str := "hello"
|
str := "hello"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := cryptor.HmacMd5(str, key)
|
hms := cryptor.HmacMd5(str, key)
|
||||||
@@ -753,6 +763,39 @@ func main() {
|
|||||||
// e834306eab892d872525d4918a7a639a
|
// e834306eab892d872525d4918a7a639a
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
|
||||||
|
|
||||||
|
<p>Get the md5 hmac hash of base64 string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacMd5WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="HmacSha1">HmacSha1</span>
|
||||||
|
|
||||||
<p>Get the sha1 hmac hash of string.</p>
|
<p>Get the sha1 hmac hash of string.</p>
|
||||||
@@ -760,7 +803,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha1(data, key string) string
|
func HmacSha1(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -784,6 +827,39 @@ func main() {
|
|||||||
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the hmac hash of string use sha1 with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha1WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="HmacSha256">HmacSha256</span>
|
||||||
|
|
||||||
<p>Get the sha256 hmac hash of string</p>
|
<p>Get the sha256 hmac hash of string</p>
|
||||||
@@ -791,7 +867,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha256(data, key string) string
|
func HmacSha256(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -816,6 +892,38 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the hmac hash of string use sha256 with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha256WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="HmacSha512">HmacSha512</span>
|
||||||
|
|
||||||
<p>Get the sha512 hmac hash of string.</p>
|
<p>Get the sha512 hmac hash of string.</p>
|
||||||
@@ -823,7 +931,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha512(data, key string) string
|
func HmacSha512(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -848,6 +956,38 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the hmac hash of string use sha512 with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha512WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="Md5String">Md5String</span>
|
||||||
|
|
||||||
@@ -880,6 +1020,93 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the md5 value of string with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Md5StringWithBase64(s string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>Return the md5 string of byte slice.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Md5Byte(data []byte) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>Return the md5 string of byte slice with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Md5ByteWithBase64(data []byte) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="Md5File">Md5File</span>
|
||||||
|
|
||||||
<p>Get the md5 value of file.</p>
|
<p>Get the md5 value of file.</p>
|
||||||
@@ -913,7 +1140,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha1(data string) string
|
func Sha1(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -937,6 +1164,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha1WithBase64">Sha1WithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the sha1 value (SHA-1 hash algorithm) of base64 string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha1WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="Sha256">Sha256</span>
|
||||||
|
|
||||||
<p>Get the sha256 value of string.</p>
|
<p>Get the sha256 value of string.</p>
|
||||||
@@ -944,7 +1200,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha256(data string) string
|
func Sha256(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -968,6 +1224,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha256WithBase64">Sha256WithBase64</span>
|
||||||
|
|
||||||
|
<p>Return the sha256 value (SHA256 hash algorithm) of base64 string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha256WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="Sha512">Sha512</span>
|
||||||
|
|
||||||
<p>Get the sha512 value of string.</p>
|
<p>Get the sha512 value of string.</p>
|
||||||
@@ -975,7 +1260,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha512(data string) string
|
func Sha512(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -999,6 +1284,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha512WithBase64">Sha512WithBase64</span>
|
||||||
|
|
||||||
|
<p>Get the sha512 value of string with base64.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha512WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</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>
|
### <span id="GenerateRsaKey">GenerateRsaKey</span>
|
||||||
|
|
||||||
<p>Create the rsa public and private key file in current directory.</p>
|
<p>Create the rsa public and private key file in current directory.</p>
|
||||||
@@ -6,7 +6,7 @@ cryptor加密包支持数据加密和解密,获取md5,hash值。支持base64
|
|||||||
## 源码:
|
## 源码:
|
||||||
|
|
||||||
- [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/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/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -41,14 +41,24 @@ import (
|
|||||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||||
- [HmacMd5](#HmacMd5)
|
- [HmacMd5](#HmacMd5)
|
||||||
|
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||||
- [HmacSha1](#HmacSha1)
|
- [HmacSha1](#HmacSha1)
|
||||||
|
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||||
- [HmacSha256](#HmacSha256)
|
- [HmacSha256](#HmacSha256)
|
||||||
|
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||||
- [HmacSha512](#HmacSha512)
|
- [HmacSha512](#HmacSha512)
|
||||||
|
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||||
- [Md5String](#Md5String)
|
- [Md5String](#Md5String)
|
||||||
|
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||||
|
- [Md5Byte](#Md5Byte)
|
||||||
|
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||||
- [Md5File](#Md5File)
|
- [Md5File](#Md5File)
|
||||||
- [Sha1](#Sha1)
|
- [Sha1](#Sha1)
|
||||||
|
- [Sha1WithBase64](#Sha1WithBase64)
|
||||||
- [Sha256](#Sha256)
|
- [Sha256](#Sha256)
|
||||||
|
- [Sha256WithBase64](#Sha256WithBase64)
|
||||||
- [Sha512](#Sha512)
|
- [Sha512](#Sha512)
|
||||||
|
- [Sha512WithBase64](#Sha512WithBase64)
|
||||||
- [GenerateRsaKey](#GenerateRsaKey)
|
- [GenerateRsaKey](#GenerateRsaKey)
|
||||||
- [RsaEncrypt](#RsaEncrypt)
|
- [RsaEncrypt](#RsaEncrypt)
|
||||||
- [RsaDecrypt](#RsaDecrypt)
|
- [RsaDecrypt](#RsaDecrypt)
|
||||||
@@ -728,7 +738,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacMd5(data, key string) string
|
func HmacMd5(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -742,7 +752,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
str := "hello"
|
str := "hello"
|
||||||
key := "12345"
|
key := "12345"
|
||||||
|
|
||||||
hms := cryptor.HmacMd5(str, key)
|
hms := cryptor.HmacMd5(str, key)
|
||||||
@@ -752,14 +762,46 @@ func main() {
|
|||||||
// e834306eab892d872525d4918a7a639a
|
// e834306eab892d872525d4918a7a639a
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### <span id="HmacSha1">HmacSha1</span>
|
|
||||||
|
|
||||||
<p>获取字符串sha1 hmac值。</p>
|
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串md5 hmac base64字符串值。</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha1(data, key string) string
|
func HmacMd5WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</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>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -783,6 +825,40 @@ func main() {
|
|||||||
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串的sha1 base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha1WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="HmacSha256">HmacSha256</span>
|
||||||
|
|
||||||
<p>获取字符串sha256 hmac值。</p>
|
<p>获取字符串sha256 hmac值。</p>
|
||||||
@@ -790,7 +866,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha256(data, key string) string
|
func HmacSha256(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -815,6 +891,38 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串sha256 hmac base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha256WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="HmacSha512">HmacSha512</span>
|
||||||
|
|
||||||
<p>获取字符串sha512 hmac值。</p>
|
<p>获取字符串sha512 hmac值。</p>
|
||||||
@@ -822,7 +930,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func HmacSha512(data, key string) string
|
func HmacSha512(str, key string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -847,6 +955,38 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串sha512 hmac base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HmacSha512WithBase64(str, key string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="Md5String">Md5String</span>
|
||||||
|
|
||||||
@@ -855,7 +995,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Md5String(s string) string
|
func Md5String(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -879,6 +1019,93 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串md5 base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Md5StringWithBase64(s string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</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>示例:</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>实例:</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>
|
### <span id="Md5File">Md5File</span>
|
||||||
|
|
||||||
<p>获取文件md5值。</p>
|
<p>获取文件md5值。</p>
|
||||||
@@ -912,7 +1139,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha1(data string) string
|
func Sha1(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -936,6 +1163,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha1WithBase64">Sha1WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串sha1 base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha1WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="Sha256">Sha256</span>
|
||||||
|
|
||||||
<p>获取字符串sha256值。</p>
|
<p>获取字符串sha256值。</p>
|
||||||
@@ -943,7 +1199,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha256(data string) string
|
func Sha256(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -967,6 +1223,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha256WithBase64">Sha256WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串sha256 base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha256WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="Sha512">Sha512</span>
|
||||||
|
|
||||||
<p>获取字符串sha512值。</p>
|
<p>获取字符串sha512值。</p>
|
||||||
@@ -974,7 +1259,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Sha512(data string) string
|
func Sha512(str string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -998,6 +1283,35 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Sha512WithBase64">Sha512WithBase64</span>
|
||||||
|
|
||||||
|
<p>获取字符串sha512 base64值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha512WithBase64(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</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>
|
### <span id="GenerateRsaKey">GenerateRsaKey</span>
|
||||||
|
|
||||||
<p>在当前目录下创建rsa私钥文件和公钥文件。</p>
|
<p>在当前目录下创建rsa私钥文件和公钥文件。</p>
|
||||||
470
docs/olddocs/datastructure/copyonwritelist.md
Normal file
470
docs/olddocs/datastructure/copyonwritelist.md
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
# CopyOnWriteList
|
||||||
|
|
||||||
|
CopyOnWriteList is a thread-safe list implementation that uses go slicing as its base. When writing, a new slice is copied and assigned to the original slice when writing is complete. When reading, the original slice is read directly.
|
||||||
|
|
||||||
|
## 源码
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### NewCopyOnWriteList
|
||||||
|
|
||||||
|
Returns a CopyOnWriteList with empty slices.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type CopyOnWriteList[T any] struct {
|
||||||
|
data []T
|
||||||
|
lock sync.
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCopyOnWriteList() *CopyOnWriteList
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns the length of the CopyOnWriteList.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (l *CopyOnWriteList[T]) Size() int
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns the element at the specified position in the list
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) Get(index int) *T
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Replaces the element at the specified position in this list with the specified element.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns the index of the value in the list, or -1 if not found.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) IndexOf(e T) int
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain that element.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns true if this list does not contain any elements.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) IsEmpty() bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datastructure/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
l := list.NewCopyOnWriteList([]int{})
|
||||||
|
fmt.Println(l.IsEmpty())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Contain
|
||||||
|
|
||||||
|
Determines if a CopyOnWriteList contains an element.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) Contain(e T) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns a pointer to the value at the index in the list
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) ValueOf(index int) []T
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Appends the specified element to the end of the list.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) Add(e T) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Appends all the elements of the specified collection to the end of this list
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) AddAll(e []T) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Inserts the specified element into the list at the specified position.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Removes the element at the specified position in this list.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) DeleteAt(index int) (oldValue *T, ok bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Removes the first occurrence of the specified element from this list (if it exists).
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) DeleteIf(func(T) bool) (oldValue *T, ok bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Deletes the first occurrence of the specified element from this list (if it exists).
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) DeleteBy(e T) (*T bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Deletes all elements from this list with indexes between fromIndex (included) and toIndex (not included).
|
||||||
|
(leftCloseRightOpen)
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Returns true if the specified object is equal to this list
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (c *CopyOnWriteList[T]) Equal(e []T) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```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}))
|
||||||
|
}
|
||||||
|
```
|
||||||
471
docs/olddocs/datastructure/copyonwritelist_zh-CN.md
Normal file
471
docs/olddocs/datastructure/copyonwritelist_zh-CN.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}))
|
||||||
|
}
|
||||||
|
```
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user