1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-07 22:22:29 +08:00

Compare commits

...

200 Commits

Author SHA1 Message Date
dudaodong
c949059fb1 release: v2.0.7 2022-05-18 15:29:55 +08:00
dudaodong
9c6d489db7 docs: add some new funcs documentation 2022-05-18 15:28:18 +08:00
dudaodong
45436798af fix: fix TestMinBy test function 2022-05-18 15:23:57 +08:00
dudaodong
bd0eb0682c docs: add doc for func MaxBy and MinBy 2022-05-18 15:22:44 +08:00
dudaodong
bdbc06b095 docs: add doc for funcs IndexOf and LastIndexOf 2022-05-18 15:00:09 +08:00
dudaodong
2f504ce851 test: add unit test for func LastIndexOf 2022-05-16 11:11:40 +08:00
dudaodong
02a24b461c test: add unit test for func LastIndexOf 2022-05-16 11:05:52 +08:00
dudaodong
3f7a81c005 test: add unit test for func IndexOf 2022-05-16 11:04:40 +08:00
dudaodong
cc6e10ee5a add func IndexOf and LastIndexOf 2022-05-16 10:40:33 +08:00
dudaodong
eff2f22440 test: add unit test for MinBy function 2022-05-15 18:28:40 +08:00
dudaodong
47b6747bb0 feat: add MinBy function 2022-05-15 18:25:46 +08:00
dudaodong
298219aee7 test: add unit test for MaxBy function 2022-05-15 18:21:01 +08:00
dudaodong
d5607b0a5a feat: add MaxBy function 2022-05-15 18:15:05 +08:00
IHIDCHAOS
f47873fbc7 Update system_zh-CN.md (#32)
fix typo
2022-05-15 17:28:37 +08:00
dudaodong
f24ad26692 release: v2.0.6 2022-05-12 10:13:13 +08:00
dudaodong
88de9bfac2 docs: add doc for SplitEx function 2022-05-12 10:12:19 +08:00
dudaodong
e4777a0986 docs: add doc for SplitEx function 2022-05-12 10:11:12 +08:00
franktz
84a69d1fa5 feat: strutil.SplitEx. Split a given string whether the result contains empty string (#31)
Co-authored-by: Frank.Town <tangzhi21@sfmail.sf-express.com>
2022-05-11 15:19:53 +08:00
dudaodong
5eb056277d update readme file 2022-04-27 11:51:02 +08:00
dudaodong
4e6d586251 update readme file 2022-04-27 11:42:06 +08:00
dudaodong
61c7012e17 test: add unit test TestBSTree_IsSubTree 2022-04-27 11:36:51 +08:00
dudaodong
0d48778886 feat: add HasSubTree func for BSTree 2022-04-27 10:43:01 +08:00
dudaodong
e98c46c903 feat: add IsSubTree func for BSTree 2022-04-27 10:36:11 +08:00
dudaodong
155f287ab0 refactor: add param comparator in NewBSTree func 2022-04-26 11:04:04 +08:00
dudaodong
652916b7d7 test: add unit test for PriorityQueue Dequeue function 2022-04-26 10:56:24 +08:00
dudaodong
955de2bdbf feat: add Dequeue function 2022-04-26 10:50:27 +08:00
dudaodong
a4c1d40faa test: add unit test for PriorityQueue Enqueue function 2022-04-26 10:45:19 +08:00
dudaodong
f155e0caa6 test: add unit test for PriorityQueue Enqueue function 2022-04-26 10:40:48 +08:00
dudaodong
fb0332449c feat: add IsEmpty and IsFull for PriorityQueue 2022-04-26 10:24:10 +08:00
dudaodong
68f0fd1d4c feat: add PriorityQueue 2022-04-26 10:19:31 +08:00
dudaodong
70995c5098 feat: add PriorityQueue 2022-04-26 10:18:43 +08:00
dudaodong
55e62ed8ca feat: add PriorityQueue 2022-04-26 10:18:06 +08:00
dudaodong
e614274f07 release v2.0.5 2022-04-24 10:34:25 +08:00
dudaodong
c524eb04a1 docs: add doc for concurrency in readme file 2022-04-24 10:32:55 +08:00
dudaodong
985b3cddd8 fix: fix TestTee func 2022-04-24 10:26:07 +08:00
dudaodong
abadeec007 docs: add doc for channel.go 2022-04-24 10:17:34 +08:00
dudaodong
3ab05154aa docs: add doc for channel.go 2022-04-22 17:12:41 +08:00
dudaodong
9f1c89bf0e refactor: refact FanIn func in channel.go 2022-04-21 14:31:43 +08:00
dudaodong
9444582e44 fix: fix OrDone func 2022-04-21 14:19:38 +08:00
dudaodong
c27ccad2b9 refactor: refact Or func in channel.go 2022-04-21 14:13:19 +08:00
dudaodong
d1c6c57700 feat: add func Bridge 2022-04-21 11:26:02 +08:00
dudaodong
922999037f feat: add func Tee 2022-04-21 11:18:45 +08:00
dudaodong
046e90486d feat: add func in channel.go 2022-04-19 16:21:23 +08:00
dudaodong
fc6dee9e77 feat: add func in channel.go 2022-04-19 16:03:12 +08:00
dudaodong
980ff2c363 feat: add FanIn for channel 2022-04-19 15:34:26 +08:00
dudaodong
763aa8e10d refactor: replace param done channel with ctx context 2022-04-19 14:42:55 +08:00
dudaodong
83c0d1d6e6 fix: fix misspellings 2022-04-15 17:02:34 +08:00
dudaodong
dfc6b868fb feat: add RepeateFn function 2022-04-15 16:32:55 +08:00
dudaodong
f66c0938e5 feat: add Take function to generate a chan of values taken from another chan 2022-04-15 16:22:19 +08:00
dudaodong
a4900fecb4 feat: add Repeate function to generate a chan of repeate values 2022-04-15 16:08:14 +08:00
dudaodong
dc25bdab2f feat: add Generate chan function in concurrency package 2022-04-15 15:56:06 +08:00
dudaodong
bb23c9eef8 release v2.0.4 2022-04-14 11:51:34 +08:00
dudaodong
b4cd0750e4 fix: fix http post to support multipart/form-data header 2022-04-14 11:48:39 +08:00
dudaodong
c960841491 docs: update sort function doc 2022-04-12 14:45:22 +08:00
dudaodong
5d6f9443fd refactor: rewrite sort function 2022-04-12 14:30:43 +08:00
dudaodong
5483380066 refactor: rewrite arrayqueue 2022-04-08 17:39:54 +08:00
dudaodong
20b9e5353e fix: fix goreport issue 2022-04-06 11:33:48 +08:00
dudaodong
1ec3a5af87 release v2.0.3 2022-04-06 10:54:54 +08:00
dudaodong
f31dde97b1 docs: add maputil docs in read me file 2022-04-05 14:24:33 +08:00
dudaodong
1718fd1cf1 docs: add doc for maputil package 2022-04-05 14:16:58 +08:00
dudaodong
513c0f829c docs: add doc for SymmetricDifference fun in slice doc 2022-04-05 13:47:13 +08:00
dudaodong
c51a806aff feat: add SymmetricDifference func for set 2022-04-01 18:06:34 +08:00
dudaodong
3c16d50c4b refactor: rename ReverseIntersect to SymmetricDifference 2022-04-01 18:05:02 +08:00
dudaodong
21dd6ab8aa feat: add SymmetricDifference func for set 2022-04-01 18:02:12 +08:00
dudaodong
f5bf5183cc feat: add Minus func for set 2022-04-01 16:48:37 +08:00
dudaodong
f28b5b2f92 feat: add Minus func for set 2022-04-01 16:44:25 +08:00
dudaodong
79867e8a63 feat: add ReverseIntersect function 2022-03-31 19:42:27 +08:00
dudaodong
19939c2b03 feat: add Minus func 2022-03-31 18:00:11 +08:00
dudaodong
bf7ffbfa8d feat: add Intersect func 2022-03-31 16:56:12 +08:00
dudaodong
cbb46f9cb4 feat: add Filter func 2022-03-30 19:52:43 +08:00
dudaodong
3ad142d5d7 feat: add ForEach func 2022-03-30 19:41:55 +08:00
dudaodong
1a436aeb41 feat: add Merge func 2022-03-30 18:06:22 +08:00
dudaodong
1af8fe8daf test: add unit test for Keys and Values func 2022-03-30 17:45:17 +08:00
dudaodong
ae54c8db6f feat: add Values func 2022-03-30 17:34:01 +08:00
dudaodong
be942ec33e feat: add package maputil and Keys func 2022-03-30 17:27:50 +08:00
dudaodong
fafb59dad6 update readme file 2022-03-29 11:02:27 +08:00
dudaodong
e36c01cac9 release v2.0.2 2022-03-29 11:01:31 +08:00
dudaodong
aa0afa8d94 release v1.2.7 2022-03-29 11:01:06 +08:00
dudaodong
18e0031e0e fix: fix TestInsertionSort 2022-03-26 21:06:05 +08:00
dudaodong
a5018c110c fix: fix bug in ToBytes func 2022-03-26 20:54:37 +08:00
dudaodong
142deb83b2 fix: fix InsertionSort bug 2022-03-26 18:25:42 +08:00
dudaodong
ccc0188352 feat: add DeleteValue for SinglyLink 2022-03-24 17:56:45 +08:00
dudaodong
98dba83107 release v2.0.1 2022-03-22 14:47:23 +08:00
dudaodong
9c6aff9030 fix: fix lint warning 'ineffassign' 2022-03-22 14:45:16 +08:00
dudaodong
7fd9a94922 fix: fix lint warning 'ineffassign' 2022-03-22 14:36:35 +08:00
dudaodong
dd3b1f3aed docs: add doc for some new funcs 2022-03-22 14:10:58 +08:00
dudaodong
f9dce592e8 docs: add doc for Min, Max, and Average 2022-03-22 10:43:00 +08:00
dudaodong
c4b0967623 feat: add Max, Min, and Average function 2022-03-22 10:26:43 +08:00
dudaodong
41613061d5 docs: add GroupWith doc 2022-03-21 20:10:39 +08:00
dudaodong
50ef63e27d feat: add GroupWith func 2022-03-21 15:29:10 +08:00
dudaodong
3ae4a35d04 fix: format timezone issue 2022-03-19 19:24:28 +08:00
dudaodong
89ea0ee15a fix: format timezone issue 2022-03-19 19:08:34 +08:00
dudaodong
85399e23ed fix: format timezone issue 2022-03-19 18:42:22 +08:00
dudaodong
19a6f218e6 fix: format time in local timezone 2022-03-19 18:23:06 +08:00
dudaodong
ccaf290b63 docs: add doc for datetime/conversion.go 2022-03-18 18:18:28 +08:00
dudaodong
54745d512c test: add unit test and func comment for time conversion 2022-03-18 17:48:57 +08:00
dudaodong
39234d4722 Merge branch 'main' of github.com:duke-git/lancet into main 2022-03-17 19:46:31 +08:00
dudaodong
4b4310265b fix: update TestListFileNames 2022-03-17 19:46:19 +08:00
wangxudong123
d8a982bf07 增加时间转换 (#25)
Co-authored-by: wangxd01 <wangxd01@mingyuanyun.com>
2022-03-17 19:44:24 +08:00
dudaodong
0334a6f02b docs: fix some issues 2022-03-17 11:55:52 +08:00
dudaodong
ae0c613b8e add package comment 2022-03-17 11:55:08 +08:00
dudaodong
40b2560752 docs: add v2 in import path 2022-03-17 11:33:45 +08:00
dudaodong
50c6e51393 upgrade go module v2 2022-03-17 10:57:35 +08:00
dudaodong
1434e00712 docs: add func HeapSort 2022-03-17 10:11:34 +08:00
dudaodong
76c941cff0 update readme file 2022-03-16 19:39:21 +08:00
dudaodong
bb03f31a8b release v2.0.0 2022-03-16 19:16:43 +08:00
dudaodong
c939b26cb8 refactor: interface{} -> any 2022-03-16 18:41:40 +08:00
dudaodong
af480efa8c docs: add xerror package doc 2022-03-16 18:21:30 +08:00
dudaodong
bc913d70b1 docs: update doc style 2022-03-16 18:06:06 +08:00
dudaodong
2bc87d8a6b docs: add docs/algorithm.md 2022-03-16 18:00:38 +08:00
dudaodong
2185c48eab docs: add docs/algorithm.md 2022-03-16 18:00:29 +08:00
dudaodong
59b5046a15 docs: update slice.md 2022-03-16 16:59:15 +08:00
dudaodong
569902b528 fix: fix lru cache bug 2022-03-14 11:19:30 +08:00
dudaodong
78519088ab feat: add lru cache 2022-03-11 17:05:55 +08:00
dudaodong
0c06cdb29f Merge branch 'main' into v2 2022-03-04 17:42:18 +08:00
dudaodong
e8b8ff8927 merge main branch 2022-03-01 15:00:02 +08:00
dudaodong
06bd407a0c feat: add LevelOrderTraverse func 2022-03-01 11:23:33 +08:00
dudaodong
aa28479d11 feat: update deleteTreeNode func 2022-03-01 11:13:44 +08:00
dudaodong
bf7db0ded2 feat: add DeletetNode 2022-03-01 11:04:38 +08:00
dudaodong
dd1cbf2ee3 refactor: rename Insert to InsertNode 2022-03-01 10:11:37 +08:00
dudaodong
9d5db895c9 Merge branch 'main' into v2 2022-03-01 10:02:23 +08:00
dudaodong
6b09da6e6e feat: add funcs to traverse bstree 2022-02-23 19:34:35 +08:00
dudaodong
b2b6710a1b feat: add BSTree which is binary search tree 2022-02-21 16:48:27 +08:00
dudaodong
e7ee2ed7cf Merge branch 'main' into v2 2022-02-20 11:35:43 +08:00
dudaodong
1dfd1ec1d3 Merge branch 'main' into v2 2022-02-19 21:55:09 +08:00
dudaodong
2e8834a2c1 docs: update slice.doc 2022-02-18 11:05:14 +08:00
dudaodong
df098392c2 merge main branch 2022-02-18 10:28:47 +08:00
dudaodong
5e318a78d2 refactor: remove unused code 2022-02-15 11:19:07 +08:00
dudaodong
d872d64fe0 feat: add CircularQueue 2022-02-15 10:34:14 +08:00
dudaodong
c2257493a8 fix: fix panic info text 2022-02-14 15:36:44 +08:00
dudaodong
48c1f8ffad fix: fix some spell mistake 2022-02-13 19:00:44 +08:00
dudaodong
8a4c8218d2 update func DeQueue comment 2022-02-11 10:49:33 +08:00
dudaodong
92e1321d43 refactor: rename func Length -> Size 2022-02-11 10:48:38 +08:00
dudaodong
43fb907a81 feat: add LinkedQueue 2022-02-11 10:46:48 +08:00
dudaodong
f551c56921 refactor: reconstructure souce file into the corresponding folder 2022-02-10 17:57:53 +08:00
dudaodong
85e1f711f5 feat: and Clear and IsEmpty func 2022-02-10 17:41:51 +08:00
dudaodong
ade567a620 feat: add ArrayQueue data structure 2022-02-10 17:30:37 +08:00
dudaodong
a26e519a3f refactor: rename func Length -> Size 2022-02-10 15:42:05 +08:00
dudaodong
797e47363f rename: rename StackArray -> ArrayStack, StackLink -> LinkedStack 2022-02-10 11:50:03 +08:00
dudaodong
20e1836eb7 rename: rename StackArray -> ArrayStack, StackLink -> LinkedStack 2022-02-10 11:49:46 +08:00
dudaodong
5ae746a1f0 rename: rename InsertByIndex -> InsertAt, UpdateByIndex -> UpdateAt, DeleteByIndex -> DeleteAt for release 2.0 2022-02-10 11:25:34 +08:00
dudaodong
17d271190b feat: add DoublyLink data structure 2022-02-10 10:57:17 +08:00
dudaodong
310f8bd1e1 feat: add Set data structure 2022-02-09 15:15:49 +08:00
dudaodong
bf7a4e729f feat: add func Contain, Union, Intersection 2022-02-09 11:40:08 +08:00
dudaodong
8d0ff28304 update comment for StackLink 2022-02-04 22:45:01 +08:00
dudaodong
cee9bb538f feat: add stacklink.go implements stack with link 2022-02-04 22:42:51 +08:00
dudaodong
eb59d02a08 feat: add stackarray.go implements stack with array 2022-02-04 19:35:06 +08:00
dudaodong
10ed71a3a2 refactor: rename linknode.go to node.go 2022-02-04 09:22:16 +08:00
dudaodong
0e86244559 refactor: rename linknode.go to node.go 2022-02-04 09:21:35 +08:00
dudaodong
5ab150cad3 feat: add DeleteAtHead, DeleteAtTail, DeleteAt, Reverse, Size, GetMiddleNode funcs in singlelink 2022-02-03 16:37:34 +08:00
dudaodong
3546afe86c feat: add some functons of singlelink 2022-02-02 22:41:49 +08:00
dudaodong
70077a6010 merge main branch 2022-01-26 17:47:57 +08:00
dudaodong
efdf36a817 Merge branch 'main' into v2 2022-01-26 17:44:46 +08:00
dudaodong
e233788f69 comment: add comment for List struct 2022-01-26 15:25:52 +08:00
dudaodong
957e6356f6 feat: add singlelink 2022-01-26 15:25:02 +08:00
dudaodong
887eaa528a update: algorithm package comment 2022-01-26 14:57:37 +08:00
dudaodong
33126570bd feat: add datastructure package and list implementation 2022-01-26 14:56:40 +08:00
dudaodong
5937183af0 feat: replace constraints comparable into any in some funcs 2022-01-24 15:47:47 +08:00
dudaodong
4eaa0a39d5 feat: add FindLast func 2022-01-24 15:22:43 +08:00
dudaodong
18ec73839b feat: add DifferenceWith 2022-01-24 14:53:45 +08:00
dudaodong
89aef977a2 refactor: clean code for slice/slice.go 2022-01-24 11:46:09 +08:00
dudaodong
2612569500 merge: merge main branch and refector slice func with generics 2022-01-24 11:10:12 +08:00
dudaodong
acc8b59387 comment: add comment for Unwrap 2022-01-24 10:24:10 +08:00
donutloop
2878d389c8 error: Add unwrap (#24)
Add a unwrap func helper

* Unwrap if err is nil then it returns a valid value otherwise it panics
2022-01-22 21:25:31 +08:00
dudaodong
3f8effb7a3 refactor: make BinarySearch func code clear 2022-01-21 11:57:36 +08:00
dudaodong
bd30855ae6 feat: add LinearSearch 2022-01-21 11:36:31 +08:00
dudaodong
0efe2f57c3 merge main 2022-01-19 20:47:47 +08:00
dudaodong
8868fcabed Merge branch 'main' into v2 2022-01-19 17:35:48 +08:00
dudaodong
dfbb9e30e0 feat: algorithm package, BinarySearch and BinaryIterativeSearch functions 2022-01-17 15:36:48 +08:00
dudaodong
b22be7cade refactor: change var name low -> lowIndex, high -> highIndex 2022-01-17 15:11:33 +08:00
dudaodong
87da6c6816 Merge branch 'main' into v2 2022-01-17 15:01:38 +08:00
dudaodong
912f7052a3 gofmt 2022-01-17 10:29:42 +08:00
dudaodong
e6f9b0954c feat: add CountSort 2022-01-16 17:20:20 +08:00
dudaodong
98e861cf3b feat: add QuickSort, HeapSort, and MergeSort functions 2022-01-16 16:52:17 +08:00
dudaodong
43e0ca7edf feat: add ShellSort 2022-01-14 18:17:46 +08:00
dudaodong
d491bea263 feat: add BubbleSort and InsertionSort 2022-01-14 17:57:14 +08:00
dudaodong
6f1feb96d6 experimental feature, algorithm/sorter.go try to implements sort function with go generics 2022-01-14 17:01:44 +08:00
dudaodong
d46d12f949 feat: add func ContainSubSlice 2022-01-13 11:52:21 +08:00
dudaodong
c6fc92a94c update go version to v1.18 2022-01-12 10:23:04 +08:00
dudaodong
f4fa790b72 Merge branch 'main' into v2 2022-01-12 10:05:35 +08:00
dudaodong
22798fd750 fix: fix some go report issue 2022-01-12 10:01:48 +08:00
dudaodong
907df56f86 update: make func comment consistent 2022-01-11 20:27:06 +08:00
dudaodong
3dadfa234b update: make func comment consistent 2022-01-11 19:33:15 +08:00
donutloop
f1d7154179 refactor: sort (#21)
Removed reverse func because it use to much cpu and add test cas for asc sort
2022-01-11 19:24:36 +08:00
dudaodong
dc47b9ce98 fix: fix confict in readme file 2022-01-11 18:15:09 +08:00
dudaodong
6e626851cf merge #pr20 2022-01-11 18:12:57 +08:00
donutloop
c906d8aea7 Slice: group by and without v2 (#20)
* Slice: group by and without v2

Migrate from reflection to generic

* update doc
2022-01-11 18:11:01 +08:00
dudaodong
e5e4e09308 comment without func 2022-01-11 18:10:21 +08:00
dudaodong
7ed173849a refactor: rewrite DeleteByIndex, InsertByIndex, UpdateByIndex and Without func with generics 2022-01-11 18:08:22 +08:00
donutloop
24c0d95112 Slice: reverse and shufffle v2 (#19)
* Slice: reverse and shufffle v2

Migrate from reflection to generic form

Note: after migration, old reverse must be removed

* Suffle test: remove reflection calls

* Reverse test: change name of test
2022-01-10 19:52:23 +08:00
dudaodong
e9fed34729 fmt: slice.go 2022-01-10 10:27:20 +08:00
dudaodong
9caefdb67d fmt: slice.go 2022-01-10 10:24:33 +08:00
dudaodong
681d5b6bdf update comment for Count func 2022-01-09 22:17:50 +08:00
dudaodong
b0e9758e0d Merge branch 'v2' of github.com:duke-git/lancet into v2 2022-01-09 22:15:18 +08:00
donutloop
7b9a8a55e7 Slice: CountV2 (#18)
Use generic instead of reflection
2022-01-09 22:15:03 +08:00
dudaodong
44ac82e8b8 refactor: rewrite some slice functions with go generics 2022-01-09 22:14:46 +08:00
dudaodong
c4b4cb1173 merge master: rewrite all unit test functions with assert 2022-01-09 18:33:00 +08:00
donutloop
30d798366b Slice: find v2 (#17)
* If slice len is zero then return false
* Convert find to generic form.
* If return T is nil then no items matched the predicate func
2022-01-07 20:19:27 +08:00
dudaodong
3e9a2b5c59 refactor: refact Filter, ForEach, Map func with generics 2022-01-07 17:53:55 +08:00
dudaodong
1343683b08 checkout v2 branch for generics migration 2022-01-07 17:48:00 +08:00
112 changed files with 10509 additions and 1432 deletions

View File

@@ -17,7 +17,7 @@ jobs:
fetch-depth: 2 fetch-depth: 2
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: "1.16" go-version: "1.18"
- name: Run coverage - name: Run coverage
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
- name: Upload coverage to Codecov - name: Upload coverage to Codecov

170
README.md
View File

@@ -4,13 +4,12 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.6-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.0.7-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet) [![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div> </div>
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -24,14 +23,21 @@ English | [简体中文](./README_zh-CN.md)
## Feature ## Feature
- 👏 Comprehensive, efficient and reusable. - 👏 Comprehensive, efficient and reusable.
- 💪 180+ go util functions, support string, slice, datetime, net, crypt... - 💪 300+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library. - 💅 Only depend on the go standard library.
- 🌍 Unit test for every exported function. - 🌍 Unit test for every exported function.
## Installation ## Installation
### Note:
1. <b>For users who use go1.18 and above, it is recommended to install lancet v2.x.x. Cause v2.x.x rewrite all functions with generics of go1.18.</b>
```go ```go
go get github.com/duke-git/lancet 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. now latest v1 is v1.2.9. </b>
```go
go get github.com/duke-git/lancet@v1.2.9 // below go1.18, install latest version of v1.x.x
``` ```
## Usage ## Usage
@@ -39,7 +45,7 @@ go get github.com/duke-git/lancet
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,import the strutil package like below: 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,import the strutil package like below:
```go ```go
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
## Example ## Example
@@ -51,7 +57,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -62,10 +68,49 @@ func main() {
``` ```
## API Documentation ## API Documentation
### Convertor package contains some functions for data convertion.
### 1. Algorithm package implements some basic algorithm. eg. sort, search.
```go ```go
import "github.com/duke-git/lancet/convertor" import "github.com/duke-git/lancet/v2/algorithm"
```
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)
### 2. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
```go
import "github.com/duke-git/lancet/v2/concurrency"
```
#### Function list:
- [NewChannel](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#NewChannel)
- [Bridge](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Bridge)
- [FanIn](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#FanIn)
- [Generate](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Generate)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Or)
- [OrDone](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#OrDone)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Repeat)
- [RepeatFn](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#RepeatFn)
- [Take](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Take)
- [Tee](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)
### 3. Convertor package contains some functions for data convertion.
```go
import "github.com/duke-git/lancet/v2/convertor"
``` ```
#### Function list: #### Function list:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB) - [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ColorHexToRGB)
@@ -78,10 +123,10 @@ import "github.com/duke-git/lancet/convertor"
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString) - [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap) - [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
### Cryptor package is for data encryption and decryption. ### 4. Cryptor package is for data encryption and decryption.
```go ```go
import "github.com/duke-git/lancet/cryptor" import "github.com/duke-git/lancet/v2/cryptor"
``` ```
#### Function list: #### Function list:
@@ -118,11 +163,11 @@ import "github.com/duke-git/lancet/cryptor"
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt) - [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt) - [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)
### Datetime package supports date and time format and compare. ### 5. Datetime package supports date and time format and compare.
```go ```go
import "github.com/duke-git/lancet/datetime" import "github.com/duke-git/lancet/v2/datetime"
``` ```
#### Function list: #### Function list:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay) - [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)
@@ -147,11 +192,19 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp) - [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr) - [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime) - [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
### Fileutil package implements some basic functions for file operations. ### 6. Fileutil package implements some basic functions for file operations.
```go ```go
import "github.com/duke-git/lancet/fileutil" import "github.com/duke-git/lancet/v2/fileutil"
``` ```
#### Function list #### Function list
@@ -171,18 +224,18 @@ import "github.com/duke-git/lancet/fileutil"
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip) - [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip) - [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
### Formatter contains some functions for data formatting. ### 7. Formatter contains some functions for data formatting.
```go ```go
import "github.com/duke-git/lancet/formatter" import "github.com/duke-git/lancet/v2/formatter"
``` ```
#### Function list: #### Function list:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma) - [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)
### Function package can control the flow of function execution and support part of functional programming ### 8. Function package can control the flow of function execution and support part of functional programming
```go ```go
import "github.com/duke-git/lancet/function" import "github.com/duke-git/lancet/v2/function"
``` ```
#### Function list: #### Function list:
@@ -195,26 +248,47 @@ import "github.com/duke-git/lancet/function"
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher) - [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
### Mathutil package implements some functions for math calculation. ### 9. Maputil package includes some functions to manipulate map.
```go ```go
import "github.com/duke-git/lancet/mathutil" import "github.com/duke-git/lancet/v2/maputil"
``` ```
#### Function list: #### Function list:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
### 10. Mathutil package implements some functions for math calculation.
```go
import "github.com/duke-git/lancet/v2/mathutil"
```
#### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent) - [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci) - [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial) - [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Max)
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MaxBy)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Min)
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#MinBy)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent) - [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat) - [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString) - [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound) - [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
### Netutil package contains functions to get net information and send http request. ### 11. Netutil package contains functions to get net information and send http request.
```go ```go
import "github.com/duke-git/lancet/netutil" import "github.com/duke-git/lancet/v2/netutil"
``` ```
#### Function list: #### Function list:
@@ -231,10 +305,10 @@ import "github.com/duke-git/lancet/netutil"
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch) - [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse) - [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
### Random package implements some basic functions to generate random int and string. ### 12. Random package implements some basic functions to generate random int and string.
```go ```go
import "github.com/duke-git/lancet/random" import "github.com/duke-git/lancet/v2/random"
``` ```
#### Function list: #### Function list:
@@ -243,10 +317,10 @@ import "github.com/duke-git/lancet/random"
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString) - [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4) - [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
### Retry package is for executing a function repeatedly until it was successful or canceled by the context. ### 13. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
```go ```go
import "github.com/duke-git/lancet/retry" import "github.com/duke-git/lancet/v2/retry"
``` ```
#### Function list: #### Function list:
@@ -256,10 +330,10 @@ import "github.com/duke-git/lancet/retry"
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration) - [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes) - [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
### Slice contains some functions to manipulate slice. ### 14. Slice contains some functions to manipulate slice.
```go ```go
import "github.com/duke-git/lancet/slice" import "github.com/duke-git/lancet/v2/slice"
``` ```
#### Function list: #### Function list:
@@ -271,7 +345,8 @@ import "github.com/duke-git/lancet/slice"
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count) - [Count](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Count)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference) - [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy) - [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceBy)
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteByIndex) - [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop) - [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every) - [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter) - [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
@@ -280,26 +355,29 @@ import "github.com/duke-git/lancet/slice"
- [FlattenDeep](#FlattenDeep) - [FlattenDeep](#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach) - [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy) - [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupWith)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice) - [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice) - [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection) - [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertByIndex) - [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertAt)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map) - [Map](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Map)
- [ReverseSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReverseSlice) - [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce) - [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle) - [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField) - [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some) - [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice) - [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SymmetricDifference)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique) - [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union) - [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateByIndex) - [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without) - [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
### Strutil package contains some functions to manipulate string. ### 15. Strutil package contains some functions to manipulate string.
```go ```go
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
#### Function list: #### Function list:
@@ -318,15 +396,15 @@ import "github.com/duke-git/lancet/strutil"
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart) - [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReverseStr) - [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReverseStr)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase) - [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap) - [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap) - [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
### System package contain some functions about os, runtime, shell command. ### 16. System package contain some functions about os, runtime, shell command.
```go ```go
import "github.com/duke-git/lancet/system" import "github.com/duke-git/lancet/v2/system"
``` ```
#### Function list: #### Function list:
- [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows) - [IsWindows](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsWindows)
- [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux) - [IsLinux](https://github.com/duke-git/lancet/blob/main/docs/system.md#IsLinux)
@@ -337,11 +415,12 @@ import "github.com/duke-git/lancet/system"
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv) - [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand) - [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
### Validator package contains some functions for data validation. ### 17. Validator package contains some functions for data validation.
```go ```go
import "github.com/duke-git/lancet/validator" import "github.com/duke-git/lancet/v2/validator"
``` ```
#### Function list: #### Function list:
- [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese) - [ContainChinese](https://github.com/duke-git/lancet/blob/main/docs/validator.md#ContainChinese)
@@ -370,6 +449,13 @@ import "github.com/duke-git/lancet/validator"
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword) - [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl) - [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword) - [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
### 18. xerror package implements helpers for errors.
```go
import "github.com/duke-git/lancet/v2/xerror"
```
#### Function list:
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)
## How to Contribute ## How to Contribute

View File

@@ -4,13 +4,12 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.6-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.0.7-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet) [![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div> </div>
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -24,14 +23,21 @@
## 特性 ## 特性
- 👏 全面、高效、可复用 - 👏 全面、高效、可复用
- 💪 180+常用go工具函数支持string、slice、datetime、net、crypt... - 💪 300+常用go工具函数支持string、slice、datetime、net、crypt...
- 💅 只依赖go标准库 - 💅 只依赖go标准库
- 🌍 所有导出函数单元测试覆盖率100% - 🌍 所有导出函数单元测试覆盖率100%
## 安装 ## 安装
### Note:
1. <b>对于使用go1.18及以上的用户建议安装v2.x.x。 因为v2.x.x用go1.18的泛型重写了大部分函数。</b>
```go ```go
go get github.com/duke-git/lancet go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
```
2. <b>使用go1.18以下版本的用户必须安装v1.x.x。目前最新的v1版本是v1.2.9。</b>
```go
go get github.com/duke-git/lancet@v1.2.9 // 使用go1.18以下版本, 必须安装v1.x.x版本
``` ```
## 用法 ## 用法
@@ -39,7 +45,7 @@ go get github.com/duke-git/lancet
lancet是以包的结构组织代码的使用时需要导入相应的包名。例如如果使用字符串相关函数需要导入strutil包: lancet是以包的结构组织代码的使用时需要导入相应的包名。例如如果使用字符串相关函数需要导入strutil包:
```go ```go
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
## 例子 ## 例子
@@ -51,7 +57,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -62,10 +68,48 @@ func main() {
``` ```
## API文档 ## API文档
### convertor转换器包支持一些常见的数据类型转换。
### 1. algorithm算法包实现一些基本算法。eg. sort, search.
```go ```go
import "github.com/duke-git/lancet/convertor" import "github.com/duke-git/lancet/v2/algorithm"
```
#### Function list:
- [BubbleSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)
- [CountSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#CountSort)
- [HeapSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#HeapSort)
- [InsertionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#InsertionSort)
- [MergeSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#MergeSort)
- [QuickSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#QuickSort)
- [SelectionSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#SelectionSort)
- [ShellSort](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#ShellSort)
- [BinarySearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinarySearch)
- [BinaryIterativeSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BinaryIterativeSearch)
- [LinearSearch](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LinearSearch)
- [LRUCache](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)
### 2. 并发包包含一些支持并发编程的功能。例如goroutine, channel, async等。
```go
import "github.com/duke-git/lancet/v2/concurrency"
```
#### Function list:
- [NewChannel](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#NewChannel)
- [Bridge](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Bridge)
- [FanIn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#FanIn)
- [Generate](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Generate)
- [Or](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Or)
- [OrDone](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#OrDone)
- [Repeat](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Repeat)
- [RepeatFn](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#RepeatFn)
- [Take](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Take)
- [Tee](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)
### 3. convertor转换器包支持一些常见的数据类型转换。
```go
import "github.com/duke-git/lancet/v2/convertor"
``` ```
#### 函数列表: #### 函数列表:
- [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB) - [ColorHexToRGB](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ColorHexToRGB)
@@ -78,10 +122,10 @@ import "github.com/duke-git/lancet/convertor"
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString) - [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap) - [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)
### cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。 ### 4. cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。
```go ```go
import "github.com/duke-git/lancet/cryptor" import "github.com/duke-git/lancet/v2/cryptor"
``` ```
#### 函数列表: #### 函数列表:
@@ -118,11 +162,11 @@ import "github.com/duke-git/lancet/cryptor"
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt) - [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt) - [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)
### datetime日期时间处理包格式化日期比较日期。 ### 5. datetime日期时间处理包格式化日期比较日期。
```go ```go
import "github.com/duke-git/lancet/datetime" import "github.com/duke-git/lancet/v2/datetime"
``` ```
#### 函数列表: #### 函数列表:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay) - [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)
@@ -147,11 +191,19 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp) - [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr) - [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime) - [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
### fileutil包支持文件基本操作。 ### 6. fileutil包支持文件基本操作。
```go ```go
import "github.com/duke-git/lancet/fileutil" import "github.com/duke-git/lancet/v2/fileutil"
``` ```
#### 函数列表: #### 函数列表:
@@ -171,19 +223,19 @@ import "github.com/duke-git/lancet/fileutil"
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip) - [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip) - [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
### formatter格式化器包含一些数据格式化处理方法。 ### 7. formatter格式化器包含一些数据格式化处理方法。
```go ```go
import "github.com/duke-git/lancet/formatter" import "github.com/duke-git/lancet/v2/formatter"
``` ```
#### 函数列表: #### 函数列表:
- [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma) - [Comma](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)
### function函数包控制函数执行流程包含部分函数式编程。 ### 8. function函数包控制函数执行流程包含部分函数式编程。
```go ```go
import "github.com/duke-git/lancet/function" import "github.com/duke-git/lancet/v2/function"
``` ```
#### 函数列表: #### 函数列表:
@@ -195,25 +247,46 @@ import "github.com/duke-git/lancet/function"
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay) - [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher) - [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
### mathutil包实现了一些数学计算的函数。
### 9. maputil包包括一些操作map的函数.
```go ```go
import "github.com/duke-git/lancet/mathutil" import "github.com/duke-git/lancet/v2/maputil"
```
#### 函数列表:
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Minus)
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)
### 10. mathutil包实现了一些数学计算的函数。
```go
import "github.com/duke-git/lancet/v2/mathutil"
``` ```
#### Function list: #### Function list:
- [Average](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent) - [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci) - [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial) - [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
- [Max](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Max)
- [MaxBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MaxBy)
- [Min](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Min)
- [MinBy](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#MinBy)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent) - [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat) - [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString) - [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound) - [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
### netutil网络包支持获取ip地址发送http请求。 ### 11. netutil网络包支持获取ip地址发送http请求。
```go ```go
import "github.com/duke-git/lancet/netutil" import "github.com/duke-git/lancet/v2/netutil"
``` ```
#### 函数列表: #### 函数列表:
@@ -230,10 +303,10 @@ import "github.com/duke-git/lancet/netutil"
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch) - [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse) - [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
### random随机数生成器包可以生成随机[]bytes, int, string。 ### 12. random随机数生成器包可以生成随机[]bytes, int, string。
```go ```go
import "github.com/duke-git/lancet/random" import "github.com/duke-git/lancet/v2/random"
``` ```
#### 函数列表: #### 函数列表:
@@ -241,10 +314,10 @@ import "github.com/duke-git/lancet/random"
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt) - [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString) - [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4) - [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
### retry重试执行函数直到函数运行成功或被context cancel。 ### 13. retry重试执行函数直到函数运行成功或被context cancel。
```go ```go
import "github.com/duke-git/lancet/retry" import "github.com/duke-git/lancet/v2/retry"
``` ```
#### 函数列表: #### 函数列表:
@@ -255,10 +328,10 @@ import "github.com/duke-git/lancet/retry"
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes) - [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)
### slice包包含操作切片的方法集合。 ### 14. slice包包含操作切片的方法集合。
```go ```go
import "github.com/duke-git/lancet/slice" import "github.com/duke-git/lancet/v2/slice"
``` ```
#### 函数列表: #### 函数列表:
@@ -270,7 +343,8 @@ import "github.com/duke-git/lancet/slice"
- [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count) - [Count](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Count)
- [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference) - [Difference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Difference)
- [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy) - [DifferenceBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DifferenceBy)
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteByIndex) - [DifferenceWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DifferenceWith)
- [DeleteAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop) - [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every) - [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter) - [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
@@ -279,27 +353,31 @@ import "github.com/duke-git/lancet/slice"
- [FlattenDeep](#FlattenDeep) - [FlattenDeep](#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach) - [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy) - [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
- [GroupWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupWith)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice) - [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice) - [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection) - [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertByIndex) - [InsertAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertAt)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)
- [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map) - [Map](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Map)
- [ReverseSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReverseSlice) - [Reverse](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)
- [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce) - [Reduce](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)
- [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle) - [Shuffle](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField) - [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some) - [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice) - [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SymmetricDifference)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique) - [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union) - [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateByIndex) - [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without) - [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
### strutil包含处理字符串的相关函数。 ### 15. strutil包含处理字符串的相关函数。
```go ```go
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
#### 函数列表: #### 函数列表:
@@ -318,14 +396,15 @@ import "github.com/duke-git/lancet/strutil"
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart) - [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReverseStr) - [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReverseStr)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase) - [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap) - [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap) - [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
### system包含os, runtime, shell command相关函数。 ### 16. system包含os, runtime, shell command相关函数。
```go ```go
import "github.com/duke-git/lancet/system" import "github.com/duke-git/lancet/v2/system"
``` ```
#### 函数列表: #### 函数列表:
@@ -338,10 +417,10 @@ import "github.com/duke-git/lancet/system"
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv) - [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand) - [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand)
### validator验证器包包含常用字符串格式验证函数。 ### 17. validator验证器包包含常用字符串格式验证函数。
```go ```go
import "github.com/duke-git/lancet/validator" import "github.com/duke-git/lancet/v2/validator"
``` ```
#### 函数列表: #### 函数列表:
@@ -372,6 +451,14 @@ import "github.com/duke-git/lancet/validator"
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl) - [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword) - [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
validator.md#IsWeakPassword)
### 18. xerror包实现一些错误处理函数
```go
import "github.com/duke-git/lancet/v2/xerror"
```
#### 函数列表:
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
## 如何贡献代码 ## 如何贡献代码

102
algorithm/lru_cache.go Normal file
View File

@@ -0,0 +1,102 @@
package algorithm
type lruNode[K comparable, V any] struct {
key K
value V
pre *lruNode[K, V]
next *lruNode[K, V]
}
// newLruNode return a lruNode pointer
func newLruNode[K comparable, V any](key K, value V) *lruNode[K, V] {
return &lruNode[K, V]{
key: key,
value: value,
pre: nil,
next: nil,
}
}
// LRUCache lru cache (thread unsafe)
type LRUCache[K comparable, V any] struct {
cache map[K]*lruNode[K, V]
head *lruNode[K, V]
tail *lruNode[K, V]
capacity int
length int
}
// NewLRUCache return a LRUCache pointer
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V] {
return &LRUCache[K, V]{
cache: make(map[K]*lruNode[K, V], capacity),
head: nil,
tail: nil,
capacity: capacity,
length: 0,
}
}
// Get value of key from lru cache
func (l *LRUCache[K, V]) Get(key K) (V, bool) {
var value V
node, ok := l.cache[key]
if ok {
l.moveToHead(node)
return node.value, true
}
return value, false
}
// Put value of key into lru cache
func (l *LRUCache[K, V]) Put(key K, value V) {
node, ok := l.cache[key]
if !ok {
newNode := newLruNode(key, value)
l.cache[key] = newNode
l.addNode(newNode)
if len(l.cache) > l.capacity {
oldKey := l.deleteNode(l.head)
delete(l.cache, oldKey)
}
} else {
node.value = value
l.moveToHead(node)
}
l.length = len(l.cache)
}
func (l *LRUCache[K, V]) addNode(node *lruNode[K, V]) {
if l.tail != nil {
l.tail.next = node
node.pre = l.tail
node.next = nil
}
l.tail = node
if l.head == nil {
l.head = node
}
}
func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
if node == l.tail {
l.tail = l.tail.pre
} else if node == l.head {
l.head = l.head.next
} else {
node.pre.next = node.next
node.next.pre = node.pre
}
return node.key
}
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
if l.tail == node {
return
}
l.deleteNode(node)
l.addNode(node)
}

View File

@@ -0,0 +1,36 @@
package algorithm
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestLRUCache(t *testing.T) {
asssert := internal.NewAssert(t, "TestLRUCache")
cache := NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0)
asssert.Equal(false, ok)
v, ok := cache.Get(1)
asssert.Equal(true, ok)
asssert.Equal(1, v)
v, ok = cache.Get(2)
asssert.Equal(true, ok)
asssert.Equal(2, v)
cache.Put(3, 3)
v, ok = cache.Get(1)
asssert.Equal(false, ok)
asssert.NotEqual(1, v)
v, ok = cache.Get(3)
asssert.Equal(true, ok)
asssert.Equal(3, v)
}

63
algorithm/search.go Normal file
View File

@@ -0,0 +1,63 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. TODO
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
// LinearSearch Simple linear search algorithm that iterates over all elements of an slice
// If a target is found, the index of the target is returned. Else the function return -1
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int {
for i, v := range slice {
if comparator.Compare(v, target) == 0 {
return i
}
}
return -1
}
// BinarySearch search for target within a sorted slice, recursive call itself.
// If a target is found, the index of the target is returned. Else the function return -1
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
if highIndex < lowIndex || len(sortedSlice) == 0 {
return -1
}
midIndex := int(lowIndex + (highIndex-lowIndex)/2)
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
if isMidValGreatTarget {
return BinarySearch(sortedSlice, target, lowIndex, midIndex-1, comparator)
} else if isMidValLessTarget {
return BinarySearch(sortedSlice, target, midIndex+1, highIndex, comparator)
}
return midIndex
}
// BinaryIterativeSearch search for target within a sorted slice.
// If a target is found, the index of the target is returned. Else the function return -1
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
startIndex := lowIndex
endIndex := highIndex
var midIndex int
for startIndex <= endIndex {
midIndex = int(startIndex + (endIndex-startIndex)/2)
isMidValGreatTarget := comparator.Compare(sortedSlice[midIndex], target) == 1
isMidValLessTarget := comparator.Compare(sortedSlice[midIndex], target) == -1
if isMidValGreatTarget {
endIndex = midIndex - 1
} else if isMidValLessTarget {
startIndex = midIndex + 1
} else {
return midIndex
}
}
return -1
}

33
algorithm/search_test.go Normal file
View File

@@ -0,0 +1,33 @@
package algorithm
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
func TestLinearSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestLinearSearch")
comparator := &intComparator{}
asssert.Equal(4, LinearSearch(sortedNumbers, 5, comparator))
asssert.Equal(-1, LinearSearch(sortedNumbers, 9, comparator))
}
func TestBinarySearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinarySearch")
comparator := &intComparator{}
asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}
func TestBinaryIterativeSearch(t *testing.T) {
asssert := internal.NewAssert(t, "TestBinaryIterativeSearch")
comparator := &intComparator{}
asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator))
asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator))
}

188
algorithm/sorter.go Normal file
View File

@@ -0,0 +1,188 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package algorithm contain some basic algorithm functions. eg. sort, search
package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints"
// BubbleSort use bubble to sort slice.
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
for j := 0; j < len(slice)-1-i; j++ {
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
if isCurrGreatThanNext {
swap(slice, j, j+1)
}
}
}
}
// InsertionSort use insertion to sort slice.
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
for j := i; j > 0; j-- {
isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1
if isPreLessThanCurrent {
swap(slice, j, j-1)
} else {
break
}
}
}
}
// SelectionSort use selection to sort slice.
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
for i := 0; i < len(slice); i++ {
min := i
for j := i + 1; j < len(slice); j++ {
if comparator.Compare(slice[j], slice[min]) == -1 {
min = j
}
}
swap(slice, i, min)
}
}
// ShellSort shell sort slice.
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice)
gap := 1
for gap < size/3 {
gap = 3*gap + 1
}
for gap >= 1 {
for i := gap; i < size; i++ {
for j := i; j >= gap && comparator.Compare(slice[j], slice[j-gap]) == -1; j -= gap {
swap(slice, j, j-gap)
}
}
gap = gap / 3
}
}
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
if lowIndex < highIndex {
p := partition(slice, lowIndex, highIndex, comparator)
QuickSort(slice, lowIndex, p-1, comparator)
QuickSort(slice, p+1, highIndex, comparator)
}
}
// partition split slice into two parts
func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int {
p := slice[highIndex]
i := lowIndex
for j := lowIndex; j < highIndex; j++ {
if comparator.Compare(slice[j], p) == -1 { //slice[j] < p
swap(slice, i, j)
i++
}
}
swap(slice, i, highIndex)
return i
}
// HeapSort use heap to sort slice
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
size := len(slice)
for i := size/2 - 1; i >= 0; i-- {
sift(slice, i, size-1, comparator)
}
for j := size - 1; j > 0; j-- {
swap(slice, 0, j)
sift(slice, 0, j-1, comparator)
}
}
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
i := lowIndex
j := 2*i + 1
temp := slice[i]
for j <= highIndex {
if j < highIndex && comparator.Compare(slice[j], slice[j+1]) == -1 { //slice[j] < slice[j+1]
j++
}
if comparator.Compare(temp, slice[j]) == -1 { //tmp < slice[j]
slice[i] = slice[j]
i = j
j = 2*i + 1
} else {
break
}
}
slice[i] = temp
}
// MergeSort merge sorting for slice
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) {
mergeSort(slice, 0, len(slice)-1, comparator)
}
func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) {
if lowIndex < highIndex {
mid := (lowIndex + highIndex) / 2
mergeSort(slice, lowIndex, mid, comparator)
mergeSort(slice, mid+1, highIndex, comparator)
merge(slice, lowIndex, mid, highIndex, comparator)
}
}
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) {
i := lowIndex
j := midIndex + 1
temp := []T{}
for i <= midIndex && j <= highIndex {
//slice[i] < slice[j]
if comparator.Compare(slice[i], slice[j]) == -1 {
temp = append(temp, slice[i])
i++
} else {
temp = append(temp, slice[j])
j++
}
}
if i <= midIndex {
temp = append(temp, slice[i:midIndex+1]...)
} else {
temp = append(temp, slice[j:highIndex+1]...)
}
for k := 0; k < len(temp); k++ {
slice[lowIndex+k] = temp[k]
}
}
// CountSort use count sorting for slice
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T {
size := len(slice)
out := make([]T, size)
for i := 0; i < size; i++ {
count := 0
for j := 0; j < size; j++ {
//slice[i] > slice[j]
if comparator.Compare(slice[i], slice[j]) == 1 {
count++
}
}
out[count] = slice[i]
}
return out
}
// swap two slice value at index i and j
func swap[T any](slice []T, i, j int) {
slice[i], slice[j] = slice[j], slice[i]
}

218
algorithm/sorter_test.go Normal file
View File

@@ -0,0 +1,218 @@
package algorithm
import (
"fmt"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
// People test mock data
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/v2/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
}
// var peoples = []people{
// {Name: "a", Age: 20},
// {Name: "b", Age: 10},
// {Name: "c", Age: 17},
// {Name: "d", Age: 8},
// {Name: "e", Age: 28},
// }
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
// var intSlice = []int{2, 1, 5, 3, 6, 4}
func TestBubbleSortForStructSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
BubbleSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestBubbleSortForIntSlice(t *testing.T) {
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
BubbleSort(numbers, comparator)
asssert.Equal([]int{1, 2, 3, 4, 5, 6}, numbers)
}
func TestInsertionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestInsertionSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
InsertionSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestSelectionSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestSelectionSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
SelectionSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestShellSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestShellSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
ShellSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestQuickSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestQuickSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
QuickSort(peoples, 0, len(peoples)-1, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestHeapSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestHeapSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
HeapSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestMergeSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestMergeSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
MergeSort(peoples, comparator)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", peoples)
asssert.Equal(expected, actual)
}
func TestCountSort(t *testing.T) {
asssert := internal.NewAssert(t, "TestCountSort")
peoples := []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
sortedPeopleByAge := CountSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge)
asssert.Equal(expected, actual)
}

243
concurrency/channel.go Normal file
View File

@@ -0,0 +1,243 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, async.
package concurrency
import (
"context"
"sync"
)
// Channel is a logic object which can generate or manipulate go channel
// all methods of Channel are in the book tilted《Concurrency in Go》
type Channel struct {
}
// NewChannel return a Channel instance
func NewChannel() *Channel {
return &Channel{}
}
// Generate a data of type any chan, put param `values` into the chan
func (c *Channel) Generate(ctx context.Context, values ...any) <-chan any {
dataStream := make(chan any)
go func() {
defer close(dataStream)
for _, v := range values {
select {
case <-ctx.Done():
return
case dataStream <- v:
}
}
}()
return dataStream
}
// Repeat return a data of type any chan, put param `values` into the chan repeatly until cancel the context.
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any {
dataStream := make(chan any)
go func() {
defer close(dataStream)
for {
for _, v := range values {
select {
case <-ctx.Done():
return
case dataStream <- v:
}
}
}
}()
return dataStream
}
// RepeatFn return a chan, excutes fn repeatly, and put the result into retruned chan
// until close the `done` channel
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any {
dataStream := make(chan any)
go func() {
defer close(dataStream)
for {
select {
case <-ctx.Done():
return
case dataStream <- fn():
}
}
}()
return dataStream
}
// Take return a chan whose values are tahken from another chan
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any {
takeStream := make(chan any)
go func() {
defer close(takeStream)
for i := 0; i < number; i++ {
select {
case <-ctx.Done():
return
case takeStream <- <-valueStream:
}
}
}()
return takeStream
}
// FanIn merge multiple channels into one channel
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any {
out := make(chan any)
go func() {
var wg sync.WaitGroup
wg.Add(len(channels))
for _, c := range channels {
go func(c <-chan any) {
defer wg.Done()
for v := range c {
select {
case <-ctx.Done():
return
case out <- v:
}
}
}(c)
}
wg.Wait()
close(out)
}()
return out
}
// Tee split one chanel into two channels
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any) {
out1 := make(chan any)
out2 := make(chan any)
go func() {
defer close(out1)
defer close(out2)
for val := range c.OrDone(ctx, in) {
var out1, out2 = out1, out2
for i := 0; i < 2; i++ {
select {
case <-ctx.Done():
case out1 <- val:
out1 = nil
case out2 <- val:
out2 = nil
}
}
}
}()
return out1, out2
}
// Bridge link multiply channels into one channel
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any {
valStream := make(chan any)
go func() {
defer close(valStream)
for {
var stream <-chan any
select {
case maybeStream, ok := <-chanStream:
if ok == false {
return
}
stream = maybeStream
case <-ctx.Done():
return
}
for val := range c.OrDone(ctx, stream) {
select {
case valStream <- val:
case <-ctx.Done():
}
}
}
}()
return valStream
}
// Or read one or more channels into one channel, will close when any readin channel is closed
func (c *Channel) Or(channels ...<-chan any) <-chan any {
switch len(channels) {
case 0:
return nil
case 1:
return channels[0]
}
orDone := make(chan any)
go func() {
defer close(orDone)
switch len(channels) {
case 2:
select {
case <-channels[0]:
case <-channels[1]:
}
default:
m := len(channels) / 2
select {
case <-c.Or(channels[:m]...):
case <-c.Or(channels[m:]...):
}
// select {
// case <-channels[0]:
// case <-channels[1]:
// case <-channels[2]:
// case <-c.Or(append(channels[3:], orDone)...):
// }
}
}()
return orDone
}
// OrDone read a channel into another channel, will close until cancel context.
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any {
valStream := make(chan any)
go func() {
defer close(valStream)
for {
select {
case <-ctx.Done():
return
case v, ok := <-channel:
if !ok {
return
}
select {
case valStream <- v:
case <-ctx.Done():
}
}
}
}()
return valStream
}

206
concurrency/channel_test.go Normal file
View File

@@ -0,0 +1,206 @@
package concurrency
import (
"context"
"testing"
"time"
"github.com/duke-git/lancet/v2/internal"
)
func TestGenerate(t *testing.T) {
assert := internal.NewAssert(t, "TestGenerate")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
intStream := c.Generate(ctx, 1, 2, 3)
// for v := range intStream {
// t.Log(v) //1, 2, 3
// }
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(3, <-intStream)
}
func TestRepeat(t *testing.T) {
assert := internal.NewAssert(t, "TestRepeat")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
// for v := range intStream {
// t.Log(v) //1, 2, 1, 2, 1
// }
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(1, <-intStream)
}
func TestRepeatFn(t *testing.T) {
assert := internal.NewAssert(t, "TestRepeatFn")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
}
c := NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
// for v := range dataStream {
// t.Log(v) //a, a, a
// }
assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream)
assert.Equal("a", <-dataStream)
}
func TestTake(t *testing.T) {
assert := internal.NewAssert(t, "TestTake")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers <- 1
numbers <- 2
numbers <- 3
numbers <- 4
numbers <- 5
defer close(numbers)
c := NewChannel()
intStream := c.Take(ctx, numbers, 3)
assert.Equal(1, <-intStream)
assert.Equal(2, <-intStream)
assert.Equal(3, <-intStream)
}
func TestFanIn(t *testing.T) {
assert := internal.NewAssert(t, "TestFanIn")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
channels := make([]<-chan any, 3)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
}
mergedChannel := c.FanIn(ctx, channels...)
for val := range mergedChannel {
t.Logf("\t%d\n", val)
}
assert.Equal(1, 1)
}
func TestOr(t *testing.T) {
assert := internal.NewAssert(t, "TestOr")
sig := func(after time.Duration) <-chan any {
c := make(chan interface{})
go func() {
defer close(c)
time.Sleep(after)
}()
return c
}
start := time.Now()
c := NewChannel()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
)
t.Logf("done after %v", time.Since(start))
assert.Equal(1, 1)
}
func TestOrDone(t *testing.T) {
assert := internal.NewAssert(t, "TestOrDone")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
var res any
for val := range c.OrDone(ctx, intStream) {
t.Logf("%v", val)
res = val
}
assert.Equal(1, res)
}
func TestTee(t *testing.T) {
assert := internal.NewAssert(t, "TestTee")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
inStream := c.Take(ctx, c.Repeat(ctx, 1), 4)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
val1 := val
val2 := <-out2
// t.Log("val1 is", val1)
// t.Log("val2 is", val2)
assert.Equal(1, val1)
assert.Equal(1, val2)
}
}
func TestBridge(t *testing.T) {
assert := internal.NewAssert(t, "TestBridge")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
stream <- i
close(stream)
chanStream <- stream
}
}()
return chanStream
}
index := 0
for val := range c.Bridge(ctx, genVals()) {
// t.Logf("%v ", val) //0 1 2 3 4 5 6 7 8 9
assert.Equal(index, val)
index++
}
}

View File

@@ -6,9 +6,10 @@ package convertor
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math"
"reflect" "reflect"
"regexp" "regexp"
"strconv" "strconv"
@@ -21,14 +22,44 @@ func ToBool(s string) (bool, error) {
} }
// ToBytes convert interface to bytes // ToBytes convert interface to bytes
func ToBytes(data interface{}) ([]byte, error) { func ToBytes(value any) ([]byte, error) {
var buf bytes.Buffer v := reflect.ValueOf(value)
enc := gob.NewEncoder(&buf)
err := enc.Encode(data) switch value.(type) {
if err != nil { case int, int8, int16, int32, int64:
return nil, err number := v.Int()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case uint, uint8, uint16, uint32, uint64:
number := v.Uint()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case float32:
number := float32(v.Float())
bits := math.Float32bits(number)
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, bits)
return bytes, nil
case float64:
number := v.Float()
bits := math.Float64bits(number)
bytes := make([]byte, 8)
binary.BigEndian.PutUint64(bytes, bits)
return bytes, nil
case bool:
return strconv.AppendBool([]byte{}, v.Bool()), nil
case string:
return []byte(v.String()), nil
case []byte:
return v.Bytes(), nil
default:
newValue, err := json.Marshal(value)
return newValue, err
} }
return buf.Bytes(), nil
} }
// ToChar convert string to char slice // ToChar convert string to char slice
@@ -44,7 +75,7 @@ func ToChar(s string) []string {
} }
// ToString convert value to string // ToString convert value to string
func ToString(value interface{}) string { func ToString(value any) string {
res := "" res := ""
if value == nil { if value == nil {
return res return res
@@ -76,7 +107,7 @@ func ToString(value interface{}) string {
} }
// ToJson convert value to a valid json string // ToJson convert value to a valid json string
func ToJson(value interface{}) (string, error) { func ToJson(value any) (string, error) {
res, err := json.Marshal(value) res, err := json.Marshal(value)
if err != nil { if err != nil {
return "", err return "", err
@@ -86,7 +117,7 @@ func ToJson(value interface{}) (string, error) {
} }
// ToFloat convert value to a float64, if input is not a float return 0.0 and error // ToFloat convert value to a float64, if input is not a float return 0.0 and error
func ToFloat(value interface{}) (float64, error) { func ToFloat(value any) (float64, error) {
v := reflect.ValueOf(value) v := reflect.ValueOf(value)
res := 0.0 res := 0.0
@@ -113,7 +144,7 @@ func ToFloat(value interface{}) (float64, error) {
} }
// ToInt convert value to a int64, if input is not a numeric format return 0 and error // ToInt convert value to a int64, if input is not a numeric format return 0 and error
func ToInt(value interface{}) (int64, error) { func ToInt(value any) (int64, error) {
v := reflect.ValueOf(value) v := reflect.ValueOf(value)
var res int64 var res int64
@@ -141,7 +172,7 @@ func ToInt(value interface{}) (int64, error) {
// StructToMap convert struct to map, only convert exported struct field // StructToMap convert struct to map, only convert exported struct field
// map key is specified same as struct field tag `json` value // map key is specified same as struct field tag `json` value
func StructToMap(value interface{}) (map[string]interface{}, error) { func StructToMap(value any) (map[string]any, error) {
v := reflect.ValueOf(value) v := reflect.ValueOf(value)
t := reflect.TypeOf(value) t := reflect.TypeOf(value)
@@ -152,7 +183,7 @@ func StructToMap(value interface{}) (map[string]interface{}, error) {
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value) return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
} }
res := make(map[string]interface{}) res := make(map[string]any)
fieldNum := t.NumField() fieldNum := t.NumField()
pattern := `^[A-Z]` pattern := `^[A-Z]`

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestToChar(t *testing.T) { func TestToChar(t *testing.T) {
@@ -36,26 +36,33 @@ func TestToBool(t *testing.T) {
func TestToBytes(t *testing.T) { func TestToBytes(t *testing.T) {
assert := internal.NewAssert(t, "TestToBytes") assert := internal.NewAssert(t, "TestToBytes")
cases := []interface{}{ cases := []any{
0, 0,
false, false,
"1", "1",
} }
expected := [][]byte{ expected := [][]byte{
{3, 4, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
{3, 2, 0, 0}, {102, 97, 108, 115, 101},
{4, 12, 0, 1, 49}, {49},
} }
for i := 0; i < len(cases); i++ { for i := 0; i < len(cases); i++ {
actual, _ := ToBytes(cases[i]) actual, _ := ToBytes(cases[i])
assert.Equal(expected[i], actual) assert.Equal(expected[i], actual)
} }
bytesData, err := ToBytes("abc")
if err != nil {
t.Error(err)
t.Fail()
}
assert.Equal("abc", ToString(bytesData))
} }
func TestToInt(t *testing.T) { func TestToInt(t *testing.T) {
assert := internal.NewAssert(t, "TestToInt") assert := internal.NewAssert(t, "TestToInt")
cases := []interface{}{"123", "-123", 123, cases := []any{"123", "-123", 123,
uint(123), uint8(123), uint16(123), uint32(123), uint64(123), uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float32(12.3), float64(12.3), float32(12.3), float64(12.3),
"abc", false, "111111111111111111111111111111111111111"} "abc", false, "111111111111111111111111111111111111111"}
@@ -71,7 +78,7 @@ func TestToInt(t *testing.T) {
func TestToFloat(t *testing.T) { func TestToFloat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFloat") assert := internal.NewAssert(t, "TestToFloat")
cases := []interface{}{ cases := []any{
"", "-1", "-.11", "1.23e3", ".123e10", "abc", "", "-1", "-.11", "1.23e3", ".123e10", "abc",
int(0), int8(1), int16(-1), int32(123), int64(123), int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123), uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
@@ -99,7 +106,7 @@ func TestToString(t *testing.T) {
} }
aStruct := TestStruct{Name: "TestStruct"} aStruct := TestStruct{Name: "TestStruct"}
cases := []interface{}{ cases := []any{
"", nil, "", nil,
int(0), int8(1), int16(-1), int32(123), int64(123), int(0), int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123), uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
@@ -147,7 +154,7 @@ func TestStructToMap(t *testing.T) {
100, 100,
} }
pm, _ := StructToMap(p) pm, _ := StructToMap(p)
var expected = map[string]interface{}{"name": "test"} var expected = map[string]any{"name": "test"}
assert.Equal(expected, pm) assert.Equal(expected, pm)
} }

View File

@@ -3,7 +3,7 @@ package cryptor
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAesEcbEncrypt(t *testing.T) { func TestAesEcbEncrypt(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestBase64StdEncode(t *testing.T) { func TestBase64StdEncode(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestDesEcbEncrypt(t *testing.T) { func TestDesEcbEncrypt(t *testing.T) {

View File

@@ -3,7 +3,7 @@ package cryptor
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestRsaEncrypt(t *testing.T) { func TestRsaEncrypt(t *testing.T) {

View File

@@ -0,0 +1,241 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the link, Next pointer points to a next node of the link.
type DoublyLink[T any] struct {
Head *datastructure.LinkNode[T]
length int
}
// NewDoublyLink return *DoublyLink instance
func NewDoublyLink[T any]() *DoublyLink[T] {
return &DoublyLink[T]{Head: nil}
}
// InsertAtHead insert value into doubly linklist at head index
func (link *DoublyLink[T]) InsertAtHead(value T) {
newNode := datastructure.NewLinkNode(value)
size := link.Size()
if size == 0 {
link.Head = newNode
link.length++
return
}
newNode.Next = link.Head
newNode.Pre = nil
link.Head.Pre = newNode
link.Head = newNode
link.length++
}
// InsertAtTail insert value into doubly linklist at tail index
func (link *DoublyLink[T]) InsertAtTail(value T) {
current := link.Head
if current == nil {
link.InsertAtHead(value)
return
}
for current.Next != nil {
current = current.Next
}
newNode := datastructure.NewLinkNode(value)
newNode.Next = nil
newNode.Pre = current
current.Next = newNode
link.length++
}
// InsertAt insert value into doubly linklist at index
func (link *DoublyLink[T]) InsertAt(index int, value T) error {
size := link.length
if index < 0 || index > size {
return errors.New("param index should between 0 and the length of doubly link.")
}
if index == 0 {
link.InsertAtHead(value)
return nil
}
if index == size {
link.InsertAtTail(value)
return nil
}
i := 0
current := link.Head
for current != nil {
if i == index-1 {
newNode := datastructure.NewLinkNode(value)
newNode.Next = current.Next
newNode.Pre = current
current.Next = newNode
link.length++
return nil
}
i++
current = current.Next
}
return errors.New("doubly link list no exist")
}
// DeleteAtHead delete value in doubly linklist at head index
func (link *DoublyLink[T]) DeleteAtHead() error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
link.Head = current.Next
link.Head.Pre = nil
link.length--
return nil
}
// DeleteAtTail delete value in doubly linklist at tail index
func (link *DoublyLink[T]) DeleteAtTail() error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
if current.Next == nil {
return link.DeleteAtHead()
}
for current.Next.Next != nil {
current = current.Next
}
current.Next = nil
link.length--
return nil
}
// DeleteAt delete value in doubly linklist at index
func (link *DoublyLink[T]) DeleteAt(index int) error {
if link.Head == nil {
return errors.New("doubly link list no exist")
}
current := link.Head
if current.Next == nil || index == 0 {
return link.DeleteAtHead()
}
if index == link.length-1 {
return link.DeleteAtTail()
}
if index < 0 || index > link.length-1 {
return errors.New("param index should between 0 and link size -1.")
}
i := 0
for current != nil {
if i == index-1 {
current.Next = current.Next.Next
link.length--
return nil
}
i++
current = current.Next
}
return errors.New("delete error")
}
// Reverse the linked list
func (link *DoublyLink[T]) Reverse() {
current := link.Head
var temp *datastructure.LinkNode[T]
for current != nil {
temp = current.Pre
current.Pre = current.Next
current.Next = temp
current = current.Pre
}
if temp != nil {
link.Head = temp.Pre
}
}
// GetMiddleNode return node at middle index of linked list
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
if link.Head == nil {
return nil
}
if link.Head.Next == nil {
return link.Head
}
fast := link.Head
slow := link.Head
for fast != nil {
fast = fast.Next
if fast != nil {
fast = fast.Next
slow = slow.Next
} else {
return slow
}
}
return slow
}
// Size return the count of doubly linked list
func (link *DoublyLink[T]) Size() int {
return link.length
}
// Values return slice of all doubly linklist node value
func (link *DoublyLink[T]) Values() []T {
res := []T{}
current := link.Head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Print all nodes info of a linked list
func (link *DoublyLink[T]) Print() {
current := link.Head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}
// IsEmpty checks if link is empty or not
func (link *DoublyLink[T]) IsEmpty() bool {
return link.length == 0
}
// Clear checks if link is empty or not
func (link *DoublyLink[T]) Clear() {
link.Head = nil
link.length = 0
}

View File

@@ -0,0 +1,179 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestDoublyLink_InsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
link := NewDoublyLink[int]()
link.InsertAtHead(1)
link.InsertAtHead(2)
link.InsertAtHead(3)
link.Print()
expected := []int{3, 2, 1}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_InsertAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_InsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
link := NewDoublyLink[int]()
err := link.InsertAt(1, 1)
assert.IsNotNil(err)
link.InsertAt(0, 1)
link.InsertAt(1, 2)
link.InsertAt(2, 4)
link.InsertAt(2, 3)
link.Print()
expected := []int{1, 2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAtHead(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
link := NewDoublyLink[int]()
err := link.DeleteAtHead()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtHead()
link.Print()
expected := []int{2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
link := NewDoublyLink[int]()
err := link.DeleteAtTail()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtTail()
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestDoublyLink_DeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
link := NewDoublyLink[int]()
err := link.DeleteAt(0)
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.InsertAtTail(5)
err = link.DeleteAt(5)
assert.IsNotNil(err)
err = link.DeleteAt(0)
assert.IsNil(err)
assert.Equal([]int{2, 3, 4, 5}, link.Values())
link.DeleteAt(3)
assert.Equal([]int{2, 3, 4}, link.Values())
link.DeleteAt(1)
assert.Equal(2, link.Size())
assert.Equal([]int{2, 4}, link.Values())
}
func TestDoublyLink_Reverse(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.Reverse()
link.Print()
assert.Equal([]int{4, 3, 2, 1}, link.Values())
}
func TestDoublyLink_GetMiddleNode(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
link := NewDoublyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
middle1 := link.GetMiddleNode()
assert.Equal(3, middle1.Value)
link.InsertAtTail(5)
link.InsertAtTail(6)
link.InsertAtTail(7)
middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value)
}
func TestDoublyLink_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
link := NewDoublyLink[int]()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
link.InsertAtTail(1)
assert.Equal(false, link.IsEmpty())
assert.Equal(1, link.Size())
link.Clear()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
}

View File

@@ -0,0 +1,246 @@
package datastructure
import (
"errors"
"fmt"
"reflect"
"github.com/duke-git/lancet/v2/datastructure"
)
// SinglyLink is a linked list. Whose node has a Value generics and Next pointer points to a next node of the link.
type SinglyLink[T any] struct {
Head *datastructure.LinkNode[T]
length int
}
// NewSinglyLink return *SinglyLink instance
func NewSinglyLink[T any]() *SinglyLink[T] {
return &SinglyLink[T]{Head: nil}
}
// InsertAtHead insert value into singly linklist at head index
func (link *SinglyLink[T]) InsertAtHead(value T) {
newNode := datastructure.NewLinkNode(value)
newNode.Next = link.Head
link.Head = newNode
link.length++
}
// InsertAtTail insert value into singly linklist at tail index
func (link *SinglyLink[T]) InsertAtTail(value T) {
current := link.Head
if current == nil {
link.InsertAtHead(value)
return
}
for current.Next != nil {
current = current.Next
}
newNode := datastructure.NewLinkNode(value)
newNode.Next = nil
current.Next = newNode
link.length++
}
// InsertAt insert value into singly linklist at index
func (link *SinglyLink[T]) InsertAt(index int, value T) error {
size := link.length
if index < 0 || index > size {
return errors.New("param index should between 0 and the length of singly link.")
}
if index == 0 {
link.InsertAtHead(value)
return nil
}
if index == size {
link.InsertAtTail(value)
return nil
}
i := 0
current := link.Head
for current != nil {
if i == index-1 {
newNode := datastructure.NewLinkNode(value)
newNode.Next = current.Next
current.Next = newNode
link.length++
return nil
}
i++
current = current.Next
}
return errors.New("singly link list no exist")
}
// DeleteAtHead delete value in singly linklist at head index
func (link *SinglyLink[T]) DeleteAtHead() error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
link.Head = current.Next
link.length--
return nil
}
// DeleteAtTail delete value in singly linklist at tail index
func (link *SinglyLink[T]) DeleteAtTail() error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
if current.Next == nil {
return link.DeleteAtHead()
}
for current.Next.Next != nil {
current = current.Next
}
current.Next = nil
link.length--
return nil
}
// DeleteAt delete value in singly linklist at index
func (link *SinglyLink[T]) DeleteAt(index int) error {
if link.Head == nil {
return errors.New("singly link list no exist")
}
current := link.Head
if current.Next == nil || index == 0 {
return link.DeleteAtHead()
}
if index == link.length-1 {
return link.DeleteAtTail()
}
if index < 0 || index > link.length-1 {
return errors.New("param index should between 0 and link size -1.")
}
i := 0
for current != nil {
if i == index-1 {
current.Next = current.Next.Next
link.length--
return nil
}
i++
current = current.Next
}
return errors.New("delete error")
}
// DeleteValue delete value in singly linklist
func (link *SinglyLink[T]) DeleteValue(value T) {
if link.Head == nil {
return
}
dummyHead := datastructure.NewLinkNode(value)
dummyHead.Next = link.Head
current := dummyHead
for current.Next != nil {
if reflect.DeepEqual(current.Next.Value, value) {
current.Next = current.Next.Next
link.length--
} else {
current = current.Next
}
}
link.Head = dummyHead.Next
}
// Reverse the linked list
func (link *SinglyLink[T]) Reverse() {
var pre, next *datastructure.LinkNode[T]
current := link.Head
for current != nil {
next = current.Next
current.Next = pre
pre = current
current = next
}
link.Head = pre
}
// GetMiddleNode return node at middle index of linked list
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
if link.Head == nil {
return nil
}
if link.Head.Next == nil {
return link.Head
}
fast := link.Head
slow := link.Head
for fast != nil {
fast = fast.Next
if fast != nil {
fast = fast.Next
slow = slow.Next
} else {
return slow
}
}
return slow
}
// Size return the count of singly linked list
func (link *SinglyLink[T]) Size() int {
return link.length
}
// Values return slice of all singly linklist node value
func (link *SinglyLink[T]) Values() []T {
res := []T{}
current := link.Head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// IsEmpty checks if link is empty or not
func (link *SinglyLink[T]) IsEmpty() bool {
return link.length == 0
}
// Clear checks if link is empty or not
func (link *SinglyLink[T]) Clear() {
link.Head = nil
link.length = 0
}
// Print all nodes info of a linked list
func (link *SinglyLink[T]) Print() {
current := link.Head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,208 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestSinglyLink_InsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
link := NewSinglyLink[int]()
link.InsertAtHead(1)
link.InsertAtHead(2)
link.InsertAtHead(3)
link.Print()
expected := []int{3, 2, 1}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_InsertAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_InsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
link := NewSinglyLink[int]()
err := link.InsertAt(1, 1)
assert.IsNotNil(err)
err = link.InsertAt(0, 1)
if err != nil {
t.FailNow()
}
err = link.InsertAt(1, 2)
if err != nil {
t.FailNow()
}
err = link.InsertAt(2, 4)
if err != nil {
t.FailNow()
}
err = link.InsertAt(2, 3)
if err != nil {
t.FailNow()
}
link.Print()
expected := []int{1, 2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteAtHead(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
link := NewSinglyLink[int]()
err := link.DeleteAtHead()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtHead()
link.Print()
expected := []int{2, 3, 4}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteAtTail(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
link := NewSinglyLink[int]()
err := link.DeleteAtTail()
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteAtTail()
link.Print()
expected := []int{1, 2, 3}
values := link.Values()
assert.Equal(expected, values)
}
func TestSinglyLink_DeleteValue(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.DeleteValue(2)
assert.Equal([]int{1, 3, 4}, link.Values())
link.DeleteValue(1)
assert.Equal([]int{3, 4}, link.Values())
}
func TestSinglyLink_DeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
link := NewSinglyLink[int]()
err := link.DeleteAt(0)
assert.IsNotNil(err)
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.InsertAtTail(5)
err = link.DeleteAt(5)
assert.IsNotNil(err)
err = link.DeleteAt(0)
assert.IsNil(err)
assert.Equal([]int{2, 3, 4, 5}, link.Values())
link.DeleteAt(3)
assert.Equal([]int{2, 3, 4}, link.Values())
link.DeleteAt(1)
assert.Equal(2, link.Size())
assert.Equal([]int{2, 4}, link.Values())
}
func TestSinglyLink_Reverse(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
link.Reverse()
link.Print()
assert.Equal([]int{4, 3, 2, 1}, link.Values())
}
func TestSinglyLink_GetMiddleNode(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
link.InsertAtTail(4)
middle1 := link.GetMiddleNode()
assert.Equal(3, middle1.Value)
link.InsertAtTail(5)
link.InsertAtTail(6)
link.InsertAtTail(7)
middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value)
}
func TestSinglyLink_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestSinglyLink_Clear")
link := NewSinglyLink[int]()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
link.InsertAtTail(1)
assert.Equal(false, link.IsEmpty())
assert.Equal(1, link.Size())
link.Clear()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())
}

245
datastructure/list/list.go Normal file
View File

@@ -0,0 +1,245 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
package datastructure
import (
"reflect"
)
// List is a linear table, implemented with slice
type List[T any] struct {
data []T
}
// NewList return a pointer of List
func NewList[T any](data []T) *List[T] {
return &List[T]{data: data}
}
// Data return list data
func (l *List[T]) Data() []T {
return l.data
}
// ValueOf return the value pointer at index of list data.
func (l *List[T]) ValueOf(index int) (*T, bool) {
if index < 0 || index >= len(l.data) {
return nil, false
}
return &l.data[index], true
}
// IndexOf reture the index of value. if not found return -1
func (l *List[T]) IndexOf(value T) int {
index := -1
data := l.data
for i, v := range data {
if reflect.DeepEqual(v, value) {
index = i
break
}
}
return index
}
// Contain checks if the value in the list or not
func (l *List[T]) Contain(value T) bool {
data := l.data
for _, v := range data {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Push append value to the list data
func (l *List[T]) Push(value T) {
l.data = append(l.data, value)
}
// InsertAtFirst insert value into list at first index
func (l *List[T]) InsertAtFirst(value T) {
l.InsertAt(0, value)
}
// InsertAtLast insert value into list at last index
func (l *List[T]) InsertAtLast(value T) {
l.InsertAt(len(l.data), value)
}
// InsertAt insert value into list at index
func (l *List[T]) InsertAt(index int, value T) {
data := l.data
size := len(data)
if index < 0 || index > size {
return
}
l.data = append(data[:index], append([]T{value}, data[index:]...)...)
}
// PopFirst delete the first value of list and return it
func (l *List[T]) PopFirst() (*T, bool) {
if len(l.data) == 0 {
return nil, false
}
v := l.data[0]
l.DeleteAt(0)
return &v, true
}
// PopLast delete the last value of list and return it
func (l *List[T]) PopLast() (*T, bool) {
size := len(l.data)
if size == 0 {
return nil, false
}
v := l.data[size-1]
l.DeleteAt(size - 1)
return &v, true
}
// DeleteAt delete the value of list at index
func (l *List[T]) DeleteAt(index int) {
data := l.data
size := len(data)
if index < 0 || index > size-1 {
return
}
if index == size-1 {
data = append(data[:index])
} else {
data = append(data[:index], data[index+1:]...)
}
l.data = data
}
// UpdateAt update value of list at index, index shoud between 0 and list size -1
func (l *List[T]) UpdateAt(index int, value T) {
data := l.data
size := len(data)
if index < 0 || index >= size {
return
}
l.data = append(data[:index], append([]T{value}, data[index+1:]...)...)
}
// Equtal compare list to other list, use reflect.DeepEqual
func (l *List[T]) Equtal(other *List[T]) bool {
if len(l.data) != len(other.data) {
return false
}
for i := 0; i < len(l.data); i++ {
if !reflect.DeepEqual(l.data[i], other.data[i]) {
return false
}
}
return true
}
// IsEmpty check if the list is empty or not
func (l *List[T]) IsEmpty() bool {
return len(l.data) == 0
}
// Clear the data of list
func (l *List[T]) Clear() {
l.data = make([]T, 0, 0)
}
// Clone return a copy of list
func (l *List[T]) Clone() *List[T] {
cl := NewList(make([]T, len(l.data)))
copy(cl.data, l.data)
return cl
}
// Merge two list, return new list, don't change original list
func (l *List[T]) Merge(other *List[T]) *List[T] {
l1, l2 := len(l.data), len(other.data)
ml := NewList(make([]T, l1+l2, l1+l2))
data := append([]T{}, append(l.data, other.data...)...)
ml.data = data
return ml
}
// Size return number of list data items
func (l *List[T]) Size() int {
return len(l.data)
}
// Swap the value of index i and j in list
func (l *List[T]) Swap(i, j int) {
size := len(l.data)
if i < 0 || i >= size || j < 0 || j >= size {
return
}
l.data[i], l.data[j] = l.data[j], l.data[i]
}
// Reverse the item order of list
func (l *List[T]) Reverse() {
for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 {
l.data[i], l.data[j] = l.data[j], l.data[i]
}
}
// Unique remove duplicate items in list
func (l *List[T]) Unique() {
data := l.data
size := len(data)
uniqueData := make([]T, 0, 0)
for i := 0; i < size; i++ {
value := data[i]
skip := true
for _, v := range uniqueData {
if reflect.DeepEqual(value, v) {
skip = false
break
}
}
if skip {
uniqueData = append(uniqueData, value)
}
}
l.data = uniqueData
}
// Union creates a new list contain all element in list l and other, remove duplicate element.
func (l *List[T]) Union(other *List[T]) *List[T] {
res := NewList([]T{})
res.data = append(res.data, l.data...)
res.data = append(res.data, other.data...)
res.Unique()
return res
}
// Intersection creates a new list whose element both be contained in list l and other
func (l *List[T]) Intersection(other *List[T]) *List[T] {
res := NewList(make([]T, 0, 0))
for _, v := range l.data {
if other.Contain(v) {
res.data = append(res.data, v)
}
}
return res
}

View File

@@ -0,0 +1,272 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestListData(t *testing.T) {
assert := internal.NewAssert(t, "TestListData")
list := NewList([]int{1, 2, 3})
assert.Equal([]int{1, 2, 3}, list.Data())
}
func TestValueOf(t *testing.T) {
assert := internal.NewAssert(t, "TestValueOf")
list := NewList([]int{1, 2, 3})
v, ok := list.ValueOf(0)
assert.Equal(1, *v)
assert.Equal(true, ok)
_, ok = list.ValueOf(3)
assert.Equal(false, ok)
}
func TestIndexOf(t *testing.T) {
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3})
i := list.IndexOf(1)
assert.Equal(0, i)
i = list.IndexOf(4)
assert.Equal(-1, i)
}
func TestContain(t *testing.T) {
assert := internal.NewAssert(t, "TestContain")
list := NewList([]int{1, 2, 3})
assert.Equal(true, list.Contain(1))
assert.Equal(false, list.Contain(0))
}
func TestPush(t *testing.T) {
assert := internal.NewAssert(t, "TestPush")
list := NewList([]int{1, 2, 3})
list.Push(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
}
func TestInsertAtFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAtFirst")
list := NewList([]int{1, 2, 3})
list.InsertAtFirst(0)
assert.Equal([]int{0, 1, 2, 3}, list.Data())
}
func TestInsertAtLast(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAtLast")
list := NewList([]int{1, 2, 3})
list.InsertAtLast(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
}
func TestInsertAt(t *testing.T) {
assert := internal.NewAssert(t, "TestInsertAt")
list := NewList([]int{1, 2, 3})
list.InsertAt(-1, 0)
assert.Equal([]int{1, 2, 3}, list.Data())
list.InsertAt(4, 0)
assert.Equal([]int{1, 2, 3}, list.Data())
list.InsertAt(0, 0)
assert.Equal([]int{0, 1, 2, 3}, list.Data())
list.InsertAt(4, 4)
assert.Equal([]int{0, 1, 2, 3, 4}, list.Data())
}
func TestPopFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestPopFirst")
list := NewList([]int{1, 2, 3})
v, ok := list.PopFirst()
assert.Equal(1, *v)
assert.Equal(true, ok)
assert.Equal([]int{2, 3}, list.Data())
list2 := NewList([]int{})
_, ok = list2.PopFirst()
assert.Equal(false, ok)
assert.Equal([]int{}, list2.Data())
}
func TestPopLast(t *testing.T) {
assert := internal.NewAssert(t, "TestPopLast")
list := NewList([]int{1, 2, 3})
v, ok := list.PopLast()
assert.Equal(3, *v)
assert.Equal(true, ok)
assert.Equal([]int{1, 2}, list.Data())
list2 := NewList([]int{})
_, ok = list2.PopLast()
assert.Equal(false, ok)
assert.Equal([]int{}, list2.Data())
}
func TestDeleteAt(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteAt")
list := NewList([]int{1, 2, 3, 4})
list.DeleteAt(-1)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.DeleteAt(4)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.DeleteAt(0)
assert.Equal([]int{2, 3, 4}, list.Data())
list.DeleteAt(2)
assert.Equal([]int{2, 3}, list.Data())
}
func TestUpdateAt(t *testing.T) {
assert := internal.NewAssert(t, "TestUpdateAt")
list := NewList([]int{1, 2, 3, 4})
list.UpdateAt(-1, 0)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.UpdateAt(4, 0)
assert.Equal([]int{1, 2, 3, 4}, list.Data())
list.UpdateAt(0, 5)
assert.Equal([]int{5, 2, 3, 4}, list.Data())
list.UpdateAt(3, 1)
assert.Equal([]int{5, 2, 3, 1}, list.Data())
}
func TestEqutal(t *testing.T) {
assert := internal.NewAssert(t, "TestEqutal")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
list3 := NewList([]int{1, 2, 3})
assert.Equal(true, list1.Equtal(list2))
assert.Equal(false, list1.Equtal(list3))
}
func TestIsEmpty(t *testing.T) {
assert := internal.NewAssert(t, "TestIsEmpty")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{})
assert.Equal(false, list1.IsEmpty())
assert.Equal(true, list2.IsEmpty())
}
func TestIsClear(t *testing.T) {
assert := internal.NewAssert(t, "TestIsClear")
list1 := NewList([]int{1, 2, 3, 4})
list1.Clear()
empty := NewList([]int{})
assert.Equal(empty, list1)
}
func TestClone(t *testing.T) {
assert := internal.NewAssert(t, "TestClone")
list1 := NewList([]int{1, 2, 3, 4})
list2 := list1.Clone()
assert.Equal(true, list1.Equtal(list2))
}
func TestMerge(t *testing.T) {
assert := internal.NewAssert(t, "TestMerge")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{1, 2, 3, 4, 4, 5, 6})
list3 := list1.Merge(list2)
assert.Equal(true, expected.Equtal(list3))
}
func TestSize(t *testing.T) {
assert := internal.NewAssert(t, "TestSize")
list := NewList([]int{1, 2, 3, 4})
empty := NewList([]int{})
assert.Equal(4, list.Size())
assert.Equal(0, empty.Size())
}
func TestSwap(t *testing.T) {
assert := internal.NewAssert(t, "TestSwap")
list := NewList([]int{1, 2, 3, 4})
expected := NewList([]int{4, 2, 3, 1})
list.Swap(0, 3)
assert.Equal(true, expected.Equtal(list))
}
func TestReverse(t *testing.T) {
assert := internal.NewAssert(t, "TestReverse")
list := NewList([]int{1, 2, 3, 4})
expected := NewList([]int{4, 3, 2, 1})
list.Reverse()
assert.Equal(true, expected.Equtal(list))
}
func TestUnique(t *testing.T) {
assert := internal.NewAssert(t, "TestUnique")
list := NewList([]int{1, 2, 2, 3, 4})
expected := NewList([]int{1, 2, 3, 4})
list.Unique()
assert.Equal(true, expected.Equtal(list))
}
func TestUnion(t *testing.T) {
assert := internal.NewAssert(t, "TestUnion")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{1, 2, 3, 4, 5, 6})
list3 := list1.Union(list2)
assert.Equal(true, expected.Equtal(list3))
}
func TestIntersection(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersection")
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{4, 5, 6})
expected := NewList([]int{4})
list3 := list1.Intersection(list2)
assert.Equal(true, expected.Equtal(list3))
}

51
datastructure/node.go Normal file
View File

@@ -0,0 +1,51 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
package datastructure
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.
type LinkNode[T any] struct {
Value T
Pre *LinkNode[T]
Next *LinkNode[T]
}
// NewLinkNode return a LinkNode pointer
func NewLinkNode[T any](value T) *LinkNode[T] {
return &LinkNode[T]{value, nil, nil}
}
// StackNode is a node in stack, which have a Value and Next pointer points to next node in the stack.
type StackNode[T any] struct {
Value T
Next *StackNode[T]
}
// NewStackNode return a StackNode pointer
func NewStackNode[T any](value T) *StackNode[T] {
return &StackNode[T]{value, nil}
}
// QueueNode is a node in a queue, which have a Value and Next pointer points to next node in the queue.
type QueueNode[T any] struct {
Value T
Next *QueueNode[T]
}
// NewQueueNode return a QueueNode pointer
func NewQueueNode[T any](value T) *QueueNode[T] {
return &QueueNode[T]{value, nil}
}
// TreeNode is node of tree
type TreeNode[T any] struct {
Value T
Left *TreeNode[T]
Right *TreeNode[T]
}
// NewTreeNode return a TreeNode pointer
func NewTreeNode[T any](val T) *TreeNode[T] {
return &TreeNode[T]{val, nil, nil}
}

View File

@@ -0,0 +1,114 @@
package datastructure
import (
"fmt"
"reflect"
)
// ArrayQueue implements queue with slice
type ArrayQueue[T any] struct {
items []T
head int
tail int
capacity int
size int
}
func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
return &ArrayQueue[T]{
items: make([]T, 0, capacity),
head: 0,
tail: 0,
capacity: capacity,
size: 0,
}
}
// Data return queue data
func (q *ArrayQueue[T]) Data() []T {
items := []T{}
for i := q.head; i < q.tail; i++ {
items = append(items, q.items[i])
}
return items
}
// Size return length of queue data
func (q *ArrayQueue[T]) Size() int {
return q.size
}
// IsEmpty checks if queue is empty or not
func (q *ArrayQueue[T]) IsEmpty() bool {
return q.size == 0
}
// Front return front value of queue
func (q *ArrayQueue[T]) Front() T {
return q.items[0]
}
// Back return back value of queue
func (q *ArrayQueue[T]) Back() T {
return q.items[q.size-1]
}
// EnQueue put element into queue
func (q *ArrayQueue[T]) Enqueue(item T) bool {
if q.head == 0 && q.tail == q.capacity {
return false
} else if q.head != 0 && q.tail == q.capacity {
for i := q.head; i < q.tail; i++ {
q.items[i-q.head] = q.items[i]
}
q.tail = q.tail - q.head
q.head = 0
}
q.items = append(q.items, item)
q.tail++
q.size++
return true
}
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *ArrayQueue[T]) Dequeue() (T, bool) {
var item T
if q.head == q.tail {
return item, false
}
item = q.items[q.head]
q.head++
q.size--
return item, true
}
// Clear the queue data
func (q *ArrayQueue[T]) Clear() {
capacity := q.capacity
q.items = make([]T, 0, capacity)
q.head = 0
q.tail = 0
q.size = 0
q.capacity = capacity
}
// Contain checks if the value is in queue or not
func (q *ArrayQueue[T]) Contain(value T) bool {
for _, v := range q.items {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Print queue data
func (q *ArrayQueue[T]) Print() {
info := "["
for i := q.head; i < q.tail; i++ {
info += fmt.Sprintf("%+v, ", q.items[i])
}
info += "]"
fmt.Println(info)
}

View File

@@ -0,0 +1,102 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestArrayQueue_Enqueue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
queue := NewArrayQueue[int](5)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
expected := []int{1, 2, 3}
data := queue.Data()
size := queue.Size()
queue.Print()
assert.Equal(expected, data)
assert.Equal(3, size)
}
func TestArrayQueue_Dequeue(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val, ok := queue.Dequeue()
assert.Equal(true, ok)
queue.Print()
assert.Equal(1, val)
assert.Equal([]int{2, 3}, queue.Data())
}
func TestArrayQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Front")
queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val := queue.Front()
queue.Print()
assert.Equal(1, val)
assert.Equal([]int{1, 2, 3}, queue.Data())
}
func TestArrayQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Back")
queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
val := queue.Back()
queue.Print()
assert.Equal(3, val)
assert.Equal([]int{1, 2, 3}, queue.Data())
}
func TestArrayQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
queue := NewArrayQueue[int](4)
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
assert.Equal(true, queue.Contain(1))
assert.Equal(false, queue.Contain(4))
}
func TestArrayQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int](4)
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size())
queue.Enqueue(1)
assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Size())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Size())
}

View File

@@ -0,0 +1,118 @@
package datastructure
import (
"errors"
"fmt"
"reflect"
)
// CircularQueue implements circular queue with slice,
// last index of CircularQueue don't contain value, so acturl capacity is size - 1
type CircularQueue[T any] struct {
data []T
front int
rear int
size int
}
// NewCircularQueue return a empty CircularQueue pointer
func NewCircularQueue[T any](size int) *CircularQueue[T] {
data := make([]T, size)
return &CircularQueue[T]{data: data, front: 0, rear: 0, size: size}
}
// Data return queue data
func (q *CircularQueue[T]) Data() []T {
data := []T{}
front := q.front
rear := q.rear
if front <= rear {
return q.data[front:rear]
}
data = append(data, q.data[front:]...)
data = append(data, q.data[0:rear]...)
return data
}
// Length return current data length of queue
func (q *CircularQueue[T]) Length() int {
if q.size == 0 {
return 0
}
return (q.rear - q.front + q.size) % q.size
}
// IsEmpty checks if queue is empty or not
func (q *CircularQueue[T]) IsEmpty() bool {
return q.front == q.rear
}
// IsFull checks if queue is full or not
func (q *CircularQueue[T]) IsFull() bool {
return (q.rear+1)%q.size == q.front
}
// Front return front value of queue
func (q *CircularQueue[T]) Front() T {
return q.data[q.front]
}
// Back return back value of queue
func (q *CircularQueue[T]) Back() T {
if q.rear-1 >= 0 {
return q.data[q.rear-1]
}
return q.data[q.size-1]
}
// EnQueue put element into queue
func (q *CircularQueue[T]) EnQueue(value T) error {
if q.IsFull() {
return errors.New("queue is full!")
}
q.data[q.rear] = value
q.rear = (q.rear + 1) % q.size
return nil
}
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *CircularQueue[T]) DeQueue() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
headItem := q.data[q.front]
var t T
q.data[q.front] = t
q.front = (q.front + 1) % q.size
return &headItem, nil
}
// Clear the queue data
func (q *CircularQueue[T]) Clear() {
q.data = []T{}
q.front = 0
q.rear = 0
q.size = 0
}
// Contain checks if the value is in queue or not
func (q *CircularQueue[T]) Contain(value T) bool {
for _, v := range q.data {
if reflect.DeepEqual(v, value) {
return true
}
}
return false
}
// Print queue data
func (q *CircularQueue[T]) Print() {
fmt.Printf("%+v\n", q)
}

View File

@@ -0,0 +1,148 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestCircularQueue_EnQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_EnQueue")
queue := NewCircularQueue[int](6)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.EnQueue(4)
queue.EnQueue(5)
queue.Print()
// assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
assert.Equal(5, queue.Length())
err := queue.EnQueue(6)
assert.IsNotNil(err)
}
func TestCircularQueue_DeQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
queue := NewCircularQueue[int](6)
assert.Equal(true, queue.IsEmpty())
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.EnQueue(4)
queue.EnQueue(5)
val, err := queue.DeQueue()
assert.IsNil(err)
assert.Equal(1, *val)
assert.Equal(false, queue.IsFull())
val, _ = queue.DeQueue()
queue.Print()
assert.Equal(2, *val)
queue.EnQueue(6)
queue.Print()
assert.Equal(false, queue.IsFull())
}
func TestCircularQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Front")
queue := NewCircularQueue[int](6)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.EnQueue(4)
queue.EnQueue(5)
queue.Print()
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
val := queue.Front()
assert.Equal(3, val)
assert.Equal(5, queue.Length())
}
func TestCircularQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Back")
queue := NewCircularQueue[int](6)
assert.Equal(true, queue.IsEmpty())
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.EnQueue(4)
queue.EnQueue(5)
queue.Print()
assert.Equal(5, queue.Back())
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
assert.Equal(7, queue.Back())
}
func TestCircularQueue_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
queue := NewCircularQueue[int](2)
queue.EnQueue(1)
assert.Equal(true, queue.Contain(1))
assert.Equal(false, queue.Contain(2))
}
func TestCircularQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
queue := NewCircularQueue[int](3)
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Length())
queue.EnQueue(1)
assert.Equal(false, queue.IsEmpty())
assert.Equal(1, queue.Length())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
assert.Equal(0, queue.Length())
}
func TestCircularQueue_Data(t *testing.T) {
assert := internal.NewAssert(t, "TestCircularQueue_Data")
queue := NewCircularQueue[int](6)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.EnQueue(4)
queue.EnQueue(5)
queue.Print()
assert.Equal([]int{1, 2, 3, 4, 5}, queue.Data())
queue.DeQueue()
queue.DeQueue()
queue.EnQueue(6)
queue.EnQueue(7)
queue.Print()
assert.Equal([]int{3, 4, 5, 6, 7}, queue.Data())
}

View File

@@ -0,0 +1,104 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// LinkedQueue implements queue with link list
type LinkedQueue[T any] struct {
head *datastructure.QueueNode[T]
tail *datastructure.QueueNode[T]
length int
}
// NewLinkedQueue return a empty LinkedQueue pointer
func NewLinkedQueue[T any]() *LinkedQueue[T] {
return &LinkedQueue[T]{head: nil, tail: nil, length: 0}
}
// Data return queue data
func (q *LinkedQueue[T]) Data() []T {
res := []T{}
current := q.head
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Size return length of queue data
func (q *LinkedQueue[T]) Size() int {
return q.length
}
// IsEmpty checks if queue is empty or not
func (q *LinkedQueue[T]) IsEmpty() bool {
return q.length == 0
}
// EnQueue add element into queue
func (q *LinkedQueue[T]) EnQueue(value T) {
newNode := datastructure.NewQueueNode(value)
if q.IsEmpty() {
q.head = newNode
q.tail = newNode
} else {
q.tail.Next = newNode
q.tail = newNode
}
q.length++
}
// DeQueue delete head element of queue then return it, if queue is empty, return nil and error
func (q *LinkedQueue[T]) DeQueue() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
head := q.head
q.head = q.head.Next
q.length--
return &head.Value, nil
}
// Front return front value of queue
func (q *LinkedQueue[T]) Front() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
return &q.head.Value, nil
}
// Back return back value of queue
func (q *LinkedQueue[T]) Back() (*T, error) {
if q.IsEmpty() {
return nil, errors.New("queue is empty")
}
return &q.tail.Value, nil
}
// Clear clear the queue data
func (q *LinkedQueue[T]) Clear() {
q.head = nil
q.tail = nil
q.length = 0
}
// Print all nodes info of queue link
func (q *LinkedQueue[T]) Print() {
current := q.head
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,84 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestLinkedQueue_EnQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_EnQueue")
queue := NewLinkedQueue[int]()
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
queue.Print()
assert.Equal([]int{1, 2, 3}, queue.Data())
assert.Equal(3, queue.Size())
}
func TestLinkedQueue_DeQueue(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
queue := NewLinkedQueue[int]()
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, _ := queue.DeQueue()
queue.Print()
assert.Equal([]int{2, 3}, queue.Data())
assert.Equal(1, *val)
}
func TestLinkedQueue_Front(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
queue := NewLinkedQueue[int]()
_, err := queue.Front()
assert.IsNotNil(err)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, err := queue.Front()
assert.Equal(1, *val)
assert.IsNil(err)
}
func TestLinkedQueue_Back(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
_, err := queue.Back()
assert.IsNotNil(err)
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
val, err := queue.Back()
assert.Equal(3, *val)
assert.IsNil(err)
}
func TestLinkedQueue_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
assert.Equal(true, queue.IsEmpty())
queue.EnQueue(1)
queue.EnQueue(2)
queue.EnQueue(3)
assert.Equal(false, queue.IsEmpty())
queue.Clear()
assert.Equal(true, queue.IsEmpty())
}

View File

@@ -0,0 +1,108 @@
package datastructure
import (
"errors"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// PriorityQueue is a priority queue implemented by binary heap tree
// type T should implements Compare function in lancetconstraints.Comparator interface.
type PriorityQueue[T any] struct {
items []T
size int
comparator lancetconstraints.Comparator
}
// NewPriorityQueue return a pointer of PriorityQueue
// param `comparator` is used to compare values in the queue
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T] {
return &PriorityQueue[T]{
items: make([]T, capacity+1),
size: 0,
comparator: comparator,
}
}
// IsEmpty checks if the queue is empty or not
func (q *PriorityQueue[T]) IsEmpty() bool {
return q.size == 0
}
// IsFull checks if the queue capacity is full or not
func (q *PriorityQueue[T]) IsFull() bool {
return q.size == len(q.items)-1
}
// Data return data slice in the queue
func (q *PriorityQueue[T]) Data() []T {
data := make([]T, q.size)
for i := 1; i < q.size+1; i++ {
data[i-1] = q.items[i]
}
return data
}
// Enqueue insert value into queue
func (q *PriorityQueue[T]) Enqueue(val T) error {
if q.IsFull() {
return errors.New("queue is already full.")
}
q.size++
q.items[q.size] = val
q.swim(q.size)
return nil
}
// Dequeue delete and return max value in queue
func (q *PriorityQueue[T]) Dequeue() (T, bool) {
var val T
if q.IsEmpty() {
return val, false
}
max := q.items[1]
q.swap(1, q.size)
q.size--
q.sink(1)
//set zero value for rest values of the queue
q.items[q.size+1] = val
return max, true
}
// swim when child's key is larger than parent's key, exchange them.
func (q *PriorityQueue[T]) swim(index int) {
for index > 1 && q.comparator.Compare(q.items[index/2], q.items[index]) < 0 {
q.swap(index, index/2)
index = index / 2
}
}
// sink when parent's key smaller than child's key, exchange parent's key with larger child's key.
func (q *PriorityQueue[T]) sink(index int) {
for 2*index <= q.size {
j := 2 * index
// get larger child node index
if j < q.size && q.comparator.Compare(q.items[j], q.items[j+1]) < 0 {
j++
}
// if parent larger than child, stop
if !(q.comparator.Compare(q.items[index], q.items[j]) < 0) {
break
}
q.swap(index, j)
index = j
}
}
// swap the two values at index i and j
func (q *PriorityQueue[T]) swap(i, j int) {
q.items[i], q.items[j] = q.items[j], q.items[i]
}

View File

@@ -0,0 +1,60 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
type intComparator struct{}
func (c *intComparator) Compare(v1, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
func TestPriorityQueue_Enqueue(t *testing.T) {
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
comparator := &intComparator{}
pq := NewPriorityQueue[int](10, comparator)
assert.Equal(true, pq.IsEmpty())
assert.Equal(false, pq.IsFull())
for i := 1; i < 11; i++ {
pq.Enqueue(i)
}
assert.Equal(true, pq.IsFull())
queueData := pq.Data()
assert.Equal([]int{10, 9, 6, 7, 8, 2, 5, 1, 4, 3}, queueData)
}
func TestPriorityQueue_Dequeue(t *testing.T) {
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
comparator := &intComparator{}
pq := NewPriorityQueue[int](10, comparator)
_, ok := pq.Dequeue()
assert.Equal(false, ok)
for i := 1; i < 11; i++ {
pq.Enqueue(i)
}
val, ok := pq.Dequeue()
assert.Equal(true, ok)
assert.Equal(10, val)
assert.Equal([]int{9, 8, 6, 7, 3, 2, 5, 1, 4}, pq.Data())
}

136
datastructure/set/set.go Normal file
View File

@@ -0,0 +1,136 @@
package datastructure
// Set is a data container, like slice, but element of set is not duplicate
type Set[T comparable] map[T]bool
// NewSet return a instance of set
func NewSet[T comparable](values ...T) Set[T] {
set := make(Set[T])
set.Add(values...)
return set
}
// Add value to set
func (s Set[T]) Add(values ...T) {
for _, v := range values {
s[v] = true
}
}
// Contain checks if set contains value or not
func (s Set[T]) Contain(value T) bool {
_, ok := s[value]
return ok
}
// Contain checks if set contains other set
func (s Set[T]) ContainAll(other Set[T]) bool {
for k := range other {
_, ok := s[k]
if !ok {
return false
}
}
return true
}
// Clone return a copy of set
func (s Set[T]) Clone() Set[T] {
set := NewSet[T]()
set.Add(s.Values()...)
return set
}
// Delete value of set
func (s Set[T]) Delete(values ...T) {
for _, v := range values {
delete(s, v)
}
}
// Equal checks if two set has same elements or not
func (s Set[T]) Equal(other Set[T]) bool {
if s.Size() != other.Size() {
return false
}
return s.ContainAll(other) && other.ContainAll(s)
}
// Iterate call function by every element of set
func (s Set[T]) Iterate(fn func(value T)) {
for v := range s {
fn(v)
}
}
// IsEmpty checks the set is empty or not
func (s Set[T]) IsEmpty() bool {
return len(s) == 0
}
// Size get the number of elements in set
func (s Set[T]) Size() int {
return len(s)
}
// Values return all values of set
func (s Set[T]) Values() []T {
values := make([]T, 0, 0)
s.Iterate(func(value T) {
values = append(values, value)
})
return values
}
// Union creates a new set contain all element of set s and other
func (s Set[T]) Union(other Set[T]) Set[T] {
set := s.Clone()
set.Add(other.Values()...)
return set
}
// Intersection creates a new set whose element both be contained in set s and other
func (s Set[T]) Intersection(other Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if other.Contain(value) {
set.Add(value)
}
})
return set
}
// SymmetricDifference creates a new set whose element is in set1 or set2, but not in both sets
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if !other.Contain(value) {
set.Add(value)
}
})
other.Iterate(func(value T) {
if !s.Contain(value) {
set.Add(value)
}
})
return set
}
// Minus creates an set of whose element in origin set but not in compared set
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
set := NewSet[T]()
s.Iterate(func(value T) {
if !comparedSet.Contain(value) {
set.Add(value)
}
})
return set
}

View File

@@ -0,0 +1,149 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestSet_Add(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Add")
set := NewSet[int]()
set.Add(1, 2, 3)
expected := NewSet(1, 2, 3)
assert.Equal(true, set.Equal(expected))
}
func TestSet_Contain(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Contain")
set := NewSet[int]()
set.Add(1, 2, 3)
assert.Equal(true, set.Contain(1))
assert.Equal(false, set.Contain(4))
}
func TestSet_ContainAll(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_ContainAll")
set1 := NewSet(1, 2, 3)
set2 := NewSet(1, 2)
set3 := NewSet(1, 2, 3, 4)
assert.Equal(true, set1.ContainAll(set2))
assert.Equal(false, set1.ContainAll(set3))
}
func TestSet_Clone(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Clone")
set1 := NewSet(1, 2, 3)
set2 := set1.Clone()
assert.Equal(true, set1.Size() == set2.Size())
assert.Equal(true, set1.ContainAll(set2))
}
func TestSet_Delete(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Delete")
set := NewSet[int]()
set.Add(1, 2, 3)
set.Delete(3)
expected := NewSet(1, 2)
assert.Equal(true, set.Equal(expected))
}
func TestSet_Equal(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Equal")
set1 := NewSet(1, 2, 3)
set2 := NewSet(1, 2, 3)
set3 := NewSet(1, 2, 3, 4)
assert.Equal(true, set1.Equal(set2))
assert.Equal(false, set1.Equal(set3))
}
func TestSet_Iterate(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Iterate")
set := NewSet(1, 2, 3)
arr := []int{}
set.Iterate(func(value int) {
arr = append(arr, value)
})
assert.Equal(3, len(arr))
}
func TestSet_IsEmpty(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_IsEmpty")
set := NewSet[int]()
assert.Equal(true, set.IsEmpty())
}
func TestSet_Size(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Size")
set := NewSet(1, 2, 3)
assert.Equal(3, set.Size())
}
func TestSet_Values(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Values")
set := NewSet(1, 2, 3)
values := set.Values()
assert.Equal(3, len(values))
}
func TestSet_Union(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Union")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(1, 2, 3, 4, 5)
unionSet := set1.Union(set2)
assert.Equal(expected, unionSet)
}
func TestSet_Intersection(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Intersection")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(2, 3)
intersectionSet := set1.Intersection(set2)
assert.Equal(expected, intersectionSet)
}
func TestSet_SymmetricDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
assert.Equal(NewSet(1, 4, 5), set1.SymmetricDifference(set2))
}
func TestSet_Minus(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_Minus")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
set3 := NewSet(2, 3)
assert.Equal(NewSet(1), set1.Minus(set2))
assert.Equal(NewSet(4, 5), set2.Minus(set3))
}

View File

@@ -0,0 +1,62 @@
package datastructure
import "errors"
// ArrayStack implements stack with slice
type ArrayStack[T any] struct {
data []T
length int
}
// NewArrayStack return a empty ArrayStack pointer
func NewArrayStack[T any]() *ArrayStack[T] {
return &ArrayStack[T]{data: []T{}, length: 0}
}
// Data return stack data
func (s *ArrayStack[T]) Data() []T {
return s.data
}
// Size return length of stack data
func (s *ArrayStack[T]) Size() int {
return s.length
}
// IsEmpty checks if stack is empty or not
func (s *ArrayStack[T]) IsEmpty() bool {
return s.length == 0
}
// Push element into stack
func (s *ArrayStack[T]) Push(value T) {
s.data = append([]T{value}, s.data...)
s.length++
}
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
func (s *ArrayStack[T]) Pop() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
topItem := s.data[0]
s.data = s.data[1:]
s.length--
return &topItem, nil
}
// Peak return the top element of stack then return it
func (s *ArrayStack[T]) Peak() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
return &s.data[0], nil
}
// Clear the stack data
func (s *ArrayStack[T]) Clear() {
s.data = []T{}
s.length = 0
}

View File

@@ -0,0 +1,77 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestArrayStack_Push(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Push")
stack := NewArrayStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data()
length := stack.Size()
assert.Equal(expected, values)
assert.Equal(3, length)
}
func TestArrayStack_Pop(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Pop")
stack := NewArrayStack[int]()
_, err := stack.Pop()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Pop()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
assert.Equal(expected, stack.Data())
}
func TestArrayStack_Peak(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Peak")
stack := NewArrayStack[int]()
_, err := stack.Peak()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Peak()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
}
func TestArrayStack_Clear(t *testing.T) {
assert := internal.NewAssert(t, "TestArrayStack_Clear")
stack := NewArrayStack[int]()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
stack.Push(1)
assert.Equal(false, stack.IsEmpty())
assert.Equal(1, stack.Size())
stack.Clear()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
}

View File

@@ -0,0 +1,94 @@
package datastructure
import (
"errors"
"fmt"
"github.com/duke-git/lancet/v2/datastructure"
)
// LinkedStack implements stack with link list
type LinkedStack[T any] struct {
top *datastructure.StackNode[T]
length int
}
// NewLinkedStack return a empty LinkedStack pointer
func NewLinkedStack[T any]() *LinkedStack[T] {
return &LinkedStack[T]{top: nil, length: 0}
}
// Data return stack data
func (s *LinkedStack[T]) Data() []T {
res := []T{}
current := s.top
for current != nil {
res = append(res, current.Value)
current = current.Next
}
return res
}
// Size return length of stack data
func (s *LinkedStack[T]) Size() int {
return s.length
}
// IsEmpty checks if stack is empty or not
func (s *LinkedStack[T]) IsEmpty() bool {
return s.length == 0
}
// Push element into stack
func (s *LinkedStack[T]) Push(value T) {
newNode := datastructure.NewStackNode(value)
top := s.top
if top == nil {
s.top = newNode
} else {
newNode.Next = top
s.top = newNode
}
s.length++
}
// Pop delete the top element of stack then return it, if stack is empty, return nil and error
func (s *LinkedStack[T]) Pop() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
top := s.top
s.top = s.top.Next
s.length--
return &top.Value, nil
}
// Peak return the top element of stack then return it
func (s *LinkedStack[T]) Peak() (*T, error) {
if s.IsEmpty() {
return nil, errors.New("stack is empty")
}
return &s.top.Value, nil
}
// Clear clear the stack data
func (s *LinkedStack[T]) Clear() {
s.top = nil
s.length = 0
}
// Print all nodes info of stack link
func (s *LinkedStack[T]) Print() {
current := s.top
info := "[ "
for current != nil {
info += fmt.Sprintf("%+v, ", current)
current = current.Next
}
info += " ]"
fmt.Println(info)
}

View File

@@ -0,0 +1,80 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestLinkedStack_Push(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Push")
stack := NewLinkedStack[int]()
stack.Push(1)
stack.Push(2)
stack.Push(3)
stack.Print()
expected := []int{3, 2, 1}
values := stack.Data()
size := stack.Size()
assert.Equal(expected, values)
assert.Equal(3, size)
}
func TestLinkedStack_Pop(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
stack := NewLinkedStack[int]()
_, err := stack.Pop()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Pop()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
stack.Print()
assert.Equal(expected, stack.Data())
}
func TestLinkedStack_Peak(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
stack := NewLinkedStack[int]()
_, err := stack.Peak()
assert.IsNotNil(err)
stack.Push(1)
stack.Push(2)
stack.Push(3)
topItem, err := stack.Peak()
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
}
func TestLinkedStack_Empty(t *testing.T) {
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
stack := NewLinkedStack[int]()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
stack.Push(1)
assert.Equal(false, stack.IsEmpty())
assert.Equal(1, stack.Size())
stack.Clear()
assert.Equal(true, stack.IsEmpty())
assert.Equal(0, stack.Size())
}

View File

@@ -0,0 +1,108 @@
package datastructure
import (
"math"
"github.com/duke-git/lancet/v2/datastructure"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
// BSTree is a binary search tree data structure in which each node has at most two children,
// which are referred to as the left child and the right child.
// In BSTree: leftNode < rootNode < rightNode
// type T should implements Compare function in lancetconstraints.Comparator interface.
type BSTree[T any] struct {
root *datastructure.TreeNode[T]
comparator lancetconstraints.Comparator
}
// NewBSTree create a BSTree pointer
// param `comparator` is used to compare values in the tree
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T] {
root := datastructure.NewTreeNode(rootData)
return &BSTree[T]{root, comparator}
}
// InsertNode insert data into BSTree
func (t *BSTree[T]) InsertNode(data T) {
root := t.root
newNode := datastructure.NewTreeNode(data)
if root == nil {
t.root = newNode
} else {
insertTreeNode(root, newNode, t.comparator)
}
}
// DeletetNode delete data into BSTree
func (t *BSTree[T]) DeletetNode(data T) {
deleteTreeNode(t.root, data, t.comparator)
}
// NodeLevel get node level in BSTree
func (t *BSTree[T]) NodeLevel(node *datastructure.TreeNode[T]) int {
if node == nil {
return 0
}
left := float64(t.NodeLevel(node.Left))
right := float64(t.NodeLevel(node.Right))
return int(math.Max(left, right)) + 1
}
// PreOrderTraverse traverse tree node in pre order
func (t *BSTree[T]) PreOrderTraverse() []T {
return preOrderTraverse(t.root)
}
// PostOrderTraverse traverse tree node in post order
func (t *BSTree[T]) PostOrderTraverse() []T {
return postOrderTraverse(t.root)
}
// InOrderTraverse traverse tree node in mid order
func (t *BSTree[T]) InOrderTraverse() []T {
return inOrderTraverse(t.root)
}
// LevelOrderTraverse traverse tree node in level order
func (t *BSTree[T]) LevelOrderTraverse() []T {
traversal := make([]T, 0)
levelOrderTraverse(t.root, &traversal)
return traversal
}
// Depth returns the calculated depth of a binary saerch tree
func (t *BSTree[T]) Depth() int {
return calculateDepth(t.root, 0)
}
// IsSubTree checks if the tree `t` has `subTree` or not
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool {
return hasSubTree(t.root, subTree.root, t.comparator)
}
func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T],
comparator lancetconstraints.Comparator) bool {
res := false
if superTreeRoot != nil && subTreeRoot != nil {
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) == 0 {
res = isSubTree(superTreeRoot, subTreeRoot, comparator)
}
if !res {
res = hasSubTree(superTreeRoot.Left, subTreeRoot, comparator)
}
if !res {
res = hasSubTree(superTreeRoot.Right, subTreeRoot, comparator)
}
}
return res
}
// Print the bstree structure
func (t *BSTree[T]) Print() {
maxLevel := t.NodeLevel(t.root)
nodes := []*datastructure.TreeNode[T]{t.root}
printTreeNodes(nodes, 1, maxLevel)
}

View File

@@ -0,0 +1,157 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
type intComparator struct{}
func (c *intComparator) Compare(v1, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
func TestBSTree_InsertNode(t *testing.T) {
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
bstree.Print()
}
func TestBSTree_PreOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
acturl := bstree.PreOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
}
func TestBSTree_PostOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
acturl := bstree.PostOrderTraverse()
t.Log(acturl)
assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
}
func TestBSTree_InOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
acturl := bstree.InOrderTraverse()
t.Log(acturl)
assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
}
func TestBSTree_LevelOrderTraverse(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
bstree.Print()
acturl := bstree.LevelOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
}
func TestBSTree_DeletetNode(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_DeletetNode")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
bstree.Print()
bstree.DeletetNode(4)
bstree.Print()
acturl1 := bstree.InOrderTraverse()
t.Log(acturl1)
assert.Equal([]int{2, 5, 6, 7}, acturl1)
//todo
// bstree.DeletetNode(6, comparator)
// bstree.Print()
// acturl2 := bstree.InOrderTraverse()
// t.Log(acturl2)
// assert.Equal([]int{2, 5, 7}, acturl2)
}
func TestBSTree_Depth(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_Depth")
bstree := NewBSTree(6, &intComparator{})
bstree.InsertNode(7)
bstree.InsertNode(5)
bstree.InsertNode(2)
bstree.InsertNode(4)
bstree.Print()
assert.Equal(bstree.Depth(), 4)
}
func TestBSTree_IsSubTree(t *testing.T) {
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
superTree := NewBSTree(8, &intComparator{})
superTree.InsertNode(4)
superTree.InsertNode(5)
superTree.InsertNode(6)
superTree.InsertNode(9)
superTree.InsertNode(4)
superTree.Print()
subTree := NewBSTree(5, &intComparator{})
subTree.InsertNode(4)
subTree.InsertNode(6)
subTree.Print()
assert.Equal(true, superTree.HasSubTree(subTree))
assert.Equal(false, subTree.HasSubTree(superTree))
}

View File

@@ -0,0 +1,238 @@
package datastructure
import (
"fmt"
"math"
"github.com/duke-git/lancet/v2/datastructure"
"github.com/duke-git/lancet/v2/lancetconstraints"
)
func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, node.Value)
data = append(data, preOrderTraverse(node.Left)...)
data = append(data, preOrderTraverse(node.Right)...)
}
return data
}
func postOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, preOrderTraverse(node.Left)...)
data = append(data, preOrderTraverse(node.Right)...)
data = append(data, node.Value)
}
return data
}
func inOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
data := []T{}
if node != nil {
data = append(data, inOrderTraverse(node.Left)...)
data = append(data, node.Value)
data = append(data, inOrderTraverse(node.Right)...)
}
return data
}
func preOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
fmt.Printf("%v, ", node.Value)
preOrderPrint(node.Left)
preOrderPrint(node.Right)
}
func postOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
preOrderPrint(node.Left)
preOrderPrint(node.Right)
fmt.Printf("%v, ", node.Value)
}
func inOrderPrint[T any](node *datastructure.TreeNode[T]) {
if node == nil {
return
}
inOrderPrint(node.Left)
fmt.Printf("%v, ", node.Value)
inOrderPrint(node.Right)
}
func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T) {
var q []*datastructure.TreeNode[T] // queue
var n *datastructure.TreeNode[T] // temp node
q = append(q, root)
for len(q) != 0 {
n, q = q[0], q[1:]
*traversal = append(*traversal, n.Value)
if n.Left != nil {
q = append(q, n.Left)
}
if n.Right != nil {
q = append(q, n.Right)
}
}
}
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) {
if comparator.Compare(newNode.Value, rootNode.Value) == -1 {
if rootNode.Left == nil {
rootNode.Left = newNode
} else {
insertTreeNode(rootNode.Left, newNode, comparator)
}
} else {
if rootNode.Right == nil {
rootNode.Right = newNode
} else {
insertTreeNode(rootNode.Right, newNode, comparator)
}
}
}
// todo, delete root node failed
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator lancetconstraints.Comparator) *datastructure.TreeNode[T] {
if node == nil {
return nil
}
if comparator.Compare(data, node.Value) == -1 {
node.Left = deleteTreeNode(node.Left, data, comparator)
} else if comparator.Compare(data, node.Value) == 1 {
node.Right = deleteTreeNode(node.Right, data, comparator)
} else {
if node.Left == nil {
node = node.Right
} else if node.Right == nil {
node = node.Left
} else {
l := node.Right
d := inOrderSuccessor(l)
d.Left = node.Left
return node.Right
}
}
return node
}
func inOrderSuccessor[T any](root *datastructure.TreeNode[T]) *datastructure.TreeNode[T] {
cur := root
for cur.Left != nil {
cur = cur.Left
}
return cur
}
func printTreeNodes[T any](nodes []*datastructure.TreeNode[T], level, maxLevel int) {
if len(nodes) == 0 || isAllNil(nodes) {
return
}
floor := maxLevel - level
endgeLines := int(math.Pow(float64(2), (math.Max(float64(floor)-1, 0))))
firstSpaces := int(math.Pow(float64(2), float64(floor))) - 1
betweenSpaces := int(math.Pow(float64(2), float64(floor)+1)) - 1
printSpaces(firstSpaces)
newNodes := []*datastructure.TreeNode[T]{}
for _, node := range nodes {
if node != nil {
fmt.Printf("%v", node.Value)
newNodes = append(newNodes, node.Left)
newNodes = append(newNodes, node.Right)
} else {
newNodes = append(newNodes, nil)
newNodes = append(newNodes, nil)
printSpaces(1)
}
printSpaces(betweenSpaces)
}
fmt.Println("")
for i := 1; i <= endgeLines; i++ {
for j := 0; j < len(nodes); j++ {
printSpaces(firstSpaces - i)
if nodes[j] == nil {
printSpaces(endgeLines + endgeLines + i + 1)
continue
}
if nodes[j].Left != nil {
fmt.Print("/")
} else {
printSpaces(1)
}
printSpaces(i + i - 1)
if nodes[j].Right != nil {
fmt.Print("\\")
} else {
printSpaces(1)
}
printSpaces(endgeLines + endgeLines - 1)
}
fmt.Println("")
}
printTreeNodes(newNodes, level+1, maxLevel)
}
// printSpaces
func printSpaces(n int) {
for i := 0; i < n; i++ {
fmt.Print(" ")
}
}
func isAllNil[T any](nodes []*datastructure.TreeNode[T]) bool {
for _, v := range nodes {
if v != nil {
return false
}
}
return true
}
func calculateDepth[T any](node *datastructure.TreeNode[T], depth int) int {
if node == nil {
return depth
}
return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1))
}
func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) bool {
if subTreeRoot == nil {
return true
}
if superTreeRoot == nil {
return false
}
if comparator.Compare(superTreeRoot.Value, subTreeRoot.Value) != 0 {
return false
}
res := isSubTree(superTreeRoot.Left, subTreeRoot.Left, comparator) && isSubTree(superTreeRoot.Right, subTreeRoot.Right, comparator)
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}

60
datetime/conversion.go Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license.
package datetime
import "time"
type theTime struct {
unix int64
}
// NewUnixNow return unix timestamp of current time
func NewUnixNow() *theTime {
return &theTime{unix: time.Now().Unix()}
}
// NewUnix return unix timestamp of specified time
func NewUnix(unix int64) *theTime {
return &theTime{unix: unix}
}
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss"
func NewFormat(t string) (*theTime, error) {
timeLayout := "2006-01-02 15:04:05"
loc := time.FixedZone("CST", 8*3600)
tt, err := time.ParseInLocation(timeLayout, t, loc)
if err != nil {
return nil, err
}
return &theTime{unix: tt.Unix()}, nil
}
// NewISO8601 return unix timestamp of specified iso8601 time string
func NewISO8601(iso8601 string) (*theTime, error) {
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
if err != nil {
return nil, err
}
return &theTime{unix: t.Unix()}, nil
}
// ToUnix return unix timestamp
func (t *theTime) ToUnix() int64 {
return t.unix
}
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time
func (t *theTime) ToFormat() string {
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
}
// ToFormatForTpl return the time string which format is specified tpl
func (t *theTime) ToFormatForTpl(tpl string) string {
return time.Unix(t.unix, 0).Format(tpl)
}
// ToFormatForTpl return iso8601 time string
func (t *theTime) ToIso8601() string {
return time.Unix(t.unix, 0).Format(time.RFC3339)
}

View File

@@ -0,0 +1,53 @@
package datetime
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestToUnix(t *testing.T) {
assert := internal.NewAssert(t, "TestToUnix")
tm1 := NewUnixNow()
unixTimestamp := tm1.ToUnix()
tm2 := NewUnix(unixTimestamp)
assert.Equal(tm1, tm2)
}
func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormat -> ", tm.ToFormat())
}
func TestToFormatForTpl(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormatForTpl")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
}
func TestToIso8601(t *testing.T) {
assert := internal.NewAssert(t, "TestToIso8601")
_, err := NewISO8601("2022-03-18 17:04:05")
assert.IsNotNil(err)
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
assert.IsNil(err)
t.Log("ToIso8601 -> ", tm.ToIso8601())
}

View File

@@ -4,7 +4,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAddDay(t *testing.T) { func TestAddDay(t *testing.T) {

598
docs/algorithm.md Normal file
View File

@@ -0,0 +1,598 @@
# Algorithm
Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div>
## Source
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
<div STYLE="page-break-after: always;"></div>
## Usage
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Algorithm](#algorithm)
- [Source](#source)
- [Usage](#usage)
- [Index](#index)
- [Documentation](#documentation)
- [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
- [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
- [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
- [<span id="ShellSort">ShellSort</span>](#shellsort)
- [<span id="QuickSort">QuickSort</span>](#quicksort)
- [<span id="HeapSort">HeapSort</span>](#heapsort)
- [<span id="MergeSort">MergeSort</span>](#mergesort)
- [<span id="CountSort">CountSort</span>](#countsort)
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
- [<span id="LRUCache">LRUCache</span>](#lrucache)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="BubbleSort">BubbleSort</span>
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
}
var peoples = []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator)
fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="ShellSort">ShellSort</span>
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="QuickSort">QuickSort</span>
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="HeapSort">HeapSort</span>
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="MergeSort">MergeSort</span>
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="CountSort">CountSort</span>
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b>
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>LinearSearch Simple linear search algorithm that iterates over all elements of an slice. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LRUCache">LRUCache</span>
<p>LRUCache implements mem cache with lru.</p>
<b>Signature:</b>
```go
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
cache := algorithm.NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
v, ok := cache.Get(1) // v->1, ok->true
}
```

598
docs/algorithm_zh-CN.md Normal file
View File

@@ -0,0 +1,598 @@
# Algorithm
algorithm算法包实现一些基本算法sortsearchlrucache。
<div STYLE="page-break-after: always;"></div>
## 源码
- [https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go](https://github.com/duke-git/lancet/blob/main/algorithm/sorter.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/search.go](https://github.com/duke-git/lancet/blob/main/algorithm/search.go)
- [https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go](https://github.com/duke-git/lancet/blob/main/algorithm/lru_cache.go)
<div STYLE="page-break-after: always;"></div>
## 用法
```go
import (
"github.com/duke-git/lancet/v2/algorithm"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Algorithm](#algorithm)
- [源码](#源码)
- [用法](#用法)
- [目录](#目录)
- [文档](#文档)
- [<span id="BubbleSort">BubbleSort</span>](#bubblesort)
- [<span id="InsertionSort">InsertionSort</span>](#insertionsort)
- [<span id="SelectionSort">SelectionSort</span>](#selectionsort)
- [<span id="ShellSort">ShellSort</span>](#shellsort)
- [<span id="QuickSort">QuickSort</span>](#quicksort)
- [<span id="HeapSort">HeapSort</span>](#heapsort)
- [<span id="MergeSort">MergeSort</span>](#mergesort)
- [<span id="CountSort">CountSort</span>](#countsort)
- [<span id="BinarySearch">BinarySearch</span>](#binarysearch)
- [<span id="BinaryIterativeSearch">BinaryIterativeSearch</span>](#binaryiterativesearch)
- [<span id="LinearSearch">LinearSearch</span>](#linearsearch)
- [<span id="LRUCache">LRUCache</span>](#lrucache)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="BubbleSort">BubbleSort</span>
<p>冒泡排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="InsertionSort">InsertionSort</span>
<p>插入排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type people struct {
Name string
Age int
}
// PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people)
p2, _ := v2.(people)
//ascending order
if p1.Age < p2.Age {
return -1
} else if p1.Age > p2.Age {
return 1
}
return 0
//decending order
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
}
var peoples = []people{
{Name: "a", Age: 20},
{Name: "b", Age: 10},
{Name: "c", Age: 17},
{Name: "d", Age: 8},
{Name: "e", Age: 28},
}
comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator)
fmt.Println(intSlice) //[{d 8} {b 10} {c 17} {a 20} {e 28}]
}
```
### <span id="SelectionSort">SelectionSort</span>
<p>选择排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="ShellSort">ShellSort</span>
<p>希尔排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="QuickSort">QuickSort</span>
<p>快速排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func QuickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.QuickSort(intSlice, 0, len(intSlice)-1, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="HeapSort">HeapSort</span>
<p>堆排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="MergeSort">MergeSort</span>
<p>归并排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="CountSort">CountSort</span>
<p>计数排序参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6}
}
```
### <span id="BinarySearch">BinarySearch</span>
<p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LinearSearch">LinearSearch</span>
<p>线性查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<b>函数签名:</b>
```go
func LinearSearch[T any](slice []T, target T, comparator lancetconstraints.Comparator) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int {
val1, _ := v1.(int)
val2, _ := v2.(int)
//ascending order
if val1 < val2 {
return -1
} else if val1 > val2 {
return 1
}
return 0
}
intSlice := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{}
foundIndex := algorithm.LinearSearch(intSlice, 5, comparator)
fmt.Println(foundIndex) //2
notFoundIndex := algorithm.LinearSearch(sortedNumbers, 0, comparator)
fmt.Println(notFoundIndex) //-1
}
```
### <span id="LRUCache">LRUCache</span>
<p>lru实现缓存</p>
<b>函数签名:</b>
```go
func NewLRUCache[K comparable, V any](capacity int) *LRUCache[K, V]
func (l *LRUCache[K, V]) Get(key K) (V, bool)
func (l *LRUCache[K, V]) Put(key K, value V)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/algorithm"
)
func main() {
cache := algorithm.NewLRUCache[int, int](2)
cache.Put(1, 1)
cache.Put(2, 2)
_, ok := cache.Get(0) // ok -> false
v, ok := cache.Get(1) // v->1, ok->true
}
```

390
docs/concurrency.md Normal file
View File

@@ -0,0 +1,390 @@
# Concurrency
Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, async.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/concurrency"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
### Channel
- [NewChannel](#NewChannel)
- [Bridge](#Bridge)
- [FanIn](#FanIn)
- [Generate](#Generate)
- [Or](#Or)
- [OrDone](#OrDone)
- [Repeat](#Repeat)
- [RepeatFn](#RepeatFn)
- [Take](#Take)
- [Tee](#Tee)
<div STYLE="page-break-after: always;"></div>
## Documentation
## Channel
### <span id="NewChannel">NewChannel</span>
<p>return a Channel pointer instance.</p>
<b>Signature:</b>
```go
type Channel struct {}
func NewChannel() *Channel
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
c := concurrency.NewChannel()
}
```
### <span id="Bridge">Bridge</span>
<p>Link multiple channels into one channel until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
stream <- i
close(stream)
chanStream <- stream
}
}()
return chanStream
}
index := 0
for val := range c.Bridge(ctx, genVals()) {
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
}
}
```
### <span id="FanIn">FanIn</span>
<p>merge multiple channels into one channel until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
channels := make([]<-chan any, 3)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
}
mergedChannel := c.FanIn(ctx, channels...)
for val := range mergedChannel {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure)
}
}
```
### <span id="Repeat">Repeat</span>
<p>Return a chan, put param `values` into the chan repeatly until cancel the context.</p>
<b>Signature:</b>
```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1
}
}
```
### <span id="RepeatFn">RepeatFn</span>
<p>Return a chan, excutes fn repeatly, and put the result into retruned chan until cancel context.</p>
<b>Signature:</b>
```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
}
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream {
fmt.Println(v) //a, a, a
}
}
```
### <span id="Or">Or</span>
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
<b>Signature:</b>
```go
func (c *Channel) Or(channels ...<-chan any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
sig := func(after time.Duration) <-chan any {
c := make(chan interface{})
go func() {
defer close(c)
time.Sleep(after)
}()
return c
}
start := time.Now()
c := concurrency.NewChannel()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
)
fmt.Println("done after %v", time.Since(start)) //1.003s
}
```
### <span id="OrDone">OrDone</span>
<p>Read a channel into another channel, will close until cancel context.</p>
<b>Signature:</b>
```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1
}
}
```
### <span id="Take">Take</span>
<p>Return a chan whose values are tahken from another chan until cancel context.</p>
<b>Signature:</b>
```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers <- 1
numbers <- 2
numbers <- 3
numbers <- 4
numbers <- 5
defer close(numbers)
c := concurrency.NewChannel()
intStream := c.Take(ctx, numbers, 3)
for val := range intStream {
fmt.Println(val) //1, 2, 3
}
}
```
### <span id="Tee">Tee</span>
<p>Split one chanel into two channels until cancel context.</p>
<b>Signature:</b>
```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any)
```
<b>Example:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
fmt.Println(val) //1
fmt.Println(<-out2) //1
}
}
```

390
docs/concurrency_zh-CN.md Normal file
View File

@@ -0,0 +1,390 @@
# Concurrency
并发包包含一些支持并发编程的功能。例如goroutine, channel, async等。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/concurrency"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
### Channel
- [NewChannel](#NewChannel)
- [Bridge](#Bridge)
- [FanIn](#FanIn)
- [Generate](#Generate)
- [Or](#Or)
- [OrDone](#OrDone)
- [Repeat](#Repeat)
- [RepeatFn](#RepeatFn)
- [Take](#Take)
- [Tee](#Tee)
<div STYLE="page-break-after: always;"></div>
## 文档
### Channel
### <span id="NewChannel">NewChannel</span>
<p>返回一个 Channel 指针实例</p>
<b>函数签名:</b>
```go
type Channel struct {}
func NewChannel() *Channel
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
c := concurrency.NewChannel()
}
```
### <span id="Bridge">Bridge</span>
<p>将多个通道链接到一个通道,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Bridge(ctx context.Context, chanStream <-chan <-chan any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
genVals := func() <-chan <-chan any {
chanStream := make(chan (<-chan any))
go func() {
defer close(chanStream)
for i := 0; i < 10; i++ {
stream := make(chan any, 1)
stream <- i
close(stream)
chanStream <- stream
}
}()
return chanStream
}
index := 0
for val := range c.Bridge(ctx, genVals()) {
fmt.Printf("%v ", val) //0 1 2 3 4 5 6 7 8 9
}
}
```
### <span id="FanIn">FanIn</span>
<p>将多个通道合并为一个通道,直到取消上下文</p>
<b>函数签名:</b>
```go
func (c *Channel) FanIn(ctx context.Context, channels ...<-chan any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
channels := make([]<-chan any, 3)
for i := 0; i < 3; i++ {
channels[i] = c.Take(ctx, c.Repeat(ctx, i), 3)
}
mergedChannel := c.FanIn(ctx, channels...)
for val := range mergedChannel {
fmt.Println("\t%d\n", val) //1,2,1,0,0,1,0,2,2 (order not for sure)
}
}
```
### <span id="Repeat">Repeat</span>
<p>返回一个chan将参数`values`重复放入chan直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Repeat(ctx context.Context, values ...any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 5)
for v := range intStream {
fmt.Println(v) //1, 2, 1, 2, 1
}
}
```
### <span id="RepeatFn">RepeatFn</span>
<p>返回一个chan重复执行函数fn并将结果放入返回的chan直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) RepeatFn(ctx context.Context, fn func() any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func() any {
s := "a"
return s
}
c := concurrency.NewChannel()
dataStream := c.Take(ctx, c.RepeatFn(ctx, fn), 3)
for v := range dataStream {
fmt.Println(v) //a, a, a
}
}
```
### <span id="Or">Or</span>
<p>将一个或多个通道读取到一个通道中,当任何读取通道关闭时将结束读取。</p>
<b>函数签名:</b>
```go
func (c *Channel) Or(channels ...<-chan any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
sig := func(after time.Duration) <-chan any {
c := make(chan interface{})
go func() {
defer close(c)
time.Sleep(after)
}()
return c
}
start := time.Now()
c := concurrency.NewChannel()
<-c.Or(
sig(1*time.Second),
sig(2*time.Second),
sig(3*time.Second),
sig(4*time.Second),
sig(5*time.Second),
)
fmt.Println("done after %v", time.Since(start)) //1.003s
}
```
### <span id="OrDone">OrDone</span>
<p>将一个通道读入另一个通道,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) OrDone(ctx context.Context, channel <-chan any) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
intStream := c.Take(ctx, c.Repeat(ctx, 1), 3)
for val := range c.OrDone(ctx, intStream) {
fmt.Println(val) //1
}
}
```
### <span id="Take">Take</span>
<p>返回一个chan其值从另一个chan获取直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Take(ctx context.Context, valueStream <-chan any, number int) <-chan any
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
numbers := make(chan any, 5)
numbers <- 1
numbers <- 2
numbers <- 3
numbers <- 4
numbers <- 5
defer close(numbers)
c := concurrency.NewChannel()
intStream := c.Take(ctx, numbers, 3)
for val := range intStream {
fmt.Println(val) //1, 2, 3
}
}
```
### <span id="Tee">Tee</span>
<p>将一个通道分成两个通道,直到取消上下文。</p>
<b>函数签名:</b>
```go
func (c *Channel) Tee(ctx context.Context, in <-chan any) (<-chan any, <-chan any)
```
<b>例子:</b>
```go
package main
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/concurrency"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
c := concurrency.NewChannel()
inStream := c.Take(ctx, c.Repeat(ctx, 1, 2), 4)
out1, out2 := c.Tee(ctx, inStream)
for val := range out1 {
fmt.Println(val) //1
fmt.Println(<-out2) //1
}
}
```

View File

@@ -5,14 +5,14 @@ Package convertor contains some functions for data type convertion.
## 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/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
``` ```
@@ -50,12 +50,12 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
colorHex := "#003366" colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex) r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102 fmt.Println(r, g, b) //0,51,102
} }
``` ```
@@ -78,14 +78,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
r := 0 r := 0
g := 51 g := 51
b := 102 b := 102
colorHex := ColorRGBToHex(r, g, b) colorHex := convertor.ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366 fmt.Println(colorHex) //#003366
} }
@@ -109,7 +109,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -136,7 +136,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ToBytes(data interface{}) ([]byte, error) func ToBytes(data any) ([]byte, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -145,7 +145,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -175,7 +175,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -199,7 +199,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ToFloat(value interface{}) (float64, error) func ToFloat(value any) (float64, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -208,7 +208,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -232,7 +232,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ToInt(value interface{}) (int64, error) func ToInt(value any) (int64, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -241,7 +241,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -265,7 +265,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ToJson(value interface{}) (string, error) func ToJson(value any) (string, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -274,7 +274,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -293,7 +293,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ToString(value interface{}) string func ToString(value any) string
``` ```
<b>Example:</b> <b>Example:</b>
@@ -302,7 +302,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -321,7 +321,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func StructToMap(value interface{}) (map[string]interface{}, error) func StructToMap(value any) (map[string]any, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -330,7 +330,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ convertor转换器包支持一些常见的数据类型转换
## 源码: ## 源码:
[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>
@@ -13,7 +13,7 @@ convertor转换器包支持一些常见的数据类型转换
```go ```go
import ( import (
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
``` ```
@@ -52,12 +52,12 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
colorHex := "#003366" colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex) r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102 fmt.Println(r, g, b) //0,51,102
} }
``` ```
@@ -80,14 +80,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
r := 0 r := 0
g := 51 g := 51
b := 102 b := 102
colorHex := ColorRGBToHex(r, g, b) colorHex := convertor.ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366 fmt.Println(colorHex) //#003366
} }
@@ -111,7 +111,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -138,7 +138,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToBytes(data interface{}) ([]byte, error) func ToBytes(data any) ([]byte, error)
``` ```
<b>列子:</b> <b>列子:</b>
@@ -147,7 +147,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -177,7 +177,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -201,7 +201,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToFloat(value interface{}) (float64, error) func ToFloat(value any) (float64, error)
``` ```
<b>列子:</b> <b>列子:</b>
@@ -210,7 +210,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -234,7 +234,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToInt(value interface{}) (int64, error) func ToInt(value any) (int64, error)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -243,7 +243,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -267,7 +267,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToJson(value interface{}) (string, error) func ToJson(value any) (string, error)
``` ```
<b>列子:</b> <b>列子:</b>
@@ -276,7 +276,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -295,7 +295,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToString(value interface{}) string func ToString(value any) string
``` ```
<b>例子:</b> <b>例子:</b>
@@ -304,7 +304,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {
@@ -323,7 +323,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func StructToMap(value interface{}) (map[string]interface{}, error) func StructToMap(value any) (map[string]any, error)
``` ```
<b>列子:</b> <b>列子:</b>
@@ -332,7 +332,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/convertor" "github.com/duke-git/lancet/v2/convertor"
) )
func main() { func main() {

View File

@@ -15,7 +15,7 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
``` ```
@@ -80,7 +80,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -110,7 +110,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -140,7 +140,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -171,7 +171,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -202,7 +202,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -234,7 +234,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -264,7 +264,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -295,7 +295,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -325,7 +325,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -356,7 +356,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -384,7 +384,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -412,7 +412,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -443,7 +443,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -475,7 +475,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -506,7 +506,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -538,7 +538,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -570,7 +570,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -600,7 +600,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -631,7 +631,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -661,7 +661,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -693,7 +693,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -721,7 +721,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -749,7 +749,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -777,7 +777,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -806,7 +806,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -834,7 +834,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -862,7 +862,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -890,7 +890,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -918,7 +918,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -946,7 +946,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -976,7 +976,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -1012,7 +1012,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {

View File

@@ -15,7 +15,7 @@ cryptor加密包支持数据加密和解密获取md5hash值。支持base64
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
``` ```
@@ -80,7 +80,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -110,7 +110,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -140,7 +140,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -171,7 +171,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -203,7 +203,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -235,7 +235,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -265,7 +265,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -296,7 +296,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -326,7 +326,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -356,7 +356,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -384,7 +384,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -412,7 +412,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -443,7 +443,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -475,7 +475,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -506,7 +506,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -538,7 +538,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -570,7 +570,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -600,7 +600,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -631,7 +631,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -661,7 +661,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -692,7 +692,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -720,7 +720,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -748,7 +748,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -776,7 +776,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -805,7 +805,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -833,7 +833,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -861,7 +861,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -889,7 +889,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -917,7 +917,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -945,7 +945,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -975,7 +975,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {
@@ -1009,7 +1009,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/cryptor" "github.com/duke-git/lancet/v2/cryptor"
) )
func main() { func main() {

View File

@@ -5,14 +5,15 @@ Package datetime supports date and time format and compare.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go) - [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
- [https://github.com/duke-git/lancet/blob/main/datetime/conversion.go](https://github.com/duke-git/lancet/blob/main/datetime/conversion.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/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
``` ```
@@ -28,7 +29,6 @@ import (
- [BeginOfWeek](#BeginOfWeek) - [BeginOfWeek](#BeginOfWeek)
- [BeginOfMonth](#BeginOfMonth) - [BeginOfMonth](#BeginOfMonth)
- [BeginOfYear](#BeginOfYear) - [BeginOfYear](#BeginOfYear)
- [EndOfMinute](#EndOfMinute) - [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour) - [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay) - [EndOfDay](#EndOfDay)
@@ -41,9 +41,19 @@ import (
- [GetZeroHourTimestamp](#GetZeroHourTimestamp) - [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp) - [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr) - [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime) - [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
@@ -86,7 +96,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -115,7 +125,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -143,7 +153,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -171,7 +181,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -197,7 +207,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -223,7 +233,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -251,7 +261,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -279,7 +289,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -306,7 +316,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -334,7 +344,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -360,7 +370,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -386,7 +396,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -414,7 +424,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -442,7 +452,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -469,7 +479,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -496,7 +506,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -523,7 +533,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -550,7 +560,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -577,7 +587,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -604,7 +614,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -630,7 +640,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -656,7 +666,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -667,3 +677,221 @@ func main() {
### <span id="NewUnixNow">NewUnixNow</span>
<p>Return unix timestamp of current time</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>Return unix timestamp of specified int64 value.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>Return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>Return unix timestamp of specified iso8601 time string.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>Return unix timestamp.</p>
<b>Signature:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>Return time string 'yyyy-mm-dd hh:mm:ss'.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormat() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>Return the time string which format is specified tpl.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>Return iso8601 time string.</p>
<b>Signature:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,14 +5,14 @@ datetime日期时间处理包格式化日期比较日期。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go) - [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
``` ```
@@ -28,7 +28,6 @@ import (
- [BeginOfWeek](#BeginOfWeek) - [BeginOfWeek](#BeginOfWeek)
- [BeginOfMonth](#BeginOfMonth) - [BeginOfMonth](#BeginOfMonth)
- [BeginOfYear](#BeginOfYear) - [BeginOfYear](#BeginOfYear)
- [EndOfMinute](#EndOfMinute) - [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour) - [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay) - [EndOfDay](#EndOfDay)
@@ -43,6 +42,15 @@ import (
- [FormatTimeToStr](#FormatTimeToStr) - [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime) - [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
@@ -85,7 +93,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -114,7 +122,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -142,7 +150,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -170,7 +178,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -196,7 +204,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -222,7 +230,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -250,7 +258,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -278,7 +286,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -305,7 +313,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -333,7 +341,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -359,7 +367,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -385,7 +393,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -413,7 +421,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -441,7 +449,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -468,7 +476,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -495,7 +503,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -522,7 +530,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -549,7 +557,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -576,7 +584,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -603,7 +611,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -629,7 +637,7 @@ package main
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -655,7 +663,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
@@ -665,4 +673,221 @@ func main() {
``` ```
### <span id="NewUnixNow">NewUnixNow</span>
<p>创建一个当前时间的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>创建一个unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>创建一个iso8601格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>返回unix时间戳</p>
<b>函数签名:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormat() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>返回tpl格式指定的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>返回iso8601日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,14 +5,14 @@ Package fileutil implements some basic functions for file operations.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go) - [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
``` ```
@@ -56,7 +56,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -82,7 +82,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -107,7 +107,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -135,7 +135,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -155,7 +155,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func MiMeType(file interface{}) string func MiMeType(file any) string
``` ```
<b>Example:</b> <b>Example:</b>
@@ -165,7 +165,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -196,7 +196,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -223,7 +223,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -249,7 +249,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -278,7 +278,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -304,7 +304,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -332,7 +332,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -365,7 +365,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -398,7 +398,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -427,7 +427,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {

View File

@@ -5,14 +5,14 @@ fileutil包支持文件基本操作。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go) - [https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
``` ```
@@ -56,7 +56,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -82,7 +82,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -107,7 +107,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -135,7 +135,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -155,7 +155,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func MiMeType(file interface{}) string func MiMeType(file any) string
``` ```
<b>例子:</b> <b>例子:</b>
@@ -165,7 +165,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -196,7 +196,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -223,7 +223,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -249,7 +249,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -278,7 +278,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -304,7 +304,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -332,7 +332,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -365,7 +365,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -398,7 +398,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {
@@ -427,7 +427,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/fileutil" "github.com/duke-git/lancet/v2/fileutil"
) )
func main() { func main() {

View File

@@ -5,14 +5,14 @@ formatter contains some functions for data formatting.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go) - [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.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/formatter" "github.com/duke-git/lancet/v2/formatter"
) )
``` ```
@@ -34,7 +34,7 @@ Param should be number or numberic string.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Comma(v interface{}, symbol string) string func Comma(v any, symbol string) string
``` ```
<b>Example:</b> <b>Example:</b>
@@ -43,7 +43,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/formatter" "github.com/duke-git/lancet/v2/formatter"
) )
func main() { func main() {

View File

@@ -5,14 +5,14 @@ formatter格式化器包含一些数据格式化处理方法。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go) - [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/formatter" "github.com/duke-git/lancet/v2/formatter"
) )
``` ```
@@ -33,7 +33,7 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Comma(v interface{}, symbol string) string func Comma(v any, symbol string) string
``` ```
<b>例子:</b> <b>例子:</b>
@@ -42,7 +42,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/formatter" "github.com/duke-git/lancet/v2/formatter"
) )
func main() { func main() {

View File

@@ -5,15 +5,15 @@ Package function can control the flow of function execution and support part of
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go) - [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go) - [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
``` ```
@@ -40,7 +40,7 @@ import (
<b>Signature:</b> <b>Signature:</b>
```go ```go
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value func After(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>Example:</b> <b>Example:</b>
@@ -49,7 +49,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -59,7 +59,7 @@ func main() {
return i return i
}) })
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) { print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s) fmt.Printf("arr[%d] is %s \n", i, s)
fn(i) fn(i)
@@ -87,7 +87,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value func Before(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>Example:</b> <b>Example:</b>
@@ -96,8 +96,8 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func main() { func main() {
@@ -109,7 +109,7 @@ func main() {
}) })
var res []int64 var res []int64
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) { appendStr := func(i int, s string, fn cb) {
v := fn(i) v := fn(i)
res = append(res, v[0].Int()) res = append(res, v[0].Int())
@@ -133,8 +133,8 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
type Fn func(...interface{}) interface{} type Fn func(...any) any
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} func (f Fn) Curry(i any) func(...any) any
``` ```
<b>Example:</b> <b>Example:</b>
@@ -143,14 +143,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
add := func(a, b int) int { add := func(a, b int) int {
return a + b return a + b
} }
var addCurry function.Fn = func(values ...interface{}) interface{} { var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int)) return add(values[0].(int), values[1].(int))
} }
add1 := addCurry.Curry(1) add1 := addCurry.Curry(1)
@@ -168,7 +168,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} func Compose(fnList ...func(...any) any) func(...any) any
``` ```
<b>Example:</b> <b>Example:</b>
@@ -177,14 +177,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
add1 := func(v ...interface{}) interface{} { add1 := func(v ...any) any {
return v[0].(int) + 1 return v[0].(int) + 1
} }
add2 := func(v ...interface{}) interface{} { add2 := func(v ...any) any {
return v[0].(int) + 2 return v[0].(int) + 2
} }
@@ -213,7 +213,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -246,7 +246,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Delay(delay time.Duration, fn interface{}, args ...interface{}) func Delay(delay time.Duration, fn any, args ...any)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -255,7 +255,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -275,7 +275,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool func Schedule(d time.Duration, fn any, args ...any) chan bool
``` ```
<b>Example:</b> <b>Example:</b>
@@ -284,7 +284,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -327,7 +327,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {

View File

@@ -5,15 +5,15 @@ function函数包控制函数执行流程包含部分函数式编程。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go) - [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go) - [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
``` ```
@@ -40,7 +40,7 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value func After(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例子:</b> <b>例子:</b>
@@ -49,7 +49,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -59,7 +59,7 @@ func main() {
return i return i
}) })
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) { print := func(i int, s string, fn cb) {
fmt.Printf("arr[%d] is %s \n", i, s) fmt.Printf("arr[%d] is %s \n", i, s)
fn(i) fn(i)
@@ -87,7 +87,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value func Before(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例子:</b> <b>例子:</b>
@@ -96,8 +96,8 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func main() { func main() {
@@ -109,7 +109,7 @@ func main() {
}) })
var res []int64 var res []int64
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) { appendStr := func(i int, s string, fn cb) {
v := fn(i) v := fn(i)
res = append(res, v[0].Int()) res = append(res, v[0].Int())
@@ -133,8 +133,8 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
type Fn func(...interface{}) interface{} type Fn func(...any) any
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} func (f Fn) Curry(i any) func(...any) any
``` ```
<b>例子:</b> <b>例子:</b>
@@ -143,14 +143,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
add := func(a, b int) int { add := func(a, b int) int {
return a + b return a + b
} }
var addCurry function.Fn = func(values ...interface{}) interface{} { var addCurry function.Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int)) return add(values[0].(int), values[1].(int))
} }
add1 := addCurry.Curry(1) add1 := addCurry.Curry(1)
@@ -168,7 +168,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} func Compose(fnList ...func(...any) any) func(...any) any
``` ```
<b>例子:</b> <b>例子:</b>
@@ -177,14 +177,14 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
add1 := func(v ...interface{}) interface{} { add1 := func(v ...any) any {
return v[0].(int) + 1 return v[0].(int) + 1
} }
add2 := func(v ...interface{}) interface{} { add2 := func(v ...any) any {
return v[0].(int) + 2 return v[0].(int) + 2
} }
@@ -213,7 +213,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -246,7 +246,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Delay(delay time.Duration, fn interface{}, args ...interface{}) func Delay(delay time.Duration, fn any, args ...any)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -255,7 +255,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -275,7 +275,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool func Schedule(d time.Duration, fn any, args ...any) chan bool
``` ```
<b>例子:</b> <b>例子:</b>
@@ -284,7 +284,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {
@@ -327,7 +327,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/function" "github.com/duke-git/lancet/v2/function"
) )
func main() { func main() {

304
docs/maputil.md Normal file
View File

@@ -0,0 +1,304 @@
# 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/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.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)
<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) // 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
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"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,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"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) // []int{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",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
}
```
### <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,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"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) // []string{"a", "a", "b", "c", "d"}
}
```

304
docs/maputil_zh-CN.md Normal file
View File

@@ -0,0 +1,304 @@
# Maputil
maputil包包括一些操作map的函数。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.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)
<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) // 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
})
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"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,
}
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"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) // []int{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",
}
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
}
```
### <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,
}
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"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)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
}
```

View File

@@ -5,7 +5,7 @@ Package mathutil implements some functions for math calculation.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go) - [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> <div STYLE="page-break-after: always;"></div>
@@ -13,16 +13,22 @@ Package mathutil implements some functions for math calculation.
## Example: ## Example:
```go ```go
import ( import (
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
``` ```
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Average](#Average)
- [Exponent](#Exponent) - [Exponent](#Exponent)
- [Fibonacci](#Fibonacci) - [Fibonacci](#Fibonacci)
- [Factorial](#Factorial) - [Factorial](#Factorial)
- [Max](#Max)
- [MaxBy](#MaxBy)
- [Min](#Min)
- [MinBy](#MaxBy)
- [Percent](#Percent) - [Percent](#Percent)
- [RoundToFloat](#RoundToFloat) - [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString) - [RoundToString](#RoundToString)
@@ -33,6 +39,35 @@ import (
## Documentation ## 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 lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
}
```
### <span id="Exponent">Exponent</span> ### <span id="Exponent">Exponent</span>
<p>Calculate x to the nth power.</p> <p>Calculate x to the nth power.</p>
@@ -48,7 +83,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -75,7 +110,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -104,7 +139,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -117,6 +152,138 @@ func main() {
### <span id="Max">Max</span>
<p>Return max value of numbers.</p>
<b>Signature:</b>
```go
func Max[T lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //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() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res3) //“”
}
```
### <span id="Min">Min</span>
<p>Return min value of numbers.</p>
<b>Signature:</b>
```go
func Min[T lancetconstraints.Number](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //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() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res3) //“”
}
```
### <span id="Percent">Percent</span> ### <span id="Percent">Percent</span>
<p>calculate the percentage of val to total, retain n decimal places.</p> <p>calculate the percentage of val to total, retain n decimal places.</p>
@@ -132,7 +299,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -158,7 +325,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -188,7 +355,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -217,7 +384,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ mathutil包实现了一些数学计算的函数.
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go) - [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> <div STYLE="page-break-after: always;"></div>
@@ -13,16 +13,21 @@ mathutil包实现了一些数学计算的函数.
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
``` ```
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Average](#Average)
- [Exponent](#Exponent) - [Exponent](#Exponent)
- [Fibonacci](#Fibonacci) - [Fibonacci](#Fibonacci)
- [Factorial](#Factorial) - [Factorial](#Factorial)
- [Max](#Max)
- [MaxBy](#MaxBy)
- [Min](#Min)
- [MinBy](#MaxBy)
- [Percent](#Percent) - [Percent](#Percent)
- [RoundToFloat](#RoundToFloat) - [RoundToFloat](#RoundToFloat)
@@ -34,6 +39,33 @@ import (
## Documentation ## Documentation
### <span id="Average">Average</span>
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
<b>函数签名:</b>
```go
func Average[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Average(0, 0)) //0
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3
}
```
### <span id="Exponent">Exponent</span> ### <span id="Exponent">Exponent</span>
<p>指数计算x的n次方</p> <p>指数计算x的n次方</p>
@@ -49,7 +81,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -76,7 +108,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -105,7 +137,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -117,6 +149,137 @@ func main() {
``` ```
### <span id="Max">Max</span>
<p>返回参数中的最大数</p>
<b>函数签名:</b>
```go
func Max[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Max(0, 0)) //0
fmt.Println(mathutil.Max(1, 2, 3)) //3
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //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() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
fmt.Println(res3) //“”
}
```
### <span id="Min">Min</span>
<p>返回参数中的最小数</p>
<b>函数签名:</b>
```go
func Min[T lancetconstraints.Number](numbers ...T) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
fmt.Println(mathutil.Min(0, 0)) //0
fmt.Println(mathutil.Min(1, 2, 3)) //1
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //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() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
fmt.Println(res3) //“”
}
```
### <span id="Percent">Percent</span> ### <span id="Percent">Percent</span>
<p>计算百分比保留n位小数</p> <p>计算百分比保留n位小数</p>
@@ -133,7 +296,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -159,7 +322,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -189,7 +352,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {
@@ -218,7 +381,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/mathutil" "github.com/duke-git/lancet/v2/mathutil"
) )
func main() { func main() {

View File

@@ -5,16 +5,16 @@ Package netutil contains functions to get net information and send http request.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go) - [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.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/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
``` ```
@@ -46,7 +46,7 @@ import (
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ConvertMapToQueryString(param map[string]interface{}) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>Example:</b> <b>Example:</b>
@@ -55,11 +55,11 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
var m = map[string]interface{}{ var m = map[string]any{
"c": 3, "c": 3,
"a": 1, "a": 1,
"b": 2, "b": 2,
@@ -88,7 +88,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -117,7 +117,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -144,7 +144,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -184,7 +184,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -215,7 +215,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -237,10 +237,10 @@ func main() {
```go ```go
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpGet(url string, params ...interface{}) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -251,7 +251,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -279,10 +279,10 @@ func main() {
```go ```go
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPost(url string, params ...interface{}) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -294,7 +294,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -328,10 +328,10 @@ func main() {
```go ```go
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPut(url string, params ...interface{}) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -343,7 +343,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -378,10 +378,10 @@ func main() {
```go ```go
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpDelete(url string, params ...interface{}) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -393,7 +393,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -417,10 +417,10 @@ func main() {
```go ```go
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any,
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPatch(url string, params ...interface{}) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -432,7 +432,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -466,7 +466,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ParseHttpResponse(resp *http.Response, obj interface{}) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>Example:</b> <b>Example:</b>
@@ -478,7 +478,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {

View File

@@ -5,16 +5,15 @@ netutil网络包支持获取ip地址发送http请求。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
``` ```
@@ -46,7 +45,7 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ConvertMapToQueryString(param map[string]interface{}) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>例子:</b> <b>例子:</b>
@@ -55,11 +54,11 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
var m = map[string]interface{}{ var m = map[string]any{
"c": 3, "c": 3,
"a": 1, "a": 1,
"b": 2, "b": 2,
@@ -88,7 +87,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -116,7 +115,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -143,7 +142,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -183,7 +182,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -214,7 +213,7 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -236,10 +235,10 @@ func main() {
```go ```go
// params[0] http请求header类型必须是http.Header或者map[string]string // params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{} // params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte // params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpGet(url string, params ...interface{}) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -250,7 +249,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -278,10 +277,10 @@ func main() {
```go ```go
// params[0] http请求header类型必须是http.Header或者map[string]string // params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{} // params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte // params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPost(url string, params ...interface{}) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -293,7 +292,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -327,10 +326,10 @@ func main() {
```go ```go
// params[0] http请求header类型必须是http.Header或者map[string]string // params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{} // params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte // params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPut(url string, params ...interface{}) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
@@ -342,7 +341,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -377,10 +376,10 @@ func main() {
```go ```go
// params[0] http请求header类型必须是http.Header或者map[string]string // params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{} // params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte // params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpDelete(url string, params ...interface{}) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -392,7 +391,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -416,10 +415,10 @@ func main() {
```go ```go
// params[0] http请求header类型必须是http.Header或者map[string]string // params[0] http请求header类型必须是http.Header或者map[string]string
// params[1] http查询字符串类型必须是url.Values或者map[string]interface{} // params[1] http查询字符串类型必须是url.Values或者map[string]any
// params[2] post请求体类型必须是[]byte // params[2] post请求体类型必须是[]byte
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPatch(url string, params ...interface{}) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b> <b>例子:</b>
@@ -431,7 +430,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {
@@ -465,7 +464,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ParseHttpResponse(resp *http.Response, obj interface{}) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>例子:</b> <b>例子:</b>
@@ -477,7 +476,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"github.com/duke-git/lancet/netutil" "github.com/duke-git/lancet/v2/netutil"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package random implements some basic functions to generate random int and string
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go) - [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package random implements some basic functions to generate random int and string
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
``` ```
@@ -45,7 +45,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -70,7 +70,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -96,7 +96,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -123,7 +123,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ random随机数生成器包可以生成随机[]bytes, int, string。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go) - [https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ random随机数生成器包可以生成随机[]bytes, int, string。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
``` ```
@@ -46,7 +46,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -71,7 +71,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -97,7 +97,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {
@@ -123,7 +123,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/random" "github.com/duke-git/lancet/v2/random"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package retry is for executing a function repeatedly until it was successful or
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package retry is for executing a function repeatedly until it was successful or
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
``` ```
@@ -46,7 +46,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
"time" "time"
) )
@@ -92,7 +92,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -134,7 +134,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -173,7 +173,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -213,7 +213,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ retry重试执行函数直到函数运行成功或被context cancel。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ retry重试执行函数直到函数运行成功或被context cancel。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
``` ```
@@ -94,7 +94,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -136,7 +136,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -175,7 +175,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {
@@ -215,7 +215,7 @@ import (
"fmt" "fmt"
"errors" "errors"
"log" "log"
"github.com/duke-git/lancet/retry" "github.com/duke-git/lancet/v2/retry"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package slice implements some functions to manipulate slice.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go) - [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package slice implements some functions to manipulate slice.
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
``` ```
@@ -28,7 +28,8 @@ import (
- [Count](#Count) - [Count](#Count)
- [Difference](#Difference) - [Difference](#Difference)
- [DifferenceBy](#DifferenceBy) - [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex) - [DifferenceWith](#DifferenceWith)
- [DeleteAt](#DeleteAt)
- [Drop](#Drop) - [Drop](#Drop)
- [Every](#Every) - [Every](#Every)
- [Filter](#Filter) - [Filter](#Filter)
@@ -38,43 +39,44 @@ import (
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [GroupBy](#GroupBy) - [GroupBy](#GroupBy)
- [GroupWith](#GroupWith)
- [IntSlice](#IntSlice) - [IntSlice](#IntSlice)
- [InterfaceSlice](#InterfaceSlice) - [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex) - [InsertAt](#InsertAt)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [Map](#Map) - [Map](#Map)
- [ReverseSlice](#ReverseSlice) - [Reverse](#Reverse)
- [Reduce](#Reduce) - [Reduce](#Reduce)
- [Shuffle](#Shuffle) - [Shuffle](#Shuffle)
- [SortByField](#SortByField) - [SortByField](#SortByField)
- [Some](#Some) - [Some](#Some)
- [StringSlice](#StringSlice) - [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [UpdateByIndex](#UpdateByIndex) - [UpdateAt](#UpdateAt)
- [Without](#Without) - [Without](#Without)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
## Note:
1. param which type is interface{} in below functions should be slice.
### <span id="Contain">Contain</span> ### <span id="Contain">Contain</span>
<p>Check if the value is in the slice or not. iterableType param can be string, map or slice.</p> <p>Check if the value is in the slice or not.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Contain(iterableType interface{}, value interface{}) bool func Contain[T any](slice []T, value T) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -90,14 +92,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ContainSubSlice(slice interface{}, subslice interface{}) bool func ContainSubSlice[T any](slice, subslice []T) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -115,20 +117,20 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Chunk(slice []interface{}, size int) [][]interface{} func Chunk[T any](slice []T, size int) [][]T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
arr := []string{"a", "b", "c", "d", "e"} arr := []string{"a", "b", "c", "d", "e"}
res := slice.Chunk(InterfaceSlice(arr), 3) res := slice.Chunk(InterfaceSlice(arr), 3)
fmt.Println(res) //[][]interface{}{{"a", "b", "c"}, {"d", "e"}} fmt.Println(res) //[][]any{{"a", "b", "c"}, {"d", "e"}}
} }
``` ```
@@ -140,14 +142,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Compact(slice interface{}) interface{} func Compact[T any](slice []T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -163,14 +165,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Concat(slice interface{}, values ...interface{}) interface{} func Concat[T any](slice []T, values ...[]T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -185,19 +187,19 @@ func main() {
### <span id="Count">Count</span> ### <span id="Count">Count</span>
<p>Count iterates over elements of slice, returns a count of all matched elements. The function signature should be func(index int, value interface{}) bool.</p> <p>Count iterates over elements of slice, returns a count of all matched elements.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Count(slice, function interface{}) int func Count[T any](slice []T, predicate func(index int, t T) bool) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -220,14 +222,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Difference(slice1, slice2 interface{}) interface{} func Difference[T comparable](slice, comparedSlice []T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -248,14 +250,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn interface{}) interface{} func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -271,29 +273,55 @@ func main() {
``` ```
### <span id="DifferenceWith">DifferenceWith</span>
<p>DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice.</p>
### <span id="DeleteByIndex">DeleteByIndex</span>
<p>Delete the element of slice from start index to end index - 1.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
res1 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 3) s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
res := slice.DifferenceWith(s1, s2, isDouble)
fmt.Println(res) //[]int{1, 5}
}
```
### <span id="DeleteAt">DeleteAt</span>
<p>Delete the element of slice from start index to end index - 1.</p>
<b>Signature:</b>
```go
func DeleteAt[T any](slice []T, start int, end ...int)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 3)
fmt.Println(res1) //[]string{"a", "b", "c", "e"} fmt.Println(res1) //[]string{"a", "b", "c", "e"}
res2 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 0, 2) res2 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 0, 2)
fmt.Println(res2) //[]string{"c", "d", "e"} fmt.Println(res2) //[]string{"c", "d", "e"}
} }
@@ -308,14 +336,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Drop(slice interface{}, n int) interface{} func Drop[T any](slice []T, n int) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -334,19 +362,19 @@ func main() {
### <span id="Every">Every</span> ### <span id="Every">Every</span>
<p>Return true if all of the values in the slice pass the predicate function. The function signature should be func(index int, value interface{}) bool.</p> <p>Return true if all of the values in the slice pass the predicate function.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Every(slice, function interface{}) bool func Every[T any](slice []T, predicate func(index int, t T) bool) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -364,19 +392,19 @@ func main() {
### <span id="Filter">Filter</span> ### <span id="Filter">Filter</span>
<p>Return all elements which match the function. Function signature should be func(index int, value interface{}) bool.</p> <p>Return all elements which match the function.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Filter(slice, function interface{}) interface{} func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -393,19 +421,19 @@ func main() {
### <span id="Find">Find</span> ### <span id="Find">Find</span>
<p>Iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool.</p> <p>Iterates over elements of slice, returning the first one that passes a truth test on function.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Find(slice, function interface{}) (interface{}, bool) func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -424,19 +452,19 @@ func main() {
### <span id="FindLast">FindLast</span> ### <span id="FindLast">FindLast</span>
<p>iterates over elements of slice from end to begin, returning the last one that passes a truth test on function. The function signature should be func(index int, value interface{}) bool.</p> <p>iterates over elements of slice from end to begin, returning the last one that passes a truth test on function.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func FindLast(slice, function interface{}) (interface{}, bool) func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -459,14 +487,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func FlattenDeep(slice interface{}) interface{} func FlattenDeep(slice any) any
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -481,19 +509,19 @@ func main() {
### <span id="ForEach">ForEach</span> ### <span id="ForEach">ForEach</span>
<p>Iterates over elements of slice and invokes function for each element, function signature should be func(index int, value interface{}).</p> <p>Iterates over elements of slice and invokes function for each element.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ForEach(slice, function interface{}) func ForEach[T any](slice []T, iteratee func(index int, t T))
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -510,19 +538,19 @@ func main() {
### <span id="GroupBy">GroupBy</span> ### <span id="GroupBy">GroupBy</span>
<p>Iterates over elements of the slice, each element will be group by criteria, returns two slices. The function signature should be func(index int, value interface{}) bool.</p> <p>Iterates over elements of the slice, each element will be group by criteria, returns two slices.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func GroupBy(slice, function interface{}) (interface{}, interface{}) func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -540,24 +568,52 @@ func main() {
### <span id="IntSlice">IntSlice</span> ### <span id="GroupWith">GroupWith</span>
<p>Convert interface slice to int slice.</p> <p>Return a map composed of keys generated from the results of running each element of slice thru iteratee.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func IntSlice(slice interface{}) []int func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var nums = []interface{}{1, 2, 3} nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
res := slice.GroupWith(nums, floor)
fmt.Println(res) //map[float64][]float64{ 4: {4.2}, 6: {6.1, 6.3},}
}
```
### <span id="IntSlice">IntSlice</span>
<p>Convert interface slice to int slice.</p>
<b>Signature:</b>
```go
func IntSlice(slice any) []int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
var nums = []any{1, 2, 3}
res := slice.IntSlice(nums) res := slice.IntSlice(nums)
fmt.Println(res) //[]int{1, 2, 3} fmt.Println(res) //[]int{1, 2, 3}
} }
@@ -572,20 +628,20 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func InterfaceSlice(slice interface{}) []interface{} func InterfaceSlice(slice any) []any
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var nums = []int{}{1, 2, 3} var nums = []int{}{1, 2, 3}
res := slice.InterfaceSlice(nums) res := slice.InterfaceSlice(nums)
fmt.Println(res) //[]interface{}{1, 2, 3} fmt.Println(res) //[]any{1, 2, 3}
} }
``` ```
@@ -598,14 +654,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Intersection(slices ...interface{}) interface{} func Intersection[T any](slices ...[]T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -620,29 +676,29 @@ func main() {
### <span id="InsertByIndex">InsertByIndex</span> ### <span id="InsertAt">InsertAt</span>
<p>insert the element into slice at index.</p> <p>insert the element into slice at index.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) func InsertAt[T any](slice []T, index int, value any) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
s := []string{"a", "b", "c"} s := []string{"a", "b", "c"}
res1, _ := slice.InsertByIndex(s, 0, "1") res1, _ := slice.InsertAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "a", "b", "c"} fmt.Println(res1) //[]string{"1", "a", "b", "c"}
res2, _ := slice.InsertByIndex(s, 3, []string{"1", "2", "3"}) res2, _ := slice.InsertAt(s, 3, []string{"1", "2", "3"})
fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"} fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"}
} }
``` ```
@@ -650,20 +706,77 @@ func main() {
### <span id="Map">Map</span> ### <span id="IndexOf">IndexOf</span>
<p>Creates an slice of values by running each element in slice thru function, function signature should be func(index int, value interface{}) interface{}.</p> <p>Returns the index at which the first occurrence of a value is found in a slice or return -1 if the value cannot be found.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Map(slice, function interface{}) interface{} func IndexOf[T any](slice []T, value T) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.IndexOf(arr, "a")
fmt.Println(res1) //0
res2 := slice.IndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="LastIndexOf">LastIndexOf</span>
<p>Returns the index at which the last occurrence of a value is found in a slice or return -1 if the value cannot be found.</p>
<b>Signature:</b>
```go
func LastIndexOf[T any](slice []T, value T) int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.LastIndexOf(arr, "a")
fmt.Println(res1) //1
res2 := slice.LastIndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="Map">Map</span>
<p>Creates an slice of values by running each element in slice thru function.</p>
<b>Signature:</b>
```go
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -679,25 +792,25 @@ func main() {
### <span id="ReverseSlice">ReverseSlice</span> ### <span id="Reverse">Reverse</span>
<p>Reverse the elements order in slice.</p> <p>Reverse the elements order in slice.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ReverseSlice(slice interface{}) func Reverse[T any](slice []T)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4} nums := []int{1, 2, 3, 4}
slice.ReverseSlice(nums) slice.Reverse(nums)
fmt.Println(res) //[]int{4, 3, 2, 1} fmt.Println(res) //[]int{4, 3, 2, 1}
} }
``` ```
@@ -705,19 +818,19 @@ func main() {
### <span id="Reduce">Reduce</span> ### <span id="Reduce">Reduce</span>
<p>Reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}.</p> <p>Reduce slice.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Reduce(slice, function, zero interface{}) interface{} func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -739,14 +852,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Shuffle(slice interface{}) interface{} func Shuffle[T any](slice []T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -764,14 +877,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func SortByField(slice interface{}, field string, sortType ...string) error func SortByField(slice any, field string, sortType ...string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -802,19 +915,19 @@ func main() {
### <span id="Some">Some</span> ### <span id="Some">Some</span>
<p>Return true if any of the values in the list pass the predicate function, function signature should be func(index int, value interface{}) bool.</p> <p>Return true if any of the values in the list pass the predicate function.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Some(slice, function interface{}) bool func Some[T any](slice []T, predicate func(index int, t T) bool) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -836,18 +949,18 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func StringSlice(slice interface{}) []string func StringSlice(slice any) []string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var s = []interface{}{"a", "b", "c"} var s = []any{"a", "b", "c"}
res := slice.StringSlice(s) res := slice.StringSlice(s)
fmt.Println(res) //[]string{"a", "b", "c"} fmt.Println(res) //[]string{"a", "b", "c"}
} }
@@ -856,20 +969,49 @@ func main() {
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>Create a slice whose element is in given slices, but not in both slices.</p>
<b>Signature:</b>
```go
func SymmetricDifference[T any](slices ...[]T) []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 4}
s3 := []int{1, 2, 3, 5}
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
}
```
### <span id="Unique">Unique</span> ### <span id="Unique">Unique</span>
<p>Remove duplicate elements in slice.</p> <p>Remove duplicate elements in slice.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Unique(slice interface{}) interface{} func Unique[T any](slice []T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -886,14 +1028,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Union(slices ...interface{}) interface{} func Union[T any](slices ...[]T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -907,26 +1049,26 @@ func main() {
### <span id="UpdateByIndex">UpdateByIndex</span> ### <span id="UpdateAt">UpdateAt</span>
<p>Update the slice element at index. if param index < 0 or index >= len(slice), will return error. </p> <p>Update the slice element at index. if param index < 0 or index >= len(slice), will return error. </p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) func UpdateAt[T any](slice []T, index int, value T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
s := []string{"a", "b", "c"} s := []string{"a", "b", "c"}
res1, _ := slice.UpdateByIndex(s, 0, "1") res1, _ := slice.UpdateAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "b", "c"} fmt.Println(res1) //[]string{"1", "b", "c"}
} }
``` ```
@@ -940,14 +1082,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Without(slice interface{}, values ...interface{}) interface{} func Without[T any](slice []T, values ...T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ slice包包含操作切片的方法集合。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go) - [https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ slice包包含操作切片的方法集合。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
``` ```
@@ -28,7 +28,8 @@ import (
- [Count](#Count) - [Count](#Count)
- [Difference](#Difference) - [Difference](#Difference)
- [DifferenceBy](#DifferenceBy) - [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex) - [DifferenceWith](#DifferenceWith)
- [DeleteAt](#DeleteAt)
- [Drop](#Drop) - [Drop](#Drop)
- [Every](#Every) - [Every](#Every)
- [Filter](#Filter) - [Filter](#Filter)
@@ -38,20 +39,24 @@ import (
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [GroupBy](#GroupBy) - [GroupBy](#GroupBy)
- [GroupWith](#GroupWith)
- [IntSlice](#IntSlice) - [IntSlice](#IntSlice)
- [InterfaceSlice](#InterfaceSlice) - [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex) - [InsertAt](#InsertAt)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [Map](#Map) - [Map](#Map)
- [ReverseSlice](#ReverseSlice) - [Reverse](#Reverse)
- [Reduce](#Reduce) - [Reduce](#Reduce)
- [Shuffle](#Shuffle) - [Shuffle](#Shuffle)
- [SortByField](#SortByField) - [SortByField](#SortByField)
- [Some](#Some) - [Some](#Some)
- [StringSlice](#StringSlice) - [StringSlice](#StringSlice)
- [SymmetricDifference](#SymmetricDifference)
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [UpdateByIndex](#UpdateByIndex) - [UpdateAt](#UpdateAt)
- [Without](#Without) - [Without](#Without)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -64,14 +69,14 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Contain(iterableType interface{}, value interface{}) bool func Contain[T any](slice []T, value T) bool
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -87,14 +92,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ContainSubSlice(slice interface{}, subslice interface{}) bool func ContainSubSlice[T any](slice, subslice []T) bool
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -112,20 +117,20 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Chunk(slice []interface{}, size int) [][]interface{} func Chunk[T any](slice []T, size int) [][]T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
arr := []string{"a", "b", "c", "d", "e"} arr := []string{"a", "b", "c", "d", "e"}
res := slice.Chunk(InterfaceSlice(arr), 3) res := slice.Chunk(InterfaceSlice(arr), 3)
fmt.Println(res) //[][]interface{}{{"a", "b", "c"}, {"d", "e"}} fmt.Println(res) //[][]any{{"a", "b", "c"}, {"d", "e"}}
} }
``` ```
@@ -137,14 +142,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Compact(slice interface{}) interface{} func Compact[T any](slice []T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -160,14 +165,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Concat(slice interface{}, values ...interface{}) interface{} func Concat[T any](slice []T, values ...[]T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -182,19 +187,19 @@ func main() {
### <span id="Count">Count</span> ### <span id="Count">Count</span>
<p>遍历切片对每个元素执行函数function. 返回符合函数返回值为true的元素的个数函数签名必须是func(index int, value interface{}) bool</p> <p>遍历切片对每个元素执行函数function. 返回符合函数返回值为true的元素的个数</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Count(slice, function interface{}) int func Count[T any](slice []T, predicate func(index int, t T) bool) int
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -217,14 +222,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Difference(slice1, slice2 interface{}) interface{} func Difference[T comparable](slice, comparedSlice []T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -245,14 +250,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn interface{}) interface{} func DifferenceBy[T any](slice []T, comparedSlice []T, iteratee func(index int, t T) T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -269,28 +274,56 @@ func main() {
### <span id="DifferenceWith">DifferenceWith</span>
### <span id="DeleteByIndex">DeleteByIndex</span> <p>DifferenceWith 接受比较器,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定</p>
<p>删除切片中从开始索引到结束索引-1的元素</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
res1 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 3) s1 := []int{1, 2, 3, 4, 5}
s2 := []int{4, 5, 6, 7, 8}
isDouble := func(v1, v2 int) bool {
return v2 == 2*v1
}
res := slice.DifferenceWith(s1, s2, isDouble)
fmt.Println(res) //[]int{1, 5}
}
```
### <span id="DeleteAt">DeleteAt</span>
<p>删除切片中从开始索引到结束索引-1的元素</p>
<b>函数签名:</b>
```go
func DeleteAt[T any](slice []T, start int, end ...int)
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res1 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 3)
fmt.Println(res1) //[]string{"a", "b", "c", "e"} fmt.Println(res1) //[]string{"a", "b", "c", "e"}
res2 := slice.DeleteByIndex([]string{"a", "b", "c", "d", "e"}, 0, 2) res2 := slice.DeleteAt([]string{"a", "b", "c", "d", "e"}, 0, 2)
fmt.Println(res2) //[]string{"c", "d", "e"} fmt.Println(res2) //[]string{"c", "d", "e"}
} }
@@ -305,14 +338,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Drop(slice interface{}, n int) interface{} func Drop[T any](slice []T, n int) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -331,19 +364,19 @@ func main() {
### <span id="Every">Every</span> ### <span id="Every">Every</span>
<p>如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value interface{}) bool</p> <p>如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value any) bool</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Every(slice, function interface{}) bool func Every[T any](slice []T, predicate func(index int, t T) bool) bool
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -361,19 +394,19 @@ func main() {
### <span id="Filter">Filter</span> ### <span id="Filter">Filter</span>
<p>返回与函数匹配的所有元素。 函数签名应该是 func(index int, value interface{}) bool</p> <p>返回与函数匹配的所有元素。 函数签名应该是 func(index int, value any) bool</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Filter(slice, function interface{}) interface{} func Filter[T any](slice []T, predicate func(index int, t T) bool) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -390,19 +423,19 @@ func main() {
### <span id="Find">Find</span> ### <span id="Find">Find</span>
<p>遍历slice的元素返回第一个通过function真值测试的元素。函数签名应该是 func(index int, value interface{}) bool</p> <p>遍历slice的元素返回第一个通过function真值测试的元素</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Find(slice, function interface{}) (interface{}, bool) func Find[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -421,19 +454,19 @@ func main() {
### <span id="FindLast">FindLast</span> ### <span id="FindLast">FindLast</span>
<p>从头到尾遍历 slice 的元素,返回最后一个通过函数真值测试的元素。 函数签名应该是 func(index int, value interface{}) bool。</p> <p>从头到尾遍历 slice 的元素,返回最后一个通过函数真值测试的元素。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func FindLast(slice, function interface{}) (interface{}, bool) func FindLast[T any](slice []T, predicate func(index int, t T) bool) (*T, bool)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -456,14 +489,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func FlattenDeep(slice interface{}) interface{} func FlattenDeep(slice any) any
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -478,19 +511,19 @@ func main() {
### <span id="ForEach">ForEach</span> ### <span id="ForEach">ForEach</span>
<p>遍历slice的元素并为每个元素调用函数函数签名应该是func(index int, value interface{})</p> <p>遍历slice的元素并为每个元素调用函数</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ForEach(slice, function interface{}) func ForEach[T any](slice []T, iteratee func(index int, t T))
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -507,19 +540,19 @@ func main() {
### <span id="GroupBy">GroupBy</span> ### <span id="GroupBy">GroupBy</span>
<p>迭代切片的元素,每个元素将按条件分组,返回两个切片。 函数签名应该是func(index int, value interface{}) bool</p> <p>迭代切片的元素,每个元素将按条件分组,返回两个切片</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func GroupBy(slice, function interface{}) (interface{}, interface{}) func GroupBy[T any](slice []T, groupFn func(index int, t T) bool) ([]T, []T)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -536,6 +569,32 @@ func main() {
### <span id="GroupWith">GroupWith</span>
<p>创建一个mapkey是iteratee遍历slice中的每个元素返回的结果。 分组值的顺序是由他们出现在slice中的顺序确定的。每个键对应的值负责生成key的元素组成的数组。iteratee调用1个参数 (value)</p>
<b>函数签名:</b>
```go
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []float64{6.1, 4.2, 6.3}
floor := func(num float64) float64 {
return math.Floor(num)
}
res := slice.GroupWith(nums, floor)
fmt.Println(res) //map[float64][]float64{ 4: {4.2}, 6: {6.1, 6.3},}
}
```
### <span id="IntSlice">IntSlice</span> ### <span id="IntSlice">IntSlice</span>
<p>将接口切片转换为int切片</p> <p>将接口切片转换为int切片</p>
@@ -543,18 +602,18 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func IntSlice(slice interface{}) []int func IntSlice(slice any) []int
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var nums = []interface{}{1, 2, 3} var nums = []any{1, 2, 3}
res := slice.IntSlice(nums) res := slice.IntSlice(nums)
fmt.Println(res) //[]int{1, 2, 3} fmt.Println(res) //[]int{1, 2, 3}
} }
@@ -569,20 +628,20 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func InterfaceSlice(slice interface{}) []interface{} func InterfaceSlice(slice any) []any
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var nums = []int{}{1, 2, 3} var nums = []int{}{1, 2, 3}
res := slice.InterfaceSlice(nums) res := slice.InterfaceSlice(nums)
fmt.Println(res) //[]interface{}{1, 2, 3} fmt.Println(res) //[]any{1, 2, 3}
} }
``` ```
@@ -595,14 +654,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Intersection(slices ...interface{}) interface{} func Intersection[T any](slices ...[]T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -617,29 +676,29 @@ func main() {
### <span id="InsertByIndex">InsertByIndex</span> ### <span id="InsertAt">InsertAt</span>
<p>将元素插入到索引处的切片中</p> <p>将元素插入到索引处的切片中</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) func InsertAt[T any](slice []T, index int, value any) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
s := []string{"a", "b", "c"} s := []string{"a", "b", "c"}
res1, _ := slice.InsertByIndex(s, 0, "1") res1, _ := slice.InsertAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "a", "b", "c"} fmt.Println(res1) //[]string{"1", "a", "b", "c"}
res2, _ := slice.InsertByIndex(s, 3, []string{"1", "2", "3"}) res2, _ := slice.InsertAt(s, 3, []string{"1", "2", "3"})
fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"} fmt.Println(res2) //[]string{"a", "b", "c", "1", "2", "3"}
} }
``` ```
@@ -647,20 +706,76 @@ func main() {
### <span id="Map">Map</span> ### <span id="IndexOf">IndexOf</span>
<p>通过运行函数slice中的每个元素来创建一个值切片函数签名应该是func(index int, value interface{}) interface{}。</p> <p>返回在切片中找到值的第一个匹配项的索引,如果找不到值,则返回-1</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Map(slice, function interface{}) interface{} func IndexOf[T any](slice []T, value T) int
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.IndexOf(arr, "a")
fmt.Println(res1) //0
res2 := slice.IndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="LastIndexOf">LastIndexOf</span>
<p>返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1</p>
<b>函数签名:</b>
```go
func LastIndexOf[T any](slice []T, value T) int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.LastIndexOf(arr, "a")
fmt.Println(res1) //1
res2 := slice.LastIndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="Map">Map</span>
<p>通过运行函数slice中的每个元素来创建一个新切片</p>
<b>函数签名:</b>
```go
func Map[T any, U any](slice []T, iteratee func(index int, t T) U) []U
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -676,25 +791,25 @@ func main() {
### <span id="ReverseSlice">ReverseSlice</span> ### <span id="Reverse">Reverse</span>
<p>反转切片中的元素顺序</p> <p>反转切片中的元素顺序</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ReverseSlice(slice interface{}) func Reverse[T any](slice []T)
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
nums := []int{1, 2, 3, 4} nums := []int{1, 2, 3, 4}
slice.ReverseSlice(nums) slice.Reverse(nums)
fmt.Println(res) //[]int{4, 3, 2, 1} fmt.Println(res) //[]int{4, 3, 2, 1}
} }
``` ```
@@ -702,19 +817,19 @@ func main() {
### <span id="Reduce">Reduce</span> ### <span id="Reduce">Reduce</span>
<p>将slice中的元素运行函数返回运行结果。函数签名应该是func(index int, value1, value2 interface{}) interface{}。</p> <p>将slice中的元素依次运行函数,返回运行结果</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Reduce(slice, function, zero interface{}) interface{} func Reduce[T any](slice []T, iteratee func(index int, t1, t2 T) T, initial T) T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -736,14 +851,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Shuffle(slice interface{}) interface{} func Shuffle[T any](slice []T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -761,14 +876,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func SortByField(slice interface{}, field string, sortType ...string) error func SortByField(slice any, field string, sortType ...string) error
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -799,19 +914,19 @@ func main() {
### <span id="Some">Some</span> ### <span id="Some">Some</span>
<p>如果列表中的任何值通过谓词函数则返回true函数签名应该是func(index int, value interface{}) bool .</p> <p>如果列表中的任何值通过谓词函数则返回true</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Some(slice, function interface{}) bool func Some[T any](slice []T, predicate func(index int, t T) bool) bool
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -833,18 +948,18 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func StringSlice(slice interface{}) []string func StringSlice(slice any) []string
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
var s = []interface{}{"a", "b", "c"} var s = []any{"a", "b", "c"}
res := slice.StringSlice(s) res := slice.StringSlice(s)
fmt.Println(res) //[]string{"a", "b", "c"} fmt.Println(res) //[]string{"a", "b", "c"}
} }
@@ -853,20 +968,48 @@ func main() {
### <span id="Unique">Unique</span> ### <span id="SymmetricDifference">SymmetricDifference</span>
<p>删除切片中的重复元素</p> <p>返回一个切片,其中的元素存在于参数切片中,但不同时存储在于参数切片中(交集取反)</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Unique(slice interface{}) interface{} func SymmetricDifference[T any](slices ...[]T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
)
func main() {
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 4}
s3 := []int{1, 2, 3, 5}
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
}
```
### <span id="Unique">Unique</span>
<p>删除切片中的重复元素</p>
<b>函数签名:</b>
```go
func Unique[T any](slice []T) []T
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -883,14 +1026,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Union(slices ...interface{}) interface{} func Union[T any](slices ...[]T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
@@ -904,26 +1047,26 @@ func main() {
### <span id="UpdateByIndex">UpdateByIndex</span> ### <span id="UpdateAt">UpdateAt</span>
<p>更新索引处的切片元素。 如果 param index < 0 或 index >= len(slice),将返回错误</p> <p>更新索引处的切片元素。 如果 param index < 0 或 index >= len(slice),将返回错误</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) func UpdateAt[T any](slice []T, index int, value T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {
s := []string{"a", "b", "c"} s := []string{"a", "b", "c"}
res1, _ := slice.UpdateByIndex(s, 0, "1") res1, _ := slice.UpdateAt(s, 0, "1")
fmt.Println(res1) //[]string{"1", "b", "c"} fmt.Println(res1) //[]string{"1", "b", "c"}
} }
``` ```
@@ -937,14 +1080,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Without(slice interface{}, values ...interface{}) interface{} func Without[T any](slice []T, values ...T) []T
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/slice" "github.com/duke-git/lancet/v2/slice"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package strutil contains some functions to manipulate string.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go) - [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package strutil contains some functions to manipulate string.
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
``` ```
@@ -34,6 +34,7 @@ import (
- [PadStart](#PadStart) - [PadStart](#PadStart)
- [ReverseStr](#ReverseStr) - [ReverseStr](#ReverseStr)
- [SnakeCase](#SnakeCase) - [SnakeCase](#SnakeCase)
- [SplitEx](#SplitEx)
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
@@ -57,7 +58,7 @@ func After(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -87,7 +88,7 @@ func AfterLast(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -118,7 +119,7 @@ func Before(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -149,7 +150,7 @@ func BeforeLast(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -180,7 +181,7 @@ func CamelCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -214,7 +215,7 @@ func Capitalize(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -237,14 +238,14 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func IsString(v interface{}) bool func IsString(v any) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -272,7 +273,7 @@ func KebabCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -306,7 +307,7 @@ func LowerFirst(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -340,7 +341,7 @@ func UpperFirst(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -374,7 +375,7 @@ func PadEnd(source string, size int, padStr string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -408,7 +409,7 @@ func PadStart(source string, size int, padStr string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -442,7 +443,7 @@ func ReverseStr(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -469,7 +470,7 @@ func SnakeCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -493,6 +494,43 @@ func main() {
### <span id="SplitEx">SplitEx</span>
<p>Split a given string whether the result contains empty string.</p>
<b>Signature:</b>
```go
func SplitEx(s, sep string, removeEmptyString bool) []string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
arr1 := strutil.SplitEx(" a b c ", "", true)
fmt.Println(arr1) //[]string{}
arr2 := strutil.SplitEx(" a b c ", " ", false)
fmt.Println(arr2) //[]string{"", "a", "b", "c", ""}
arr3 := strutil.SplitEx(" a b c ", " ", true)
fmt.Println(arr3) //[]string{"a", "b", "c"}
arr4 := strutil.SplitEx(" a = b = c = ", " = ", false)
fmt.Println(arr4) //[]string{" a", "b", "c", ""}
arr5 := strutil.SplitEx(" a = b = c = ", " = ", true)
fmt.Println(arr5) //[]string{" a", "b", "c"}
}
```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>Wrap a string with another string.</p> <p>Wrap a string with another string.</p>
@@ -506,7 +544,7 @@ func Wrap(str string, wrapWith string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -543,7 +581,7 @@ func Unwrap(str string, wrapToken string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ strutil包含处理字符串的相关函数。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go) - [https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ strutil包含处理字符串的相关函数。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
``` ```
@@ -34,6 +34,7 @@ import (
- [PadStart](#PadStart) - [PadStart](#PadStart)
- [ReverseStr](#ReverseStr) - [ReverseStr](#ReverseStr)
- [SnakeCase](#SnakeCase) - [SnakeCase](#SnakeCase)
- [SplitEx](#SplitEx)
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
@@ -58,7 +59,7 @@ func After(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -88,7 +89,7 @@ func AfterLast(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -119,7 +120,7 @@ func Before(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -150,7 +151,7 @@ func BeforeLast(s, char string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -181,7 +182,7 @@ func CamelCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -215,7 +216,7 @@ func Capitalize(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -238,14 +239,14 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func IsString(v interface{}) bool func IsString(v any) bool
``` ```
<b>例子:</b> <b>例子:</b>
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -273,7 +274,7 @@ func KebabCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -307,7 +308,7 @@ func LowerFirst(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -341,7 +342,7 @@ func UpperFirst(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -375,7 +376,7 @@ func PadEnd(source string, size int, padStr string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -409,7 +410,7 @@ func PadStart(source string, size int, padStr string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -443,7 +444,7 @@ func ReverseStr(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -470,7 +471,7 @@ func SnakeCase(s string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -493,6 +494,41 @@ func main() {
### <span id="SplitEx">SplitEx</span>
<p>分割字符串为切片removeEmptyString参数指定是否去除空字符串</p>
<b>函数签名:</b>
```go
func SplitEx(s, sep string, removeEmptyString bool) []string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
arr1 := strutil.SplitEx(" a b c ", "", true)
fmt.Println(arr1) //[]string{}
arr2 := strutil.SplitEx(" a b c ", " ", false)
fmt.Println(arr2) //[]string{"", "a", "b", "c", ""}
arr3 := strutil.SplitEx(" a b c ", " ", true)
fmt.Println(arr3) //[]string{"a", "b", "c"}
arr4 := strutil.SplitEx(" a = b = c = ", " = ", false)
fmt.Println(arr4) //[]string{" a", "b", "c", ""}
arr5 := strutil.SplitEx(" a = b = c = ", " = ", true)
fmt.Println(arr5) //[]string{" a", "b", "c"}
}
```
### <span id="Wrap">Wrap</span> ### <span id="Wrap">Wrap</span>
<p>用另一个字符串包裹一个字符串</p> <p>用另一个字符串包裹一个字符串</p>
@@ -507,7 +543,7 @@ func Wrap(str string, wrapWith string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {
@@ -544,7 +580,7 @@ func Unwrap(str string, wrapToken string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/strutil" "github.com/duke-git/lancet/v2/strutil"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package system contains some functions about os, runtime, shell command.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package system contains some functions about os, runtime, shell command.
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
``` ```
@@ -48,7 +48,7 @@ func IsWindows() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -73,7 +73,7 @@ func IsLinux() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -97,7 +97,7 @@ func IsMac() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -121,7 +121,7 @@ func GetOsEnv(key string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -145,7 +145,7 @@ func SetOsEnv(key, value string) error
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -170,7 +170,7 @@ func RemoveOsEnv(key string) error
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -196,7 +196,7 @@ func CompareOsEnv(key, comparedEnv string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -222,7 +222,7 @@ func ExecCommand(command string) (stdout, stderr string, err error)
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ system包含os, runtime, shell command相关函数。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ system包含os, runtime, shell command相关函数。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
``` ```
@@ -48,7 +48,7 @@ func IsWindows() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -73,7 +73,7 @@ func IsLinux() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -97,7 +97,7 @@ func IsMac() bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -121,7 +121,7 @@ func GetOsEnv(key string) string
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -145,7 +145,7 @@ func SetOsEnv(key, value string) error
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -170,7 +170,7 @@ func RemoveOsEnv(key string) error
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -196,7 +196,7 @@ func CompareOsEnv(key, comparedEnv string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {
@@ -209,7 +209,7 @@ func main() {
### <span id="ExecCommand">CompareOsEnv</span> ### <span id="ExecCommand">ExecCommand</span>
<p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p> <p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p>
<b>Signature:</b> <b>Signature:</b>
@@ -222,7 +222,7 @@ func ExecCommand(command string) (stdout, stderr string, err error)
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/system" "github.com/duke-git/lancet/v2/system"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ Package validator contains some functions for data validation.
## Source: ## Source:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go) - [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ Package validator contains some functions for data validation.
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
``` ```
@@ -67,7 +67,7 @@ func ContainChinese(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -97,7 +97,7 @@ func ContainLetter(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -128,7 +128,7 @@ func ContainLower(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -159,7 +159,7 @@ func ContainUpper(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -190,7 +190,7 @@ func IsAlpha(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -218,7 +218,7 @@ func IsAllUpper(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -246,7 +246,7 @@ func IsAllLower(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -274,7 +274,7 @@ func IsBase64(base64 string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -302,7 +302,7 @@ func IsChineseMobile(mobileNum string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -329,7 +329,7 @@ func IsChineseIdNum(id string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -357,7 +357,7 @@ func IsChinesePhone(phone string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -385,7 +385,7 @@ func IsCreditCard(creditCart string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -413,7 +413,7 @@ func IsDns(dns string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -444,7 +444,7 @@ func IsEmail(email string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -473,7 +473,7 @@ func IsEmptyString(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -501,7 +501,7 @@ func IsFloatStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -530,7 +530,7 @@ func IsNumberStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -559,7 +559,7 @@ func IsJSON(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -588,7 +588,7 @@ func IsRegexMatch(s, regex string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -614,7 +614,7 @@ func IsIntStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -641,7 +641,7 @@ func IsIp(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -668,7 +668,7 @@ func IsIpV4(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -695,7 +695,7 @@ func IsIpV6(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -722,7 +722,7 @@ func IsStrongPassword(password string, length int) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -750,7 +750,7 @@ func IsUrl(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -778,7 +778,7 @@ func IsWeakPassword(password string, length int) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {

View File

@@ -5,7 +5,7 @@ validator验证器包包含常用字符串格式验证函数。
## 源码: ## 源码:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go) - [https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -13,7 +13,7 @@ validator验证器包包含常用字符串格式验证函数。
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
``` ```
@@ -67,7 +67,7 @@ func ContainChinese(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -97,7 +97,7 @@ func ContainLetter(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -128,7 +128,7 @@ func ContainLower(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -159,7 +159,7 @@ func ContainUpper(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -190,7 +190,7 @@ func IsAlpha(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -218,7 +218,7 @@ func IsAllUpper(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -246,7 +246,7 @@ func IsAllLower(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -274,7 +274,7 @@ func IsBase64(base64 string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -302,7 +302,7 @@ func IsChineseMobile(mobileNum string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -329,7 +329,7 @@ func IsChineseIdNum(id string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -357,7 +357,7 @@ func IsChinesePhone(phone string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -385,7 +385,7 @@ func IsCreditCard(creditCart string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -413,7 +413,7 @@ func IsDns(dns string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -444,7 +444,7 @@ func IsEmail(email string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -473,7 +473,7 @@ func IsEmptyString(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -501,7 +501,7 @@ func IsFloatStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -530,7 +530,7 @@ func IsNumberStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -559,7 +559,7 @@ func IsJSON(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -588,7 +588,7 @@ func IsRegexMatch(s, regex string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -614,7 +614,7 @@ func IsIntStr(s string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -641,7 +641,7 @@ func IsIp(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -668,7 +668,7 @@ func IsIpV4(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -695,7 +695,7 @@ func IsIpV6(ipstr string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -722,7 +722,7 @@ func IsStrongPassword(password string, length int) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -750,7 +750,7 @@ func IsUrl(str string) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {
@@ -778,7 +778,7 @@ func IsWeakPassword(password string, length int) bool
```go ```go
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/validator" "github.com/duke-git/lancet/v2/validator"
) )
func main() { func main() {

57
docs/xerror.md Normal file
View File

@@ -0,0 +1,57 @@
# Xerror
Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Unwrap">Unwrap</span>
<p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
<b>Signature:</b>
```go
func Unwrap[T any](val T, err error) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
}()
xerror.Unwrap(strconv.Atoi("4o2"))
}
```

57
docs/xerror_zh-CN.md Normal file
View File

@@ -0,0 +1,57 @@
# Xerror
xerror错误处理逻辑封装
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/xerror/xerror.go](https://github.com/duke-git/lancet/blob/main/xerror/xerror.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/xerror"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Unwrap](#Unwrap)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Unwrap">Unwrap</span>
<p>如果err为nil则展开则它返回一个有效值。 如果err不是nil则Unwrap使用err发生恐慌。</p>
<b>函数签名:</b>
```go
func Unwrap[T any](val T, err error) T
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error()
}()
xerror.Unwrap(strconv.Atoi("4o2"))
}
```

View File

@@ -263,7 +263,7 @@ func FileMode(path string) (fs.FileMode, error) {
// MiMeType return file mime type // MiMeType return file mime type
// param `file` should be string(file path) or *os.File // param `file` should be string(file path) or *os.File
func MiMeType(file interface{}) string { func MiMeType(file any) string {
var mediatype string var mediatype string
readBuffer := func(f *os.File) ([]byte, error) { readBuffer := func(f *os.File) ([]byte, error) {

View File

@@ -4,7 +4,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestIsExist(t *testing.T) { func TestIsExist(t *testing.T) {
@@ -76,10 +76,10 @@ func TestCopyFile(t *testing.T) {
func TestListFileNames(t *testing.T) { func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames") assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("../datetime/") filesInPath, err := ListFileNames("./")
assert.IsNil(err) assert.IsNil(err)
expected := []string{"datetime.go", "datetime_test.go"} expected := []string{"file.go", "file_test.go"}
assert.Equal(expected, filesInPath) assert.Equal(expected, filesInPath)
} }

View File

@@ -7,7 +7,7 @@ package formatter
import "strings" import "strings"
// Comma add comma to number by every 3 numbers from right. ahead by symbol char // Comma add comma to number by every 3 numbers from right. ahead by symbol char
func Comma(v interface{}, symbol string) string { func Comma(v any, symbol string) string {
s := numString(v) s := numString(v)
dotIndex := strings.Index(s, ".") dotIndex := strings.Index(s, ".")
if dotIndex != -1 { if dotIndex != -1 {

View File

@@ -14,7 +14,7 @@ func commaString(s string) string {
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:]) return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
} }
func numString(value interface{}) string { func numString(value any) string {
switch reflect.TypeOf(value).Kind() { switch reflect.TypeOf(value).Kind() {
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64: case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
return fmt.Sprintf("%v", value) return fmt.Sprintf("%v", value)

View File

@@ -3,7 +3,7 @@ package formatter
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestComma(t *testing.T) { func TestComma(t *testing.T) {

View File

@@ -10,11 +10,11 @@ import (
) )
// After creates a function that invokes func once it's called n or more times // After creates a function that invokes func once it's called n or more times
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value { func After(n int, fn any) func(args ...any) []reflect.Value {
// Catch programming error while constructing the closure // Catch programming error while constructing the closure
mustBeFunction(fn) mustBeFunction(fn)
return func(args ...interface{}) []reflect.Value { return func(args ...any) []reflect.Value {
n-- n--
if n < 1 { if n < 1 {
return unsafeInvokeFunc(fn, args...) return unsafeInvokeFunc(fn, args...)
@@ -24,11 +24,11 @@ func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
} }
// Before creates a function that invokes func once it's called less than n times // Before creates a function that invokes func once it's called less than n times
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value { func Before(n int, fn any) func(args ...any) []reflect.Value {
// Catch programming error while constructing the closure // Catch programming error while constructing the closure
mustBeFunction(fn) mustBeFunction(fn)
var res []reflect.Value var res []reflect.Value
return func(args ...interface{}) []reflect.Value { return func(args ...any) []reflect.Value {
if n > 0 { if n > 0 {
res = unsafeInvokeFunc(fn, args...) res = unsafeInvokeFunc(fn, args...)
} }
@@ -40,20 +40,20 @@ func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
} }
} }
// Fn is for curry function which is func(...interface{}) interface{} // Fn is for curry function which is func(...any) any
type Fn func(...interface{}) interface{} type Fn func(...any) any
// Curry make a curry function // Curry make a curry function
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} { func (f Fn) Curry(i any) func(...any) any {
return func(values ...interface{}) interface{} { return func(values ...any) any {
v := append([]interface{}{i}, values...) v := append([]any{i}, values...)
return f(v...) return f(v...)
} }
} }
// Compose compose the functions from right to left // Compose compose the functions from right to left
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} { func Compose(fnList ...func(...any) any) func(...any) any {
return func(s ...interface{}) interface{} { return func(s ...any) any {
f := fnList[0] f := fnList[0]
restFn := fnList[1:] restFn := fnList[1:]
@@ -66,7 +66,7 @@ func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) in
} }
// Delay make the function execution after delayed time // Delay make the function execution after delayed time
func Delay(delay time.Duration, fn interface{}, args ...interface{}) { func Delay(delay time.Duration, fn any, args ...any) {
// Catch programming error while constructing the closure // Catch programming error while constructing the closure
mustBeFunction(fn) mustBeFunction(fn)
@@ -95,7 +95,7 @@ func Debounced(fn func(), duration time.Duration) func() {
} }
// Schedule invoke function every duration time, util close the returned bool chan // Schedule invoke function every duration time, util close the returned bool chan
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool { func Schedule(d time.Duration, fn any, args ...any) chan bool {
// Catch programming error while constructing the closure // Catch programming error while constructing the closure
mustBeFunction(fn) mustBeFunction(fn)

View File

@@ -5,7 +5,7 @@ import (
"reflect" "reflect"
) )
func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value { func invokeFunc(fn any, args ...any) []reflect.Value {
fv := functionValue(fn) fv := functionValue(fn)
params := make([]reflect.Value, len(args)) params := make([]reflect.Value, len(args))
for i, item := range args { for i, item := range args {
@@ -14,7 +14,7 @@ func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
return fv.Call(params) return fv.Call(params)
} }
func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value { func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
fv := reflect.ValueOf(fn) fv := reflect.ValueOf(fn)
params := make([]reflect.Value, len(args)) params := make([]reflect.Value, len(args))
for i, item := range args { for i, item := range args {
@@ -23,7 +23,7 @@ func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
return fv.Call(params) return fv.Call(params)
} }
func functionValue(function interface{}) reflect.Value { func functionValue(function any) reflect.Value {
v := reflect.ValueOf(function) v := reflect.ValueOf(function)
if v.Kind() != reflect.Func { if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function)) panic(fmt.Sprintf("Invalid function type, value of type %T", function))
@@ -31,7 +31,7 @@ func functionValue(function interface{}) reflect.Value {
return v return v
} }
func mustBeFunction(function interface{}) { func mustBeFunction(function any) {
v := reflect.ValueOf(function) v := reflect.ValueOf(function)
if v.Kind() != reflect.Func { if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function)) panic(fmt.Sprintf("Invalid function type, value of type %T", function))

View File

@@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAfter(t *testing.T) { func TestAfter(t *testing.T) {
@@ -16,7 +16,7 @@ func TestAfter(t *testing.T) {
fmt.Println("print done") fmt.Println("print done")
return i return i
}) })
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
print := func(i int, s string, fn cb) { print := func(i int, s string, fn cb) {
fmt.Printf("print: arr[%d] is %s \n", i, s) fmt.Printf("print: arr[%d] is %s \n", i, s)
v := fn(i) v := fn(i)
@@ -42,7 +42,7 @@ func TestBefore(t *testing.T) {
}) })
var res []int64 var res []int64
type cb func(args ...interface{}) []reflect.Value type cb func(args ...any) []reflect.Value
appendStr := func(i int, s string, fn cb) { appendStr := func(i int, s string, fn cb) {
v := fn(i) v := fn(i)
res = append(res, v[0].Int()) res = append(res, v[0].Int())
@@ -62,7 +62,7 @@ func TestCurry(t *testing.T) {
add := func(a, b int) int { add := func(a, b int) int {
return a + b return a + b
} }
var addCurry Fn = func(values ...interface{}) interface{} { var addCurry Fn = func(values ...any) any {
return add(values[0].(int), values[1].(int)) return add(values[0].(int), values[1].(int))
} }
add1 := addCurry.Curry(1) add1 := addCurry.Curry(1)
@@ -72,10 +72,10 @@ func TestCurry(t *testing.T) {
func TestCompose(t *testing.T) { func TestCompose(t *testing.T) {
assert := internal.NewAssert(t, "TestCompose") assert := internal.NewAssert(t, "TestCompose")
toUpper := func(a ...interface{}) interface{} { toUpper := func(a ...any) any {
return strings.ToUpper(a[0].(string)) return strings.ToUpper(a[0].(string))
} }
toLower := func(a ...interface{}) interface{} { toLower := func(a ...any) any {
return strings.ToLower(a[0].(string)) return strings.ToLower(a[0].(string))
} }

View File

@@ -3,7 +3,7 @@ package function
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestWatcher(t *testing.T) { func TestWatcher(t *testing.T) {

4
go.mod
View File

@@ -1,3 +1,3 @@
module github.com/duke-git/lancet module github.com/duke-git/lancet/v2
go 1.16 go 1.18

View File

@@ -30,14 +30,14 @@ func NewAssert(t *testing.T, caseName string) *Assert {
} }
// Equal check if expected is equal with actual // Equal check if expected is equal with actual
func (a *Assert) Equal(expected, actual interface{}) { func (a *Assert) Equal(expected, actual any) {
if compare(expected, actual) != compareEqual { if compare(expected, actual) != compareEqual {
makeTestFailed(a.T, a.CaseName, expected, actual) makeTestFailed(a.T, a.CaseName, expected, actual)
} }
} }
// NotEqual check if expected is not equal with actual // NotEqual check if expected is not equal with actual
func (a *Assert) NotEqual(expected, actual interface{}) { func (a *Assert) NotEqual(expected, actual any) {
if compare(expected, actual) == compareEqual { if compare(expected, actual) == compareEqual {
expectedInfo := fmt.Sprintf("not %v", expected) expectedInfo := fmt.Sprintf("not %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual) makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -45,7 +45,7 @@ func (a *Assert) NotEqual(expected, actual interface{}) {
} }
// Greater check if expected is greate than actual // Greater check if expected is greate than actual
func (a *Assert) Greater(expected, actual interface{}) { func (a *Assert) Greater(expected, actual any) {
if compare(expected, actual) != compareGreater { if compare(expected, actual) != compareGreater {
expectedInfo := fmt.Sprintf("> %v", expected) expectedInfo := fmt.Sprintf("> %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual) makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -53,7 +53,7 @@ func (a *Assert) Greater(expected, actual interface{}) {
} }
// GreaterOrEqual check if expected is greate than or equal with actual // GreaterOrEqual check if expected is greate than or equal with actual
func (a *Assert) GreaterOrEqual(expected, actual interface{}) { func (a *Assert) GreaterOrEqual(expected, actual any) {
isGreatOrEqual := compare(expected, actual) == compareGreater || compare(expected, actual) == compareEqual isGreatOrEqual := compare(expected, actual) == compareGreater || compare(expected, actual) == compareEqual
if !isGreatOrEqual { if !isGreatOrEqual {
expectedInfo := fmt.Sprintf(">= %v", expected) expectedInfo := fmt.Sprintf(">= %v", expected)
@@ -62,7 +62,7 @@ func (a *Assert) GreaterOrEqual(expected, actual interface{}) {
} }
// Less check if expected is less than actual // Less check if expected is less than actual
func (a *Assert) Less(expected, actual interface{}) { func (a *Assert) Less(expected, actual any) {
if compare(expected, actual) != compareLess { if compare(expected, actual) != compareLess {
expectedInfo := fmt.Sprintf("< %v", expected) expectedInfo := fmt.Sprintf("< %v", expected)
makeTestFailed(a.T, a.CaseName, expectedInfo, actual) makeTestFailed(a.T, a.CaseName, expectedInfo, actual)
@@ -70,7 +70,7 @@ func (a *Assert) Less(expected, actual interface{}) {
} }
// LessOrEqual check if expected is less than or equal with actual // LessOrEqual check if expected is less than or equal with actual
func (a *Assert) LessOrEqual(expected, actual interface{}) { func (a *Assert) LessOrEqual(expected, actual any) {
isLessOrEqual := compare(expected, actual) == compareLess || compare(expected, actual) == compareEqual isLessOrEqual := compare(expected, actual) == compareLess || compare(expected, actual) == compareEqual
if !isLessOrEqual { if !isLessOrEqual {
expectedInfo := fmt.Sprintf("<= %v", expected) expectedInfo := fmt.Sprintf("<= %v", expected)
@@ -79,14 +79,14 @@ func (a *Assert) LessOrEqual(expected, actual interface{}) {
} }
// IsNil check if value is nil // IsNil check if value is nil
func (a *Assert) IsNil(value interface{}) { func (a *Assert) IsNil(value any) {
if value != nil { if value != nil {
makeTestFailed(a.T, a.CaseName, nil, value) makeTestFailed(a.T, a.CaseName, nil, value)
} }
} }
// IsNotNil check if value is not nil // IsNotNil check if value is not nil
func (a *Assert) IsNotNil(value interface{}) { func (a *Assert) IsNotNil(value any) {
if value == nil { if value == nil {
makeTestFailed(a.T, a.CaseName, "not nil", value) makeTestFailed(a.T, a.CaseName, "not nil", value)
} }
@@ -94,7 +94,7 @@ func (a *Assert) IsNotNil(value interface{}) {
// compare x and y return : // compare x and y return :
// x > y -> 1, x < y -> -1, x == y -> 0, x != y -> -2 // x > y -> 1, x < y -> -1, x == y -> 0, x != y -> -2
func compare(x, y interface{}) int { func compare(x, y any) int {
vx := reflect.ValueOf(x) vx := reflect.ValueOf(x)
vy := reflect.ValueOf(y) vy := reflect.ValueOf(y)
@@ -163,7 +163,7 @@ func compare(x, y interface{}) int {
} }
// logFailedInfo make test failed and log error info // logFailedInfo make test failed and log error info
func makeTestFailed(t *testing.T, caseName string, expected, actual interface{}) { func makeTestFailed(t *testing.T, caseName string, expected, actual any) {
_, file, line, _ := runtime.Caller(2) _, file, line, _ := runtime.Caller(2)
errInfo := fmt.Sprintf("Case %v failed. file: %v, line: %v, expected: %v, actual: %v.", caseName, file, line, expected, actual) errInfo := fmt.Sprintf("Case %v failed. file: %v, line: %v, expected: %v, actual: %v.", caseName, file, line, expected, actual)
t.Error(errInfo) t.Error(errInfo)

View File

@@ -0,0 +1,18 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package lancetconstraints contain some comstomer constraints.
package lancetconstraints
// Comparator is for comparing two values
type Comparator interface {
// Compare v1 and v2
// Ascending order: should return 1 -> v1 > v2, 0 -> v1 = v2, -1 -> v1 < v2
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
Compare(v1, v2 any) int
}
// Number contains all types of number and uintptr, used for generics constraint
type Number interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64
}

106
maputil/map.go Normal file
View File

@@ -0,0 +1,106 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package maputil includes some functions to manipulate map.
package maputil
import "reflect"
// Keys returns a slice of the map's keys
func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
// Values returns a slice of the map's values
func Values[K comparable, V any](m map[K]V) []V {
values := make([]V, 0, len(m))
for _, v := range m {
values = append(values, v)
}
return values
}
// Merge maps, next key will overwrite previous key
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
res := make(map[K]V, 0)
for _, m := range maps {
for k, v := range m {
res[k] = v
}
}
return res
}
// ForEach executes iteratee funcation for every key and value pair in map
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
for k, v := range m {
iteratee(k, v)
}
}
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
res := make(map[K]V)
for k, v := range m {
if predicate(k, v) {
res[k] = v
}
}
return res
}
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
if len(maps) == 0 {
return map[K]V{}
}
if len(maps) == 1 {
return maps[0]
}
var res map[K]V
reducer := func(m1, m2 map[K]V) map[K]V {
m := make(map[K]V)
for k, v1 := range m1 {
if v2, ok := m2[k]; ok && reflect.DeepEqual(v1, v2) {
m[k] = v1
}
}
return m
}
reduceMaps := make([]map[K]V, 2, 2)
res = reducer(maps[0], maps[1])
for i := 2; i < len(maps); i++ {
reduceMaps[0] = res
reduceMaps[1] = maps[i]
res = reducer(reduceMaps[0], reduceMaps[1])
}
return res
}
// Minus creates an map of whose key in mapA but not in mapB
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
res := make(map[K]V)
for k, v := range mapA {
if _, ok := mapB[k]; !ok {
res[k] = v
}
}
return res
}

150
maputil/map_test.go Normal file
View File

@@ -0,0 +1,150 @@
package maputil
import (
"sort"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestKeys(t *testing.T) {
assert := internal.NewAssert(t, "TestKeys")
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
keys := Keys(m)
sort.Ints(keys)
assert.Equal([]int{1, 2, 3, 4, 5}, keys)
}
func TestValues(t *testing.T) {
assert := internal.NewAssert(t, "TestValues")
m := map[int]string{
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
values := Values(m)
sort.Strings(values)
assert.Equal([]string{"a", "a", "b", "c", "d"}, values)
}
func TestMerge(t *testing.T) {
assert := internal.NewAssert(t, "TestMerge")
m1 := map[int]string{
1: "a",
2: "b",
}
m2 := map[int]string{
1: "1",
3: "2",
}
expected := map[int]string{
1: "1",
2: "b",
3: "2",
}
acturl := Merge(m1, m2)
assert.Equal(expected, acturl)
}
func TestForEach(t *testing.T) {
assert := internal.NewAssert(t, "TestForEach")
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
var sum int
ForEach(m, func(_ string, value int) {
sum += value
})
assert.Equal(10, sum)
}
func TestFilter(t *testing.T) {
assert := internal.NewAssert(t, "TestFilter")
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
acturl := Filter(m, isEven)
assert.Equal(map[string]int{
"b": 2,
"d": 4,
}, acturl)
}
func TestIntersect(t *testing.T) {
assert := internal.NewAssert(t, "TestIntersect")
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,
}
assert.Equal(map[string]int{"a": 1, "b": 2, "c": 3}, Intersect(m1))
assert.Equal(map[string]int{"a": 1, "b": 2}, Intersect(m1, m2))
assert.Equal(map[string]int{"a": 1}, Intersect(m1, m2, m3))
}
func TestMinus(t *testing.T) {
assert := internal.NewAssert(t, "TestMinus")
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"a": 11,
"b": 22,
"d": 33,
}
assert.Equal(map[string]int{"c": 3}, Minus(m1, m2))
}

View File

@@ -9,6 +9,8 @@ import (
"math" "math"
"strconv" "strconv"
"strings" "strings"
"github.com/duke-git/lancet/v2/lancetconstraints"
) )
// Exponent calculate x^n // Exponent calculate x^n
@@ -90,3 +92,82 @@ func TruncRound(x float64, n int) float64 {
res, _ := strconv.ParseFloat(newFloat, 64) res, _ := strconv.ParseFloat(newFloat, 64)
return res return res
} }
// Max return max value of params
func Max[T lancetconstraints.Number](numbers ...T) T {
max := numbers[0]
for _, v := range numbers {
if max < v {
max = v
}
}
return max
}
// MaxBy search the maximum value of a slice using the given comparator function.
func MaxBy[T any](slice []T, comparator func(T, T) bool) T {
var max T
if len(slice) == 0 {
return max
}
max = slice[0]
for i := 1; i < len(slice); i++ {
val := slice[i]
if comparator(val, max) {
max = val
}
}
return max
}
// Min return min value of params
func Min[T lancetconstraints.Number](numbers ...T) T {
min := numbers[0]
for _, v := range numbers {
if min > v {
min = v
}
}
return min
}
// MinBy search the minimum value of a slice using the given comparator function.
func MinBy[T any](slice []T, comparator func(T, T) bool) T {
var min T
if len(slice) == 0 {
return min
}
min = slice[0]
for i := 1; i < len(slice); i++ {
val := slice[i]
if comparator(val, min) {
min = val
}
}
return min
}
// Average return average value of params
func Average[T lancetconstraints.Number](numbers ...T) T {
var sum T
n := T(len(numbers))
for _, v := range numbers {
sum += v
}
return sum / n
}

View File

@@ -3,7 +3,7 @@ package mathutil
import ( import (
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestExponent(t *testing.T) { func TestExponent(t *testing.T) {
@@ -70,3 +70,67 @@ func TestTruncRound(t *testing.T) {
assert.Equal(TruncRound(0.125, 3), float64(0.125)) assert.Equal(TruncRound(0.125, 3), float64(0.125))
assert.Equal(TruncRound(33.33333, 2), float64(33.33)) assert.Equal(TruncRound(33.33333, 2), float64(33.33))
} }
func TestAverage(t *testing.T) {
assert := internal.NewAssert(t, "TestAverage")
assert.Equal(Average(0, 0), 0)
assert.Equal(Average(1, 1), 1)
avg := Average(1.2, 1.4)
t.Log(avg)
assert.Equal(1.3, RoundToFloat(avg, 1))
}
func TestMax(t *testing.T) {
assert := internal.NewAssert(t, "TestMax")
assert.Equal(Max(0, 0), 0)
assert.Equal(Max(1, 2, 3), 3)
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
}
func TestMaxBy(t *testing.T) {
assert := internal.NewAssert(t, "MaxBy")
res1 := MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
assert.Equal("abc", res1)
res2 := MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
assert.Equal("abd", res2)
res3 := MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2)
})
assert.Equal("", res3)
}
func TestMin(t *testing.T) {
assert := internal.NewAssert(t, "TestMin")
assert.Equal(Min(0, 0), 0)
assert.Equal(Min(1, 2, 3), 1)
assert.Equal(Min(1.2, 1.4, 1.1, 1.4), 1.1)
}
func TestMinBy(t *testing.T) {
assert := internal.NewAssert(t, "TestMinBy")
res1 := MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
assert.Equal("a", res1)
res2 := MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
assert.Equal("ab", res2)
res3 := MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2)
})
assert.Equal("", res3)
}

View File

@@ -6,7 +6,8 @@
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required. // HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is: // HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
// params[0] is header which type should be http.Header or map[string]string, // params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{}, // params[1] is query param which type should be url.Values or map[string]any, when content-type header is
// multipart/form-data or application/x-www-form-urlencoded, params[1] should be url.Values
// params[2] is post body which type should be []byte. // params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
package netutil package netutil
@@ -21,32 +22,32 @@ import (
) )
//HttpGet send get http request //HttpGet send get http request
func HttpGet(url string, params ...interface{}) (*http.Response, error) { func HttpGet(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodGet, url, params...) return doHttpRequest(http.MethodGet, url, params...)
} }
//HttpPost send post http request //HttpPost send post http request
func HttpPost(url string, params ...interface{}) (*http.Response, error) { func HttpPost(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPost, url, params...) return doHttpRequest(http.MethodPost, url, params...)
} }
//HttpPut send put http request //HttpPut send put http request
func HttpPut(url string, params ...interface{}) (*http.Response, error) { func HttpPut(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPut, url, params...) return doHttpRequest(http.MethodPut, url, params...)
} }
//HttpDelete send delete http request //HttpDelete send delete http request
func HttpDelete(url string, params ...interface{}) (*http.Response, error) { func HttpDelete(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodDelete, url, params...) return doHttpRequest(http.MethodDelete, url, params...)
} }
// HttpPatch send patch http request // HttpPatch send patch http request
func HttpPatch(url string, params ...interface{}) (*http.Response, error) { func HttpPatch(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPatch, url, params...) return doHttpRequest(http.MethodPatch, url, params...)
} }
// ParseHttpResponse decode http response to specified interface // ParseHttpResponse decode http response to specified interface
func ParseHttpResponse(resp *http.Response, obj interface{}) error { func ParseHttpResponse(resp *http.Response, obj any) error {
if resp == nil { if resp == nil {
return errors.New("InvalidResp") return errors.New("InvalidResp")
} }
@@ -55,7 +56,7 @@ func ParseHttpResponse(resp *http.Response, obj interface{}) error {
} }
// ConvertMapToQueryString convert map to sorted url query string // ConvertMapToQueryString convert map to sorted url query string
func ConvertMapToQueryString(param map[string]interface{}) string { func ConvertMapToQueryString(param map[string]any) string {
if param == nil { if param == nil {
return "" return ""
} }

View File

@@ -4,9 +4,10 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"log" "log"
"net/url"
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestHttpGet(t *testing.T) { func TestHttpGet(t *testing.T) {
@@ -46,6 +47,29 @@ func TestHttpPost(t *testing.T) {
t.Log("response: ", resp.StatusCode, string(body)) t.Log("response: ", resp.StatusCode, string(body))
} }
func TestHttpPostFormData(t *testing.T) {
apiUrl := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
// "Content-Type": "application/x-www-form-urlencoded",
"Content-Type": "multipart/form-data",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestAddToDo")
resp, err := HttpPost(apiUrl, header, postData, nil)
if err != nil {
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
}
func TestHttpPut(t *testing.T) { func TestHttpPut(t *testing.T) {
url := "https://jsonplaceholder.typicode.com/todos/1" url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{ header := map[string]string{
@@ -104,7 +128,7 @@ func TestHttpDelete(t *testing.T) {
func TestConvertMapToQueryString(t *testing.T) { func TestConvertMapToQueryString(t *testing.T) {
assert := internal.NewAssert(t, "TestConvertMapToQueryString") assert := internal.NewAssert(t, "TestConvertMapToQueryString")
var m = map[string]interface{}{ var m = map[string]any{
"c": 3, "c": 3,
"a": 1, "a": 1,
"b": 2, "b": 2,

View File

@@ -10,7 +10,7 @@ import (
"strings" "strings"
) )
func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response, error) { func doHttpRequest(method, reqUrl string, params ...any) (*http.Response, error) {
if len(reqUrl) == 0 { if len(reqUrl) == 0 {
return nil, errors.New("url should be specified") return nil, errors.New("url should be specified")
} }
@@ -60,7 +60,7 @@ func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response
return resp, e return resp, e
} }
func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam interface{}) error { func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam any) error {
err := setHeader(req, header) err := setHeader(req, header)
if err != nil { if err != nil {
return err return err
@@ -72,7 +72,7 @@ func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam
return nil return nil
} }
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body interface{}) error { func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body any) error {
err := setHeader(req, header) err := setHeader(req, header)
if err != nil { if err != nil {
return err return err
@@ -81,14 +81,20 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
if err != nil { if err != nil {
return err return err
} }
err = setBodyByte(req, body) if req.Header.Get("Content-Type") == "multipart/form-data" || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
formData := queryParam.(url.Values)
err = setBodyByte(req, []byte(formData.Encode()))
} else {
err = setBodyByte(req, body)
}
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func setHeader(req *http.Request, header interface{}) error { func setHeader(req *http.Request, header any) error {
if header != nil { if header != nil {
switch v := header.(type) { switch v := header.(type) {
case map[string]string: case map[string]string:
@@ -122,11 +128,11 @@ func setUrl(req *http.Request, reqUrl string) error {
return nil return nil
} }
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error { func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
var values url.Values var values url.Values
if queryParam != nil { if queryParam != nil {
switch v := queryParam.(type) { switch v := queryParam.(type) {
case map[string]interface{}: case map[string]any:
values = url.Values{} values = url.Values{}
for k := range v { for k := range v {
values.Set(k, fmt.Sprintf("%v", v[k])) values.Set(k, fmt.Sprintf("%v", v[k]))
@@ -134,7 +140,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
case url.Values: case url.Values:
values = v values = v
default: default:
return errors.New("query params type should be url.Values or map[string]interface{}") return errors.New("query params type should be url.Values or map[string]any")
} }
} }
@@ -155,7 +161,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
return nil return nil
} }
func setBodyByte(req *http.Request, body interface{}) error { func setBodyByte(req *http.Request, body any) error {
if body != nil { if body != nil {
switch b := body.(type) { switch b := body.(type) {
case []byte: case []byte:
@@ -168,7 +174,7 @@ func setBodyByte(req *http.Request, body interface{}) error {
return nil return nil
} }
func getClient(client interface{}) (*http.Client, error) { func getClient(client any) (*http.Client, error) {
c := http.Client{} c := http.Client{}
if client != nil { if client != nil {
switch v := client.(type) { switch v := client.(type) {

View File

@@ -4,7 +4,7 @@ import (
"net" "net"
"testing" "testing"
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestGetInternalIp(t *testing.T) { func TestGetInternalIp(t *testing.T) {

Some files were not shown because too many files have changed in this diff Show More