1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

Compare commits

...

349 Commits

Author SHA1 Message Date
dudaodong
967e6a3493 doc: update doc for v2.3.1 2024-05-14 10:47:27 +08:00
dudaodong
5b24801e49 merge qa branch 2024-05-14 10:11:29 +08:00
dudaodong
974ba525a6 Merge branch 'rc' into v2 2024-05-14 10:10:45 +08:00
chentong
f0235c40b6 fix: json tag omitempty convert error (#218) 2024-05-14 10:08:56 +08:00
dudaodong
712a215ea6 reset 2024-05-14 10:02:56 +08:00
dudaodong
7893f828d3 fix: fix get tag failed 2024-05-13 17:49:34 +08:00
Yang Li
53fa210f09 refactor slice.Unique() (#215) 2024-05-09 10:43:59 +08:00
dudaodong
de9ee08be4 test: update net error handle 2024-04-18 14:23:36 +08:00
dudaodong
5381450bea feat: fix email validation failed 2024-04-18 14:18:33 +08:00
Cannian
6853d627f4 refactor(slice): optimize function (#211) 2024-04-06 09:16:28 +08:00
Joker-desire
e461acdb72 fix(netutil): Add proxy IP to send request (#210)
* fix(netutil): Add proxy ip to send request

* fix(netutil): Add proxy IP to send request

---------

Co-authored-by: 杨崟 <yangyin@addcn.com>
2024-04-03 16:52:53 +08:00
dudaodong
2a796adf85 fix: support nest struct in StructToUrlValues 2024-04-02 17:38:40 +08:00
Cannian
5e6e8d82a8 feat(maputil): add ToSortedSlicesDefault method and ToSortedSlicesWithComparator method (#206) 2024-03-31 21:04:55 +08:00
Cannian
e9280b8c25 add Concat method (#204)
* feat(strutil): add Concat method

* feat(strutil): add Concat method
2024-03-25 10:26:37 +08:00
dudaodong
bb6f10a1fb rename CONTRIBUTING file 2024-03-17 10:30:24 +08:00
dudaodong
33b4cffe60 rename CONTRIBUTING file 2024-03-17 10:30:07 +08:00
Cannian
2b765b49e0 refactor(set): pop method randomly removes an element and return (#202) 2024-03-17 10:28:25 +08:00
dudaodong
004dbdc32e doc: update doc for RightPadding and LeftPadding 2024-03-12 09:52:02 +08:00
donutloop
ab50e8120a Slice: padding (#201)
* LeftPadding adds padding to the left begin of a slice.
* RightPadding adds padding to the right end of a slice.
2024-03-10 21:24:17 +08:00
dudaodong
73c97af7d8 doc: update doc for Break function 2024-03-08 21:39:06 +08:00
donutloop
5e8a065eaa Slice: break (#200)
Splits a slice into two based on a predicate function. It starts appending to the second slice after the first element that matches the predicate. All elements after the first match are included in the second slice, regardless of whether they match the predicate or not.
2024-03-07 14:11:19 +08:00
dudaodong
aa74400607 doc: fix doc text error 2024-03-06 16:19:20 +08:00
dudaodong
a6eaaef563 doc: add go playground demo 2024-03-06 15:28:55 +08:00
dudaodong
1b31014f81 doc: add go playground demo 2024-03-06 14:52:35 +08:00
dudaodong
036847577d release v2.3.0 2024-03-05 14:57:16 +08:00
dudaodong
d21edd1cde doc: add doc for retry package 2024-03-05 14:38:42 +08:00
dudaodong
c58c50327c doc: add doc for ChunkRead and ParallelChunkRead 2024-03-05 11:42:03 +08:00
dudaodong
9bfdc686f8 doc: update contribution_guide file 2024-03-05 10:47:51 +08:00
dudaodong
5ca8f6ef6f doc: update doc 2024-03-05 10:45:40 +08:00
dudaodong
a54d4c79a0 doc: update doc for mathutil package 2024-03-04 19:52:49 +08:00
Cannian
f7b54986aa feat(mathutil): add DIv, FloorToFloat, FloorToString, CeilToFloat, CeilToString (#199) 2024-03-04 17:40:31 +08:00
dudaodong
92fae4273b doc: update doc for new added functions 2024-03-04 16:42:59 +08:00
dudaodong
0d29f5437a doc: update doc for new added functions 2024-03-04 16:41:54 +08:00
dudaodong
e95d7c82cd doc: update doc for function package 2024-03-04 10:19:39 +08:00
donutloop
e138043289 Function: AcceptIf (#198)
AcceptIf returns another function of the same signature as the apply function but also includes a bool value to indicate success or failure.
A predicate function that takes an argument of type T and returns a bool.
An apply function that also takes an argument of type T and returns a modified value of the same type.
2024-03-04 10:00:43 +08:00
dudaodong
aabfcb7bde doc: update doc for HammingDistance 2024-03-03 21:55:27 +08:00
donutloop
0b5e884371 Strutil: HammingDistance func (#197)
* Strutil: HammingDistance func

The Hamming distance is the number of positions at which the corresponding symbols are different

* Add hamming distance doc
2024-03-03 21:48:34 +08:00
dudaodong
3d1bd08434 doc: update doc for new functions 2024-03-01 22:38:57 +08:00
dudaodong
a62ad71791 Merge branch 'rc' into v2 2024-03-01 21:45:08 +08:00
Cannian
c02c4f813b refactor(mathutil): round related method support generics (#195) 2024-03-01 16:04:23 +08:00
pigwantacat
235d2f2486 修复MAXIMUM_CAPACITY超过int最大值 (#196)
* refactor:refactor random function

* fix:fix random function

---------

Co-authored-by: zhuhebin <zhuhebin@fengtaisec.com>
2024-03-01 15:52:49 +08:00
dudaodong
e9380a3d9f fix: fix unused parameters vet issue 2024-03-01 10:05:28 +08:00
Cannian
81d13c2f1a feat(convertor): add ToBase64 related method (#194) 2024-02-29 19:22:32 +08:00
dudaodong
7290296849 update Contributing Guide 2024-02-29 11:49:34 +08:00
dudaodong
8a8460a592 Merge branch 'rc' into v2 2024-02-29 11:34:53 +08:00
dudaodong
7a98c431d3 Merge branch 'main' of github.com:duke-git/lancet 2024-02-29 11:32:44 +08:00
colorcrow
606d887230 增加ParallelChunkRead方法,分块并发读取超大文本 (#192) 2024-02-29 11:32:10 +08:00
donutloop
473f9c9f3e Iterator: general refactoring and reset method (#193)
Feature

Reset allows for the iteration process over a sequence to be restarted from the beginning.
It enables reusing the iterator for multiple traversals without needing to recreate it.

Refactoring

It is a idiomatic practice to design functions and methods to return concrete struct types.
This approach promotes flexibility and decoupling, allowing the calling code to work with any implementation that satisfies the interface
2024-02-29 11:30:12 +08:00
dudaodong
9ff3d0e79c create rc branch for release candidate 2024-02-29 11:25:20 +08:00
dudaodong
5db1d07d6d Merge branch 'main' into v2 2024-02-28 15:55:59 +08:00
Cannian
6c6d14828a feat(set, doc): add ToSlice,ToSortedSlice method,fix doc (#189) 2024-02-28 15:43:34 +08:00
donutloop
0e1593c67b Slice: Add SetToDefaultIf (#187)
SetToDefaultIf sets elements to their zero value if they match the given predicate.
It retains the positions of the elements in the slice.
It returns slice of T and the count of modified slice items
2024-02-28 11:27:23 +08:00
cannian1
6c7f38d8b3 feat: more readable panic (#183) 2024-02-27 10:38:08 +08:00
donutloop
069812e0ee Hashmap: Add FilterByValue (#184)
The FilterByValue function is a method defined on the HashMap type. It generates a new HashMap
containing only the elements that satisfy a specified condition,
as determined by a predicate function applied to each element's value.

Note: Will add later doc
2024-02-27 10:36:26 +08:00
dudaodong
4a539a23c8 doc: add doc for Xnor and Nand in function package 2024-02-26 10:10:37 +08:00
dudaodong
0b1dab0399 Merge branch 'main' into v2 2024-02-26 10:02:00 +08:00
donutloop
805e2543d0 Add functional predicate NAND (#182)
Add new function, NAND, designed to create a composed predicate representing the logical NAND operation
applied to a list of predicates. The NAND operation is a logical operation
that returns true only if all perdicate result in false otherwise false
2024-02-26 09:58:19 +08:00
dudaodong
a3d518da76 remove test_src directory 2024-02-25 20:29:49 +08:00
dudaodong
e3e2d8394c Merge branch 'v2' of github.com:duke-git/lancet into v2 2024-02-25 20:25:44 +08:00
yunxuan
0eeaa06055 feat(fileutil): add CopyDir func (#180)
* add fileutil.CopyDir

* remove debug code
2024-02-25 20:25:00 +08:00
donutloop
a43bc554ee Add functional predicate XNOR (#181)
Add new function, Xnor, designed to create a composed predicate representing
the logical Exclusive NOR (XNOR) operation applied to a list of predicates.
The XNOR operation is a logical operation that returns true only
if all operands have the same boolean value
2024-02-25 20:24:47 +08:00
dudaodong
aebab7c944 refactor: break change, rename constructor of set (NewSet->New, NewSetFromSlice->FromSlice) 2024-02-25 09:32:32 +08:00
dudaodong
665bad4ca3 doc: update doc for IndexOfFunc and LastIndexOfFunc 2024-02-25 09:25:07 +08:00
donutloop
e4901e99e9 Fix optional doc links (#179) 2024-02-24 18:12:44 +08:00
donutloop
4277e8eca5 CopyOnWriteList add IndexOfFunc and LastIndexOfFunc (#178)
Allow users to apply functional predicates alongside 'index of' and 'last index of' search methods in this specialized list variant
2024-02-24 17:53:58 +08:00
donutloop
fdc93c8cc7 Change naming (#177)
Utilize terminology from the Go SDK rather than introducing novel terms to describe concepts.
2024-02-24 17:25:31 +08:00
donutloop
860a499f98 Add custom backoff setter (#176)
Users should have the capability to customize the backoff pattern and accordingly adjust it within the retry mechanism.
2024-02-23 10:04:38 +08:00
dudaodong
2e1c2276a5 test: add test coverageg 2024-02-22 14:39:53 +08:00
donutloop
d367397dab Add exponential With jitter backoff (#174)
* Add exponential With jitter backoff

Adds exponential + jitter retry policy. To enable drastic slow down of sending out requests to any external system.

Jitter in computational contexts refers to the addition of a small random variation to a value
to break the symmetric patterns

* Retry with exp: Allow shift for all multiple of 2
2024-02-22 10:39:45 +08:00
dudaodong
66fd8cf651 fix: fix go vet issue 2024-02-21 11:14:19 +08:00
dudaodong
a6be1828b9 doc: add doc and example for predicate logic of function package 2024-02-21 11:13:47 +08:00
dudaodong
8f5d297572 . 2024-02-21 11:11:52 +08:00
dudaodong
a1a4fdc598 doc: update doc for optional 2024-02-21 10:38:26 +08:00
dudaodong
1610076d22 Merge branch 'main' into v2 2024-02-21 10:21:42 +08:00
donutloop
cacbf97223 Add Retry backoff policy (#173)
The aim of this policy is to enable the configuration of various types of backoff mathematical curves. Should this modification be deemed suitable,
I will proceed to implement an exponential curve backoff policy and set of custom backoff policy
Warning: It's major break
2024-02-21 10:20:24 +08:00
donutloop
cd156dba5f Add functional nor predicate (#172) 2024-02-21 10:05:54 +08:00
dudaodong
3a71a8697d fix: fix issue #169 2024-02-20 17:29:32 +08:00
dudaodong
c88fd3db86 fix: fix go vet issue, method Unwrap() []error 2024-02-20 11:41:58 +08:00
dudaodong
27d19d1717 fix: rename Seek to SeekOffset fix go vet check issue 2024-02-20 11:39:41 +08:00
dudaodong
da24bae6b4 doc: add doc for Optional type 2024-02-20 11:22:39 +08:00
donutloop
3cd9d6b68c Add functional predicate (#171)
Enable the execution of assertion functions in a functional manner.
2024-02-20 09:55:39 +08:00
dudaodong
874d09f331 refactor: make stream struct exported 2024-02-19 15:55:08 +08:00
dudaodong
fdf251ac98 add govet check to github action file 2024-02-19 15:50:19 +08:00
dudaodong
7ec2533b7a feat: add MapToStruct 2024-02-19 13:50:06 +08:00
dudaodong
9fd0603f4a fix: fix copylocks warning in Optional struct methods 2024-02-19 10:22:28 +08:00
dudaodong
9f7b416a8d Merge branch 'main' into v2 2024-02-19 10:00:21 +08:00
donutloop
bf4b2b5fd6 Add optional (#170)
* Add optional

Wrapper container with easy to understand helper methods

* Add test and rewrite test

* Add panic test

* Add TestOrElseGetHappyPath
2024-02-19 09:59:42 +08:00
dudaodong
22af59565e fix: fix issue #168 2024-02-06 16:59:01 +08:00
dudaodong
f9e047f190 feat: add SubInBetween 2024-02-06 16:47:30 +08:00
dudaodong
fa298b740d add playground demo 2024-02-01 10:41:09 +08:00
dudaodong
6d4fc981b6 release v2.2.9 2024-02-01 10:03:26 +08:00
dudaodong
4c21fe700c refactor: update StringToBytes logic 2024-01-30 10:46:55 +08:00
pigwantacat
b7370e8ef8 refactor:refactor random function (#164)
Co-authored-by: zhuhebin <zhuhebin@fengtaisec.com>
2024-01-30 10:00:14 +08:00
dudaodong
38920e3be6 fix: fix issue #162 2024-01-29 11:00:50 +08:00
dudaodong
a630a7cda9 refactor: remove struct_internal.go 2024-01-29 10:02:36 +08:00
dudaodong
66dfd9c4fd refactor: refact Comma function 2024-01-25 16:45:17 +08:00
dudaodong
be62aaac9b refactor: update signature of WriteMapsToCsv function
g
2024-01-24 11:54:42 +08:00
dudaodong
e0c9ccbce3 doc: add DeleteRange 2024-01-23 17:27:28 +08:00
dudaodong
d2d1e5a055 feat: refact DeleteAt and add DeleteRange function 2024-01-22 15:34:35 +08:00
dudaodong
bbc58c7e46 fix: fix the map key order issue of WriteMapsToCsv 2024-01-22 11:10:02 +08:00
dudaodong
ac2ecceaec refactor: refact reduce function 2024-01-03 10:46:28 +08:00
dudaodong
a06bb8ee6a fix: fix unit test for WriteMapsToCsv 2024-01-01 18:32:41 +08:00
dudaodong
27b5702fd3 fix: fix unit test for WriteMapsToCsv 2024-01-01 17:51:32 +08:00
dudaodong
b2c3fa0ab8 fix: fix golint issue 2024-01-01 17:43:11 +08:00
dudaodong
4afc838937 doc: add doc for WriteMapsToCsv 2024-01-01 17:40:32 +08:00
colorcrow
3482f80d1c WriteCsvFile自定义分割符,增加map切片写入csv,增加追踪函数运行时间的函数 (#157)
* WriteCsvFile now support custom delimiter,Add write map slice to csv

* add trace func time
2024-01-01 16:54:04 +08:00
suacrbah
565f2893b9 feat: add support for seeking and read one line at a time from file (#158)
* feat: add support for seeking and read one line at a time from file

* feat: add support for calculating folder total size

---------

Co-authored-by: Suacrbah <5744580+Suacrbah@user.noreply.gitee.com>
2024-01-01 16:50:54 +08:00
dudaodong
1b1b10d0ee merge main branch 2023-12-29 10:17:04 +08:00
Gregory Koganovskiy
c5c3888ffc Fix typos in README (#154) 2023-12-29 10:12:29 +08:00
duckjiangwei
11214986cc add new func & docs error repair (#153)
* feat: add method IsTargetType()

* docs:document error repair
2023-12-28 10:27:32 +08:00
dudaodong
0bc7b83e59 Merge branch 'main' into v2 2023-12-21 10:03:35 +08:00
duckjiangwei
6225418074 improvement:optimize bubble sort (#152) 2023-12-21 10:02:23 +08:00
dudaodong
ddd265de78 fix: fix comment error 2023-12-19 15:36:07 +08:00
dudaodong
80e48f06ca refactor: rename lancetconstraints package name to constraints 2023-12-16 19:29:06 +08:00
dudaodong
0b976e9a4c fix: fix failed unit test 2023-12-11 15:45:02 +08:00
dudaodong
96320069f4 doc: update for release v2.2.8 2023-12-11 15:30:33 +08:00
dudaodong
c5297ec329 fix: fix failed unit test 2023-12-11 15:04:54 +08:00
dudaodong
aa4b61ff85 release v2.2.8 2023-12-11 14:59:20 +08:00
dudaodong
7dbd7002a3 doc: update doc for new release 2023-12-11 14:58:28 +08:00
dudaodong
a995db445a doc: update doc for random package 2023-12-08 11:57:39 +08:00
dudaodong
6e5b67bee7 feat: add RandFloat and RandFloats 2023-12-07 19:41:45 +08:00
dudaodong
52b8ea8166 doc: update doc for random package 2023-12-07 19:13:05 +08:00
dudaodong
6fe8a9efe7 feat: add RandSymbolChar 2023-12-07 17:56:12 +08:00
dudaodong
dcef06e9da fix: fix dns regex matcher 2023-12-07 09:54:03 +08:00
dudaodong
8f410bf9cb Merge branch 'main' into v2 2023-12-01 16:43:36 +08:00
dengrandpa
9cd6eb4ddf fix(validator): [IsChineseIdNum] fix 身份证效验 新增 省份、生日、效验码效验,修改ContainLower/IsNumber 注释错误 (#149)
* fix: 修改 README_zh-CN.md datetime 重复 IsLeapYear问题

* fix: 修改 README_zh-CN.md 18. slice 回到目录

* fix(validator): [IsChineseIdNum] fix 身份证效验 新增 省份、生日、效验码效验,修改ContainLower/IsNumber 注释错误

* fix(validator): [IsChineseIdNum] fix 修改测试

---------

Co-authored-by: dengjiaxiang <19181730103@189.cn>
Co-authored-by: dengrandpa <dengrandpapa@outlook.com>
2023-12-01 16:42:35 +08:00
dudaodong
bf581162ee Merge branch 'main' into v2 2023-11-29 11:46:09 +08:00
dengrandpa
bd984fa378 fix: 修改 README_zh-CN.md 文档错误 (#147)
* fix: 修改 README_zh-CN.md datetime 重复 IsLeapYear问题

* fix: 修改 README_zh-CN.md 18. slice 回到目录

---------

Co-authored-by: dengjiaxiang <19181730103@189.cn>
2023-11-29 11:43:54 +08:00
dudaodong
d7f23e2dee Merge branch 'main' into v2 2023-11-22 17:20:17 +08:00
o98k
3802c715c3 [feature]<slice>: support random item (#146)
Signed-off-by: o98k-ok <hggend@gmail.com>
2023-11-22 16:51:37 +08:00
dudaodong
4b12173f24 Merge branch 'main' into v2 2023-11-16 15:28:34 +08:00
guangwu
31c618c187 chore: use bytes.Equal instead (#144) 2023-11-16 15:26:20 +08:00
dudaodong
6497b321b0 refactor: clean code 2023-10-30 17:55:18 +08:00
dudaodong
bda78201f5 doc: update readme file 2023-10-28 17:02:24 +08:00
dudaodong
0753ea2801 feat: add context for httpClient SendRequest function 2023-10-18 19:13:34 +08:00
dudaodong
e25b53712b doc: add play ground demo 2023-10-08 11:19:44 +08:00
dudaodong
56c9327a86 release v2.2.7 2023-10-07 11:40:38 +08:00
dudaodong
11eb559998 update readme file 2023-10-07 11:15:14 +08:00
dudaodong
61a612a06a update: update Enqueue and Dequeue 2023-10-07 10:53:45 +08:00
dudaodong
2351ab4714 Merge branch 'v2' of github.com:duke-git/lancet into v2 2023-09-24 19:09:31 +08:00
dudaodong
88eec858b4 test: add test file 2023-09-24 19:09:19 +08:00
dudaodong
14c37b5a5f Merge branch 'v2' of github.com:duke-git/lancet into v2 2023-09-23 13:48:40 +08:00
dudaodong
ad8b1d424c Merge branch 'main' into v2 2023-09-23 13:48:25 +08:00
flytutu
a9f01d8a69 [opt] currentPath support windows and linux (#139)
Co-authored-by: hesu <hesu@eacomp.com>
2023-09-23 13:45:21 +08:00
o98k
781b89d51a feat(fileutil): add ReadFile func (#140) 2023-09-23 13:45:02 +08:00
dudaodong
073c77e751 refactor: remove unused code 2023-09-19 17:44:49 +08:00
dudaodong
91a0d3077d doc: update cryptor doc 2023-09-17 16:22:47 +08:00
dudaodong
17b34f8f19 doc: add doc for GenerateRsaKeyPair, RsaEncryptOAEP, RsaDecryptOAEP 2023-09-14 14:15:10 +08:00
dudaodong
8ff37f0eff feat: add GenerateRsaKeyPair, RsaEncryptOAEP, RsaDecryptOAEP 2023-09-14 14:06:54 +08:00
elza
f445ecbaf8 feat: add IsNotBlank func (#132)
Co-authored-by: yuanyou <yuanyou@kezaihui.com>
2023-09-13 15:29:26 +08:00
dudaodong
b698fec50f doc: add go playground demo 2023-09-11 15:59:35 +08:00
dudaodong
b38bb66b34 doc: update readme file 2023-09-11 11:51:45 +08:00
dudaodong
bdfdeaf496 merge branch 'main' into v2 2023-09-11 11:40:46 +08:00
dudaodong
172c44c07a doc: update doc site 2023-09-11 11:39:21 +08:00
dudaodong
534263eb08 release v2.2.6 2023-09-11 11:38:45 +08:00
dudaodong
a25b1ac7e3 doc: update doc site 2023-09-11 11:35:37 +08:00
dudaodong
d84f9777ea doc: update doc site 2023-09-11 11:33:39 +08:00
godaner
f9caaf8063 Update strutil.md (#130)
Update Coverts string to upper KEBAB-CASE,... to Coverts string to upper snake_case,...
2023-09-08 20:14:10 +08:00
dudaodong
f198711d1c doc: add doc for new functions 2023-09-07 16:03:08 +08:00
dudaodong
19378ca4d1 feat: add IsVisa, IsMasterCard, IsAmericanExpress, IsUnionPay, IsChinaUnionPay 2023-09-06 18:05:15 +08:00
dudaodong
71c7733eb0 feat: add IsBin, IsHex, IsBase64URL, IsJWT 2023-09-06 17:42:31 +08:00
dudaodong
20786c360b test: add cases for TestIsIpV4 and TestIsIpV6 2023-09-06 16:27:14 +08:00
dudaodong
51fafa110e merge main 2023-09-06 16:19:11 +08:00
Wang Huan
07fc453b74 fix the bug in cloning slices (#129)
* test: add test cases for cloning slices.

* fix: fix the bug in cloning slices.
2023-09-06 16:16:25 +08:00
dudaodong
b309044981 doc: add doc for Partition 2023-09-04 16:23:23 +08:00
dudaodong
541e6d4ea3 feat: add Partition for slice 2023-09-04 11:30:50 +08:00
dudaodong
4037b96cc4 refactor: update SortByField 2023-09-04 11:03:22 +08:00
dudaodong
8e484c4a6f doc: update doc site 2023-09-04 10:31:02 +08:00
dudaodong
dd339563bc doc: add contribution and contributors to doc site 2023-09-01 16:47:33 +08:00
dudaodong
9567dcc57f doc: update doc site 2023-09-01 16:01:17 +08:00
dudaodong
de104ebeb6 doc: update contributors setting 2023-08-31 17:07:31 +08:00
dudaodong
eebd95395f doc: add contributors setting 2023-08-31 16:59:38 +08:00
dudaodong
56265647ff doc: update doc styles 2023-08-31 16:42:33 +08:00
dudaodong
756da3719d doc: update doc styles 2023-08-31 15:45:47 +08:00
dudaodong
f3008ac7c4 doc: update sponsor part 2023-08-31 15:11:02 +08:00
dudaodong
c6583d3b83 doc: update sponsor part 2023-08-31 15:03:36 +08:00
dudaodong
a3d7bac72e doc: add sponsor part 2023-08-31 14:56:40 +08:00
dudaodong
74b4d53514 doc: add sponsor doc 2023-08-31 14:45:40 +08:00
dudaodong
a08afe0d77 Merge branch 'main' into v2 2023-08-31 11:17:06 +08:00
DuDaoDong
ee680aa84c Create FUNDING.yml 2023-08-31 11:15:49 +08:00
dudaodong
caa74064f0 doc: update CONTRIBUTING doc 2023-08-31 10:06:12 +08:00
dudaodong
abc94c0b26 doc: remove dist 2023-08-30 20:01:23 +08:00
dudaodong
86bcdce07b doc: remove dist 2023-08-30 20:01:09 +08:00
dudaodong
789f5d933d doc: update readme file 2023-08-30 17:52:41 +08:00
dudaodong
156fd2ef5d doc: build doc 2023-08-30 15:08:27 +08:00
dudaodong
ea036b3a81 doc: add space size for build doc 2023-08-30 14:52:38 +08:00
dudaodong
3daca8b331 doc: update validator doc 2023-08-30 14:25:12 +08:00
dudaodong
21a952d2be doc: update doc styles 2023-08-30 11:59:04 +08:00
dudaodong
03d331dfb6 doc: update doc for website 2023-08-30 11:46:16 +08:00
dudaodong
ef79e1305e doc: add links to site 2023-08-30 10:37:51 +08:00
dudaodong
7c2670d019 doc: add Contributing Guide 2023-08-29 18:01:57 +08:00
dudaodong
31f64c0a98 doc: update doc for website 2023-08-29 17:20:54 +08:00
dudaodong
28b8986cbe doc: update doc styles 2023-08-29 15:20:04 +08:00
dudaodong
b4ff33ce80 doc: update doc site 2023-08-29 15:12:32 +08:00
dudaodong
25fa117712 doc: update doc site 2023-08-29 14:09:29 +08:00
dudaodong
0c9f539e3d doc: add dist folder 2023-08-29 11:49:29 +08:00
dudaodong
05bd1afaa6 doc: build doc 2023-08-29 11:47:43 +08:00
dudaodong
51cb665110 doc: fix tag error 2023-08-29 11:40:40 +08:00
dudaodong
47c368e8f2 doc: update doc for slice retry random package 2023-08-28 16:41:36 +08:00
dudaodong
3127360b28 doc: update doc for slice retry random package 2023-08-28 16:41:14 +08:00
dudaodong
5b6def5ff0 doc: update style link 2023-08-27 11:50:44 +08:00
dudaodong
33d99ad7d4 doc: add demo 2023-08-27 11:43:48 +08:00
dudaodong
8bd31d39c3 docs: update doc 2023-08-27 11:41:29 +08:00
dudaodong
a418549525 doc: update meta url 2023-08-25 17:43:10 +08:00
dudaodong
1f849efe1c doc: update doc for datetime fileutil formatter function package 2023-08-25 14:31:49 +08:00
dudaodong
8ad374bb21 doc: update doc for datastructure package 2023-08-25 11:05:33 +08:00
dudaodong
a69d886565 doc: add go playground demo 2023-08-25 10:49:16 +08:00
dudaodong
cf58542b4a doc: add new doc for convertor and cryptor 2023-08-25 10:47:16 +08:00
dudaodong
51f166d1d9 doc: update doc styles 2023-08-24 19:27:47 +08:00
dudaodong
fbeb031b40 doc: update doc 2023-08-24 19:07:24 +08:00
dudaodong
095cfc0aab doc: add new site for doc 2023-08-24 17:47:03 +08:00
ggymm
e66ab154bc fix: 覆盖写入字符串到文件问题 (#128) 2023-08-24 16:36:44 +08:00
dudaodong
91bc1a512c test: update TestZipFolder 2023-08-22 10:49:46 +08:00
dudaodong
8753255026 doc: update link in readme 2023-08-22 10:43:52 +08:00
dudaodong
9cf1f13fec doc: update link in readme 2023-08-22 10:39:37 +08:00
dudaodong
5d78bae4bb doc: update link in readme 2023-08-22 10:34:16 +08:00
dudaodong
27777eecc0 doc: update copyonwritelist doc 2023-08-22 10:26:39 +08:00
dudaodong
1a7e0e8792 doc: add copyonwritelist 2023-08-22 10:25:21 +08:00
dudaodong
02b7aa8f33 update version 2023-08-22 10:18:21 +08:00
dudaodong
f188d3d08f doc: add doc for InDelta 2023-08-21 11:05:11 +08:00
dudaodong
0c924b859e Merge branch 'main' into v2 2023-08-21 11:00:23 +08:00
warpmatrix
c5a5a07462 feat: InDelta (#127) 2023-08-15 09:53:16 +08:00
dudaodong
1ff5dd6df0 Merge branch 'main' into v2 2023-08-03 15:06:15 +08:00
Faucherwind
b5f86a488c feat: CopyOnWriteList adds more functions such as ForEach, Sort... (#126)
* feat: CopyOnWriteList adds more functions such as ForEach, Sort

* feat: CopyOnWriteList adds more functions such as ForEach, Sort
2023-08-03 15:05:30 +08:00
dudaodong
1390b7a964 fix: fix bug of Zip 2023-08-03 10:45:48 +08:00
dudaodong
c3e28a9fc0 fix: fix bug of Zip 2023-08-02 20:17:55 +08:00
dudaodong
e924429d6e fix: fix test case TestConcurrentMap_GetAndDelete 2023-08-02 11:33:27 +08:00
dudaodong
7079b1f704 format doc 2023-08-02 11:29:51 +08:00
Faucherwind
40cad365c0 feat: add CopyOnWriteList. A thread-safe list. (#125)
* fix: use loop to get value . On Get() and Contains()

* fix: Use reflect. DeepEqual() determines whether the keys are equal

* feat: add CopyOnWriteList. A thread-safe list.

* fix: fix failed unit test

* feat: add Equal() in CopyOnWriteList.

fix: update some function`s  names

* doc: add copyonwritelist.md and copyonwritelist_zh-CN.md
2023-08-02 11:10:10 +08:00
Faucherwind
6386ab908d fix: use loop to get value . On Get() and Contains() (#124)
* fix: use loop to get value . On Get() and Contains()

* fix: Use reflect. DeepEqual() determines whether the keys are equal
2023-08-01 11:14:45 +08:00
dudaodong
bb563724c7 doc: add go playground demo 2023-08-01 11:01:57 +08:00
dudaodong
72924d4486 release v2.2.4 2023-08-01 09:58:53 +08:00
dudaodong
231f8b04b4 doc: add new function doc for v2.2.4 2023-07-30 13:22:32 +08:00
dudaodong
daa932fee3 update: make IsWeekend deprecated 2023-07-30 12:47:00 +08:00
dudaodong
1b0691f1d5 Merge branch 'main' into v2 2023-07-30 12:41:03 +08:00
CyJaySong
0b6a00bd99 IsWeekend func Deprecated (#123)
* expand BeginOfWeek、EndOfWeek

* IsWeekend func Deprecated
2023-07-30 12:39:26 +08:00
dudaodong
4ab98664bb refactor: rename file name 2023-07-28 17:55:36 +08:00
dudaodong
31eb5f4d1f feat: add HmacMd5WithBase64 2023-07-28 17:53:46 +08:00
dudaodong
0ae5d17a06 doc: add doc for CurrentMap 2023-07-27 15:08:55 +08:00
dudaodong
4558d7a3c2 test: add test for currentmap 2023-07-27 11:54:52 +08:00
dudaodong
4715301240 doc: update doc for cryptor package 2023-07-27 11:20:06 +08:00
dudaodong
1c58ee23f1 feat: add Timestamp,TimestampMilli,TimestampMicro, TimestampNano 2023-07-26 17:28:15 +08:00
dudaodong
2a303d5e4b doc: update format 2023-07-26 15:28:20 +08:00
dudaodong
326e7881a6 feat: add NowDateOrTime 2023-07-26 15:03:59 +08:00
dudaodong
31e8b12674 feat: add timezone support for FormatTimeToStr and FormatStrToTime 2023-07-26 14:40:12 +08:00
dudaodong
a0431d9435 fix: fix TestConcurrentMap_Delete test failed 2023-07-25 10:21:11 +08:00
dudaodong
0456b65cc7 test: add example for cryptor package new functions 2023-07-25 10:18:54 +08:00
dudaodong
989b4dd791 test: add test for cryptor package new functions 2023-07-25 10:06:25 +08:00
dudaodong
a76b02fbba Merge branch 'main' into v2 2023-07-24 17:28:41 +08:00
hoslo
2d7747738a feat: add base cryptor method (#119)
Co-authored-by: shuai_yang <shuai_yang@intsig.net>
2023-07-24 17:24:17 +08:00
dudaodong
fe0cb04137 feat: add ConcurrentMap 2023-07-24 17:10:45 +08:00
dudaodong
fe0264f628 refactor: clean code 2023-07-24 15:42:36 +08:00
dudaodong
65396cee32 Merge branch 'main' into v2 2023-07-23 15:43:35 +08:00
Ta
544702b460 fix: remove unused message in pointer.md (#117) 2023-07-23 15:42:54 +08:00
dudaodong
d8936cdcb5 doc: add doc for pointer 2023-07-23 13:26:07 +08:00
dudaodong
d4b97d6b20 Merge branch 'main' into v2 2023-07-23 13:13:56 +08:00
Ta
5caa14c838 feat: add UnwarpOr and UnwarpOrDefault to pointer pkg (#116) 2023-07-23 13:09:50 +08:00
dudaodong
0d0848ac67 refactor: use for loop than for range 2023-07-10 10:56:53 +08:00
dudaodong
d5334f892f feat: add Join 2023-07-10 10:51:43 +08:00
dudaodong
36ef5b3bd3 doc: add doc for HasKey 2023-07-10 10:39:55 +08:00
dudaodong
6f48b00c88 feat: add HasKey 2023-07-10 10:33:04 +08:00
dudaodong
7b744c299e fix: fix bug of CreateDir 2023-07-10 10:13:23 +08:00
dudaodong
154ec56780 doc: add go playground demo 2023-07-04 16:31:13 +08:00
dudaodong
584aabdf62 release v2.2.3 2023-07-03 14:09:04 +08:00
dudaodong
1b754a6264 doc: update link in readme 2023-07-03 11:57:50 +08:00
dudaodong
06a558d797 doc: update link in readme 2023-07-03 11:21:49 +08:00
dudaodong
423779d3ff doc: update link in readme 2023-07-03 11:14:55 +08:00
dudaodong
78c17a9e7b doc: update link in readme 2023-07-03 10:52:26 +08:00
dudaodong
529b9317d0 doc: update link in readme 2023-07-03 10:48:04 +08:00
dudaodong
dc838f645b doc: update link in readme 2023-07-03 10:43:05 +08:00
dudaodong
7f559c4940 doc: update link in readme 2023-07-03 10:42:22 +08:00
dudaodong
acb08dfd90 doc: update link in readme 2023-07-03 10:40:50 +08:00
dudaodong
ffe46fd06d update readme file 2023-07-02 22:31:17 +08:00
dudaodong
b419e46b9b doc: add package index 2023-07-02 22:12:47 +08:00
dudaodong
8fbcdfd515 doc: add pointer and tuple package to readme file 2023-07-02 21:06:10 +08:00
dudaodong
f03f48210c doc: update system package 2023-06-30 15:12:18 +08:00
dudaodong
742944e2f0 doc: add doc for tuple package 2023-06-30 15:11:26 +08:00
dudaodong
c0b491ad78 doc: add example for tuple package 2023-06-30 11:20:46 +08:00
dudaodong
e9abae2a92 doc: add doc for pointer package 2023-06-30 10:31:22 +08:00
dudaodong
8229de2f10 test: add parallel running for all unit test functions 2023-06-30 10:18:45 +08:00
dudaodong
ab364744b6 test: add parallel running for all unit test functions 2023-06-29 14:49:28 +08:00
dudaodong
17ff84fa1f test: add test for Tuple Zip and Unzip 2023-06-29 11:34:43 +08:00
dudaodong
bf50baa07d feat: add GetTodayStartTime and GetTodayEndTime 2023-06-29 11:03:28 +08:00
dudaodong
7d56da8108 feat: add Md5Byte 2023-06-29 10:33:29 +08:00
dudaodong
16c2df711b feat: add unzip for tuple 2023-06-28 20:06:02 +08:00
dudaodong
015f8c3f5c feat: add zip 2023-06-28 19:41:46 +08:00
dudaodong
ba25701d89 feat: add zip 2023-06-28 17:52:12 +08:00
dudaodong
a0cb4bb266 doc: add example for tuple package 2023-06-28 16:25:43 +08:00
dudaodong
d6ba7497f9 feat: add Tuple package 2023-06-28 15:58:41 +08:00
dudaodong
7da931e0a0 feat: add Abs 2023-06-27 10:24:35 +08:00
dudaodong
8f49078eb3 doc: add go playground demo 2023-06-20 14:04:18 +08:00
dudaodong
3050d93703 release v2.2.2 2023-06-20 11:11:27 +08:00
dudaodong
efcfbfb6a1 fix: fix failed unit test 2023-06-20 11:10:33 +08:00
dudaodong
844b7a2c3b release v2.2.2 2023-06-20 10:59:12 +08:00
dudaodong
c8a536eafc doc: add doc for ZipAppendEntry 2023-06-17 19:54:09 +08:00
dudaodong
0fd268face Merge branch 'main' into v2 2023-06-17 19:38:53 +08:00
TheLastSunset
8ced7e887f feat: add ZipAppendEntry (#113) 2023-06-17 19:36:42 +08:00
dudaodong
957568ed5c doc: format code in doc file 2023-06-15 10:13:27 +08:00
dudaodong
fffabd0ffa Merge branch 'main' into v2 2023-06-13 13:58:29 +08:00
Mickls
e839af3ef9 feat: Add support for uploading files in SendRequest (#111) 2023-06-13 13:55:47 +08:00
dudaodong
1650e70d04 Merge branch 'main' into v2 2023-06-13 10:15:17 +08:00
Thijs Schreijer
23382b2b76 fix doc comment typo (#110) 2023-06-12 20:13:14 +08:00
dudaodong
daa3aa3da2 doc: update text error 2023-06-09 11:31:16 +08:00
dudaodong
be355a23f3 doc: add doc for Utf8ToGbk and GbkToUtf8 2023-06-09 11:29:29 +08:00
dudaodong
95af83b0cb doc: add doc for Sum 2023-06-09 11:23:24 +08:00
dudaodong
1efdbc0973 doc: add doc for RemoveWhiteSpace 2023-06-09 11:19:35 +08:00
dudaodong
9b829aa695 feat: add RemoveWhiteSpace 2023-06-08 16:47:31 +08:00
dudaodong
bfa9091c09 test: clean code 2023-06-08 16:25:48 +08:00
dudaodong
c11d63c2e2 feat: add Sum 2023-06-08 16:18:25 +08:00
dudaodong
83832daeb1 feat: add Utf8ToGbk and GbkToUtf8 2023-06-08 15:50:44 +08:00
dudaodong
7311f84772 test: add test file 2023-06-08 14:50:46 +08:00
dudaodong
a63d78111e test: update ExampleRandUniqueIntSlice 2023-06-08 14:41:17 +08:00
dudaodong
e2fc2f1bc9 feat: add WirteCsvFile 2023-06-08 14:40:37 +08:00
dudaodong
23a0135947 doc: add doc for RandUniqueIntSlice 2023-06-07 14:21:29 +08:00
dudaodong
013b6457bb Merge branch 'main' into v2 2023-06-07 11:38:20 +08:00
dudaodong
e08a62b0ba doc: add doc for Log function 2023-06-07 11:37:12 +08:00
Liu Shuang
850800a233 feat: add RandUniqueIntSlice (#108) 2023-06-07 11:33:37 +08:00
dudaodong
a6a8fd88bc feat: add Log function 2023-06-06 14:34:40 +08:00
dudaodong
2f6ee84443 feat: add Of and Unwrap 2023-06-02 11:48:17 +08:00
dudaodong
b1c6614549 refactor: clean code 2023-06-01 16:58:42 +08:00
dudaodong
a8761eefb0 doc: update package comment for datastructure package 2023-06-01 14:28:04 +08:00
dudaodong
cbf8cfdffa doc: add go playground demo 2023-06-01 14:11:57 +08:00
dudaodong
286a187942 fix: fix go report validation issue 2023-06-01 11:49:49 +08:00
dudaodong
b787e99528 release v2.2.1 2023-06-01 10:45:32 +08:00
dudaodong
e54c9b2850 doc: add new function to readme file 2023-06-01 10:44:00 +08:00
dudaodong
8944109c4c doc: add doc for WriteBytesToFile and WriteStringToFile 2023-05-31 17:42:34 +08:00
dudaodong
10e3732f32 feat: add IsWeekend 2023-05-31 17:13:06 +08:00
dudaodong
a415597c6b Merge branch 'main' into v2 2023-05-31 17:06:47 +08:00
hhhhhxm
69b32fd043 新增判断是否是周末的方法 (#105)
* 新增判断是否是周末的方法

* 新增判断是否是周末的方法

---------

Co-authored-by: huangxingming <huangxingming@kezaihui.com>
2023-05-31 17:05:20 +08:00
dudaodong
75ed359084 feat: add WriteBytesToFile and WriteStringToFile 2023-05-31 16:56:18 +08:00
dudaodong
2c71b6375c doc: add doc for ContainsAny and ContainsAll 2023-05-31 15:56:20 +08:00
dudaodong
2894bec80c feat: add ContainsAll and ContainsAny 2023-05-31 10:51:16 +08:00
dudaodong
09ec5b97a6 doc: add doc for DayOfYear 2023-05-31 10:04:59 +08:00
hhhhhxm
46ecb117a5 增加判断某个日期是一年当中的第几天的方法 (#103)
* 增加判断某个日期是一年当中的第几天的方法

* 修改下函数名字

---------

Co-authored-by: huangxingming <huangxingming@kezaihui.com>
2023-05-31 09:54:23 +08:00
dudaodong
388171e739 doc: add doc for BetweenSeconds 2023-05-30 17:47:16 +08:00
dudaodong
6fbaf2b005 refactor: update TestBetweenSeconds and ExampleBetweenSeconds 2023-05-30 17:44:28 +08:00
dudaodong
53a91cad71 Merge branch 'main' into v2 2023-05-30 17:38:58 +08:00
tlei995
a51a182fb2 feat:add betweenSeconds func (#102)
Co-authored-by: leitao <leitao@kezaihui.com>
2023-05-30 17:37:29 +08:00
dudaodong
64982f0c89 fix: fix body param bug when send post request 2023-05-30 10:51:33 +08:00
dudaodong
f38f69ce17 Merge branch 'main' into v2 2023-05-29 20:10:34 +08:00
燕归来
a33ea3d013 fix: timeFormat["yyyy-mm-dd hh"] should be "2006-01-02 15" (#99) (#100)
* fix: timeFormat["yyyy-mm-dd hh"] should be "2006-01-02 15" (#99)

* test: add use cases for FormatTimeToStr
2023-05-29 20:08:17 +08:00
dudaodong
e35462fb14 fix: fix format error in init function 2023-05-29 16:09:30 +08:00
dudaodong
af106a4a8e doc: add doc for Cos and Sin 2023-05-28 20:12:40 +08:00
dudaodong
ec7232ec40 update readme file 2023-05-25 19:29:59 +08:00
dudaodong
67c1b54b5a feat: add Cos and Sin function 2023-05-25 17:51:40 +08:00
dudaodong
e149ae2f72 feat: add HideString 2023-05-23 18:39:59 +08:00
dudaodong
b1fcfce188 doc: add go playground demo 2023-05-19 11:42:29 +08:00
dudaodong
259dbce85e doc: add go playground demo 2023-05-19 11:42:17 +08:00
will
78aa679670 feat: add ContainNumber for validator (#97)
Co-authored-by: sunyaoyao <sunyaoyao@kezaihui.com>
2023-05-19 11:23:19 +08:00
238 changed files with 33130 additions and 7233 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
liberapay: Duke_Du
patreon: DukeDu

View File

@@ -3,11 +3,11 @@ on:
push: push:
branches: branches:
- main - main
# - v2 - rc
pull_request: pull_request:
branches: branches:
- main - main
# - v2 - rc
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -17,8 +17,10 @@ jobs:
fetch-depth: 2 fetch-depth: 2
- uses: actions/setup-go@v2 - uses: actions/setup-go@v2
with: with:
go-version: "1.18" go-version: "1.20"
- 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: Run govet
run: go vet -v ./...
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
run: bash <(curl -s https://codecov.io/bash) run: bash <(curl -s https://codecov.io/bash)

6
.gitignore vendored
View File

@@ -6,6 +6,10 @@ fileutil/*.txt
fileutil/*.zip fileutil/*.zip
fileutil/*.link fileutil/*.link
fileutil/unzip/* fileutil/unzip/*
fileutil/tempdir/*
slice/testdata/* slice/testdata/*
cryptor/*.pem cryptor/*.pem
test test
docs/node_modules
docs/.vitepress/cache
docs/.vitepress/dist

37
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,37 @@
# Lancet Contributing Guide
Hi! Thank you for choosing Lancet.
Lancet is a powerful, efficient, and reusable util function library of go. It makes Go dev easier by taking the hassle out of working with concurrency, net, math, slice, string, etc.
We are excited that you are interested in contributing to lancet. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
## Issue Guidelines
- Issues are exclusively for bug reports, feature requests and design-related topics. Other questions may be closed directly.
- Before submitting an issue, please check if similar problems have already been issued.
- Please specify which version of Lancet and Go you are using, and provide OS information. [Go Playground](https://go.dev/play/) is recommended to build a live demo so that your issue can be reproduced clearly.
## Pull Request Guidelines
- Fork this repository to your own account. Do not create branches here.
- Commit info should be formatted as `type(scope): info about commit`. eg. `fix(package): [scrollbar] fix xxx bug`.
1. type: type must be one of [chore, docs, feat, fix, refactor, release, test].
2. scope: scope must be one of [package, file, internal].
3. header: header must not be longer than 72 characters.
- Rebase before creating a PR to keep commit history clear.
- Before submitting a PR, please execute the unit test command: `go test -v ./...` to ensure that all unit test tasks should pass.
- Make sure PRs are created to `rc` branch instead of other branch.
- If your PR fixes a bug, please provide a description about the related bug.
- If the PR is for a new feature, make sure to complete the relevant documentation (/lancet/docs/en/api/packages).

37
CONTRIBUTING.zh-CN.md Normal file
View File

@@ -0,0 +1,37 @@
# Lancet 贡献指南
Hi! 首先感谢你使用 Lancet。
lancet柳叶刀是一个功能强大、全面、高效、可复用的go语言工具函数库。它消除了处理并发、网络、数学、切片、字符串等的麻烦使 Go 开发变得更容易。
Lancet 的成长离不开大家的支持,如果你愿意为 Lancet 贡献代码或提供建议,请阅读以下内容。
## Issue 规范
- issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。
- 在提交 issue 之前,请搜索相关内容是否已被提出。
- 请说明 Lancet 和 Go 的版本号,并提供操作系统信息。推荐使用 [Go Playground](https://go.dev/play/) 生成在线 demo这能够更直观地重现问题。
## Pull Request 规范
- 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。
- commit 信息要以 `type(scope): 描述信息` 的形式填写,例如 `fix(package): [scrollbar] fix xxx bug`
1. type: 必须是 chore, docs, feat, fix, refactor, release, test 其中的一个。
2. scope: 必须是 package, file, internal 其中的一个。
3. header: 描述信息不要超过 72 个字符。
- 提交 PR 前请 rebase确保 commit 记录的整洁。
- 提交 PR 前请执行单元测试命令go test -v ./...,确保所有单元测试任务通过。
- 确保 PR 是提交到 `rc` 分支,而不是其他分支。
- 如果是修复 bug请在 PR 中给出描述信息。
- 如果PR是新功能确保完成相关文档(/lancet/docs/api/packages)。

1471
README.md

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ import (
) )
func TestLRUCache(t *testing.T) { func TestLRUCache(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestLRUCache") asssert := internal.NewAssert(t, "TestLRUCache")
cache := NewLRUCache[int, int](3) cache := NewLRUCache[int, int](3)

View File

@@ -4,7 +4,7 @@
// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. // Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph.
package algorithm package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints" import "github.com/duke-git/lancet/v2/constraints"
// Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search // Search algorithms see https://github.com/TheAlgorithms/Go/tree/master/search
@@ -23,7 +23,7 @@ func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int {
// BinarySearch return the index of target within a sorted slice, use binary search (recursive call itself). // BinarySearch return the index of target within a sorted slice, use binary search (recursive call itself).
// If not found return -1. // If not found return -1.
// Play: https://go.dev/play/p/t6MeGiUSN47 // Play: https://go.dev/play/p/t6MeGiUSN47
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int { func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int {
if highIndex < lowIndex || len(sortedSlice) == 0 { if highIndex < lowIndex || len(sortedSlice) == 0 {
return -1 return -1
} }
@@ -44,7 +44,7 @@ func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, com
// BinaryIterativeSearch return the index of target within a sorted slice, use binary search (no recursive). // BinaryIterativeSearch return the index of target within a sorted slice, use binary search (no recursive).
// If not found return -1. // If not found return -1.
// Play: https://go.dev/play/p/Anozfr8ZLH3 // Play: https://go.dev/play/p/Anozfr8ZLH3
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int { func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int {
startIndex := lowIndex startIndex := lowIndex
endIndex := highIndex endIndex := highIndex

View File

@@ -7,6 +7,7 @@ import (
) )
func TestLinearSearch(t *testing.T) { func TestLinearSearch(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestLinearSearch") asssert := internal.NewAssert(t, "TestLinearSearch")
numbers := []int{3, 4, 5, 3, 2, 1} numbers := []int{3, 4, 5, 3, 2, 1}
@@ -19,6 +20,7 @@ func TestLinearSearch(t *testing.T) {
} }
func TestBinarySearch(t *testing.T) { func TestBinarySearch(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBinarySearch") asssert := internal.NewAssert(t, "TestBinarySearch")
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8} sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}

View File

@@ -3,24 +3,29 @@
package algorithm package algorithm
import "github.com/duke-git/lancet/v2/lancetconstraints" import "github.com/duke-git/lancet/v2/constraints"
// BubbleSort applys the bubble sort algorithm to sort the collection, will change the original collection data. // BubbleSort applys the bubble sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/GNdv7Jg2Taj // Play: https://go.dev/play/p/GNdv7Jg2Taj
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) { func BubbleSort[T any](slice []T, comparator constraints.Comparator) {
for i := 0; i < len(slice); i++ { for i := 0; i < len(slice); i++ {
breakTag := false
for j := 0; j < len(slice)-1-i; j++ { for j := 0; j < len(slice)-1-i; j++ {
isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1 isCurrGreatThanNext := comparator.Compare(slice[j], slice[j+1]) == 1
if isCurrGreatThanNext { if isCurrGreatThanNext {
swap(slice, j, j+1) swap(slice, j, j+1)
breakTag = true
} }
} }
if !breakTag {
break
}
} }
} }
// InsertionSort applys the insertion sort algorithm to sort the collection, will change the original collection data. // InsertionSort applys the insertion sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/G5LJiWgJJW6 // Play: https://go.dev/play/p/G5LJiWgJJW6
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) { func InsertionSort[T any](slice []T, comparator constraints.Comparator) {
for i := 0; i < len(slice); i++ { for i := 0; i < len(slice); i++ {
for j := i; j > 0; j-- { for j := i; j > 0; j-- {
isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1 isPreLessThanCurrent := comparator.Compare(slice[j], slice[j-1]) == -1
@@ -35,7 +40,7 @@ func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
// SelectionSort applys the selection sort algorithm to sort the collection, will change the original collection data. // SelectionSort applys the selection sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/oXovbkekayS // Play: https://go.dev/play/p/oXovbkekayS
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) { func SelectionSort[T any](slice []T, comparator constraints.Comparator) {
for i := 0; i < len(slice); i++ { for i := 0; i < len(slice); i++ {
min := i min := i
for j := i + 1; j < len(slice); j++ { for j := i + 1; j < len(slice); j++ {
@@ -49,7 +54,7 @@ func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) {
// ShellSort applys the shell sort algorithm to sort the collection, will change the original collection data. // ShellSort applys the shell sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/3ibkszpJEu3 // Play: https://go.dev/play/p/3ibkszpJEu3
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) { func ShellSort[T any](slice []T, comparator constraints.Comparator) {
size := len(slice) size := len(slice)
gap := 1 gap := 1
@@ -69,11 +74,11 @@ func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) {
// QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1. // QuickSort quick sorting for slice, lowIndex is 0 and highIndex is len(slice)-1.
// Play: https://go.dev/play/p/7Y7c1Elk3ax // Play: https://go.dev/play/p/7Y7c1Elk3ax
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) { func QuickSort[T any](slice []T, comparator constraints.Comparator) {
quickSort(slice, 0, len(slice)-1, comparator) quickSort(slice, 0, len(slice)-1, comparator)
} }
func quickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) { func quickSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
if lowIndex < highIndex { if lowIndex < highIndex {
p := partition(slice, lowIndex, highIndex, comparator) p := partition(slice, lowIndex, highIndex, comparator)
quickSort(slice, lowIndex, p-1, comparator) quickSort(slice, lowIndex, p-1, comparator)
@@ -82,7 +87,7 @@ func quickSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
} }
// partition split slice into two parts // partition split slice into two parts
func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int { func partition[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) int {
p := slice[highIndex] p := slice[highIndex]
i := lowIndex i := lowIndex
for j := lowIndex; j < highIndex; j++ { for j := lowIndex; j < highIndex; j++ {
@@ -99,7 +104,7 @@ func partition[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
// HeapSort applys the heap sort algorithm to sort the collection, will change the original collection data. // HeapSort applys the heap sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/u6Iwa1VZS_f // Play: https://go.dev/play/p/u6Iwa1VZS_f
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) { func HeapSort[T any](slice []T, comparator constraints.Comparator) {
size := len(slice) size := len(slice)
for i := size/2 - 1; i >= 0; i-- { for i := size/2 - 1; i >= 0; i-- {
@@ -111,7 +116,7 @@ func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) {
} }
} }
func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) { func sift[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
i := lowIndex i := lowIndex
j := 2*i + 1 j := 2*i + 1
@@ -133,11 +138,11 @@ func sift[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraint
// MergeSort applys the merge sort algorithm to sort the collection, will change the original collection data. // MergeSort applys the merge sort algorithm to sort the collection, will change the original collection data.
// Play: https://go.dev/play/p/ydinn9YzUJn // Play: https://go.dev/play/p/ydinn9YzUJn
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) { func MergeSort[T any](slice []T, comparator constraints.Comparator) {
mergeSort(slice, 0, len(slice)-1, comparator) mergeSort(slice, 0, len(slice)-1, comparator)
} }
func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) { func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator constraints.Comparator) {
if lowIndex < highIndex { if lowIndex < highIndex {
mid := (lowIndex + highIndex) / 2 mid := (lowIndex + highIndex) / 2
mergeSort(slice, lowIndex, mid, comparator) mergeSort(slice, lowIndex, mid, comparator)
@@ -146,7 +151,7 @@ func mergeSort[T any](slice []T, lowIndex, highIndex int, comparator lancetconst
} }
} }
func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lancetconstraints.Comparator) { func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator constraints.Comparator) {
i := lowIndex i := lowIndex
j := midIndex + 1 j := midIndex + 1
temp := []T{} temp := []T{}
@@ -175,7 +180,7 @@ func merge[T any](slice []T, lowIndex, midIndex, highIndex int, comparator lance
// CountSort applys the count sort algorithm to sort the collection, don't change the original collection data. // CountSort applys the count sort algorithm to sort the collection, don't change the original collection data.
// Play: https://go.dev/play/p/tB-Umgm0DrP // Play: https://go.dev/play/p/tB-Umgm0DrP
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T { func CountSort[T any](slice []T, comparator constraints.Comparator) []T {
size := len(slice) size := len(slice)
out := make([]T, size) out := make([]T, size)

View File

@@ -16,7 +16,7 @@ type people struct {
// PeopleAageComparator sort people slice by age field // PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{} type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/v2/lancetconstraints/constraints.go/Comparator // Compare implements github.com/duke-git/lancet/v2/constraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int { func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people) p1, _ := v1.(people)
p2, _ := v2.(people) p2, _ := v2.(people)
@@ -46,6 +46,7 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func TestBubbleSortForStructSlice(t *testing.T) { func TestBubbleSortForStructSlice(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice") asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
peoples := []people{ peoples := []people{
@@ -65,6 +66,7 @@ func TestBubbleSortForStructSlice(t *testing.T) {
} }
func TestBubbleSortForIntSlice(t *testing.T) { func TestBubbleSortForIntSlice(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice") asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
numbers := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
@@ -75,6 +77,7 @@ func TestBubbleSortForIntSlice(t *testing.T) {
} }
func TestInsertionSort(t *testing.T) { func TestInsertionSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestInsertionSort") asssert := internal.NewAssert(t, "TestInsertionSort")
peoples := []people{ peoples := []people{
@@ -94,6 +97,7 @@ func TestInsertionSort(t *testing.T) {
} }
func TestSelectionSort(t *testing.T) { func TestSelectionSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestSelectionSort") asssert := internal.NewAssert(t, "TestSelectionSort")
peoples := []people{ peoples := []people{
@@ -113,6 +117,7 @@ func TestSelectionSort(t *testing.T) {
} }
func TestShellSort(t *testing.T) { func TestShellSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestShellSort") asssert := internal.NewAssert(t, "TestShellSort")
peoples := []people{ peoples := []people{
@@ -132,6 +137,7 @@ func TestShellSort(t *testing.T) {
} }
func TestQuickSort(t *testing.T) { func TestQuickSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestQuickSort") asssert := internal.NewAssert(t, "TestQuickSort")
peoples := []people{ peoples := []people{
@@ -151,6 +157,7 @@ func TestQuickSort(t *testing.T) {
} }
func TestHeapSort(t *testing.T) { func TestHeapSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestHeapSort") asssert := internal.NewAssert(t, "TestHeapSort")
peoples := []people{ peoples := []people{
@@ -170,6 +177,7 @@ func TestHeapSort(t *testing.T) {
} }
func TestMergeSort(t *testing.T) { func TestMergeSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestMergeSort") asssert := internal.NewAssert(t, "TestMergeSort")
peoples := []people{ peoples := []people{
@@ -189,6 +197,7 @@ func TestMergeSort(t *testing.T) {
} }
func TestCountSort(t *testing.T) { func TestCountSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestCountSort") asssert := internal.NewAssert(t, "TestCountSort")
peoples := []people{ peoples := []people{

View File

@@ -10,6 +10,8 @@ import (
"time" "time"
"github.com/duke-git/lancet/v2/convertor" "github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/mathutil"
"golang.org/x/exp/constraints"
) )
// operator type // operator type
@@ -62,3 +64,9 @@ func LessOrEqual(left, right any) bool {
func GreaterOrEqual(left, right any) bool { func GreaterOrEqual(left, right any) bool {
return compareValue(greaterOrEqual, left, right) return compareValue(greaterOrEqual, left, right)
} }
// InDelta checks if two values are equal or not within a delta.
// Play: https://go.dev/play/p/TuDdcNtMkjo
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool {
return float64(mathutil.Abs(left-right)) <= delta
}

View File

@@ -168,3 +168,29 @@ func ExampleGreaterOrEqual() {
// false // false
// false // false
} }
func ExampleInDelta() {
result1 := InDelta(1, 1, 0)
result2 := InDelta(1, 2, 0)
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
result4 := InDelta(2.0/3.0, 0.0, 0.001)
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// false
// true
// false
// false
// true
}

View File

@@ -70,7 +70,7 @@ func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind)
switch operator { switch operator {
case equal: case equal:
if bytes.Compare(bytesObj1, bytesObj2) == 0 { if bytes.Equal(bytesObj1, bytesObj2) {
return true return true
} }
case lessThan: case lessThan:

View File

@@ -1,6 +1,7 @@
package compare package compare
import ( import (
"encoding/json"
"testing" "testing"
"time" "time"
@@ -8,8 +9,10 @@ import (
) )
func TestEqual(t *testing.T) { func TestEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqual") assert := internal.NewAssert(t, "TestEqual")
// basic type
assert.Equal(true, Equal(1, 1)) assert.Equal(true, Equal(1, 1))
assert.Equal(true, Equal(int64(1), int64(1))) assert.Equal(true, Equal(int64(1), int64(1)))
assert.Equal(true, Equal("a", "a")) assert.Equal(true, Equal("a", "a"))
@@ -24,6 +27,7 @@ func TestEqual(t *testing.T) {
assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3})) assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3}))
assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"})) assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}))
// time
time1 := time.Now() time1 := time.Now()
time2 := time1.Add(time.Second) time2 := time1.Add(time.Second)
time3 := time1.Add(time.Second) time3 := time1.Add(time.Second)
@@ -31,6 +35,7 @@ func TestEqual(t *testing.T) {
assert.Equal(false, Equal(time1, time2)) assert.Equal(false, Equal(time1, time2))
assert.Equal(true, Equal(time2, time3)) assert.Equal(true, Equal(time2, time3))
// struct
st1 := struct { st1 := struct {
A string A string
B string B string
@@ -57,9 +62,23 @@ func TestEqual(t *testing.T) {
assert.Equal(true, Equal(st1, st2)) assert.Equal(true, Equal(st1, st2))
assert.Equal(false, Equal(st1, st3)) assert.Equal(false, Equal(st1, st3))
//byte slice
bs1 := []byte("hello")
bs2 := []byte("hello")
assert.Equal(true, Equal(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`123`), &jsonNumber2)
assert.Equal(true, Equal(jsonNumber1, jsonNumber2))
} }
func TestEqualValue(t *testing.T) { func TestEqualValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqualValue") assert := internal.NewAssert(t, "TestEqualValue")
assert.Equal(true, EqualValue(1, 1)) assert.Equal(true, EqualValue(1, 1))
@@ -67,9 +86,17 @@ func TestEqualValue(t *testing.T) {
assert.Equal(true, EqualValue(1, "1")) assert.Equal(true, EqualValue(1, "1"))
assert.Equal(false, EqualValue(1, "2")) assert.Equal(false, EqualValue(1, "2"))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`123`), &jsonNumber2)
assert.Equal(true, EqualValue(jsonNumber1, 123))
} }
func TestLessThan(t *testing.T) { func TestLessThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessThan") assert := internal.NewAssert(t, "TestLessThan")
assert.Equal(true, LessThan(1, 2)) assert.Equal(true, LessThan(1, 2))
@@ -82,9 +109,21 @@ func TestLessThan(t *testing.T) {
assert.Equal(false, LessThan(1, 1)) assert.Equal(false, LessThan(1, 1))
assert.Equal(false, LessThan(1, int64(1))) assert.Equal(false, LessThan(1, int64(1)))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, LessThan(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, LessThan(jsonNumber1, jsonNumber2))
} }
func TestGreaterThan(t *testing.T) { func TestGreaterThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan") assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterThan(2, 1)) assert.Equal(true, GreaterThan(2, 1))
@@ -98,9 +137,21 @@ func TestGreaterThan(t *testing.T) {
assert.Equal(false, GreaterThan(1, 2)) assert.Equal(false, GreaterThan(1, 2))
assert.Equal(false, GreaterThan(int64(2), 1)) assert.Equal(false, GreaterThan(int64(2), 1))
assert.Equal(false, GreaterThan("b", "c")) assert.Equal(false, GreaterThan("b", "c"))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, GreaterThan(bs2, bs1))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, GreaterThan(jsonNumber2, jsonNumber1))
} }
func TestLessOrEqual(t *testing.T) { func TestLessOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessOrEqual") assert := internal.NewAssert(t, "TestLessOrEqual")
assert.Equal(true, LessOrEqual(1, 2)) assert.Equal(true, LessOrEqual(1, 2))
@@ -114,9 +165,21 @@ func TestLessOrEqual(t *testing.T) {
assert.Equal(false, LessOrEqual(2, 1)) assert.Equal(false, LessOrEqual(2, 1))
assert.Equal(false, LessOrEqual(1, int64(2))) assert.Equal(false, LessOrEqual(1, int64(2)))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, LessOrEqual(bs1, bs2))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, LessOrEqual(jsonNumber1, jsonNumber2))
} }
func TestGreaterOrEqual(t *testing.T) { func TestGreaterOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan") assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterOrEqual(2, 1)) assert.Equal(true, GreaterOrEqual(2, 1))
@@ -131,4 +194,31 @@ func TestGreaterOrEqual(t *testing.T) {
assert.Equal(false, GreaterOrEqual(1, 2)) assert.Equal(false, GreaterOrEqual(1, 2))
assert.Equal(false, GreaterOrEqual(int64(2), 1)) assert.Equal(false, GreaterOrEqual(int64(2), 1))
assert.Equal(false, GreaterOrEqual("b", "c")) assert.Equal(false, GreaterOrEqual("b", "c"))
bs1 := []byte("hello1")
bs2 := []byte("hello2")
assert.Equal(true, GreaterOrEqual(bs2, bs1))
// json.Number
var jsonNumber1, jsonNumber2 json.Number
json.Unmarshal([]byte(`123`), &jsonNumber1)
json.Unmarshal([]byte(`124`), &jsonNumber2)
assert.Equal(true, GreaterOrEqual(jsonNumber2, jsonNumber1))
}
func TestInDelta(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInDelta")
assert.Equal(true, InDelta(1, 1, 0))
assert.Equal(false, InDelta(1, 2, 0))
assert.Equal(true, InDelta(2.0/3.0, 0.66667, 0.001))
assert.Equal(false, InDelta(2.0/3.0, 0.0, 0.001))
assert.Equal(false, InDelta(float64(74.96)-float64(20.48), 54.48, 0))
assert.Equal(true, InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14))
assert.Equal(false, InDelta(float64(float32(80.45)), float64(80.45), 0))
assert.Equal(true, InDelta(float64(float32(80.45)), float64(80.45), 1e-5))
} }

View File

@@ -9,6 +9,7 @@ import (
) )
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGenerate") assert := internal.NewAssert(t, "TestGenerate")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -23,6 +24,7 @@ func TestGenerate(t *testing.T) {
} }
func TestRepeat(t *testing.T) { func TestRepeat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRepeat") assert := internal.NewAssert(t, "TestRepeat")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -39,6 +41,7 @@ func TestRepeat(t *testing.T) {
} }
func TestRepeatFn(t *testing.T) { func TestRepeatFn(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRepeatFn") assert := internal.NewAssert(t, "TestRepeatFn")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -57,6 +60,7 @@ func TestRepeatFn(t *testing.T) {
} }
func TestTake(t *testing.T) { func TestTake(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTake") assert := internal.NewAssert(t, "TestTake")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -79,6 +83,7 @@ func TestTake(t *testing.T) {
} }
func TestFanIn(t *testing.T) { func TestFanIn(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFanIn") assert := internal.NewAssert(t, "TestFanIn")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -101,6 +106,7 @@ func TestFanIn(t *testing.T) {
} }
func TestOr(t *testing.T) { func TestOr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr") assert := internal.NewAssert(t, "TestOr")
sig := func(after time.Duration) <-chan any { sig := func(after time.Duration) <-chan any {
@@ -127,6 +133,7 @@ func TestOr(t *testing.T) {
} }
func TestOrDone(t *testing.T) { func TestOrDone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOrDone") assert := internal.NewAssert(t, "TestOrDone")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -141,6 +148,7 @@ func TestOrDone(t *testing.T) {
} }
func TestTee(t *testing.T) { func TestTee(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTee") assert := internal.NewAssert(t, "TestTee")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -159,6 +167,7 @@ func TestTee(t *testing.T) {
} }
func TestBridge(t *testing.T) { func TestBridge(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBridge") assert := internal.NewAssert(t, "TestBridge")
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())

View File

@@ -11,6 +11,8 @@ import (
type TestStruct struct{} type TestStruct struct{}
func TestBool(t *testing.T) { func TestBool(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBool") assert := internal.NewAssert(t, "TestBool")
// bool // bool
@@ -63,6 +65,8 @@ func TestBool(t *testing.T) {
} }
func TestAnd(t *testing.T) { func TestAnd(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAnd") assert := internal.NewAssert(t, "TestAnd")
assert.Equal(false, And(0, 1)) assert.Equal(false, And(0, 1))
assert.Equal(false, And(0, "")) assert.Equal(false, And(0, ""))
@@ -71,6 +75,8 @@ func TestAnd(t *testing.T) {
} }
func TestOr(t *testing.T) { func TestOr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr") assert := internal.NewAssert(t, "TestOr")
assert.Equal(false, Or(0, "")) assert.Equal(false, Or(0, ""))
assert.Equal(true, Or(0, 1)) assert.Equal(true, Or(0, 1))
@@ -79,6 +85,8 @@ func TestOr(t *testing.T) {
} }
func TestXor(t *testing.T) { func TestXor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr") assert := internal.NewAssert(t, "TestOr")
assert.Equal(false, Xor(0, 0)) assert.Equal(false, Xor(0, 0))
assert.Equal(true, Xor(0, 1)) assert.Equal(true, Xor(0, 1))
@@ -87,6 +95,8 @@ func TestXor(t *testing.T) {
} }
func TestNor(t *testing.T) { func TestNor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestNor") assert := internal.NewAssert(t, "TestNor")
assert.Equal(true, Nor(0, 0)) assert.Equal(true, Nor(0, 0))
assert.Equal(false, Nor(0, 1)) assert.Equal(false, Nor(0, 1))
@@ -95,6 +105,8 @@ func TestNor(t *testing.T) {
} }
func TestXnor(t *testing.T) { func TestXnor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestXnor") assert := internal.NewAssert(t, "TestXnor")
assert.Equal(true, Xnor(0, 0)) assert.Equal(true, Xnor(0, 0))
assert.Equal(false, Xnor(0, 1)) assert.Equal(false, Xnor(0, 1))
@@ -103,6 +115,8 @@ func TestXnor(t *testing.T) {
} }
func TestNand(t *testing.T) { func TestNand(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestNand") assert := internal.NewAssert(t, "TestNand")
assert.Equal(true, Nand(0, 0)) assert.Equal(true, Nand(0, 0))
assert.Equal(true, Nand(0, 1)) assert.Equal(true, Nand(0, 1))
@@ -111,7 +125,10 @@ func TestNand(t *testing.T) {
} }
func TestTernaryOperator(t *testing.T) { func TestTernaryOperator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TernaryOperator") assert := internal.NewAssert(t, "TernaryOperator")
trueValue := "1" trueValue := "1"
falseValue := "0" falseValue := "0"

View File

@@ -1,8 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved. // Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package lancetconstraints contain some comstomer constraints. // Package constraints contain some custom interface.
package lancetconstraints package constraints
// Comparator is for comparing two values // Comparator is for comparing two values
type Comparator interface { type Comparator interface {

View File

@@ -6,17 +6,21 @@ package convertor
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/binary" "encoding/binary"
"encoding/gob" "encoding/gob"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"math" "math"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/duke-git/lancet/v2/structs" "github.com/duke-git/lancet/v2/structs"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
) )
// ToBool convert string to boolean. // ToBool convert string to boolean.
@@ -349,7 +353,7 @@ func CopyProperties[T, U any](dst T, src U) error {
} }
// ToInterface converts reflect value to its interface type. // ToInterface converts reflect value to its interface type.
// Play: todo // Play: https://go.dev/play/p/syqw0-WG7Xd
func ToInterface(v reflect.Value) (value interface{}, ok bool) { func ToInterface(v reflect.Value) (value interface{}, ok bool) {
if v.IsValid() && v.CanInterface() { if v.IsValid() && v.CanInterface() {
return v.Interface(), true return v.Interface(), true
@@ -375,3 +379,107 @@ func ToInterface(v reflect.Value) (value interface{}, ok bool) {
return nil, false return nil, false
} }
} }
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
// Play: https://go.dev/play/p/9FlIaFLArIL
func Utf8ToGbk(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewEncoder())
b, err := io.ReadAll(r)
return b, err
}
// GbkToUtf8 convert GBK encoding data to utf8 encoding data.
// Play: https://go.dev/play/p/OphmHCN_9u8
func GbkToUtf8(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
b, err := io.ReadAll(r)
return b, err
}
// ToStdBase64 convert data to standard base64 encoding.
// Play: https://go.dev/play/p/_fLJqJD3NMo
func ToStdBase64(value any) string {
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
return ""
}
switch value.(type) {
case []byte:
return base64.StdEncoding.EncodeToString(value.([]byte))
case string:
return base64.StdEncoding.EncodeToString([]byte(value.(string)))
case error:
return base64.StdEncoding.EncodeToString([]byte(value.(error).Error()))
default:
marshal, err := json.Marshal(value)
if err != nil {
return ""
}
return base64.StdEncoding.EncodeToString(marshal)
}
}
// ToUrlBase64 convert data to URL base64 encoding.
// Play: https://go.dev/play/p/C_d0GlvEeUR
func ToUrlBase64(value any) string {
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
return ""
}
switch value.(type) {
case []byte:
return base64.URLEncoding.EncodeToString(value.([]byte))
case string:
return base64.URLEncoding.EncodeToString([]byte(value.(string)))
case error:
return base64.URLEncoding.EncodeToString([]byte(value.(error).Error()))
default:
marshal, err := json.Marshal(value)
if err != nil {
return ""
}
return base64.URLEncoding.EncodeToString(marshal)
}
}
// ToRawStdBase64 convert data to raw standard base64 encoding.
// Play: https://go.dev/play/p/wSAr3sfkDcv
func ToRawStdBase64(value any) string {
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
return ""
}
switch value.(type) {
case []byte:
return base64.RawStdEncoding.EncodeToString(value.([]byte))
case string:
return base64.RawStdEncoding.EncodeToString([]byte(value.(string)))
case error:
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
default:
marshal, err := json.Marshal(value)
if err != nil {
return ""
}
return base64.RawStdEncoding.EncodeToString(marshal)
}
}
// ToRawUrlBase64 convert data to raw URL base64 encoding.
// Play: https://go.dev/play/p/HwdDPFcza1O
func ToRawUrlBase64(value any) string {
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
return ""
}
switch value.(type) {
case []byte:
return base64.RawURLEncoding.EncodeToString(value.([]byte))
case string:
return base64.RawURLEncoding.EncodeToString([]byte(value.(string)))
case error:
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
default:
marshal, err := json.Marshal(value)
if err != nil {
return ""
}
return base64.RawURLEncoding.EncodeToString(marshal)
}
}

View File

@@ -1,9 +1,13 @@
package convertor package convertor
import ( import (
"errors"
"fmt" "fmt"
"reflect" "reflect"
"strconv" "strconv"
"unicode/utf8"
"github.com/duke-git/lancet/v2/validator"
) )
func ExampleToBool() { func ExampleToBool() {
@@ -364,3 +368,206 @@ func ExampleToInterface() {
// abc // abc
// true // true
} }
func ExampleUtf8ToGbk() {
utf8Data := []byte("hello")
gbkData, _ := Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
func ExampleGbkToUtf8() {
gbkData, _ := Utf8ToGbk([]byte("hello"))
utf8Data, _ := GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
func ExampleToStdBase64() {
// if you want to see the result, please use 'base64.StdEncoding.DecodeString()' to decode the result
afterEncode := ToStdBase64(nil)
fmt.Println(afterEncode)
stringVal := "hello"
afterEncode = ToStdBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = ToStdBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = ToStdBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = ToStdBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = ToStdBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = ToStdBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = ToStdBase64(errVal)
fmt.Println(afterEncode)
// Output:
//
// aGVsbG8=
// aGVsbG8=
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
// MTIzLjQ1Ng==
// dHJ1ZQ==
// ZXJy
}
func ExampleToUrlBase64() {
// if you want to see the result, please use 'base64.URLEncoding.DecodeString()' to decode the result
stringVal := "hello"
afterEncode := ToUrlBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = ToUrlBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = ToUrlBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = ToUrlBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = ToUrlBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = ToUrlBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = ToUrlBase64(errVal)
fmt.Println(afterEncode)
// Output:
// aGVsbG8=
// aGVsbG8=
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
// MTIzLjQ1Ng==
// dHJ1ZQ==
// ZXJy
}
func ExampleToRawStdBase64() {
// if you want to see the result, please use 'base64.RawStdEncoding.DecodeString()' to decode the result
stringVal := "hello"
afterEncode := ToRawStdBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = ToRawStdBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = ToRawStdBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = ToRawStdBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = ToRawStdBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = ToRawStdBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = ToRawStdBase64(errVal)
fmt.Println(afterEncode)
// Output:
// aGVsbG8
// aGVsbG8
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
// MTIzLjQ1Ng
// dHJ1ZQ
// ZXJy
}
func ExampleToRawUrlBase64() {
// if you want to see the result, please use 'base64.RawURLEncoding.DecodeString()' to decode the result
stringVal := "hello"
afterEncode := ToRawUrlBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = ToRawUrlBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = ToRawUrlBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = ToRawUrlBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = ToRawUrlBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = ToRawUrlBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = ToRawUrlBase64(errVal)
fmt.Println(afterEncode)
// Output:
// aGVsbG8
// aGVsbG8
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
// MTIzLjQ1Ng
// dHJ1ZQ
// ZXJy
}

View File

@@ -99,7 +99,7 @@ func (c *cloner) cloneArray(v reflect.Value) reflect.Value {
for i := 0; i < v.Len(); i++ { for i := 0; i < v.Len(); i++ {
val := c.clone(v.Index(i)) val := c.clone(v.Index(i))
if val.IsValid() { if !val.IsValid() {
continue continue
} }

View File

@@ -1,16 +1,24 @@
package convertor package convertor
import ( import (
"encoding/base64"
"errors"
"fmt" "fmt"
"io"
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
"unicode/utf8"
"unsafe"
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
"github.com/duke-git/lancet/v2/slice" "github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/validator"
) )
func TestToChar(t *testing.T) { func TestToChar(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToChar") assert := internal.NewAssert(t, "TestToChar")
cases := []string{"", "abc", "1 2#3"} cases := []string{"", "abc", "1 2#3"}
@@ -25,6 +33,8 @@ func TestToChar(t *testing.T) {
} }
func TestToChannel(t *testing.T) { func TestToChannel(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToChannel") assert := internal.NewAssert(t, "TestToChannel")
ch := ToChannel([]int{1, 2, 3}) ch := ToChannel([]int{1, 2, 3})
@@ -37,6 +47,8 @@ func TestToChannel(t *testing.T) {
} }
func TestToBool(t *testing.T) { func TestToBool(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToBool") assert := internal.NewAssert(t, "TestToBool")
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"} cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
@@ -49,6 +61,8 @@ func TestToBool(t *testing.T) {
} }
func TestToBytes(t *testing.T) { func TestToBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToBytes") assert := internal.NewAssert(t, "TestToBytes")
cases := []any{ cases := []any{
@@ -75,6 +89,8 @@ func TestToBytes(t *testing.T) {
} }
func TestToInt(t *testing.T) { func TestToInt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToInt") assert := internal.NewAssert(t, "TestToInt")
cases := []any{"123", "-123", 123, cases := []any{"123", "-123", 123,
@@ -91,6 +107,8 @@ func TestToInt(t *testing.T) {
} }
func TestToFloat(t *testing.T) { func TestToFloat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFloat") assert := internal.NewAssert(t, "TestToFloat")
cases := []any{ cases := []any{
@@ -109,6 +127,8 @@ func TestToFloat(t *testing.T) {
} }
func TestToString(t *testing.T) { func TestToString(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToString") assert := internal.NewAssert(t, "TestToString")
aMap := make(map[string]int) aMap := make(map[string]int)
@@ -144,6 +164,8 @@ func TestToString(t *testing.T) {
} }
} }
func TestToJson(t *testing.T) { func TestToJson(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToJson") assert := internal.NewAssert(t, "TestToJson")
var aMap = map[string]int{"a": 1, "b": 2, "c": 3} var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
@@ -159,6 +181,8 @@ func TestToJson(t *testing.T) {
} }
func TestToMap(t *testing.T) { func TestToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToMap") assert := internal.NewAssert(t, "TestToMap")
type Message struct { type Message struct {
@@ -178,6 +202,8 @@ func TestToMap(t *testing.T) {
} }
func TestStructToMap(t *testing.T) { func TestStructToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestStructToMap") assert := internal.NewAssert(t, "TestStructToMap")
t.Run("StructToMap", func(_ *testing.T) { t.Run("StructToMap", func(_ *testing.T) {
@@ -213,6 +239,8 @@ func TestStructToMap(t *testing.T) {
} }
func TestMapToSlice(t *testing.T) { func TestMapToSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMapToSlice") assert := internal.NewAssert(t, "TestMapToSlice")
aMap := map[string]int{"a": 1, "b": 2, "c": 3} aMap := map[string]int{"a": 1, "b": 2, "c": 3}
@@ -227,6 +255,8 @@ func TestMapToSlice(t *testing.T) {
} }
func TestColorHexToRGB(t *testing.T) { func TestColorHexToRGB(t *testing.T) {
t.Parallel()
colorHex := "#003366" colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex) r, g, b := ColorHexToRGB(colorHex)
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b) colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
@@ -237,6 +267,8 @@ func TestColorHexToRGB(t *testing.T) {
} }
func TestColorRGBToHex(t *testing.T) { func TestColorRGBToHex(t *testing.T) {
t.Parallel()
r := 0 r := 0
g := 51 g := 51
b := 102 b := 102
@@ -248,6 +280,8 @@ func TestColorRGBToHex(t *testing.T) {
} }
func TestToPointer(t *testing.T) { func TestToPointer(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToPointer") assert := internal.NewAssert(t, "TestToPointer")
result := ToPointer(123) result := ToPointer(123)
@@ -255,6 +289,8 @@ func TestToPointer(t *testing.T) {
} }
func TestEncodeByte(t *testing.T) { func TestEncodeByte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEncodeByte") assert := internal.NewAssert(t, "TestEncodeByte")
byteData, _ := EncodeByte("abc") byteData, _ := EncodeByte("abc")
@@ -264,6 +300,8 @@ func TestEncodeByte(t *testing.T) {
} }
func TestDecodeByte(t *testing.T) { func TestDecodeByte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDecodeByte") assert := internal.NewAssert(t, "TestDecodeByte")
var obj string var obj string
@@ -274,6 +312,8 @@ func TestDecodeByte(t *testing.T) {
} }
func TestDeepClone(t *testing.T) { func TestDeepClone(t *testing.T) {
t.Parallel()
// assert := internal.NewAssert(t, "TestDeepClone") // assert := internal.NewAssert(t, "TestDeepClone")
type Struct struct { type Struct struct {
@@ -301,6 +341,7 @@ func TestDeepClone(t *testing.T) {
Nil: nil, Nil: nil,
// unexported: "can't be cloned", // unexported: "can't be cloned",
}, },
[]interface{}{1, &Struct{Str: "test"}, Struct{Str: "test2"}},
} }
for i, item := range cases { for i, item := range cases {
@@ -317,6 +358,8 @@ func TestDeepClone(t *testing.T) {
} }
func TestCopyProperties(t *testing.T) { func TestCopyProperties(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCopyProperties") assert := internal.NewAssert(t, "TestCopyProperties")
type Disk struct { type Disk struct {
@@ -369,6 +412,8 @@ func TestCopyProperties(t *testing.T) {
} }
func TestToInterface(t *testing.T) { func TestToInterface(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToInterface") assert := internal.NewAssert(t, "TestToInterface")
cases := []reflect.Value{ cases := []reflect.Value{
@@ -396,3 +441,303 @@ func TestToInterface(t *testing.T) {
assert.EqualValues(nil, nilVal) assert.EqualValues(nil, nilVal)
assert.Equal(false, ok) assert.Equal(false, ok)
} }
func TestUtf8ToGbk(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUtf8ToGbk")
utf8Data := []byte("hello")
gbkData, err := Utf8ToGbk(utf8Data)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal(true, validator.IsGBK(gbkData))
assert.IsNil(err)
}
func TestGbkToUtf8(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGbkToUtf8")
gbkData, err := Utf8ToGbk([]byte("hello"))
utf8Data, err := GbkToUtf8(gbkData)
assert.IsNil(err)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal("hello", string(utf8Data))
}
func TestToStdBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToStdBase64")
r1 := ToStdBase64("abc")
d1, _ := base64.StdEncoding.DecodeString(r1)
assert.Equal("abc", string(d1))
r2 := ToStdBase64([]byte("abc"))
d2, _ := base64.StdEncoding.DecodeString(r2)
assert.Equal("abc", string(d2))
r3 := ToStdBase64(123)
d3, _ := base64.StdEncoding.DecodeString(r3)
assert.Equal("123", string(d3))
r4 := ToStdBase64(11.11)
d4, _ := base64.StdEncoding.DecodeString(r4)
assert.Equal("11.11", string(d4))
r5 := ToStdBase64(map[string]any{"name": "duke", "quantity": 1})
d5, _ := base64.StdEncoding.DecodeString(r5)
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
r6 := ToStdBase64([]int64{7, 5, 9, 4, 23})
d6, _ := base64.StdEncoding.DecodeString(r6)
assert.Equal("[7,5,9,4,23]", string(d6))
r7 := ToStdBase64([]string{"7", "5", "9", "4", "23"})
d7, _ := base64.StdEncoding.DecodeString(r7)
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
r8 := ToStdBase64(nil)
d8, _ := base64.StdEncoding.DecodeString(r8)
assert.Equal("", string(d8))
ch := make(chan int, 3)
ch <- 1
ch <- 2
r9 := ToStdBase64(ch)
d9, _ := base64.StdEncoding.DecodeString(r9)
assert.Equal("", string(d9))
r10 := ToStdBase64(io.EOF)
d10, _ := base64.StdEncoding.DecodeString(r10)
assert.Equal("EOF", string(d10))
r11 := ToStdBase64(errors.New("test"))
d11, _ := base64.StdEncoding.DecodeString(r11)
assert.Equal("test", string(d11))
typedNil := (*int)(nil)
r12 := ToStdBase64(typedNil)
d12, _ := base64.StdEncoding.DecodeString(r12)
assert.Equal("", string(d12))
type nilInterface interface {
}
var nI nilInterface = nil
d13, _ := base64.StdEncoding.DecodeString(ToStdBase64(nI))
assert.Equal("", string(d13))
var p unsafe.Pointer
d14, _ := base64.StdEncoding.DecodeString(ToStdBase64(p))
assert.Equal("", string(d14))
}
func TestToUrlBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToUrlBase64")
r1 := ToUrlBase64("abc")
d1, _ := base64.URLEncoding.DecodeString(r1)
assert.Equal("abc", string(d1))
r2 := ToUrlBase64([]byte("abc"))
d2, _ := base64.URLEncoding.DecodeString(r2)
assert.Equal("abc", string(d2))
r3 := ToUrlBase64(123)
d3, _ := base64.URLEncoding.DecodeString(r3)
assert.Equal("123", string(d3))
r4 := ToUrlBase64(11.11)
d4, _ := base64.URLEncoding.DecodeString(r4)
assert.Equal("11.11", string(d4))
r5 := ToUrlBase64(map[string]any{"name": "duke", "quantity": 1})
d5, _ := base64.URLEncoding.DecodeString(r5)
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
r6 := ToUrlBase64([]int64{7, 5, 9, 4, 23})
d6, _ := base64.URLEncoding.DecodeString(r6)
assert.Equal("[7,5,9,4,23]", string(d6))
r7 := ToUrlBase64([]string{"7", "5", "9", "4", "23"})
d7, _ := base64.URLEncoding.DecodeString(r7)
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
r8 := ToUrlBase64(nil)
d8, _ := base64.URLEncoding.DecodeString(r8)
assert.Equal("", string(d8))
ch := make(chan int, 3)
ch <- 1
ch <- 2
r9 := ToUrlBase64(ch)
d9, _ := base64.URLEncoding.DecodeString(r9)
assert.Equal("", string(d9))
r10 := ToUrlBase64(io.EOF)
d10, _ := base64.URLEncoding.DecodeString(r10)
assert.Equal("EOF", string(d10))
r11 := ToUrlBase64(errors.New("test"))
d11, _ := base64.URLEncoding.DecodeString(r11)
assert.Equal("test", string(d11))
typedNil := (*int)(nil)
r12 := ToUrlBase64(typedNil)
d12, _ := base64.URLEncoding.DecodeString(r12)
assert.Equal("", string(d12))
type nilInterface interface {
}
var nI nilInterface = nil
d13, _ := base64.URLEncoding.DecodeString(ToUrlBase64(nI))
assert.Equal("", string(d13))
var p unsafe.Pointer
d14, _ := base64.URLEncoding.DecodeString(ToUrlBase64(p))
assert.Equal("", string(d14))
r15 := ToUrlBase64("4+3/4?=")
d15, _ := base64.URLEncoding.DecodeString(r15)
assert.Equal("4+3/4?=", string(d15))
}
func TestToRawStdBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToRawStdBase64")
r1 := ToRawStdBase64("abc")
d1, _ := base64.RawStdEncoding.DecodeString(r1)
assert.Equal("abc", string(d1))
r2 := ToRawStdBase64([]byte("abc"))
d2, _ := base64.RawStdEncoding.DecodeString(r2)
assert.Equal("abc", string(d2))
r3 := ToRawStdBase64(123)
d3, _ := base64.RawStdEncoding.DecodeString(r3)
assert.Equal("123", string(d3))
r4 := ToRawStdBase64(11.11)
d4, _ := base64.RawStdEncoding.DecodeString(r4)
assert.Equal("11.11", string(d4))
r5 := ToRawStdBase64(map[string]any{"name": "duke", "quantity": 1})
d5, _ := base64.RawStdEncoding.DecodeString(r5)
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
r6 := ToRawStdBase64([]int64{7, 5, 9, 4, 23})
d6, _ := base64.RawStdEncoding.DecodeString(r6)
assert.Equal("[7,5,9,4,23]", string(d6))
r7 := ToRawStdBase64([]string{"7", "5", "9", "4", "23"})
d7, _ := base64.RawStdEncoding.DecodeString(r7)
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
r8 := ToRawStdBase64(nil)
d8, _ := base64.RawStdEncoding.DecodeString(r8)
assert.Equal("", string(d8))
ch := make(chan int, 3)
ch <- 1
ch <- 2
r9 := ToRawStdBase64(ch)
d9, _ := base64.RawStdEncoding.DecodeString(r9)
assert.Equal("", string(d9))
r10 := ToRawStdBase64(io.EOF)
d10, _ := base64.RawStdEncoding.DecodeString(r10)
assert.Equal("EOF", string(d10))
r11 := ToRawStdBase64(errors.New("test"))
d11, _ := base64.RawStdEncoding.DecodeString(r11)
assert.Equal("test", string(d11))
typedNil := (*int)(nil)
r12 := ToRawStdBase64(typedNil)
d12, _ := base64.RawStdEncoding.DecodeString(r12)
assert.Equal("", string(d12))
type nilInterface interface {
}
var nI nilInterface = nil
d13, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(nI))
assert.Equal("", string(d13))
var p unsafe.Pointer
d14, _ := base64.RawStdEncoding.DecodeString(ToRawStdBase64(p))
assert.Equal("", string(d14))
}
func TestToRawUrlBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToRawUrlBase64")
r1 := ToRawUrlBase64("abc")
d1, _ := base64.RawURLEncoding.DecodeString(r1)
assert.Equal("abc", string(d1))
r2 := ToRawUrlBase64([]byte("abc"))
d2, _ := base64.RawURLEncoding.DecodeString(r2)
assert.Equal("abc", string(d2))
r3 := ToRawUrlBase64(123)
d3, _ := base64.RawURLEncoding.DecodeString(r3)
assert.Equal("123", string(d3))
r4 := ToRawUrlBase64(11.11)
d4, _ := base64.RawURLEncoding.DecodeString(r4)
assert.Equal("11.11", string(d4))
r5 := ToRawUrlBase64(map[string]any{"name": "duke", "quantity": 1})
d5, _ := base64.RawURLEncoding.DecodeString(r5)
assert.Equal("{\"name\":\"duke\",\"quantity\":1}", string(d5))
r6 := ToRawUrlBase64([]int64{7, 5, 9, 4, 23})
d6, _ := base64.RawURLEncoding.DecodeString(r6)
assert.Equal("[7,5,9,4,23]", string(d6))
r7 := ToRawUrlBase64([]string{"7", "5", "9", "4", "23"})
d7, _ := base64.RawURLEncoding.DecodeString(r7)
assert.Equal("[\"7\",\"5\",\"9\",\"4\",\"23\"]", string(d7))
r8 := ToRawUrlBase64(nil)
d8, _ := base64.RawURLEncoding.DecodeString(r8)
assert.Equal("", string(d8))
ch := make(chan int, 3)
ch <- 1
ch <- 2
r9 := ToRawUrlBase64(ch)
d9, _ := base64.RawURLEncoding.DecodeString(r9)
assert.Equal("", string(d9))
r10 := ToRawUrlBase64(io.EOF)
d10, _ := base64.RawURLEncoding.DecodeString(r10)
assert.Equal("EOF", string(d10))
r11 := ToRawUrlBase64(errors.New("test"))
d11, _ := base64.RawURLEncoding.DecodeString(r11)
assert.Equal("test", string(d11))
typedNil := (*int)(nil)
r12 := ToRawUrlBase64(typedNil)
d12, _ := base64.RawURLEncoding.DecodeString(r12)
assert.Equal("", string(d12))
type nilInterface interface {
}
var nI nilInterface = nil
d13, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(nI))
assert.Equal("", string(d13))
var p unsafe.Pointer
d14, _ := base64.RawURLEncoding.DecodeString(ToRawUrlBase64(p))
assert.Equal("", string(d14))
r15 := ToRawUrlBase64("4+3/4?=")
d15, _ := base64.RawURLEncoding.DecodeString(r15)
assert.Equal("4+3/4?=", string(d15))
}

View File

@@ -40,6 +40,30 @@ func Md5String(s string) string {
return hex.EncodeToString(h.Sum(nil)) return hex.EncodeToString(h.Sum(nil))
} }
// Md5StringWithBase64 return the md5 value of string with base64.
// Play: https://go.dev/play/p/Lx4gH7Vdr5_y
func Md5StringWithBase64(s string) string {
h := md5.New()
h.Write([]byte(s))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// Md5Byte return the md5 string of byte slice.
// Play: https://go.dev/play/p/suraalH8lyC
func Md5Byte(data []byte) string {
h := md5.New()
h.Write(data)
return hex.EncodeToString(h.Sum(nil))
}
// Md5ByteWithBase64 return the md5 string of byte slice with base64.
// Play: https://go.dev/play/p/Tcb-Z7LN2ax
func Md5ByteWithBase64(data []byte) string {
h := md5.New()
h.Write(data)
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// Md5File return the md5 value of file. // Md5File return the md5 value of file.
func Md5File(filename string) (string, error) { func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil { if fileInfo, err := os.Stat(filename); err != nil {
@@ -74,56 +98,112 @@ func Md5File(filename string) (string, error) {
// HmacMd5 return the hmac hash of string use md5. // HmacMd5 return the hmac hash of string use md5.
// Play: https://go.dev/play/p/uef0q1fz53I // Play: https://go.dev/play/p/uef0q1fz53I
func HmacMd5(data, key string) string { func HmacMd5(str, key string) string {
h := hmac.New(md5.New, []byte(key))
h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte("")))
}
// HmacMd5WithBase64 return the hmac hash of string use md5 with base64.
// https://go.dev/play/p/UY0ng2AefFC
func HmacMd5WithBase64(data, key string) string {
h := hmac.New(md5.New, []byte(key)) h := hmac.New(md5.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte(""))) return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha1 return the hmac hash of string use sha1. // HmacSha1 return the hmac hash of string use sha1.
// Play: https://go.dev/play/p/1UI4oQ4WXKM // Play: https://go.dev/play/p/1UI4oQ4WXKM
func HmacSha1(data, key string) string { func HmacSha1(str, key string) string {
h := hmac.New(sha1.New, []byte(key)) h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha1WithBase64 return the hmac hash of string use sha1 with base64.
// Play: https://go.dev/play/p/47JmmGrnF7B
func HmacSha1WithBase64(str, key string) string {
h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// HmacSha256 return the hmac hash of string use sha256. // HmacSha256 return the hmac hash of string use sha256.
// Play: https://go.dev/play/p/HhpwXxFhhC0 // Play: https://go.dev/play/p/HhpwXxFhhC0
func HmacSha256(data, key string) string { func HmacSha256(str, key string) string {
h := hmac.New(sha256.New, []byte(key)) h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha256WithBase64 return the hmac hash of string use sha256 with base64.
// Play: https://go.dev/play/p/EKbkUvPTLwO
func HmacSha256WithBase64(str, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// HmacSha512 return the hmac hash of string use sha512. // HmacSha512 return the hmac hash of string use sha512.
// Play: https://go.dev/play/p/59Od6m4A0Ud // Play: https://go.dev/play/p/59Od6m4A0Ud
func HmacSha512(data, key string) string { func HmacSha512(str, key string) string {
h := hmac.New(sha512.New, []byte(key)) h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(str))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha512WithBase64 return the hmac hash of string use sha512 with base64.
// Play: https://go.dev/play/p/c6dSe3E2ydU
func HmacSha512WithBase64(str, key string) string {
h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(str))
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
}
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string. // Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
// Play: https://go.dev/play/p/_m_uoD1deMT // Play: https://go.dev/play/p/_m_uoD1deMT
func Sha1(data string) string { func Sha1(str string) string {
sha1 := sha1.New() sha1 := sha1.New()
sha1.Write([]byte(data)) sha1.Write([]byte(str))
return hex.EncodeToString(sha1.Sum([]byte(""))) return hex.EncodeToString(sha1.Sum([]byte("")))
} }
// Sha1WithBase64 return the sha1 value (SHA-1 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/fSyx-Gl2l2-
func Sha1WithBase64(str string) string {
sha1 := sha1.New()
sha1.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha1.Sum([]byte("")))
}
// Sha256 return the sha256 value (SHA256 hash algorithm) of string. // Sha256 return the sha256 value (SHA256 hash algorithm) of string.
// Play: https://go.dev/play/p/tU9tfBMIAr1 // Play: https://go.dev/play/p/tU9tfBMIAr1
func Sha256(data string) string { func Sha256(str string) string {
sha256 := sha256.New() sha256 := sha256.New()
sha256.Write([]byte(data)) sha256.Write([]byte(str))
return hex.EncodeToString(sha256.Sum([]byte(""))) return hex.EncodeToString(sha256.Sum([]byte("")))
} }
// Sha256WithBase64 return the sha256 value (SHA256 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/85IXJHIal1k
func Sha256WithBase64(str string) string {
sha256 := sha256.New()
sha256.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha256.Sum([]byte("")))
}
// Sha512 return the sha512 value (SHA512 hash algorithm) of string. // Sha512 return the sha512 value (SHA512 hash algorithm) of string.
// Play: https://go.dev/play/p/3WsvLYZxsHa // Play: https://go.dev/play/p/3WsvLYZxsHa
func Sha512(data string) string { func Sha512(str string) string {
sha512 := sha512.New() sha512 := sha512.New()
sha512.Write([]byte(data)) sha512.Write([]byte(str))
return hex.EncodeToString(sha512.Sum([]byte(""))) return hex.EncodeToString(sha512.Sum([]byte("")))
} }
// Sha512WithBase64 return the sha512 value (SHA512 hash algorithm) of base64 string.
// Play: https://go.dev/play/p/q_fY2rA-k5I
func Sha512WithBase64(str string) string {
sha512 := sha512.New()
sha512.Write([]byte(str))
return base64.StdEncoding.EncodeToString(sha512.Sum([]byte("")))
}

View File

@@ -7,21 +7,51 @@ import (
) )
func TestBase64StdEncode(t *testing.T) { func TestBase64StdEncode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBase64StdEncode") assert := internal.NewAssert(t, "TestBase64StdEncode")
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world")) assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
} }
func TestBase64StdDecode(t *testing.T) { func TestBase64StdDecode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBase64StdDecode") assert := internal.NewAssert(t, "TestBase64StdDecode")
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ=")) assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
} }
func TestMd5String(t *testing.T) { func TestMd5String(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5String") assert := internal.NewAssert(t, "TestMd5String")
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello")) assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
} }
func TestMd5StringWithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5StringWithBase64")
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5StringWithBase64("hello"))
}
func TestMd5Byte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5Byte")
data := []byte{'a'}
assert.Equal("0cc175b9c0f1b6a831c399e269772661", Md5Byte(data))
}
func TestMd5ByteWithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5ByteWithBase64")
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5ByteWithBase64([]byte("hello")))
}
func TestMd5File(t *testing.T) { func TestMd5File(t *testing.T) {
t.Parallel()
fileMd5, err := Md5File("./basic.go") fileMd5, err := Md5File("./basic.go")
assert := internal.NewAssert(t, "TestMd5File") assert := internal.NewAssert(t, "TestMd5File")
assert.IsNotNil(fileMd5) assert.IsNotNil(fileMd5)
@@ -29,11 +59,22 @@ func TestMd5File(t *testing.T) {
} }
func TestHmacMd5(t *testing.T) { func TestHmacMd5(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHmacMd5") assert := internal.NewAssert(t, "TestHmacMd5")
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345")) assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
} }
func TestHmacMd5WithBase64(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHmacMd5WithBase64")
assert.Equal("6DQwbquJLYclJdSRinpjmg==", HmacMd5WithBase64("hello", "12345"))
}
func TestHmacSha1(t *testing.T) { func TestHmacSha1(t *testing.T) {
t.Parallel()
s := "hello world" s := "hello world"
key := "12345" key := "12345"
hmacSha1 := HmacSha1(s, key) hmacSha1 := HmacSha1(s, key)
@@ -43,17 +84,45 @@ func TestHmacSha1(t *testing.T) {
assert.Equal(expected, hmacSha1) assert.Equal(expected, hmacSha1)
} }
func TestHmacSha256(t *testing.T) { func TestHmacSha1WithBase64(t *testing.T) {
s := "hello world" t.Parallel()
s := "hello"
key := "12345" key := "12345"
hmacSha256 := HmacSha256(s, key) hmacSha1 := HmacSha1WithBase64(s, key)
expected := "XGqdsMzLkuNu0DI/0Jt/k23prOA="
assert := internal.NewAssert(t, "TestHmacSha1")
assert.Equal(expected, hmacSha1)
}
func TestHmacSha256(t *testing.T) {
t.Parallel()
str := "hello world"
key := "12345"
hmacSha256 := HmacSha256(str, key)
expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8" expected := "9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8"
assert := internal.NewAssert(t, "TestHmacSha256") assert := internal.NewAssert(t, "TestHmacSha256")
assert.Equal(expected, hmacSha256) assert.Equal(expected, hmacSha256)
} }
func TestHmacSha256WithBase64(t *testing.T) {
t.Parallel()
str := "hello"
key := "12345"
hms := HmacSha256WithBase64(str, key)
expected := "MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU="
assert := internal.NewAssert(t, "TestHmacSha256WithBase64")
assert.Equal(expected, hms)
}
func TestHmacSha512(t *testing.T) { func TestHmacSha512(t *testing.T) {
t.Parallel()
s := "hello world" s := "hello world"
key := "12345" key := "12345"
hmacSha512 := HmacSha512(s, key) hmacSha512 := HmacSha512(s, key)
@@ -63,7 +132,21 @@ func TestHmacSha512(t *testing.T) {
assert.Equal(expected, hmacSha512) assert.Equal(expected, hmacSha512)
} }
func TestHmacSha512WithBase64(t *testing.T) {
t.Parallel()
str := "hello"
key := "12345"
hms := HmacSha512WithBase64(str, key)
expected := "3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A=="
assert := internal.NewAssert(t, "TestHmacSha512WithBase64")
assert.Equal(expected, hms)
}
func TestSha1(t *testing.T) { func TestSha1(t *testing.T) {
t.Parallel()
s := "hello world" s := "hello world"
sha1 := Sha1(s) sha1 := Sha1(s)
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed" expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
@@ -72,7 +155,19 @@ func TestSha1(t *testing.T) {
assert.Equal(expected, sha1) assert.Equal(expected, sha1)
} }
func TestSha1WithBase64(t *testing.T) {
t.Parallel()
str := Sha1WithBase64("hello")
expected := "qvTGHdzF6KLavt4PO0gs2a6pQ00="
assert := internal.NewAssert(t, "TestSha1WithBase64")
assert.Equal(expected, str)
}
func TestSha256(t *testing.T) { func TestSha256(t *testing.T) {
t.Parallel()
s := "hello world" s := "hello world"
sha256 := Sha256(s) sha256 := Sha256(s)
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9" expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
@@ -81,7 +176,19 @@ func TestSha256(t *testing.T) {
assert.Equal(expected, sha256) assert.Equal(expected, sha256)
} }
func TestSha256WithBase64(t *testing.T) {
t.Parallel()
str := Sha256WithBase64("hello")
expected := "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
assert := internal.NewAssert(t, "TestSha256WithBase64")
assert.Equal(expected, str)
}
func TestSha512(t *testing.T) { func TestSha512(t *testing.T) {
t.Parallel()
s := "hello world" s := "hello world"
sha512 := Sha512(s) sha512 := Sha512(s)
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f" expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"
@@ -89,3 +196,13 @@ func TestSha512(t *testing.T) {
assert := internal.NewAssert(t, "TestSha512") assert := internal.NewAssert(t, "TestSha512")
assert.Equal(expected, sha512) assert.Equal(expected, sha512)
} }
func TestSha512WithBase64(t *testing.T) {
t.Parallel()
str := Sha512WithBase64("hello")
expected := "m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=="
assert := internal.NewAssert(t, "TestSha512WithBase64")
assert.Equal(expected, str)
}

View File

@@ -13,6 +13,7 @@ import (
"crypto/des" "crypto/des"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"io" "io"
@@ -75,6 +76,11 @@ func AesEcbDecrypt(encrypted, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD // Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcEncrypt(data, key []byte) []byte { func AesCbcEncrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize()) data = pkcs7Padding(data, block.BlockSize())
@@ -94,6 +100,11 @@ func AesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD // Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcDecrypt(encrypted, key []byte) []byte { func AesCbcDecrypt(encrypted, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize] iv := encrypted[:aes.BlockSize]
@@ -110,6 +121,11 @@ func AesCbcDecrypt(encrypted, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/SpaZO0-5Nsp // Play: https://go.dev/play/p/SpaZO0-5Nsp
func AesCtrCrypt(data, key []byte) []byte { func AesCtrCrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize()) iv := bytes.Repeat([]byte("1"), block.BlockSize())
@@ -125,6 +141,11 @@ func AesCtrCrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH // Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbEncrypt(data, key []byte) []byte { func AesCfbEncrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -147,6 +168,11 @@ func AesCfbEncrypt(data, key []byte) []byte {
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32. // len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH // Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbDecrypt(encrypted, key []byte) []byte { func AesCfbDecrypt(encrypted, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
if len(encrypted) < aes.BlockSize { if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short") panic("encrypted data is too short")
} }
@@ -166,6 +192,11 @@ func AesCfbDecrypt(encrypted, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F // Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbEncrypt(data, key []byte) []byte { func AesOfbEncrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -188,6 +219,11 @@ func AesOfbEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F // Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbDecrypt(data, key []byte) []byte { func AesOfbDecrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -254,6 +290,11 @@ func DesEcbDecrypt(encrypted, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1 // Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcEncrypt(data, key []byte) []byte { func DesCbcEncrypt(data, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, _ := des.NewCipher(key) block, _ := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize()) data = pkcs7Padding(data, block.BlockSize())
@@ -274,6 +315,11 @@ func DesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1 // Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcDecrypt(encrypted, key []byte) []byte { func DesCbcDecrypt(encrypted, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, _ := des.NewCipher(key) block, _ := des.NewCipher(key)
iv := encrypted[:des.BlockSize] iv := encrypted[:des.BlockSize]
@@ -290,6 +336,11 @@ func DesCbcDecrypt(encrypted, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/9-T6OjKpcdw // Play: https://go.dev/play/p/9-T6OjKpcdw
func DesCtrCrypt(data, key []byte) []byte { func DesCtrCrypt(data, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, _ := des.NewCipher(key) block, _ := des.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize()) iv := bytes.Repeat([]byte("1"), block.BlockSize())
@@ -305,6 +356,11 @@ func DesCtrCrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL // Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbEncrypt(data, key []byte) []byte { func DesCfbEncrypt(data, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -326,6 +382,11 @@ func DesCfbEncrypt(data, key []byte) []byte {
// len(encrypted) should be great than 16, len(key) should be 8. // len(encrypted) should be great than 16, len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL // Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbDecrypt(encrypted, key []byte) []byte { func DesCfbDecrypt(encrypted, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, _ := des.NewCipher(key) block, _ := des.NewCipher(key)
if len(encrypted) < des.BlockSize { if len(encrypted) < des.BlockSize {
panic("encrypted data is too short") panic("encrypted data is too short")
@@ -340,9 +401,14 @@ func DesCfbDecrypt(encrypted, key []byte) []byte {
} }
// DesOfbEncrypt encrypt data with key use DES OFB algorithm // DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J // Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbEncrypt(data, key []byte) []byte { func DesOfbEncrypt(data, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -364,6 +430,11 @@ func DesOfbEncrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J // Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbDecrypt(data, key []byte) []byte { func DesOfbDecrypt(data, key []byte) []byte {
size := len(key)
if size != 8 {
panic("key length shoud be 8")
}
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -505,3 +576,32 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
} }
return plainText return plainText
} }
// GenerateRsaKeyPair create rsa private and public key.
// Play: https://go.dev/play/p/sSVmkfENKMz
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey) {
privateKey, _ := rsa.GenerateKey(rand.Reader, keySize)
return privateKey, &privateKey.PublicKey
}
// RsaEncryptOAEP encrypts the given data with RSA-OAEP.
// Play: https://go.dev/play/p/sSVmkfENKMz
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error) {
encryptedBytes, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &key, data, label)
if err != nil {
return nil, err
}
return encryptedBytes, nil
}
// RsaDecryptOAEP decrypts the data with RSA-OAEP.
// Play: https://go.dev/play/p/sSVmkfENKMz
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error) {
decryptedBytes, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, ciphertext, label)
if err != nil {
return nil, err
}
return decryptedBytes, nil
}

View File

@@ -1,6 +1,8 @@
package cryptor package cryptor
import "fmt" import (
"fmt"
)
func ExampleAesEcbEncrypt() { func ExampleAesEcbEncrypt() {
data := "hello" data := "hello"
@@ -322,89 +324,187 @@ func ExampleHmacMd5() {
key := "12345" key := "12345"
hms := HmacMd5(str, key) hms := HmacMd5(str, key)
fmt.Println(hms) fmt.Println(hms)
// Output: // Output:
// e834306eab892d872525d4918a7a639a // e834306eab892d872525d4918a7a639a
} }
func ExampleHmacMd5WithBase64() {
str := "hello"
key := "12345"
hms := HmacMd5WithBase64(str, key)
fmt.Println(hms)
// Output:
// 6DQwbquJLYclJdSRinpjmg==
}
func ExampleHmacSha1() { func ExampleHmacSha1() {
str := "hello" str := "hello"
key := "12345" key := "12345"
hms := HmacSha1(str, key) hms := HmacSha1(str, key)
fmt.Println(hms) fmt.Println(hms)
// Output: // Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0 // 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
} }
func ExampleHmacSha1WithBase64() {
str := "hello"
key := "12345"
hms := HmacSha1WithBase64(str, key)
fmt.Println(hms)
// Output:
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
}
func ExampleHmacSha256() { func ExampleHmacSha256() {
str := "hello" str := "hello"
key := "12345" key := "12345"
hms := HmacSha256(str, key) hms := HmacSha256(str, key)
fmt.Println(hms) fmt.Println(hms)
// Output: // Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75 // 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
} }
func ExampleHmacSha256WithBase64() {
str := "hello"
key := "12345"
hms := HmacSha256WithBase64(str, key)
fmt.Println(hms)
// Output:
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
}
func ExampleHmacSha512() { func ExampleHmacSha512() {
str := "hello" str := "hello"
key := "12345" key := "12345"
hms := HmacSha512(str, key) hms := HmacSha512(str, key)
fmt.Println(hms) fmt.Println(hms)
// Output: // Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc // dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
} }
func ExampleMd5String() { func ExampleHmacSha512WithBase64() {
str := "hello" str := "hello"
key := "12345"
md5Str := Md5String(str) hms := HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
func ExampleMd5String() {
md5Str := Md5String("hello")
fmt.Println(md5Str) fmt.Println(md5Str)
// Output: // Output:
// 5d41402abc4b2a76b9719d911017c592 // 5d41402abc4b2a76b9719d911017c592
} }
func ExampleMd5StringWithBase64() {
md5Str := Md5StringWithBase64("hello")
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
func ExampleMd5Byte() {
md5Str := Md5Byte([]byte{'a'})
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
func ExampleMd5ByteWithBase64() {
md5Str := Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
func ExampleSha1() { func ExampleSha1() {
str := "hello" result := Sha1("hello")
result := Sha1(str)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d // aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
} }
func ExampleSha1WithBase64() {
result := Sha1WithBase64("hello")
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
func ExampleSha256() { func ExampleSha256() {
str := "hello" result := Sha256("hello")
result := Sha256(str)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 // 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
} }
func ExampleSha256WithBase64() {
result := Sha256WithBase64("hello")
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
func ExampleSha512() { func ExampleSha512() {
str := "hello" result := Sha512("hello")
result := Sha512(str)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043 // 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
} }
func ExampleSha512WithBase64() {
result := Sha512WithBase64("hello")
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}
func ExampleRsaEncryptOAEP() {
pri, pub := GenerateRsaKeyPair(1024)
data := []byte("hello world")
label := []byte("123456")
encrypted, err := RsaEncryptOAEP(data, label, *pub)
if err != nil {
return
}
decrypted, err := RsaDecryptOAEP([]byte(encrypted), label, *pri)
if err != nil {
return
}
fmt.Println(string(decrypted))
// Output:
// hello world
}

View File

@@ -7,6 +7,8 @@ import (
) )
func TestAesEcbEncrypt(t *testing.T) { func TestAesEcbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -18,6 +20,8 @@ func TestAesEcbEncrypt(t *testing.T) {
} }
func TestAesCbcEncrypt(t *testing.T) { func TestAesCbcEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -29,6 +33,8 @@ func TestAesCbcEncrypt(t *testing.T) {
} }
func TestAesCtrCrypt(t *testing.T) { func TestAesCtrCrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -40,6 +46,8 @@ func TestAesCtrCrypt(t *testing.T) {
} }
func TestAesCfbEncrypt(t *testing.T) { func TestAesCfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -51,6 +59,8 @@ func TestAesCfbEncrypt(t *testing.T) {
} }
func TestAesOfbEncrypt(t *testing.T) { func TestAesOfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
@@ -62,6 +72,8 @@ func TestAesOfbEncrypt(t *testing.T) {
} }
func TestDesEcbEncrypt(t *testing.T) { func TestDesEcbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
@@ -73,6 +85,8 @@ func TestDesEcbEncrypt(t *testing.T) {
} }
func TestDesCbcEncrypt(t *testing.T) { func TestDesCbcEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
@@ -84,6 +98,8 @@ func TestDesCbcEncrypt(t *testing.T) {
} }
func TestDesCtrCrypt(t *testing.T) { func TestDesCtrCrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
@@ -95,6 +111,8 @@ func TestDesCtrCrypt(t *testing.T) {
} }
func TestDesCfbEncrypt(t *testing.T) { func TestDesCfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
@@ -106,6 +124,8 @@ func TestDesCfbEncrypt(t *testing.T) {
} }
func TestDesOfbEncrypt(t *testing.T) { func TestDesOfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
@@ -117,6 +137,8 @@ func TestDesOfbEncrypt(t *testing.T) {
} }
func TestRsaEncrypt(t *testing.T) { func TestRsaEncrypt(t *testing.T) {
t.Parallel()
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem") err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil { if err != nil {
t.FailNow() t.FailNow()
@@ -128,3 +150,21 @@ func TestRsaEncrypt(t *testing.T) {
assert := internal.NewAssert(t, "TestRsaEncrypt") assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted)) assert.Equal(string(data), string(decrypted))
} }
func TestRsaEncryptOAEP(t *testing.T) {
assert := internal.NewAssert(t, "TestRsaEncrypt")
t.Parallel()
pri, pub := GenerateRsaKeyPair(1024)
data := []byte("hello world")
label := []byte("123456")
encrypted, err := RsaEncryptOAEP(data, label, *pub)
assert.IsNil(err)
decrypted, err := RsaDecryptOAEP([]byte(encrypted), label, *pri)
assert.IsNil(err)
assert.Equal("hello world", string(decrypted))
}

View File

@@ -1,12 +1,13 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved. // Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph. // Package datastructure implements some data structure. hashmap structure.
package datastructure package datastructure
import ( import (
"fmt" "fmt"
"hash/fnv" "hash/fnv"
"reflect"
) )
var defaultMapCapacity uint64 = 1 << 10 var defaultMapCapacity uint64 = 1 << 10
@@ -45,13 +46,24 @@ func NewHashMapWithCapacity(size, capacity uint64) *HashMap {
func (hm *HashMap) Get(key any) any { func (hm *HashMap) Get(key any) any {
hashValue := hm.hash(key) hashValue := hm.hash(key)
node := hm.table[hashValue] node := hm.table[hashValue]
if node != nil { for node != nil {
return node.value if reflect.DeepEqual(node.key, key) {
return node.value
}
node = node.next
} }
return nil return nil
} }
// GetOrDefault return the value of given key in hashmap, if not found return default value
func (hm *HashMap) GetOrDefault(key any, defaultValue any) any {
value := hm.Get(key)
if value == nil {
return defaultValue
}
return value
}
// Put new key value in hashmap // Put new key value in hashmap
func (hm *HashMap) Put(key any, value any) { func (hm *HashMap) Put(key any, value any) {
hm.putValue(hm.hash(key), key, value) hm.putValue(hm.hash(key), key, value)
@@ -90,7 +102,13 @@ func (hm *HashMap) Delete(key any) {
// Contains checks if given key is in hashmap or not // Contains checks if given key is in hashmap or not
func (hm *HashMap) Contains(key any) bool { func (hm *HashMap) Contains(key any) bool {
node := hm.table[hm.hash(key)] node := hm.table[hm.hash(key)]
return node != nil for node != nil {
if reflect.DeepEqual(node.key, key) {
return true
}
node = node.next
}
return false
} }
// Iterate executes iteratee funcation for every key and value pair of hashmap (random order) // Iterate executes iteratee funcation for every key and value pair of hashmap (random order)
@@ -105,6 +123,25 @@ func (hm *HashMap) Iterate(iteratee func(key, value any)) {
} }
} }
// FilterByValue returns a filtered HashMap.
// If any value is not matching the perdicate function then it returns nil
// otherwise it returns the HashMap with selected values.
func (hm *HashMap) FilterByValue(perdicate func(value any) bool) *HashMap {
var filteredHM *HashMap
if hm.size > 0 {
for i := 0; i < len(hm.table); i++ {
item := hm.table[i]
if item != nil && perdicate(item.value) {
if filteredHM == nil {
filteredHM = NewHashMap()
}
filteredHM.Put(item.key, item.value)
}
}
}
return filteredHM
}
// Keys returns a slice of the hashmap's keys (random order) // Keys returns a slice of the hashmap's keys (random order)
func (hm *HashMap) Keys() []any { func (hm *HashMap) Keys() []any {
keys := make([]any, int(hm.size)) keys := make([]any, int(hm.size))
@@ -150,6 +187,11 @@ func (hm *HashMap) resize() {
} }
} }
// Size returns current size of Hashmap
func (hm *HashMap) Size() uint64 {
return hm.size
}
func (hm *HashMap) hash(key any) uint64 { func (hm *HashMap) hash(key any) uint64 {
h := fnv.New64a() h := fnv.New64a()
_, _ = h.Write([]byte(fmt.Sprintf("%v", key))) _, _ = h.Write([]byte(fmt.Sprintf("%v", key)))

View File

@@ -32,6 +32,8 @@ func TestHashMap_Resize(t *testing.T) {
} }
func TestHashMap_Delete(t *testing.T) { func TestHashMap_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Delete") assert := internal.NewAssert(t, "TestHashMap_Delete")
hm := NewHashMap() hm := NewHashMap()
@@ -44,6 +46,8 @@ func TestHashMap_Delete(t *testing.T) {
} }
func TestHashMap_Contains(t *testing.T) { func TestHashMap_Contains(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Contains") assert := internal.NewAssert(t, "TestHashMap_Contains")
hm := NewHashMap() hm := NewHashMap()
@@ -54,6 +58,8 @@ func TestHashMap_Contains(t *testing.T) {
} }
func TestHashMap_KeysValues(t *testing.T) { func TestHashMap_KeysValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_KeysValues") assert := internal.NewAssert(t, "TestHashMap_KeysValues")
hm := NewHashMap() hm := NewHashMap()
@@ -68,3 +74,55 @@ func TestHashMap_KeysValues(t *testing.T) {
assert.Equal(3, len(values)) assert.Equal(3, len(values))
assert.Equal(3, len(keys)) assert.Equal(3, len(keys))
} }
func TestHashMap_Keys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Keys")
hm := NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
keys := hm.Keys()
assert.Equal(3, len(keys))
}
func TestHashMap_GetOrDefault(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_GetOrDefault")
hm := NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
assert.Equal(1, hm.GetOrDefault("a", 5))
assert.Equal(5, hm.GetOrDefault("d", 5))
}
func TestHashMap_FilterByValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_FilterByValue")
hm := NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
hm.Put("d", 4)
hm.Put("e", 5)
hm.Put("f", 6)
filteredHM := hm.FilterByValue(func(value any) bool {
return value.(int) == 1 || value.(int) == 3
})
assert.Equal(uint64(2), filteredHM.Size())
}

View File

@@ -1,24 +1,24 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved. // Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph. // Package datastructure implements some data structure. MaxHeap is a binary max heap.
package datastructure package datastructure
import ( import (
"fmt" "fmt"
"github.com/duke-git/lancet/v2/lancetconstraints" "github.com/duke-git/lancet/v2/constraints"
) )
// MaxHeap implements a binary max heap // MaxHeap implements a binary max heap
// type T should implements Compare function in lancetconstraints.Comparator interface. // type T should implements Compare function in constraints.Comparator interface.
type MaxHeap[T any] struct { type MaxHeap[T any] struct {
data []T data []T
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
// NewMaxHeap returns a MaxHeap instance with the given comparator. // NewMaxHeap returns a MaxHeap instance with the given comparator.
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] { func NewMaxHeap[T any](comparator constraints.Comparator) *MaxHeap[T] {
return &MaxHeap[T]{ return &MaxHeap[T]{
data: make([]T, 0), data: make([]T, 0),
comparator: comparator, comparator: comparator,
@@ -26,7 +26,7 @@ func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] {
} }
// BuildMaxHeap builds a MaxHeap instance with data and given comparator. // BuildMaxHeap builds a MaxHeap instance with data and given comparator.
func BuildMaxHeap[T any](data []T, comparator lancetconstraints.Comparator) *MaxHeap[T] { func BuildMaxHeap[T any](data []T, comparator constraints.Comparator) *MaxHeap[T] {
heap := &MaxHeap[T]{ heap := &MaxHeap[T]{
data: make([]T, 0, len(data)), data: make([]T, 0, len(data)),
comparator: comparator, comparator: comparator,

View File

@@ -21,6 +21,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
} }
func TestMaxHeap_BuildMaxHeap(t *testing.T) { func TestMaxHeap_BuildMaxHeap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap") assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11} values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
@@ -33,6 +35,8 @@ func TestMaxHeap_BuildMaxHeap(t *testing.T) {
} }
func TestMaxHeap_Push(t *testing.T) { func TestMaxHeap_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Push") assert := internal.NewAssert(t, "TestMaxHeap_Push")
heap := NewMaxHeap[int](&intComparator{}) heap := NewMaxHeap[int](&intComparator{})
@@ -51,6 +55,8 @@ func TestMaxHeap_Push(t *testing.T) {
} }
func TestMaxHeap_Pop(t *testing.T) { func TestMaxHeap_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Pop") assert := internal.NewAssert(t, "TestMaxHeap_Pop")
heap := NewMaxHeap[int](&intComparator{}) heap := NewMaxHeap[int](&intComparator{})
@@ -70,6 +76,8 @@ func TestMaxHeap_Pop(t *testing.T) {
} }
func TestMaxHeap_Peek(t *testing.T) { func TestMaxHeap_Peek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Peek") assert := internal.NewAssert(t, "TestMaxHeap_Peek")
heap := NewMaxHeap[int](&intComparator{}) heap := NewMaxHeap[int](&intComparator{})

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
package datastructure package datastructure
import ( import (

View File

@@ -7,6 +7,8 @@ import (
) )
func TestDoublyLink_InsertAtFirst(t *testing.T) { func TestDoublyLink_InsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst") assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -22,6 +24,8 @@ func TestDoublyLink_InsertAtFirst(t *testing.T) {
} }
func TestDoublyLink_InsertAtTail(t *testing.T) { func TestDoublyLink_InsertAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail") assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -37,12 +41,12 @@ func TestDoublyLink_InsertAtTail(t *testing.T) {
} }
func TestDoublyLink_InsertAt(t *testing.T) { func TestDoublyLink_InsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt") assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
link.InsertAt(1, 1) //do nothing link.InsertAt(1, 1) //do nothing
link.InsertAt(0, 1) link.InsertAt(0, 1)
link.InsertAt(1, 2) link.InsertAt(1, 2)
link.InsertAt(2, 4) link.InsertAt(2, 4)
@@ -55,6 +59,8 @@ func TestDoublyLink_InsertAt(t *testing.T) {
} }
func TestDoublyLink_DeleteAtHead(t *testing.T) { func TestDoublyLink_DeleteAtHead(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead") assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -74,6 +80,8 @@ func TestDoublyLink_DeleteAtHead(t *testing.T) {
} }
func TestDoublyLink_DeleteAtTail(t *testing.T) { func TestDoublyLink_DeleteAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail") assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -93,6 +101,8 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
} }
func TestDoublyLink_DeleteAt(t *testing.T) { func TestDoublyLink_DeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt") assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -116,6 +126,8 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
} }
func TestDoublyLink_Reverse(t *testing.T) { func TestDoublyLink_Reverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_Reverse") assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -130,6 +142,8 @@ func TestDoublyLink_Reverse(t *testing.T) {
} }
func TestDoublyLink_GetMiddleNode(t *testing.T) { func TestDoublyLink_GetMiddleNode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode") assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
@@ -149,10 +163,11 @@ func TestDoublyLink_GetMiddleNode(t *testing.T) {
} }
func TestDoublyLink_Clear(t *testing.T) { func TestDoublyLink_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_Clear") assert := internal.NewAssert(t, "TestDoublyLink_Clear")
link := NewDoublyLink[int]() link := NewDoublyLink[int]()
assert.Equal(true, link.IsEmpty()) assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size()) assert.Equal(0, link.Size())

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
package datastructure package datastructure
import ( import (

View File

@@ -7,6 +7,8 @@ import (
) )
func TestSinglyLink_InsertAtFirst(t *testing.T) { func TestSinglyLink_InsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst") assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -22,6 +24,8 @@ func TestSinglyLink_InsertAtFirst(t *testing.T) {
} }
func TestSinglyLink_InsertAtTail(t *testing.T) { func TestSinglyLink_InsertAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail") assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -37,6 +41,8 @@ func TestSinglyLink_InsertAtTail(t *testing.T) {
} }
func TestSinglyLink_InsertAt(t *testing.T) { func TestSinglyLink_InsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt") assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -57,6 +63,8 @@ func TestSinglyLink_InsertAt(t *testing.T) {
} }
func TestSinglyLink_DeleteAtHead(t *testing.T) { func TestSinglyLink_DeleteAtHead(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead") assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -78,10 +86,11 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
} }
func TestSinglyLink_DeleteAtTail(t *testing.T) { func TestSinglyLink_DeleteAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail") assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
link.InsertAtTail(1) link.InsertAtTail(1)
link.InsertAtTail(2) link.InsertAtTail(2)
link.InsertAtTail(3) link.InsertAtTail(3)
@@ -96,10 +105,11 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
} }
func TestSinglyLink_DeleteValue(t *testing.T) { func TestSinglyLink_DeleteValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue") assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
link.InsertAtTail(1) link.InsertAtTail(1)
link.InsertAtTail(2) link.InsertAtTail(2)
link.InsertAtTail(2) link.InsertAtTail(2)
@@ -114,10 +124,11 @@ func TestSinglyLink_DeleteValue(t *testing.T) {
} }
func TestSinglyLink_DeleteAt(t *testing.T) { func TestSinglyLink_DeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt") assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
link.InsertAtTail(1) link.InsertAtTail(1)
link.InsertAtTail(2) link.InsertAtTail(2)
link.InsertAtTail(3) link.InsertAtTail(3)
@@ -136,6 +147,8 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
} }
func TestSinglyLink_Reverse(t *testing.T) { func TestSinglyLink_Reverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_Reverse") assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -149,6 +162,8 @@ func TestSinglyLink_Reverse(t *testing.T) {
} }
func TestSinglyLink_GetMiddleNode(t *testing.T) { func TestSinglyLink_GetMiddleNode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode") assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
link := NewSinglyLink[int]() link := NewSinglyLink[int]()
@@ -163,6 +178,7 @@ func TestSinglyLink_GetMiddleNode(t *testing.T) {
link.InsertAtTail(5) link.InsertAtTail(5)
link.InsertAtTail(6) link.InsertAtTail(6)
link.InsertAtTail(7) link.InsertAtTail(7)
middle2 := link.GetMiddleNode() middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value) assert.Equal(4, middle2.Value)
} }

View File

@@ -0,0 +1,379 @@
package datastructure
import (
"reflect"
"sort"
"sync"
)
type CopyOnWriteList[T any] struct {
data []T
lock sync.Locker
}
// NewCopyOnWriteList Creates an empty list.
func NewCopyOnWriteList[T any](data []T) *CopyOnWriteList[T] {
return &CopyOnWriteList[T]{data: data, lock: &sync.RWMutex{}}
}
func (c *CopyOnWriteList[T]) getList() []T {
return c.data
}
func (c *CopyOnWriteList[T]) setList(data []T) {
c.data = data
}
// Size returns the number of elements in this list.
func (c *CopyOnWriteList[T]) Size() int {
return len(c.getList())
}
// IsEmpty returns true if this list contains no elements.
func (c *CopyOnWriteList[T]) IsEmpty() bool {
return c.Size() == 0
}
// Contain returns true if this list contains the specified element.
func (c *CopyOnWriteList[T]) Contain(e T) bool {
list := c.getList()
return indexOf(e, list, 0, c.Size()) >= 0
}
// ValueOf returns the index of the first occurrence of the specified element in this list, or null if this list does not contain the element.
func (c *CopyOnWriteList[T]) ValueOf(index int) (*T, bool) {
list := c.getList()
if index < 0 || index >= len(c.data) {
return nil, false
}
return get(list, index), true
}
// IndexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
func (c *CopyOnWriteList[T]) IndexOf(e T) int {
list := c.getList()
return indexOf(e, list, 0, c.Size())
}
// indexOf returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
// start the start position of the search (inclusive)
// end the end position of the search (exclusive)
func indexOf[T any](o T, e []T, start int, end int) int {
if start >= end {
return -1
}
for i := start; i < end; i++ {
if reflect.DeepEqual(e[i], o) {
return i
}
}
return -1
}
// LastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int {
list := c.getList()
return lastIndexOf(e, list, 0, c.Size())
}
// lastIndexOf returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
// start the start position of the search (inclusive)
// end the end position of the search (exclusive)
func lastIndexOf[T any](o T, e []T, start int, end int) int {
if start >= end {
return -1
}
for i := end - 1; i >= start; i-- {
if reflect.DeepEqual(e[i], o) {
return i
}
}
return -1
}
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying the
// functional predicate f(T) bool
// if not found return -1.
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int {
index := -1
data := l.getList()
for i := len(data) - 1; i >= 0; i-- {
if f(data[i]) {
index = i
break
}
}
return index
}
// IndexOfFunc returns the first index satisfying the functional predicate f(v) bool
// if not found return -1.
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int {
index := -1
data := l.getList()
for i, v := range data {
if f(v) {
index = i
break
}
}
return index
}
// get returns the element at the specified position in this list.
func get[T any](o []T, index int) *T {
return &o[index]
}
// Get returns the element at the specified position in this list.
func (c *CopyOnWriteList[T]) Get(index int) *T {
list := c.getList()
if index < 0 || index >= len(list) {
return nil
}
return get(list, index)
}
func (c *CopyOnWriteList[T]) set(index int, e T) (oldValue *T) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
oldValue = get(list, index)
if reflect.DeepEqual(oldValue, e) {
c.setList(list)
} else {
newList := make([]T, len(list))
copy(newList, list)
newList[index] = e
c.setList(newList)
}
return
}
// Set replaces the element at the specified position in this list with the specified element.
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool) {
list := c.getList()
if index < 0 || index >= len(list) {
return oldValue, false
}
return c.set(index, e), true
}
// Add appends the specified element to the end of this list.
func (c *CopyOnWriteList[T]) Add(e T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
newList := make([]T, len(list)+1)
copy(newList, list)
newList[len(list)] = e
c.setList(newList)
return true
}
// AddAll appends all the elements in the specified collection to the end of this list
func (c *CopyOnWriteList[T]) AddAll(e []T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
newList := make([]T, len(list)+len(e))
copy(newList, list)
copy(newList[len(list):], e)
c.setList(newList)
return true
}
// AddByIndex inserts the specified element at the specified position in this list.
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
if index < 0 || index > length {
return false
}
var newList []T
var numMove = length - index
if numMove == 0 {
newList = make([]T, length+1)
copy(newList, list)
} else {
newList = make([]T, length+1)
copy(newList, list[:index])
copy(newList[index+1:], list[index:])
}
newList[index] = e
c.setList(newList)
return true
}
// delete removes the element at the specified position in this list.
func (c *CopyOnWriteList[T]) delete(index int) *T {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
oldValue := get(list, index)
numMove := length - index - 1
var newList []T
if numMove == 0 {
newList = make([]T, length-1)
copy(newList, list[:index])
} else {
newList = make([]T, length-1)
copy(newList, list[:index])
copy(newList[index:], list[index+1:])
}
c.setList(newList)
return oldValue
}
// DeleteAt removes the element at the specified position in this list.
func (c *CopyOnWriteList[T]) DeleteAt(index int) (*T, bool) {
list := c.getList()
if index < 0 || index >= len(list) {
return nil, false
}
return c.delete(index), true
}
// DeleteBy removes the first occurrence of the specified element from this list, if it is present.
func (c *CopyOnWriteList[T]) DeleteBy(o T) (*T, bool) {
list := c.getList()
index := indexOf(o, list, 0, len(list))
if index == -1 {
return nil, false
}
return c.delete(index), true
}
// DeleteRange removes from this list all the elements whose index is between fromIndex, inclusive, and toIndex, exclusive.
// left close and right open
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
if start < 0 || end > length || start > end {
return
}
var newList []T
numMove := length - end
if numMove == 0 {
newList = make([]T, length-(end-start))
copy(newList, list[:start])
} else {
newList = make([]T, length-(end-start))
copy(newList, list[:start])
copy(newList[start:], list[end:])
}
c.setList(newList)
}
// DeleteIf removes all the elements of this collection that satisfy the given predicate.
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
length := len(list)
var newList []T
for i := 0; i < length; i++ {
if !f(list[i]) {
newList = append(newList, list[i])
}
}
c.setList(newList)
}
// Equal returns true if the specified object is equal to this list.
func (c *CopyOnWriteList[T]) Equal(other *[]T) bool {
if other == nil {
return false
}
if c.Size() != len(*other) {
return false
}
list := c.getList()
otherList := NewCopyOnWriteList(*other).getList()
for i := 0; i < len(list); i++ {
if !reflect.DeepEqual(list[i], otherList[i]) {
return false
}
}
return true
}
// Clear removes all the elements from this list.
func (c *CopyOnWriteList[T]) Clear() {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
list = make([]T, 0)
c.setList(list)
}
// Merge a tow list to one, change the list
func (c *CopyOnWriteList[T]) Merge(other []T) {
lock := c.lock
lock.Lock()
defer lock.Unlock()
list := c.getList()
list = append(list, other...)
c.setList(list)
}
// ForEach performs the given action for each element of the Iterable until all elements have been processed
// or the action throws an exception.
func (c *CopyOnWriteList[T]) ForEach(f func(T)) {
list := c.getList()
for i := 0; i < len(list); i++ {
f(list[i])
}
}
// Sort sorts this list according to the order induced by the specified Comparator.
func (c *CopyOnWriteList[T]) Sort(compare func(o1 T, o2 T) bool) {
lock := c.lock
lock.Lock()
list := c.getList()
sort.Slice(list, func(i, j int) bool {
return compare(list[i], list[j])
})
c.setList(list)
}
func (c *CopyOnWriteList[T]) SubList(start int, end int) (newList []T) {
lock := c.lock
lock.Lock()
list := c.getList()
length := len(list)
defer lock.Unlock()
if start < 0 || end > length || start > end {
return []T{}
}
newList = make([]T, end-start)
copy(newList, list[start:end])
c.setList(newList)
return
}

View File

@@ -0,0 +1,268 @@
package datastructure
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestCopyOnWriteList_ValueOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
of, ok := list.ValueOf(3)
assert.Equal(4, *of)
assert.Equal(true, ok)
_, ok = list.ValueOf(6)
assert.Equal(false, ok)
}
func TestCopyOnWriteList_Contain(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Contains")
assert.Equal(true, list.Contain(3))
}
func TestCopyOnWriteList_IsEmpty(t *testing.T) {
list := NewCopyOnWriteList([]int{})
assert := internal.NewAssert(t, "CopyOnWriteList_IsEmpty")
assert.Equal(true, list.IsEmpty())
}
func TestCopyOnWriteList_Size(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_size")
assert.Equal(5, list.Size())
}
func TestCopyOnWriteList_GetList(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_GetList")
assert.Equal([]int{1, 2, 3, 4, 5}, list.getList())
}
func TestCopyOnWriteList_Get(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Get")
i := list.Get(2)
assert.Equal(3, *i)
}
func TestCopyOnWriteList_Set(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Set")
list.Set(2, 6)
assert.Equal(6, list.getList()[2])
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.Set(0, 6)
assert.Equal(6, list.getList()[0])
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.Set(0, 1)
assert.Equal(1, list.getList()[0])
}
func TestCopyOnWriteList_Add(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_Add")
list.Add(6)
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
}
func TestCopyOnWriteList_AddAll(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_AddAll")
list.AddAll([]int{6, 7, 8})
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8}, list.getList())
}
func TestCopyOnWriteList_AddByIndex(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_AddByIndex")
list.AddByIndex(2, 6)
assert.Equal([]int{1, 2, 6, 3, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.AddByIndex(0, 6)
assert.Equal([]int{6, 1, 2, 3, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.AddByIndex(5, 6)
assert.Equal([]int{1, 2, 3, 4, 5, 6}, list.getList())
}
func TestCopyOnWriteList_DeleteAt2(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByIndex")
list.DeleteAt(2)
assert.Equal([]int{1, 2, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.DeleteAt(4)
assert.Equal([]int{1, 2, 3, 4}, list.getList())
}
func TestCopyOnWriteList_RemoveByValue(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveByValue")
list.DeleteBy(3)
assert.Equal([]int{1, 2, 4, 5}, list.getList())
}
func TestCopyOnWriteList_DeleteRange(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
assert := internal.NewAssert(t, "CopyOnWriteList_RemoveRange")
list.DeleteRange(1, 3)
assert.Equal([]int{1, 4, 5}, list.getList())
list = NewCopyOnWriteList([]int{1, 2, 3, 4, 5})
list.DeleteRange(0, 5)
assert.Equal([]int{}, list.getList())
}
func TestCopyOnWriteList_LastIndexOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_LastIndexOf")
assert.Equal(5, list.LastIndexOf(3))
}
func TestCopyOnWriteList_DeleteAt(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteAt")
list.DeleteAt(2)
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
}
func TestCopyOnWriteList_DeleteBy(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteBy")
list.DeleteBy(3)
assert.Equal([]int{1, 2, 4, 5, 3}, list.getList())
}
func TestCopyOnWriteList_DeleteIf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_DeleteIf")
list.DeleteIf(func(i int) bool {
return i%2 == 0
})
assert.Equal([]int{1, 3, 5, 3}, list.getList())
}
func TestCopyOnWriteList_Equal(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_Equal")
assert.Equal(true, list.Equal(&[]int{1, 2, 3, 4, 5, 3, 6}))
}
func TestCopyOnWriteList_ForEach(t *testing.T) {
testList := make([]int, 0)
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_ForEach")
list.ForEach(func(i int) {
testList = append(testList, i)
})
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6}, testList)
list.ForEach(func(i int) {
list.Add(i)
})
assert.Equal([]int{1, 2, 3, 4, 5, 3, 6, 1, 2, 3, 4, 5, 3, 6}, list.getList())
}
func TestCopyOnWriteList_Clear(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 2, 3, 4, 5, 3, 6})
assert := internal.NewAssert(t, "CopyOnWriteList_Clear")
list.Clear()
assert.Equal([]int{}, list.getList())
}
func TestCopyOnWriteList_Merge(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9})
assert := internal.NewAssert(t, "CopyOnWriteList_Merge")
list.Merge([]int{2, 4, 6, 8, 10})
assert.Equal([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10}, list.getList())
}
func TestCopyOnWriteList_Sort(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_Sort")
list.Sort(func(i, j int) bool {
return i < j
})
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, list.getList())
}
func TestCopyOnWriteList_IndexOf(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_IndexOf")
assert.Equal(0, list.IndexOf(1))
assert.Equal(9, list.IndexOf(10))
assert.Equal(-1, list.IndexOf(11))
}
func TestCopyOnWriteList_SubList(t *testing.T) {
list := NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert := internal.NewAssert(t, "CopyOnWriteList_SubList")
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList := list.SubList(1, 3)
assert.Equal([]int{3, 5}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList = list.SubList(1, 1)
assert.Equal([]int{}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
assert.Equal(10, list.Size())
subList = list.SubList(1, 10)
assert.Equal([]int{3, 5, 7, 9, 2, 4, 6, 8, 10}, subList)
list = NewCopyOnWriteList([]int{1, 3, 5, 7, 9, 2, 4, 6, 8, 10})
subList = list.SubList(11, 1)
assert.Equal([]int{}, subList)
}
func TestCopyOnWriteListIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOfFunc")
list := NewCopyOnWriteList([]int{1, 2, 3})
i := list.IndexOfFunc(func(a int) bool { return a == 1 })
assert.Equal(0, i)
i = list.IndexOfFunc(func(a int) bool { return a == 4 })
assert.Equal(-1, i)
}
func TestNewCopyOnWriteListLastIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLastIndexOfFunc")
list := NewCopyOnWriteList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
i := list.LastIndexOfFunc(func(a int) bool { return a == 3 })
assert.Equal(5, i)
i = list.LastIndexOfFunc(func(a int) bool { return a == 10 })
assert.Equal(-1, i)
i = list.LastIndexOfFunc(func(a int) bool { return a == 4 })
assert.Equal(6, i)
i = list.LastIndexOfFunc(func(a int) bool { return a == 1 })
assert.Equal(0, i)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved. // Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph. // Package datastructure contains some data structure. list is a linear table, implemented with slice.
package datastructure package datastructure
import ( import (
@@ -271,7 +271,7 @@ func (l *List[T]) Reverse() {
} }
} }
// Unique remove duplicate items in list. // Unique delete duplicate items in list.
func (l *List[T]) Unique() { func (l *List[T]) Unique() {
data := l.data data := l.data
size := len(data) size := len(data)
@@ -294,7 +294,7 @@ func (l *List[T]) Unique() {
l.data = uniqueData l.data = uniqueData
} }
// Union creates a new list contain all element in list l and other, remove duplicate element. // Union creates a new list contain all element in list l and other, delete duplicate element.
func (l *List[T]) Union(other *List[T]) *List[T] { func (l *List[T]) Union(other *List[T]) *List[T] {
result := NewList([]T{}) result := NewList([]T{})

View File

@@ -7,6 +7,8 @@ import (
) )
func TestListData(t *testing.T) { func TestListData(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestListData") assert := internal.NewAssert(t, "TestListData")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -14,6 +16,8 @@ func TestListData(t *testing.T) {
} }
func TestValueOf(t *testing.T) { func TestValueOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestValueOf") assert := internal.NewAssert(t, "TestValueOf")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -26,6 +30,8 @@ func TestValueOf(t *testing.T) {
} }
func TestIndexOf(t *testing.T) { func TestIndexOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf") assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -37,6 +43,8 @@ func TestIndexOf(t *testing.T) {
} }
func TestIndexOfFunc(t *testing.T) { func TestIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf") assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -48,6 +56,8 @@ func TestIndexOfFunc(t *testing.T) {
} }
func TestLastIndexOf(t *testing.T) { func TestLastIndexOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf") assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9}) list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
@@ -65,6 +75,8 @@ func TestLastIndexOf(t *testing.T) {
} }
func TestLastIndexOfFunc(t *testing.T) { func TestLastIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf") assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9}) list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
@@ -82,6 +94,8 @@ func TestLastIndexOfFunc(t *testing.T) {
} }
func TestContain(t *testing.T) { func TestContain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestContain") assert := internal.NewAssert(t, "TestContain")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -90,6 +104,8 @@ func TestContain(t *testing.T) {
} }
func TestPush(t *testing.T) { func TestPush(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPush") assert := internal.NewAssert(t, "TestPush")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -99,6 +115,8 @@ func TestPush(t *testing.T) {
} }
func TestInsertAtFirst(t *testing.T) { func TestInsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAtFirst") assert := internal.NewAssert(t, "TestInsertAtFirst")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -108,6 +126,8 @@ func TestInsertAtFirst(t *testing.T) {
} }
func TestInsertAtLast(t *testing.T) { func TestInsertAtLast(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAtLast") assert := internal.NewAssert(t, "TestInsertAtLast")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -117,6 +137,8 @@ func TestInsertAtLast(t *testing.T) {
} }
func TestInsertAt(t *testing.T) { func TestInsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAt") assert := internal.NewAssert(t, "TestInsertAt")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -135,6 +157,8 @@ func TestInsertAt(t *testing.T) {
} }
func TestPopFirst(t *testing.T) { func TestPopFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPopFirst") assert := internal.NewAssert(t, "TestPopFirst")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -150,6 +174,8 @@ func TestPopFirst(t *testing.T) {
} }
func TestPopLast(t *testing.T) { func TestPopLast(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPopLast") assert := internal.NewAssert(t, "TestPopLast")
list := NewList([]int{1, 2, 3}) list := NewList([]int{1, 2, 3})
@@ -165,6 +191,8 @@ func TestPopLast(t *testing.T) {
} }
func TestDeleteAt(t *testing.T) { func TestDeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteAt") assert := internal.NewAssert(t, "TestDeleteAt")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -183,6 +211,8 @@ func TestDeleteAt(t *testing.T) {
} }
func TestUpdateAt(t *testing.T) { func TestUpdateAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUpdateAt") assert := internal.NewAssert(t, "TestUpdateAt")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -201,6 +231,8 @@ func TestUpdateAt(t *testing.T) {
} }
func TestEqual(t *testing.T) { func TestEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqual") assert := internal.NewAssert(t, "TestEqual")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -212,6 +244,8 @@ func TestEqual(t *testing.T) {
} }
func TestIsEmpty(t *testing.T) { func TestIsEmpty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsEmpty") assert := internal.NewAssert(t, "TestIsEmpty")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -222,6 +256,8 @@ func TestIsEmpty(t *testing.T) {
} }
func TestIsClear(t *testing.T) { func TestIsClear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsClear") assert := internal.NewAssert(t, "TestIsClear")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -232,6 +268,8 @@ func TestIsClear(t *testing.T) {
} }
func TestClone(t *testing.T) { func TestClone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestClone") assert := internal.NewAssert(t, "TestClone")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -241,6 +279,8 @@ func TestClone(t *testing.T) {
} }
func TestMerge(t *testing.T) { func TestMerge(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMerge") assert := internal.NewAssert(t, "TestMerge")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -252,6 +292,8 @@ func TestMerge(t *testing.T) {
} }
func TestSize(t *testing.T) { func TestSize(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSize") assert := internal.NewAssert(t, "TestSize")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -262,6 +304,8 @@ func TestSize(t *testing.T) {
} }
func TestCap(t *testing.T) { func TestCap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCap") assert := internal.NewAssert(t, "TestCap")
data := make([]int, 0, 100) data := make([]int, 0, 100)
@@ -274,6 +318,8 @@ func TestCap(t *testing.T) {
} }
func TestSwap(t *testing.T) { func TestSwap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSwap") assert := internal.NewAssert(t, "TestSwap")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -285,6 +331,8 @@ func TestSwap(t *testing.T) {
} }
func TestReverse(t *testing.T) { func TestReverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestReverse") assert := internal.NewAssert(t, "TestReverse")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -296,6 +344,8 @@ func TestReverse(t *testing.T) {
} }
func TestUnique(t *testing.T) { func TestUnique(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUnique") assert := internal.NewAssert(t, "TestUnique")
list := NewList([]int{1, 2, 2, 3, 4}) list := NewList([]int{1, 2, 2, 3, 4})
@@ -307,6 +357,8 @@ func TestUnique(t *testing.T) {
} }
func TestUnion(t *testing.T) { func TestUnion(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUnion") assert := internal.NewAssert(t, "TestUnion")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -318,6 +370,8 @@ func TestUnion(t *testing.T) {
} }
func TestIntersection(t *testing.T) { func TestIntersection(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIntersection") assert := internal.NewAssert(t, "TestIntersection")
list1 := NewList([]int{1, 2, 3, 4}) list1 := NewList([]int{1, 2, 3, 4})
@@ -329,6 +383,8 @@ func TestIntersection(t *testing.T) {
} }
func TestDifference(t *testing.T) { func TestDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDifference") assert := internal.NewAssert(t, "TestDifference")
list1 := NewList([]int{1, 2, 3}) list1 := NewList([]int{1, 2, 3})
@@ -340,6 +396,8 @@ func TestDifference(t *testing.T) {
} }
func TestSymmetricDifference(t *testing.T) { func TestSymmetricDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSymmetricDifference") assert := internal.NewAssert(t, "TestSymmetricDifference")
list1 := NewList([]int{1, 2, 3}) list1 := NewList([]int{1, 2, 3})
@@ -351,6 +409,8 @@ func TestSymmetricDifference(t *testing.T) {
} }
func TestSubSlice(t *testing.T) { func TestSubSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSubSlice") assert := internal.NewAssert(t, "TestSubSlice")
list := NewList([]int{1, 2, 3, 4, 5, 8}) list := NewList([]int{1, 2, 3, 4, 5, 8})
@@ -367,6 +427,8 @@ func BenchmarkSubSlice(b *testing.B) {
} }
func TestDeleteIf(t *testing.T) { func TestDeleteIf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteIf") assert := internal.NewAssert(t, "TestDeleteIf")
list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1}) list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
@@ -381,10 +443,11 @@ func TestDeleteIf(t *testing.T) {
} }
func TestForEach(t *testing.T) { func TestForEach(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestForEach") assert := internal.NewAssert(t, "TestForEach")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
rs := make([]int, 0) rs := make([]int, 0)
list.ForEach(func(i int) { list.ForEach(func(i int) {
rs = append(rs, i) rs = append(rs, i)
@@ -394,6 +457,8 @@ func TestForEach(t *testing.T) {
} }
func TestRetainAll(t *testing.T) { func TestRetainAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRetainAll") assert := internal.NewAssert(t, "TestRetainAll")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -414,6 +479,8 @@ func TestRetainAll(t *testing.T) {
} }
func TestDeleteAll(t *testing.T) { func TestDeleteAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteAll") assert := internal.NewAssert(t, "TestDeleteAll")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
@@ -433,10 +500,11 @@ func TestDeleteAll(t *testing.T) {
} }
func TestIterator(t *testing.T) { func TestIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIterator") assert := internal.NewAssert(t, "TestIterator")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator() iterator := list.Iterator()
rs := make([]int, 0) rs := make([]int, 0)
@@ -449,14 +517,15 @@ func TestIterator(t *testing.T) {
} }
func TestListToMap(t *testing.T) { func TestListToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "ListToMap") assert := internal.NewAssert(t, "ListToMap")
list := NewList([]int{1, 2, 3, 4}) list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) { result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1 return n, n > 1
}) })
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
assert.Equal(expected, result) assert.Equal(expected, result)
} }

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved. // Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph. // Package datastructure implements some data structure.
package datastructure package datastructure
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link. // LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.

View File

@@ -0,0 +1,108 @@
package optional
import (
"sync"
)
// Optional is a type that may or may not contain a non-nil value.
type Optional[T any] struct {
value *T
mu *sync.RWMutex
}
// Default returns an default Optional instance.
func Default[T any]() Optional[T] {
return Optional[T]{mu: &sync.RWMutex{}}
}
// Of returns an Optional with a non-nil value.
func Of[T any](value T) Optional[T] {
return Optional[T]{value: &value, mu: &sync.RWMutex{}}
}
// FromNillable returns an Optional for a given value, which may be nil.
func FromNillable[T any](value *T) Optional[T] {
if value == nil {
return Default[T]()
}
return Optional[T]{value: value, mu: &sync.RWMutex{}}
}
// IsNotNil checks if there is a value present.
func (o Optional[T]) IsNotNil() bool {
o.mu.RLock()
defer o.mu.RUnlock()
return o.value != nil
}
// IsNil checks if the Optional is nil.
func (o Optional[T]) IsNil() bool {
return !o.IsNotNil()
}
// IfNotNil performs the given action with the value if a value is not nil.
func (o Optional[T]) IfNotNil(action func(value T)) {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value != nil {
action(*o.value)
}
}
// IfNotNilOrElse performs the action with the value if present, otherwise performs the fallback action.
func (o Optional[T]) IfNotNilOrElse(action func(value T), fallbackAction func()) {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value != nil {
action(*o.value)
} else {
fallbackAction()
}
}
// Unwarp returns the value if not nil, otherwise panics.
func (o Optional[T]) Unwarp() T {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value == nil {
panic("Optional.Get: no value present")
}
return *o.value
}
// OrElse returns the value if is not nil, otherwise returns other.
func (o Optional[T]) OrElse(other T) T {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value != nil {
return *o.value
}
return other
}
// OrElseGet returns the value if is not nil, otherwise invokes action and returns the result.
func (o Optional[T]) OrElseGet(action func() T) T {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value != nil {
return *o.value
}
return action()
}
// OrElseTrigger returns the value if present, otherwise returns an error.
func (o Optional[T]) OrElseTrigger(errorHandler func() error) (T, error) {
o.mu.RLock()
defer o.mu.RUnlock()
if o.value == nil {
return *new(T), errorHandler()
}
return *o.value, nil
}

View File

@@ -0,0 +1,151 @@
package optional
import (
"errors"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestDefault(t *testing.T) {
assert := internal.NewAssert(t, "TestEmpty")
opt := Default[int]()
assert.ShouldBeTrue(opt.IsNil())
}
func TestOf(t *testing.T) {
assert := internal.NewAssert(t, "TestOf")
value := 42
opt := Of(value)
assert.ShouldBeTrue(opt.IsNotNil())
assert.Equal(opt.Unwarp(), value)
}
func TestFromNillable(t *testing.T) {
assert := internal.NewAssert(t, "TestOfNullable")
var value *int = nil
opt := FromNillable(value)
assert.ShouldBeFalse(opt.IsNotNil())
value = new(int)
*value = 42
opt = FromNillable(value)
assert.ShouldBeTrue(opt.IsNotNil())
}
func TestOrElse(t *testing.T) {
assert := internal.NewAssert(t, "TestOrElse")
optDefault := Default[int]()
defaultValue := 100
val := optDefault.OrElse(defaultValue)
assert.Equal(val, defaultValue)
optWithValue := Of(42)
val = optWithValue.OrElse(defaultValue)
assert.Equal(val, 42)
}
func TestOrElseGetHappyPath(t *testing.T) {
assert := internal.NewAssert(t, "TestOrElseGetHappyPath")
optWithValue := Of(42)
action := func() int { return 100 }
val := optWithValue.OrElseGet(action)
assert.Equal(val, 42)
}
func TestOrElseGet(t *testing.T) {
assert := internal.NewAssert(t, "TestOrElseGet")
optDefault := Default[int]()
action := func() int { return 100 }
val := optDefault.OrElseGet(action)
assert.Equal(val, action())
}
func TestOrElseTrigger(t *testing.T) {
assert := internal.NewAssert(t, "OrElseTrigger")
optDefault := Default[int]()
_, err := optDefault.OrElseTrigger(func() error { return errors.New("no value") })
assert.Equal(err.Error(), "no value")
optWithValue := Of(42)
val, err := optWithValue.OrElseTrigger(func() error { return errors.New("no value") })
assert.IsNil(err)
assert.Equal(val, 42)
}
func TestIfNotNil(t *testing.T) {
assert := internal.NewAssert(t, "IfNotNil")
called := false
action := func(value int) { called = true }
optDefault := Default[int]()
optDefault.IfNotNil(action)
assert.ShouldBeFalse(called)
called = false // Reset for next test
optWithValue := Of(42)
optWithValue.IfNotNil(action)
assert.ShouldBeTrue(called)
}
func TestIfNotNilOrElse(t *testing.T) {
assert := internal.NewAssert(t, "TestIfNotNilOrElse")
// Test when value is present
calledWithValue := false
valueAction := func(value int) { calledWithValue = true }
fallbackAction := func() { t.Errorf("Empty action should not be called when value is present") }
optWithValue := Of(42)
optWithValue.IfNotNilOrElse(valueAction, fallbackAction)
assert.ShouldBeTrue(calledWithValue)
// Test when value is not present
calledWithEmpty := false
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
fallbackAction = func() { calledWithEmpty = true }
optDefault := Default[int]()
optDefault.IfNotNilOrElse(valueAction, fallbackAction)
assert.ShouldBeTrue(calledWithEmpty)
}
func TestGetWithPanicStandard(t *testing.T) {
assert := internal.NewAssert(t, "TestGetWithPanicStandard")
// Test when value is present
optWithValue := Of(42)
func() {
defer func() {
r := recover()
assert.IsNil(r)
}()
val := optWithValue.Unwarp()
if val != 42 {
t.Errorf("Expected Unwarp to return 42, got %v", val)
}
}()
// Test when value is not present
optDefault := Default[int]()
func() {
defer func() {
r := recover()
assert.IsNotNil(r)
}()
_ = optDefault.Unwarp()
}()
}

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure package datastructure
import ( import (
@@ -7,7 +12,7 @@ import (
// ArrayQueue implements queue with slice // ArrayQueue implements queue with slice
type ArrayQueue[T any] struct { type ArrayQueue[T any] struct {
items []T data []T
head int head int
tail int tail int
capacity int capacity int
@@ -16,7 +21,7 @@ type ArrayQueue[T any] struct {
func NewArrayQueue[T any](capacity int) *ArrayQueue[T] { func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
return &ArrayQueue[T]{ return &ArrayQueue[T]{
items: make([]T, 0, capacity), data: make([]T, 0, capacity),
head: 0, head: 0,
tail: 0, tail: 0,
capacity: capacity, capacity: capacity,
@@ -28,7 +33,7 @@ func NewArrayQueue[T any](capacity int) *ArrayQueue[T] {
func (q *ArrayQueue[T]) Data() []T { func (q *ArrayQueue[T]) Data() []T {
items := []T{} items := []T{}
for i := q.head; i < q.tail; i++ { for i := q.head; i < q.tail; i++ {
items = append(items, q.items[i]) items = append(items, q.data[i])
} }
return items return items
} }
@@ -50,40 +55,71 @@ func (q *ArrayQueue[T]) IsFull() bool {
// Front return front value of queue // Front return front value of queue
func (q *ArrayQueue[T]) Front() T { func (q *ArrayQueue[T]) Front() T {
return q.items[0] return q.data[0]
} }
// Back return back value of queue // Back return back value of queue
func (q *ArrayQueue[T]) Back() T { func (q *ArrayQueue[T]) Back() T {
return q.items[q.size-1] return q.data[q.size-1]
} }
// EnQueue put element into queue // EnQueue put element into queue
func (q *ArrayQueue[T]) Enqueue(item T) bool { func (q *ArrayQueue[T]) Enqueue(item T) bool {
if q.head == 0 && q.tail == q.capacity { if q.tail < q.capacity {
return false q.data = append(q.data, item)
} else if q.head != 0 && q.tail == q.capacity { // q.tail++
for i := q.head; i < q.tail; i++ { q.data[q.tail] = item
q.items[i-q.head] = q.items[i] } else {
//upgrade
if q.head > 0 {
for i := 0; i < q.tail-q.head; i++ {
q.data[i] = q.data[i+q.head]
}
q.tail -= q.head
q.head = 0
} else {
if q.capacity < 65536 {
if q.capacity == 0 {
q.capacity = 1
}
q.capacity *= 2
} else {
q.capacity += 2 ^ 16
}
tmp := make([]T, q.capacity, q.capacity)
copy(tmp, q.data)
q.data = tmp
} }
q.tail = q.tail - q.head
q.head = 0 q.data[q.tail] = item
} }
q.items = append(q.items, item)
q.tail++ q.tail++
q.size++ q.size++
return true return true
} }
// DeQueue remove head element of queue and return it, if queue is empty, return nil and error // DeQueue remove head element of queue and return it, if queue is empty, return nil and error
func (q *ArrayQueue[T]) Dequeue() (T, bool) { func (q *ArrayQueue[T]) Dequeue() (T, bool) {
var item T var item T
if q.head == q.tail { if q.size == 0 {
return item, false return item, false
} }
item = q.items[q.head]
item = q.data[q.head]
q.head++ q.head++
if q.head >= 1024 || q.head*2 > q.tail {
q.capacity -= q.head
q.tail -= q.head
tmp := make([]T, q.capacity, q.capacity)
copy(tmp, q.data[q.head:])
q.data = tmp
q.head = 0
}
q.size-- q.size--
return item, true return item, true
} }
@@ -91,7 +127,7 @@ func (q *ArrayQueue[T]) Dequeue() (T, bool) {
// Clear the queue data // Clear the queue data
func (q *ArrayQueue[T]) Clear() { func (q *ArrayQueue[T]) Clear() {
capacity := q.capacity capacity := q.capacity
q.items = make([]T, 0, capacity) q.data = make([]T, 0, capacity)
q.head = 0 q.head = 0
q.tail = 0 q.tail = 0
q.size = 0 q.size = 0
@@ -100,7 +136,7 @@ func (q *ArrayQueue[T]) Clear() {
// Contain checks if the value is in queue or not // Contain checks if the value is in queue or not
func (q *ArrayQueue[T]) Contain(value T) bool { func (q *ArrayQueue[T]) Contain(value T) bool {
for _, v := range q.items { for _, v := range q.data {
if reflect.DeepEqual(v, value) { if reflect.DeepEqual(v, value) {
return true return true
} }
@@ -112,7 +148,7 @@ func (q *ArrayQueue[T]) Contain(value T) bool {
func (q *ArrayQueue[T]) Print() { func (q *ArrayQueue[T]) Print() {
info := "[" info := "["
for i := q.head; i < q.tail; i++ { for i := q.head; i < q.tail; i++ {
info += fmt.Sprintf("%+v, ", q.items[i]) info += fmt.Sprintf("%+v, ", q.data[i])
} }
info += "]" info += "]"
fmt.Println(info) fmt.Println(info)

View File

@@ -7,22 +7,25 @@ import (
) )
func TestArrayQueue_Enqueue(t *testing.T) { func TestArrayQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue") assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
queue := NewArrayQueue[int](5) queue := NewArrayQueue[int](2)
queue.Enqueue(1) queue.Enqueue(1)
queue.Enqueue(2) queue.Enqueue(2)
queue.Enqueue(3) queue.Enqueue(3)
expected := []int{1, 2, 3}
data := queue.Data() data := queue.Data()
size := queue.Size() size := queue.Size()
assert.Equal(expected, data) assert.Equal([]int{1, 2, 3}, data)
assert.Equal(3, size) assert.Equal(3, size)
} }
func TestArrayQueue_Dequeue(t *testing.T) { func TestArrayQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue") assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
queue := NewArrayQueue[int](4) queue := NewArrayQueue[int](4)
@@ -38,6 +41,8 @@ func TestArrayQueue_Dequeue(t *testing.T) {
} }
func TestArrayQueue_Front(t *testing.T) { func TestArrayQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Front") assert := internal.NewAssert(t, "TestArrayQueue_Front")
queue := NewArrayQueue[int](4) queue := NewArrayQueue[int](4)
@@ -52,6 +57,8 @@ func TestArrayQueue_Front(t *testing.T) {
} }
func TestArrayQueue_Back(t *testing.T) { func TestArrayQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Back") assert := internal.NewAssert(t, "TestArrayQueue_Back")
queue := NewArrayQueue[int](4) queue := NewArrayQueue[int](4)
@@ -66,6 +73,8 @@ func TestArrayQueue_Back(t *testing.T) {
} }
func TestArrayQueue_Contain(t *testing.T) { func TestArrayQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Contain") assert := internal.NewAssert(t, "TestArrayQueue_Contain")
queue := NewArrayQueue[int](4) queue := NewArrayQueue[int](4)
@@ -78,6 +87,8 @@ func TestArrayQueue_Contain(t *testing.T) {
} }
func TestArrayQueue_Clear(t *testing.T) { func TestArrayQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Clear") assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int](4) queue := NewArrayQueue[int](4)
@@ -95,6 +106,8 @@ func TestArrayQueue_Clear(t *testing.T) {
} }
func TestArrayQueue_IsFull(t *testing.T) { func TestArrayQueue_IsFull(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_IsFull") assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
queue := NewArrayQueue[int](3) queue := NewArrayQueue[int](3)

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure package datastructure
import ( import (

View File

@@ -7,6 +7,8 @@ import (
) )
func TestCircularQueue_Enqueue(t *testing.T) { func TestCircularQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue") assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
queue := NewCircularQueue[int](6) queue := NewCircularQueue[int](6)
@@ -34,6 +36,8 @@ func TestCircularQueue_Enqueue(t *testing.T) {
} }
func TestCircularQueue_Dequeue(t *testing.T) { func TestCircularQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue") assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
queue := NewCircularQueue[int](4) queue := NewCircularQueue[int](4)
@@ -60,6 +64,8 @@ func TestCircularQueue_Dequeue(t *testing.T) {
} }
func TestCircularQueue_Front(t *testing.T) { func TestCircularQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Front") assert := internal.NewAssert(t, "TestCircularQueue_Front")
queue := NewCircularQueue[int](6) queue := NewCircularQueue[int](6)
@@ -80,6 +86,8 @@ func TestCircularQueue_Front(t *testing.T) {
} }
func TestCircularQueue_Back(t *testing.T) { func TestCircularQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Back") assert := internal.NewAssert(t, "TestCircularQueue_Back")
queue := NewCircularQueue[int](3) queue := NewCircularQueue[int](3)
@@ -103,6 +111,8 @@ func TestCircularQueue_Back(t *testing.T) {
} }
func TestCircularQueue_Contain(t *testing.T) { func TestCircularQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Contain") assert := internal.NewAssert(t, "TestCircularQueue_Contain")
queue := NewCircularQueue[int](2) queue := NewCircularQueue[int](2)
@@ -114,6 +124,8 @@ func TestCircularQueue_Contain(t *testing.T) {
} }
func TestCircularQueue_Clear(t *testing.T) { func TestCircularQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Clear") assert := internal.NewAssert(t, "TestCircularQueue_Clear")
queue := NewCircularQueue[int](3) queue := NewCircularQueue[int](3)
@@ -132,6 +144,8 @@ func TestCircularQueue_Clear(t *testing.T) {
} }
func TestCircularQueue_Data(t *testing.T) { func TestCircularQueue_Data(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Data") assert := internal.NewAssert(t, "TestCircularQueue_Data")
queue := NewCircularQueue[int](3) queue := NewCircularQueue[int](3)

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure package datastructure
import ( import (

View File

@@ -7,6 +7,8 @@ import (
) )
func TestLinkedQueue_Enqueue(t *testing.T) { func TestLinkedQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue") assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
@@ -19,6 +21,8 @@ func TestLinkedQueue_Enqueue(t *testing.T) {
} }
func TestLinkedQueue_Dequeue(t *testing.T) { func TestLinkedQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue") assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
@@ -35,6 +39,8 @@ func TestLinkedQueue_Dequeue(t *testing.T) {
} }
func TestLinkedQueue_Front(t *testing.T) { func TestLinkedQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Front") assert := internal.NewAssert(t, "TestLinkedQueue_Front")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
@@ -51,6 +57,8 @@ func TestLinkedQueue_Front(t *testing.T) {
} }
func TestLinkedQueue_Back(t *testing.T) { func TestLinkedQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Back") assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
@@ -67,6 +75,8 @@ func TestLinkedQueue_Back(t *testing.T) {
} }
func TestLinkedQueue_Clear(t *testing.T) { func TestLinkedQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Back") assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
@@ -82,10 +92,11 @@ func TestLinkedQueue_Clear(t *testing.T) {
} }
func TestLinkedQueue_Contain(t *testing.T) { func TestLinkedQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Contain") assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
queue := NewLinkedQueue[int]() queue := NewLinkedQueue[int]()
queue.Enqueue(1) queue.Enqueue(1)
queue.Enqueue(2) queue.Enqueue(2)
queue.Enqueue(3) queue.Enqueue(3)

View File

@@ -1,22 +1,27 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure package datastructure
import ( import (
"errors" "errors"
"github.com/duke-git/lancet/v2/lancetconstraints" "github.com/duke-git/lancet/v2/constraints"
) )
// PriorityQueue is a priority queue implemented by binary heap tree // PriorityQueue is a priority queue implemented by binary heap tree
// type T should implements Compare function in lancetconstraints.Comparator interface. // type T should implements Compare function in constraints.Comparator interface.
type PriorityQueue[T any] struct { type PriorityQueue[T any] struct {
items []T items []T
size int size int
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
// NewPriorityQueue return a pointer of PriorityQueue // NewPriorityQueue return a pointer of PriorityQueue
// param `comparator` is used to compare values in the queue // param `comparator` is used to compare values in the queue
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T] { func NewPriorityQueue[T any](capacity int, comparator constraints.Comparator) *PriorityQueue[T] {
return &PriorityQueue[T]{ return &PriorityQueue[T]{
items: make([]T, capacity+1), items: make([]T, capacity+1),
size: 0, size: 0,

View File

@@ -20,6 +20,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
return 0 return 0
} }
func TestPriorityQueue_Enqueue(t *testing.T) { func TestPriorityQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue") assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
comparator := &intComparator{} comparator := &intComparator{}
@@ -45,6 +47,8 @@ func TestPriorityQueue_Enqueue(t *testing.T) {
} }
func TestPriorityQueue_Dequeue(t *testing.T) { func TestPriorityQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue") assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
comparator := &intComparator{} comparator := &intComparator{}

View File

@@ -1,18 +1,24 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
package datastructure package datastructure
// Set is a data container, like slice, but element of set is not duplicate import "sort"
// Set is a data container, like slice, but element of set is not duplicate.
type Set[T comparable] map[T]struct{} type Set[T comparable] map[T]struct{}
// NewSet return a instance of set // New create a instance of set from given values.
func NewSet[T comparable](items ...T) Set[T] { func New[T comparable](items ...T) Set[T] {
set := make(Set[T]) set := make(Set[T], len(items))
set.Add(items...) set.Add(items...)
return set return set
} }
// NewSetFromSlice create a set from slice // FromSlice create a set from given slice.
func NewSetFromSlice[T comparable](items []T) Set[T] { func FromSlice[T comparable](items []T) Set[T] {
set := make(Set[T]) set := make(Set[T], len(items))
for _, item := range items { for _, item := range items {
set.Add(item) set.Add(item)
} }
@@ -73,8 +79,7 @@ func (s Set[T]) ContainAll(other Set[T]) bool {
// Clone return a copy of set // Clone return a copy of set
func (s Set[T]) Clone() Set[T] { func (s Set[T]) Clone() Set[T] {
set := NewSet[T]() set := FromSlice(s.ToSlice())
set.Add(s.Values()...)
return set return set
} }
@@ -112,14 +117,11 @@ func (s Set[T]) Size() int {
} }
// Values return all values of set // Values return all values of set
// Deprecated: Values function is deprecated and will be removed in future versions. Please use ToSlice() function instead.
//
// The ToSlice() function provides the same functionality as Values and returns a slice containing all values of the set.
func (s Set[T]) Values() []T { func (s Set[T]) Values() []T {
result := make([]T, 0, len(s)) return s.ToSlice()
s.Iterate(func(value T) {
result = append(result, value)
})
return result
} }
// Union creates a new set contain all element of set s and other // Union creates a new set contain all element of set s and other
@@ -131,7 +133,7 @@ func (s Set[T]) Union(other Set[T]) Set[T] {
// Intersection creates a new set whose element both be contained in set s and other // 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] { func (s Set[T]) Intersection(other Set[T]) Set[T] {
set := NewSet[T]() set := New[T]()
s.Iterate(func(value T) { s.Iterate(func(value T) {
if other.Contain(value) { if other.Contain(value) {
set.Add(value) set.Add(value)
@@ -143,7 +145,7 @@ func (s Set[T]) Intersection(other Set[T]) Set[T] {
// SymmetricDifference creates a new set whose element is in set1 or set2, but not in both sets // 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] { func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
set := NewSet[T]() set := New[T]()
s.Iterate(func(value T) { s.Iterate(func(value T) {
if !other.Contain(value) { if !other.Contain(value) {
set.Add(value) set.Add(value)
@@ -159,9 +161,9 @@ func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
return set return set
} }
// Minus creates an set of whose element in origin set but not in compared set // Minus creates a set of whose element in origin set but not in compared set
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] { func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
set := NewSet[T]() set := New[T]()
s.Iterate(func(value T) { s.Iterate(func(value T) {
if !comparedSet.Contain(value) { if !comparedSet.Contain(value) {
@@ -185,11 +187,34 @@ func (s Set[T]) EachWithBreak(iteratee func(item T) bool) {
// Pop delete the top element of set then return it, if set is empty, return nil-value of T and false. // Pop delete the top element of set then return it, if set is empty, return nil-value of T and false.
func (s Set[T]) Pop() (v T, ok bool) { func (s Set[T]) Pop() (v T, ok bool) {
if len(s) > 0 { if len(s) > 0 {
items := s.Values() for item := range s {
item := items[len(s)-1] v = item
delete(s, item) delete(s, item)
return item, true return v, true
}
} }
return v, false return v, false
} }
// ToSlice returns a slice containing all values of the set.
func (s Set[T]) ToSlice() []T {
if s.IsEmpty() {
return []T{}
}
result := make([]T, 0, s.Size())
s.Iterate(func(value T) {
result = append(result, value)
})
return result
}
// ToSortedSlice returns a sorted slice containing all values of the set.
func (s Set[T]) ToSortedSlice(less func(v1, v2 T) bool) []T {
result := s.ToSlice()
sort.Slice(result, func(i, j int) bool {
return less(result[i], result[j])
})
return result
}

View File

@@ -1,50 +1,60 @@
package datastructure package datastructure
import ( import (
"reflect"
"sort"
"testing" "testing"
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestSet_NewSetFromSlice(t *testing.T) { func TestSet_FromSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice") t.Parallel()
s1 := NewSetFromSlice([]int{1, 2, 2, 3}) assert := internal.NewAssert(t, "TestSet_FromSlice")
s1 := FromSlice([]int{1, 2, 2, 3})
assert.Equal(3, s1.Size()) assert.Equal(3, s1.Size())
assert.Equal(true, s1.Contain(1)) assert.Equal(true, s1.Contain(1))
assert.Equal(true, s1.Contain(2)) assert.Equal(true, s1.Contain(2))
assert.Equal(true, s1.Contain(3)) assert.Equal(true, s1.Contain(3))
s2 := NewSetFromSlice([]int{}) s2 := FromSlice([]int{})
assert.Equal(0, s2.Size()) assert.Equal(0, s2.Size())
} }
func TestSet_Add(t *testing.T) { func TestSet_Add(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Add") assert := internal.NewAssert(t, "TestSet_Add")
set := NewSet[int]() set := New[int]()
set.Add(1, 2, 3) set.Add(1, 2, 3)
expected := NewSet(1, 2, 3) cmpSet := New(1, 2, 3)
assert.Equal(true, set.Equal(expected)) assert.Equal(true, set.Equal(cmpSet))
} }
func TestSet_AddIfNotExist(t *testing.T) { func TestSet_AddIfNotExist(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_AddIfNotExist") assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
set := NewSet[int]() set := New[int]()
set.Add(1, 2, 3) set.Add(1, 2, 3)
assert.Equal(false, set.AddIfNotExist(1)) assert.Equal(false, set.AddIfNotExist(1))
assert.Equal(true, set.AddIfNotExist(4)) assert.Equal(true, set.AddIfNotExist(4))
assert.Equal(NewSet(1, 2, 3, 4), set) assert.Equal(New(1, 2, 3, 4), set)
} }
func TestSet_AddIfNotExistBy(t *testing.T) { func TestSet_AddIfNotExistBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy") assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
set := NewSet[int]() set := New[int]()
set.Add(1, 2) set.Add(1, 2)
ok := set.AddIfNotExistBy(3, func(val int) bool { ok := set.AddIfNotExistBy(3, func(val int) bool {
@@ -63,9 +73,11 @@ func TestSet_AddIfNotExistBy(t *testing.T) {
} }
func TestSet_Contain(t *testing.T) { func TestSet_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Contain") assert := internal.NewAssert(t, "TestSet_Contain")
set := NewSet[int]() set := New[int]()
set.Add(1, 2, 3) set.Add(1, 2, 3)
assert.Equal(true, set.Contain(1)) assert.Equal(true, set.Contain(1))
@@ -73,20 +85,24 @@ func TestSet_Contain(t *testing.T) {
} }
func TestSet_ContainAll(t *testing.T) { func TestSet_ContainAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_ContainAll") assert := internal.NewAssert(t, "TestSet_ContainAll")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(1, 2) set2 := New(1, 2)
set3 := NewSet(1, 2, 3, 4) set3 := New(1, 2, 3, 4)
assert.Equal(true, set1.ContainAll(set2)) assert.Equal(true, set1.ContainAll(set2))
assert.Equal(false, set1.ContainAll(set3)) assert.Equal(false, set1.ContainAll(set3))
} }
func TestSet_Clone(t *testing.T) { func TestSet_Clone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Clone") assert := internal.NewAssert(t, "TestSet_Clone")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := set1.Clone() set2 := set1.Clone()
assert.Equal(true, set1.Size() == set2.Size()) assert.Equal(true, set1.Size() == set2.Size())
@@ -94,32 +110,36 @@ func TestSet_Clone(t *testing.T) {
} }
func TestSet_Delete(t *testing.T) { func TestSet_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Delete") assert := internal.NewAssert(t, "TestSet_Delete")
set := NewSet[int]() set := New[int]()
set.Add(1, 2, 3) set.Add(1, 2, 3)
set.Delete(3) set.Delete(3)
expected := NewSet(1, 2) assert.Equal(true, set.Equal(New(1, 2)))
assert.Equal(true, set.Equal(expected))
} }
func TestSet_Equal(t *testing.T) { func TestSet_Equal(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Equal") assert := internal.NewAssert(t, "TestSet_Equal")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(1, 2, 3) set2 := New(1, 2, 3)
set3 := NewSet(1, 2, 3, 4) set3 := New(1, 2, 3, 4)
assert.Equal(true, set1.Equal(set2)) assert.Equal(true, set1.Equal(set2))
assert.Equal(false, set1.Equal(set3)) assert.Equal(false, set1.Equal(set3))
} }
func TestSet_Iterate(t *testing.T) { func TestSet_Iterate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Iterate") assert := internal.NewAssert(t, "TestSet_Iterate")
set := NewSet(1, 2, 3) set := New(1, 2, 3)
arr := []int{} arr := []int{}
set.Iterate(func(value int) { set.Iterate(func(value int) {
arr = append(arr, value) arr = append(arr, value)
@@ -129,72 +149,85 @@ func TestSet_Iterate(t *testing.T) {
} }
func TestSet_IsEmpty(t *testing.T) { func TestSet_IsEmpty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_IsEmpty") assert := internal.NewAssert(t, "TestSet_IsEmpty")
set := NewSet[int]() set := New[int]()
assert.Equal(true, set.IsEmpty()) assert.Equal(true, set.IsEmpty())
} }
func TestSet_Size(t *testing.T) { func TestSet_Size(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Size") assert := internal.NewAssert(t, "TestSet_Size")
set := NewSet(1, 2, 3) set := New(1, 2, 3)
assert.Equal(3, set.Size()) assert.Equal(3, set.Size())
} }
func TestSet_Values(t *testing.T) { func TestSet_Values(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Values") assert := internal.NewAssert(t, "TestSet_Values")
set := NewSet(1, 2, 3) set := New(1, 2, 3)
values := set.Values() values := set.Values()
assert.Equal(3, len(values)) assert.Equal(3, len(values))
} }
func TestSet_Union(t *testing.T) { func TestSet_Union(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Union") assert := internal.NewAssert(t, "TestSet_Union")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(2, 3, 4, 5) set2 := New(2, 3, 4, 5)
expected := NewSet(1, 2, 3, 4, 5)
unionSet := set1.Union(set2) unionSet := set1.Union(set2)
assert.Equal(expected, unionSet) assert.Equal(New(1, 2, 3, 4, 5), unionSet)
} }
func TestSet_Intersection(t *testing.T) { func TestSet_Intersection(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Intersection") assert := internal.NewAssert(t, "TestSet_Intersection")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(2, 3, 4, 5) set2 := New(2, 3, 4, 5)
expected := NewSet(2, 3)
intersectionSet := set1.Intersection(set2) intersectionSet := set1.Intersection(set2)
assert.Equal(expected, intersectionSet) assert.Equal(New(2, 3), intersectionSet)
} }
func TestSet_SymmetricDifference(t *testing.T) { func TestSet_SymmetricDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_SymmetricDifference") assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(2, 3, 4, 5) set2 := New(2, 3, 4, 5)
assert.Equal(NewSet(1, 4, 5), set1.SymmetricDifference(set2)) assert.Equal(New(1, 4, 5), set1.SymmetricDifference(set2))
} }
func TestSet_Minus(t *testing.T) { func TestSet_Minus(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Minus") assert := internal.NewAssert(t, "TestSet_Minus")
set1 := NewSet(1, 2, 3) set1 := New(1, 2, 3)
set2 := NewSet(2, 3, 4, 5) set2 := New(2, 3, 4, 5)
set3 := NewSet(2, 3) set3 := New(2, 3)
assert.Equal(NewSet(1), set1.Minus(set2)) assert.Equal(New(1), set1.Minus(set2))
assert.Equal(NewSet(4, 5), set2.Minus(set3)) assert.Equal(New(4, 5), set2.Minus(set3))
} }
func TestEachWithBreak(t *testing.T) { func TestEachWithBreak(t *testing.T) {
// s := NewSet(1, 2, 3, 4, 5) // s := New(1, 2, 3, 4, 5)
// var sum int // var sum int
@@ -210,22 +243,93 @@ func TestEachWithBreak(t *testing.T) {
// assert.Equal(6, sum) // assert.Equal(6, sum)
} }
// func TestPop(t *testing.T) { func TestPop(t *testing.T) {
// assert := internal.NewAssert(t, "TestPop") t.Parallel()
assert := internal.NewAssert(t, "TestSet_Pop")
// s := NewSet[int]() s := New[int]()
// val, ok := s.Pop() val, ok := s.Pop()
// assert.Equal(0, val) assert.Equal(0, val)
// assert.Equal(false, ok) assert.Equal(false, ok)
// s.Add(1) s = New(1, 2, 3, 4, 5)
// s.Add(2) sl := s.ToSlice()
// s.Add(3)
// // s = NewSet(1, 2, 3, 4, 5) val, ok = s.Pop()
assert.Equal(false, s.Contain(val))
assert.Equal(true, ok)
assert.Equal(len(sl)-1, s.Size())
// val, ok = s.Pop() var found bool
// assert.Equal(3, val)
// assert.Equal(true, ok) for _, v := range sl {
// } if v == val {
found = true
}
}
assert.Equal(true, found)
}
func TestSet_ToSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_ToSlice")
set1 := FromSlice([]int{6, 3, 1, 5, 6, 7, 1})
set2 := FromSlice([]float64{-2.65, 4.25, 4.25 - 3.14, 0})
set3 := New[string]()
slice1 := set1.ToSlice()
slice2 := set2.ToSlice()
slice3 := set3.ToSlice()
sort.Ints(slice1)
sort.Float64s(slice2)
assert.Equal(5, len(slice1))
assert.Equal(4, len(slice2))
assert.Equal(0, len(slice3))
assert.Equal(true, reflect.DeepEqual(slice1, []int{1, 3, 5, 6, 7}))
assert.Equal(true, reflect.DeepEqual(slice2, []float64{-2.65, 0, 1.11, 4.25}))
assert.Equal("[]string", reflect.TypeOf(slice3).String())
}
func TestSet_ToSortedSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_ToSortedSlice")
set1 := FromSlice([]int{6, 3, 1, 5, 6, 7, 1})
set2 := FromSlice([]float64{-2.65, 4.25, 4.25 - 3.14, 0})
type Person struct {
Name string
Age int
}
set3 := FromSlice([]Person{{"Tom", 20}, {"Jerry", 18}, {"Spike", 25}})
slice1 := set1.ToSortedSlice(func(v1, v2 int) bool {
return v1 < v2
})
slice2 := set2.ToSortedSlice(func(v1, v2 float64) bool {
return v2 < v1
})
slice3 := set3.ToSortedSlice(func(v1, v2 Person) bool {
return v1.Age < v2.Age
})
assert.Equal(5, len(slice1))
assert.Equal(4, len(slice2))
assert.Equal(3, len(slice3))
assert.Equal(true, reflect.DeepEqual(slice1, []int{1, 3, 5, 6, 7}))
assert.Equal(true, reflect.DeepEqual(slice2, []float64{4.25, 1.11, 0, -2.65}))
assert.Equal(true, reflect.DeepEqual(slice3, []Person{
{"Jerry", 18},
{"Tom", 20},
{"Spike", 25},
}))
}

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
package datastructure package datastructure
import "errors" import "errors"

View File

@@ -7,6 +7,8 @@ import (
) )
func TestArrayStack_Push(t *testing.T) { func TestArrayStack_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Push") assert := internal.NewAssert(t, "TestArrayStack_Push")
stack := NewArrayStack[int]() stack := NewArrayStack[int]()
@@ -14,15 +16,16 @@ func TestArrayStack_Push(t *testing.T) {
stack.Push(2) stack.Push(2)
stack.Push(3) stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data() values := stack.Data()
length := stack.Size() length := stack.Size()
assert.Equal(expected, values) assert.Equal([]int{3, 2, 1}, values)
assert.Equal(3, length) assert.Equal(3, length)
} }
func TestArrayStack_Pop(t *testing.T) { func TestArrayStack_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Pop") assert := internal.NewAssert(t, "TestArrayStack_Pop")
stack := NewArrayStack[int]() stack := NewArrayStack[int]()
@@ -37,11 +40,12 @@ func TestArrayStack_Pop(t *testing.T) {
assert.IsNil(err) assert.IsNil(err)
assert.Equal(3, *topItem) assert.Equal(3, *topItem)
expected := []int{2, 1} assert.Equal([]int{2, 1}, stack.Data())
assert.Equal(expected, stack.Data())
} }
func TestArrayStack_Peak(t *testing.T) { func TestArrayStack_Peak(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Peak") assert := internal.NewAssert(t, "TestArrayStack_Peak")
stack := NewArrayStack[int]() stack := NewArrayStack[int]()
@@ -56,11 +60,12 @@ func TestArrayStack_Peak(t *testing.T) {
assert.IsNil(err) assert.IsNil(err)
assert.Equal(3, *topItem) assert.Equal(3, *topItem)
expected := []int{3, 2, 1} assert.Equal([]int{3, 2, 1}, stack.Data())
assert.Equal(expected, stack.Data())
} }
func TestArrayStack_Clear(t *testing.T) { func TestArrayStack_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Clear") assert := internal.NewAssert(t, "TestArrayStack_Clear")
stack := NewArrayStack[int]() stack := NewArrayStack[int]()

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
package datastructure package datastructure
import ( import (

View File

@@ -7,6 +7,8 @@ import (
) )
func TestLinkedStack_Push(t *testing.T) { func TestLinkedStack_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Push") assert := internal.NewAssert(t, "TestLinkedStack_Push")
stack := NewLinkedStack[int]() stack := NewLinkedStack[int]()
@@ -14,15 +16,16 @@ func TestLinkedStack_Push(t *testing.T) {
stack.Push(2) stack.Push(2)
stack.Push(3) stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data() values := stack.Data()
size := stack.Size() size := stack.Size()
assert.Equal(expected, values) assert.Equal([]int{3, 2, 1}, values)
assert.Equal(3, size) assert.Equal(3, size)
} }
func TestLinkedStack_Pop(t *testing.T) { func TestLinkedStack_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Pop") assert := internal.NewAssert(t, "TestLinkedStack_Pop")
stack := NewLinkedStack[int]() stack := NewLinkedStack[int]()
@@ -37,12 +40,13 @@ func TestLinkedStack_Pop(t *testing.T) {
assert.IsNil(err) assert.IsNil(err)
assert.Equal(3, *topItem) assert.Equal(3, *topItem)
expected := []int{2, 1}
stack.Print() stack.Print()
assert.Equal(expected, stack.Data()) assert.Equal([]int{2, 1}, stack.Data())
} }
func TestLinkedStack_Peak(t *testing.T) { func TestLinkedStack_Peak(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Peak") assert := internal.NewAssert(t, "TestLinkedStack_Peak")
stack := NewLinkedStack[int]() stack := NewLinkedStack[int]()
@@ -57,11 +61,12 @@ func TestLinkedStack_Peak(t *testing.T) {
assert.IsNil(err) assert.IsNil(err)
assert.Equal(3, *topItem) assert.Equal(3, *topItem)
expected := []int{3, 2, 1} assert.Equal([]int{3, 2, 1}, stack.Data())
assert.Equal(expected, stack.Data())
} }
func TestLinkedStack_Empty(t *testing.T) { func TestLinkedStack_Empty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Empty") assert := internal.NewAssert(t, "TestLinkedStack_Empty")
stack := NewLinkedStack[int]() stack := NewLinkedStack[int]()

View File

@@ -1,24 +1,28 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. BSTree is binary search tree.
package datastructure package datastructure
import ( import (
"math" "math"
"github.com/duke-git/lancet/v2/constraints"
"github.com/duke-git/lancet/v2/datastructure" "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, // 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. // which are referred to as the left child and the right child.
// In BSTree: leftNode < rootNode < rightNode // In BSTree: leftNode < rootNode < rightNode
// type T should implements Compare function in lancetconstraints.Comparator interface. // type T should implements Compare function in constraints.Comparator interface.
type BSTree[T any] struct { type BSTree[T any] struct {
root *datastructure.TreeNode[T] root *datastructure.TreeNode[T]
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
// NewBSTree create a BSTree pointer // NewBSTree create a BSTree pointer
// param `comparator` is used to compare values in the tree // param `comparator` is used to compare values in the tree
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T] { func NewBSTree[T any](rootData T, comparator constraints.Comparator) *BSTree[T] {
root := datastructure.NewTreeNode(rootData) root := datastructure.NewTreeNode(rootData)
return &BSTree[T]{root, comparator} return &BSTree[T]{root, comparator}
} }
@@ -83,7 +87,7 @@ func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool {
} }
func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], func hasSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T],
comparator lancetconstraints.Comparator) bool { comparator constraints.Comparator) bool {
result := false result := false
if superTreeRoot != nil && subTreeRoot != nil { if superTreeRoot != nil && subTreeRoot != nil {

View File

@@ -20,16 +20,9 @@ func (c *intComparator) Compare(v1, v2 any) int {
return 0 return 0
} }
func TestBSTree_Insert(t *testing.T) {
bstree := NewBSTree(6, &intComparator{})
bstree.Insert(7)
bstree.Insert(5)
bstree.Insert(2)
bstree.Insert(4)
}
func TestBSTree_PreOrderTraverse(t *testing.T) { func TestBSTree_PreOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse") assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -44,6 +37,8 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
} }
func TestBSTree_PostOrderTraverse(t *testing.T) { func TestBSTree_PostOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse") assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -58,6 +53,8 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
} }
func TestBSTree_InOrderTraverse(t *testing.T) { func TestBSTree_InOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse") assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -72,6 +69,8 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
} }
func TestBSTree_LevelOrderTraverse(t *testing.T) { func TestBSTree_LevelOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse") assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -86,6 +85,8 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
} }
func TestBSTree_Delete(t *testing.T) { func TestBSTree_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_Delete") assert := internal.NewAssert(t, "TestBSTree_Delete")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -108,6 +109,8 @@ func TestBSTree_Delete(t *testing.T) {
} }
func TestBSTree_Depth(t *testing.T) { func TestBSTree_Depth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_Depth") assert := internal.NewAssert(t, "TestBSTree_Depth")
bstree := NewBSTree(6, &intComparator{}) bstree := NewBSTree(6, &intComparator{})
@@ -121,6 +124,8 @@ func TestBSTree_Depth(t *testing.T) {
} }
func TestBSTree_IsSubTree(t *testing.T) { func TestBSTree_IsSubTree(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_IsSubTree") assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
superTree := NewBSTree(8, &intComparator{}) superTree := NewBSTree(8, &intComparator{})

View File

@@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"math" "math"
"github.com/duke-git/lancet/v2/constraints"
"github.com/duke-git/lancet/v2/datastructure" "github.com/duke-git/lancet/v2/datastructure"
"github.com/duke-git/lancet/v2/lancetconstraints"
) )
func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T { func preOrderTraverse[T any](node *datastructure.TreeNode[T]) []T {
@@ -86,7 +86,7 @@ func levelOrderTraverse[T any](root *datastructure.TreeNode[T], traversal *[]T)
} }
} }
func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) { func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], comparator constraints.Comparator) {
if comparator.Compare(newNode.Value, rootNode.Value) == -1 { if comparator.Compare(newNode.Value, rootNode.Value) == -1 {
if rootNode.Left == nil { if rootNode.Left == nil {
rootNode.Left = newNode rootNode.Left = newNode
@@ -103,7 +103,7 @@ func insertTreeNode[T any](rootNode, newNode *datastructure.TreeNode[T], compara
} }
// todo, delete root node failed // todo, delete root node failed
func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator lancetconstraints.Comparator) *datastructure.TreeNode[T] { func deleteTreeNode[T any](node *datastructure.TreeNode[T], data T, comparator constraints.Comparator) *datastructure.TreeNode[T] {
if node == nil { if node == nil {
return nil return nil
} }
@@ -216,7 +216,7 @@ func calculateDepth[T any](node *datastructure.TreeNode[T], depth int) int {
return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1)) return max(calculateDepth(node.Left, depth+1), calculateDepth(node.Right, depth+1))
} }
func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], comparator lancetconstraints.Comparator) bool { func isSubTree[T any](superTreeRoot, subTreeRoot *datastructure.TreeNode[T], comparator constraints.Comparator) bool {
if subTreeRoot == nil { if subTreeRoot == nil {
return true return true
} }

View File

@@ -7,6 +7,8 @@ import (
) )
func TestToUnix(t *testing.T) { func TestToUnix(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToUnix") assert := internal.NewAssert(t, "TestToUnix")
tm1 := NewUnixNow() tm1 := NewUnixNow()
@@ -17,6 +19,8 @@ func TestToUnix(t *testing.T) {
} }
func TestToFormat(t *testing.T) { func TestToFormat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFormat") assert := internal.NewAssert(t, "TestToFormat")
tm, err := NewFormat("2022-03-18 17:04:05") tm, err := NewFormat("2022-03-18 17:04:05")
@@ -25,18 +29,21 @@ func TestToFormat(t *testing.T) {
} }
func TestToFormatForTpl(t *testing.T) { func TestToFormatForTpl(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFormatForTpl") assert := internal.NewAssert(t, "TestToFormatForTpl")
_, err := NewFormat("2022/03/18 17:04:05") _, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err) assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05") tm, err := NewFormat("2022-03-18 17:04:05")
// assert.Equal("2022/03/18 17:04:05", tm.ToFormatForTpl("2006/01/02 15:04:05"))
t.Log("TestToFormatForTpl", tm.ToFormatForTpl("2006/01/02 15:04:05")) t.Log("TestToFormatForTpl", tm.ToFormatForTpl("2006/01/02 15:04:05"))
assert.IsNil(err) assert.IsNil(err)
} }
func TestToIso8601(t *testing.T) { func TestToIso8601(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToIso8601") assert := internal.NewAssert(t, "TestToIso8601")
_, err := NewISO8601("2022-03-18 17:04:05") _, err := NewISO8601("2022-03-18 17:04:05")
@@ -44,6 +51,5 @@ func TestToIso8601(t *testing.T) {
tm, err := NewISO8601("2006-01-02T15:04:05.999Z") tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
t.Log("TestToIso8601", tm.ToIso8601()) t.Log("TestToIso8601", tm.ToIso8601())
// assert.Equal("2006-01-02T23:04:05+08:00", tm.ToIso8601())
assert.IsNil(err) assert.IsNil(err)
} }

View File

@@ -3,7 +3,7 @@
// Package datetime implements some functions to format date and time. // Package datetime implements some functions to format date and time.
// Note: // Note:
// 1. `format` param in FormatTimeToStr function should be as flow: // 1. `format` param in FormatTimeToStr function should be as flow (case no sensitive):
// "yyyy-mm-dd hh:mm:ss" // "yyyy-mm-dd hh:mm:ss"
// "yyyy-mm-dd hh:mm" // "yyyy-mm-dd hh:mm"
// "yyyy-mm-dd hh" // "yyyy-mm-dd hh"
@@ -18,14 +18,19 @@
// "yyyy/mm" // "yyyy/mm"
// "mm/dd" // "mm/dd"
// "dd/mm/yy hh:mm:ss" // "dd/mm/yy hh:mm:ss"
// "yyyymmdd"
// "mmddyy"
// "yyyy" // "yyyy"
// "yy"
// "mm" // "mm"
// "hh:mm:ss" // "hh:mm:ss"
// "hh:mm"
// "mm:ss" // "mm:ss"
package datetime package datetime
import ( import (
"fmt" "fmt"
"strings"
"time" "time"
) )
@@ -35,7 +40,7 @@ func init() {
timeFormat = map[string]string{ timeFormat = map[string]string{
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05", "yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
"yyyy-mm-dd hh:mm": "2006-01-02 15:04", "yyyy-mm-dd hh:mm": "2006-01-02 15:04",
"yyyy-mm-dd hh": "2006-01-02 15:04", "yyyy-mm-dd hh": "2006-01-02 15",
"yyyy-mm-dd": "2006-01-02", "yyyy-mm-dd": "2006-01-02",
"yyyy-mm": "2006-01", "yyyy-mm": "2006-01",
"mm-dd": "01-02", "mm-dd": "01-02",
@@ -47,9 +52,13 @@ func init() {
"yyyy/mm": "2006/01", "yyyy/mm": "2006/01",
"mm/dd": "01/02", "mm/dd": "01/02",
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05", "dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
"yyyymmdd": "20060102",
"mmddyy": "010206",
"yyyy": "2006", "yyyy": "2006",
"yy": "06",
"mm": "01", "mm": "01",
"hh:mm:ss": "15:04:05", "hh:mm:ss": "15:04:05",
"hh:mm": "15:04",
"mm:ss": "04:05", "mm:ss": "04:05",
} }
} }
@@ -73,7 +82,7 @@ func AddDay(t time.Time, day int64) time.Time {
} }
// AddYear add or sub year to the time. // AddYear add or sub year to the time.
// Play: todo // Play: https://go.dev/play/p/MqW2ujnBx10
func AddYear(t time.Time, year int64) time.Time { func AddYear(t time.Time, year int64) time.Time {
return t.Add(365 * 24 * time.Hour * time.Duration(year)) return t.Add(365 * 24 * time.Hour * time.Duration(year))
} }
@@ -96,6 +105,18 @@ func GetNowDateTime() string {
return time.Now().Format("2006-01-02 15:04:05") return time.Now().Format("2006-01-02 15:04:05")
} }
// GetTodayStartTime return the start time of today, format: yyyy-mm-dd 00:00:00.
// Play: https://go.dev/play/p/84siyYF7t99
func GetTodayStartTime() string {
return time.Now().Format("2006-01-02") + " 00:00:00"
}
// GetTodayEndTime return the end time of today, format: yyyy-mm-dd 23:59:59.
// Play: https://go.dev/play/p/jjrLnfoqgn3
func GetTodayEndTime() string {
return time.Now().Format("2006-01-02") + " 23:59:59"
}
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00). // GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
// Play: https://go.dev/play/p/QmL2oIaGE3q // Play: https://go.dev/play/p/QmL2oIaGE3q
func GetZeroHourTimestamp() int64 { func GetZeroHourTimestamp() int64 {
@@ -112,19 +133,40 @@ func GetNightTimestamp() int64 {
// FormatTimeToStr convert time to string. // FormatTimeToStr convert time to string.
// Play: https://go.dev/play/p/_Ia7M8H_OvE // Play: https://go.dev/play/p/_Ia7M8H_OvE
func FormatTimeToStr(t time.Time, format string) string { func FormatTimeToStr(t time.Time, format string, timezone ...string) string {
return t.Format(timeFormat[format]) tf, ok := timeFormat[strings.ToLower(format)]
if !ok {
return ""
}
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return ""
}
return t.In(loc).Format(tf)
}
return t.Format(tf)
} }
// FormatStrToTime convert string to time. // FormatStrToTime convert string to time.
// Play: https://go.dev/play/p/1h9FwdU8ql4 // Play: https://go.dev/play/p/1h9FwdU8ql4
func FormatStrToTime(str, format string) (time.Time, error) { func FormatStrToTime(str, format string, timezone ...string) (time.Time, error) {
v, ok := timeFormat[format] tf, ok := timeFormat[strings.ToLower(format)]
if !ok { if !ok {
return time.Time{}, fmt.Errorf("format %s not found", format) return time.Time{}, fmt.Errorf("format %s not support", format)
} }
return time.Parse(v, str) if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return time.Time{}, err
}
return time.ParseInLocation(tf, str, loc)
}
return time.Parse(tf, str)
} }
// BeginOfMinute return beginning minute time of day. // BeginOfMinute return beginning minute time of day.
@@ -226,7 +268,125 @@ func EndOfYear(t time.Time) time.Time {
} }
// IsLeapYear check if param year is leap year or not. // IsLeapYear check if param year is leap year or not.
// Play: todo // Play: https://go.dev/play/p/xS1eS2ejGew
func IsLeapYear(year int) bool { func IsLeapYear(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0) return year%4 == 0 && (year%100 != 0 || year%400 == 0)
} }
// BetweenSeconds returns the number of seconds between two times.
// Play: https://go.dev/play/p/n3YDRyfyXJu
func BetweenSeconds(t1 time.Time, t2 time.Time) int64 {
index := t2.Unix() - t1.Unix()
return index
}
// DayOfYear returns which day of the year the parameter date `t` is.
// Play: https://go.dev/play/p/0hjqhTwFNlH
func DayOfYear(t time.Time) int {
y, m, d := t.Date()
firstDay := time.Date(y, 1, 1, 0, 0, 0, 0, t.Location())
nowDate := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
return int(nowDate.Sub(firstDay).Hours() / 24)
}
// IsWeekend checks if passed time is weekend or not.
// Play: https://go.dev/play/p/cupRM5aZOIY
// Deprecated Use '== Weekday' instead
func IsWeekend(t time.Time) bool {
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
}
// NowDateOrTime return current datetime with specific format and timezone.
// Play: https://go.dev/play/p/EZ-begEjtT0
func NowDateOrTime(format string, timezone ...string) string {
tf, ok := timeFormat[strings.ToLower(format)]
if !ok {
return ""
}
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return ""
}
return time.Now().In(loc).Format(tf)
}
return time.Now().Format(tf)
}
// Timestamp return current second timestamp.
// Play: https://go.dev/play/p/iU5b7Vvjx6x
func Timestamp(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return t.Unix()
}
// TimestampMilli return current mill second timestamp.
// Play: https://go.dev/play/p/4gvEusOTu1T
func TimestampMilli(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Millisecond)
}
// TimestampMicro return current micro second timestamp.
// Play: https://go.dev/play/p/2maANglKHQE
func TimestampMicro(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Microsecond)
}
// TimestampNano return current nano second timestamp.
// Play: https://go.dev/play/p/A9Oq_COrcCF
func TimestampNano(timezone ...string) int64 {
t := time.Now()
if timezone != nil && timezone[0] != "" {
loc, err := time.LoadLocation(timezone[0])
if err != nil {
return 0
}
t = t.In(loc)
}
return t.UnixNano()
}
// TraceFuncTime: trace the func costed time,just call it at top of the func like `defer TraceFuncTime()()`
func TraceFuncTime() func() {
pre := time.Now()
return func() {
elapsed := time.Since(pre)
fmt.Println("Costs Time:\t", elapsed)
}
}

View File

@@ -131,15 +131,18 @@ func ExampleFormatTimeToStr() {
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss") result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd") result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss") result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4)
// Output: // Output:
// 2021-01-02 16:04:08 // 2021-01-02 16:04:08
// 2021-01-02 // 2021-01-02
// 02-01-21 16:04:08 // 02-01-21 16:04:08
// 2021-01-02 16
} }
func ExampleFormatStrToTime() { func ExampleFormatStrToTime() {
@@ -350,3 +353,58 @@ func ExampleIsLeapYear() {
// true // true
// false // false
} }
func ExampleBetweenSeconds() {
today := time.Now()
tomorrow := AddDay(today, 1)
yesterday := AddDay(today, -1)
result1 := BetweenSeconds(today, tomorrow)
result2 := BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
func ExampleDayOfYear() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
func ExampleIsWeekend() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := IsWeekend(date1)
result2 := IsWeekend(date2)
result3 := IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}

View File

@@ -8,6 +8,8 @@ import (
) )
func TestAddYear(t *testing.T) { func TestAddYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddDay") assert := internal.NewAssert(t, "TestAddDay")
now := time.Now() now := time.Now()
@@ -20,7 +22,25 @@ func TestAddYear(t *testing.T) {
assert.Equal(float64(-8760), diff2.Hours()) assert.Equal(float64(-8760), diff2.Hours())
} }
func TestBetweenSeconds(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBetweenSeconds")
today := time.Now()
tomorrow := AddDay(today, 1)
yesterday := AddDay(today, -1)
result1 := BetweenSeconds(today, tomorrow)
result2 := BetweenSeconds(today, yesterday)
assert.Equal(int64(86400), result1)
assert.Equal(int64(-86400), result2)
}
func TestAddDay(t *testing.T) { func TestAddDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddDay") assert := internal.NewAssert(t, "TestAddDay")
now := time.Now() now := time.Now()
@@ -34,6 +54,8 @@ func TestAddDay(t *testing.T) {
} }
func TestAddHour(t *testing.T) { func TestAddHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddHour") assert := internal.NewAssert(t, "TestAddHour")
now := time.Now() now := time.Now()
@@ -47,6 +69,8 @@ func TestAddHour(t *testing.T) {
} }
func TestAddMinute(t *testing.T) { func TestAddMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddMinute") assert := internal.NewAssert(t, "TestAddMinute")
now := time.Now() now := time.Now()
@@ -60,44 +84,77 @@ func TestAddMinute(t *testing.T) {
} }
func TestGetNowDate(t *testing.T) { func TestGetNowDate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowDate") assert := internal.NewAssert(t, "TestGetNowDate")
expected := time.Now().Format("2006-01-02") expected := time.Now().Format("2006-01-02")
assert.Equal(expected, GetNowDate()) assert.Equal(expected, GetNowDate())
} }
func TestGetNowTime(t *testing.T) { func TestGetNowTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowTime") assert := internal.NewAssert(t, "TestGetNowTime")
expected := time.Now().Format("15:04:05") expected := time.Now().Format("15:04:05")
assert.Equal(expected, GetNowTime()) assert.Equal(expected, GetNowTime())
} }
func TestGetNowDateTime(t *testing.T) { func TestGetNowDateTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowDateTime") assert := internal.NewAssert(t, "TestGetNowDateTime")
expected := time.Now().Format("2006-01-02 15:04:05") expected := time.Now().Format("2006-01-02 15:04:05")
assert.Equal(expected, GetNowDateTime()) assert.Equal(expected, GetNowDateTime())
} }
func TestGetTodayStartTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetTodayStartTime")
expected := time.Now().Format("2006-01-02") + " 00:00:00"
assert.Equal(expected, GetTodayStartTime())
}
func TestGetTodayEndTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetTodayEndTime")
expected := time.Now().Format("2006-01-02") + " 23:59:59"
assert.Equal(expected, GetTodayEndTime())
}
func TestFormatTimeToStr(t *testing.T) { func TestFormatTimeToStr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFormatTimeToStr") assert := internal.NewAssert(t, "TestFormatTimeToStr")
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08") datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
cases := []string{ cases := []string{
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd", "yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss", "dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
"hh:mm:ss", "yyyy/mm"} "hh:mm:ss", "yyyy/mm",
"yyyy-mm-dd hh",
}
expected := []string{ expected := []string{
"2021-01-02 16:04:08", "2021-01-02", "2021-01-02 16:04:08", "2021-01-02",
"02-01-21 16:04:08", "2021/01/02 16:04:08", "02-01-21 16:04:08", "2021/01/02 16:04:08",
"16:04:08", "2021/01"} "16:04:08", "2021/01",
"2021-01-02 16",
}
for i := 0; i < len(cases); i++ { for i := 0; i < len(cases); i++ {
actual := FormatTimeToStr(datetime, cases[i]) actual := FormatTimeToStr(datetime, cases[i])
assert.Equal(expected[i], actual) assert.Equal(expected[i], actual)
} }
ds := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss", "EST")
t.Log(ds)
} }
func TestFormatStrToTime(t *testing.T) { func TestFormatStrToTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFormatStrToTime") assert := internal.NewAssert(t, "TestFormatStrToTime")
formats := []string{ formats := []string{
@@ -109,22 +166,28 @@ func TestFormatStrToTime(t *testing.T) {
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss", "dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
"yyyy/mm"} "yyyy/mm"}
datetimeStr := []string{ expected := []string{
"2021-01-02 16:04:08", "2021-01-02", "2021-01-02 16:04:08", "2021-01-02",
"02-01-21 16:04:08", "2021/01/02 16:04:08", "02-01-21 16:04:08", "2021/01/02 16:04:08",
"2021/01"} "2021/01"}
for i := 0; i < len(cases); i++ { for i := 0; i < len(cases); i++ {
actual, err := FormatStrToTime(datetimeStr[i], cases[i]) actual, err := FormatStrToTime(expected[i], cases[i])
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
expected, _ := time.Parse(formats[i], datetimeStr[i]) expected, _ := time.Parse(formats[i], expected[i])
assert.Equal(expected, actual) assert.Equal(expected, actual)
} }
estTime, err := FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss", "EST")
t.Log(estTime)
assert.IsNil(err)
} }
func TestBeginOfMinute(t *testing.T) { func TestBeginOfMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfMinute") assert := internal.NewAssert(t, "TestBeginOfMinute")
expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local) expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local)
@@ -135,6 +198,8 @@ func TestBeginOfMinute(t *testing.T) {
} }
func TestEndOfMinute(t *testing.T) { func TestEndOfMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfMinute") assert := internal.NewAssert(t, "TestEndOfMinute")
expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local) expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local)
@@ -145,6 +210,8 @@ func TestEndOfMinute(t *testing.T) {
} }
func TestBeginOfHour(t *testing.T) { func TestBeginOfHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfHour") assert := internal.NewAssert(t, "TestBeginOfHour")
expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local) expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local)
@@ -155,6 +222,8 @@ func TestBeginOfHour(t *testing.T) {
} }
func TestEndOfHour(t *testing.T) { func TestEndOfHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfHour") assert := internal.NewAssert(t, "TestEndOfHour")
expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local) expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local)
@@ -165,6 +234,8 @@ func TestEndOfHour(t *testing.T) {
} }
func TestBeginOfDay(t *testing.T) { func TestBeginOfDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfDay") assert := internal.NewAssert(t, "TestBeginOfDay")
expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local) expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local)
@@ -175,6 +246,8 @@ func TestBeginOfDay(t *testing.T) {
} }
func TestEndOfDay(t *testing.T) { func TestEndOfDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfDay") assert := internal.NewAssert(t, "TestEndOfDay")
expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local) expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local)
@@ -185,6 +258,8 @@ func TestEndOfDay(t *testing.T) {
} }
func TestBeginOfWeek(t *testing.T) { func TestBeginOfWeek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfWeek") assert := internal.NewAssert(t, "TestBeginOfWeek")
expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local) expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local)
@@ -195,6 +270,8 @@ func TestBeginOfWeek(t *testing.T) {
} }
func TestEndOfWeek(t *testing.T) { func TestEndOfWeek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfWeek") assert := internal.NewAssert(t, "TestEndOfWeek")
expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local) expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local)
@@ -205,6 +282,8 @@ func TestEndOfWeek(t *testing.T) {
} }
func TestBeginOfMonth(t *testing.T) { func TestBeginOfMonth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfMonth") assert := internal.NewAssert(t, "TestBeginOfMonth")
expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local) expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local)
@@ -215,6 +294,8 @@ func TestBeginOfMonth(t *testing.T) {
} }
func TestEndOfMonth(t *testing.T) { func TestEndOfMonth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfMonth") assert := internal.NewAssert(t, "TestEndOfMonth")
expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local) expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local)
@@ -225,6 +306,8 @@ func TestEndOfMonth(t *testing.T) {
} }
func TestBeginOfYear(t *testing.T) { func TestBeginOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfYear") assert := internal.NewAssert(t, "TestBeginOfYear")
expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local) expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local)
@@ -235,6 +318,8 @@ func TestBeginOfYear(t *testing.T) {
} }
func TestEndOfYear(t *testing.T) { func TestEndOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfYear") assert := internal.NewAssert(t, "TestEndOfYear")
expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local) expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local)
@@ -245,6 +330,8 @@ func TestEndOfYear(t *testing.T) {
} }
func TestIsLeapYear(t *testing.T) { func TestIsLeapYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfYear") assert := internal.NewAssert(t, "TestEndOfYear")
result1 := IsLeapYear(2000) result1 := IsLeapYear(2000)
@@ -253,3 +340,73 @@ func TestIsLeapYear(t *testing.T) {
assert.Equal(true, result1) assert.Equal(true, result1)
assert.Equal(false, result2) assert.Equal(false, result2)
} }
func TestDayOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDayOfYear")
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := DayOfYear(date1)
assert.Equal(31, result1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := DayOfYear(date2)
assert.Equal(1, result2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := DayOfYear(date3)
assert.Equal(0, result3)
}
func TestIsWeekend(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsWeekend")
date := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
result := IsWeekend(date)
assert.Equal(true, result)
date1 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
result1 := IsWeekend(date1)
assert.Equal(true, result1)
date2 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result2 := IsWeekend(date2)
assert.Equal(false, result2)
}
func TestNowDateOrTime(t *testing.T) {
t.Parallel()
formats := []string{
"yyyy-mm-dd hh:mm:ss",
"yyyy-mm-dd",
"dd-mm-yy hh:mm:ss",
"yyyy/mm/dd hh:mm:ss",
"hh:mm:ss",
"yyyy/mm",
"yyyy-mm-dd hh",
}
for i := 0; i < len(formats); i++ {
result := NowDateOrTime(formats[i], "UTC")
t.Log(result)
}
}
func TestTimestamp(t *testing.T) {
t.Parallel()
ts1 := Timestamp()
t.Log(ts1)
ts2 := TimestampMilli()
t.Log(ts2)
ts3 := TimestampMicro()
t.Log(ts3)
ts4 := TimestampNano()
t.Log(ts4)
}

89
docs/.vitepress/common.ts Normal file
View File

@@ -0,0 +1,89 @@
import { defineConfig, HeadConfig } from 'vitepress'
export const META_IMAGE = '/lancet_logo.png'
export const isProduction = process.env.NETLIFY && process.env.CONTEXT === 'production'
if (process.env.NETLIFY) {
console.log('Netlify build', process.env.CONTEXT)
}
const productionHead: HeadConfig[] = [
[
'script',
{
src: 'https://unpkg.com/thesemetrics@latest',
async: '',
type: 'text/javascript',
},
],
]
const rControl = /[\u0000-\u001f]/g
const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g
const rCombining = /[\u0300-\u036F]/g
/**
* Default slugification function
*/
export const slugify = (str: string): string =>
str
.normalize('NFKD')
// Remove accents
.replace(rCombining, '')
// Remove control characters
.replace(rControl, '')
// Replace special characters
.replace(rSpecial, '-')
// ensure it doesn't start with a number
.replace(/^(\d)/, '_$1')
export const commonConfig = defineConfig({
title: 'Lancet',
appearance: true,
markdown: {
theme: {
dark: 'dracula-soft',
light: 'vitesse-light',
},
attrs: {
leftDelimiter: '%{',
rightDelimiter: '}%',
},
anchor: {
slugify,
},
},
head: [
// ['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
['link', { rel: 'icon', type: 'image/png', href: '/lancet_logo_mini.png' }],
['meta', { name: 'theme-color', content: '#5f67ee' }],
['meta', { name: 'og:type', content: 'website' }],
['meta', { name: 'og:locale', content: 'zh' }],
...(isProduction ? productionHead : []),
],
themeConfig: {
logo: { src: '/lancet_logo_mini.png', width: 24, height: 24 },
outline: [2, 3],
search: {
provider: 'local',
},
socialLinks: [
{
icon: 'github',
link: 'https://github.com/duke-git/lancet',
},
],
footer: {
copyright: 'Copyright © 2023-present Duke Du',
message: '备案号: 京ICP备2023022770号',
},
},
})

View File

@@ -0,0 +1,14 @@
import { defineConfig } from 'vitepress'
import { commonConfig } from './common'
import { zhConfig } from './zh'
import { enConfig } from './en'
// https://vitepress.dev/reference/site-config
export default defineConfig({
...commonConfig,
locales: {
root: { label: '简体中文', lang: 'zh-CN', link: '/', ...zhConfig },
en: { label: 'English', lang: 'en-US', link: '/en/', ...enConfig },
},
})

139
docs/.vitepress/en.ts Normal file
View File

@@ -0,0 +1,139 @@
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
export const META_URL = 'https://www.golancet.cn/en/'
export const META_TITLE = 'Lancet'
export const META_DESCRIPTION = 'A powerful util function library of Go'
export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
description: META_DESCRIPTION,
head: [
['meta', { property: 'og:url', content: META_URL }],
['meta', { property: 'og:description', content: META_DESCRIPTION }],
],
themeConfig: {
editLink: {
pattern: 'https://github.com/duke-git/lancet/edit/v2/docs/:path',
text: 'Suggest changes to this page',
},
nav: [
{
text: 'Home',
link: '/en/',
activeMatch: '^/en/',
},
{
text: 'Guide',
link: '/en/guide/introduction',
activeMatch: '^/en/guide/',
},
{ text: 'API', link: '/en/api/overview', activeMatch: '^/en/api/' },
{
text: 'Links',
items: [
{
text: 'Discussion',
link: 'https://github.com/duke-git/lancet/discussions',
},
{
text: 'Changelog',
link: 'https://github.com/duke-git/lancet/releases',
},
{
text: 'Contribution',
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.en-US.md',
},
],
},
],
sidebar: {
'/en/guide/': [
{
text: 'Introduction',
collapsed: false,
items: [
{
text: 'What is Lancet',
link: '/en/guide/introduction',
},
{
text: 'Getting started',
link: '/en/guide/getting_started',
},
],
},
{
text: 'Contribute Code',
collapsed: false,
items: [
{
text: 'Contribution guide',
link: '/en/guide/contribution_guide',
},
{
text: 'Contributors',
link: '/en/guide/contributors',
},
],
},
{
text: 'API Reference',
link: '/en/api/overview'
},
],
'/en/api/': [
{
text: 'Overview',
items: [{ text: 'API overview', link: '/en/api/overview' }],
},
{
text: 'Packages',
collapsed: false,
items: [
{ text: 'algorithm', link: '/en/api/packages/algorithm' },
{ text: 'compare', link: '/en/api/packages/compare' },
{ text: 'concurrency', link: '/en/api/packages/concurrency' },
{ text: 'condition', link: '/en/api/packages/condition' },
{ text: 'convertor', link: '/en/api/packages/convertor' },
{ text: 'cryptor', link: '/en/api/packages/cryptor' },
{
text: 'datastructure',
collapsed: true,
items: [
{ text: 'list', link: '/en/api/packages/datastructure/list' },
{ text: 'safelist', link: '/en/api/packages/datastructure/copyonwritelist' },
{ text: 'link', link: '/en/api/packages/datastructure/link' },
{ text: 'stack', link: '/en/api/packages/datastructure/stack' },
{ text: 'queue', link: '/en/api/packages/datastructure/queue' },
{ text: 'heap', link: '/en/api/packages/datastructure/heap' },
{ text: 'tree', link: '/en/api/packages/datastructure/tree' },
{ text: 'set', link: '/en/api/packages/datastructure/set' },
{ text: 'hashmap', link: '/en/api/packages/datastructure/hashmap' },
],
},
{ text: 'datetime', link: '/en/api/packages/datetime' },
{ text: 'fileutil', link: '/en/api/packages/fileutil' },
{ text: 'formatter', link: '/en/api/packages/formatter' },
{ text: 'function', link: '/en/api/packages/function' },
{ text: 'mathutil', link: '/en/api/packages/mathutil' },
{ text: 'maputil', link: '/en/api/packages/maputil' },
{ text: 'netutil', link: '/en/api/packages/netutil' },
{ text: 'pointer', link: '/en/api/packages/pointer' },
{ text: 'random', link: '/en/api/packages/random' },
{ text: 'retry', link: '/en/api/packages/retry' },
{ text: 'slice', link: '/en/api/packages/slice' },
{ text: 'stream', link: '/en/api/packages/stream' },
{ text: 'struct', link: '/en/api/packages/struct' },
{ text: 'strutil', link: '/en/api/packages/strutil' },
{ text: 'system', link: '/en/api/packages/system' },
{ text: 'tuple', link: '/en/api/packages/tuple' },
{ text: 'validator', link: '/en/api/packages/validator' },
{ text: 'xerror', link: '/en/api/packages/xerror' },
],
},
],
},
},
}

152
docs/.vitepress/zh.ts Normal file
View File

@@ -0,0 +1,152 @@
import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress'
export const META_URL = 'https://www.golancet.cn'
export const META_TITLE = 'Lancet'
export const META_DESCRIPTION = '一个强大的Go语言工具函数库'
export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
description: META_DESCRIPTION,
head: [
['meta', { property: 'og:url', content: META_URL }],
['meta', { property: 'og:description', content: META_DESCRIPTION }],
],
themeConfig: {
editLink: {
pattern: 'https://github.com/duke-git/lancet/edit/v2/docs/:path',
text: '对本页提出修改建议',
},
outline: {
label: '本页内容',
},
docFooter: {
prev: '上一页',
next: '下一页',
},
nav: [
{
text: '首页',
link: '/',
activeMatch: '^/',
},
{
text: '指南',
link: '/guide/introduction',
activeMatch: '^/guide/',
},
{ text: 'API', link: '/api/overview', activeMatch: '^/api/' },
{
text: '相关链接',
items: [
{
text: '论坛',
link: 'https://github.com/duke-git/lancet/discussions',
},
{
text: '更新日志',
link: 'https://github.com/duke-git/lancet/releases',
},
{
text: '参与贡献',
link: 'https://github.com/duke-git/lancet/blob/main/CONTRIBUTING.zh-CN.md',
},
],
},
],
sidebar: {
'/guide/': [
{
text: '介绍',
collapsed: false,
items: [
{
text: 'Lancet是什么',
link: '/guide/introduction',
},
{
text: '开始',
link: '/guide/getting_started',
},
],
},
{
text: '贡献代码',
collapsed: false,
items: [
{
text: '贡献指南',
link: '/guide/contribution_guide',
},
{
text: '贡献者',
link: '/guide/contributors',
},
],
},
{
text: 'API手册',
link: '/api/overview'
},
],
'/api/': [
{
text: '概览',
items: [{ text: 'API概述', link: '/api/overview' }],
},
{
text: 'API文档',
collapsed: false,
items: [
{ text: '算法', link: '/api/packages/algorithm' },
{ text: '比较器', link: '/api/packages/compare' },
{ text: '并发处理', link: '/api/packages/concurrency' },
{ text: '条件判断', link: '/api/packages/condition' },
{ text: '类型转换', link: '/api/packages/convertor' },
{ text: '加密&解密', link: '/api/packages/cryptor' },
{
text: '数据结构',
collapsed: true,
items: [
{ text: '线性表', link: '/api/packages/datastructure/list' },
{
text: '线性表(线程安全)',
link: '/api/packages/datastructure/copyonwritelist',
},
{ text: '链表', link: '/api/packages/datastructure/link' },
{ text: '栈', link: '/api/packages/datastructure/stack' },
{ text: '队列', link: '/api/packages/datastructure/queue' },
{ text: '堆', link: '/api/packages/datastructure/heap' },
{ text: '树', link: '/api/packages/datastructure/tree' },
{ text: '集合', link: '/api/packages/datastructure/set' },
{ text: 'HashMap', link: '/api/packages/datastructure/hashmap' },
],
},
{ text: '日期&时间', link: '/api/packages/datetime' },
{ text: '文件', link: '/api/packages/fileutil' },
{ text: '格式化工具', link: '/api/packages/formatter' },
{ text: '函数', link: '/api/packages/function' },
{ text: '数学工具', link: '/api/packages/mathutil' },
{ text: 'Map', link: '/api/packages/maputil' },
{ text: '网络', link: '/api/packages/netutil' },
{ text: '指针', link: '/api/packages/pointer' },
{ text: '随机数', link: '/api/packages/random' },
{ text: '重试', link: '/api/packages/retry' },
{ text: '切片', link: '/api/packages/slice' },
{ text: '流', link: '/api/packages/stream' },
{ text: '结构体', link: '/api/packages/struct' },
{ text: '字符串', link: '/api/packages/strutil' },
{ text: '系统', link: '/api/packages/system' },
{ text: '元组', link: '/api/packages/tuple' },
{ text: '验证器', link: '/api/packages/validator' },
{ text: '错误处理', link: '/api/packages/xerror' },
],
},
],
},
},
}

69
docs/api/overview.md Normal file
View File

@@ -0,0 +1,69 @@
---
outline: deep
---
# API概述
<b>lancet柳叶刀是一个功能强大、全面、高效、可复用的go语言工具函数库。包含25个包超过600个工具函数。功能涵盖字符串处理、切片处理、网络、并发、加解密、文件处理、时间/日期、流处理、迭代器等等。</b>
<style>
.package-title {
color: black;
font-size: 18px;
text-align: center;
font-weight: bold;
}
.package-container {
font-size: 16px;
border: 1px dashed;
padding: 10px;
text-align: center;
}
.package-cell {
height: 40px;
width: 140px;
display: inline-block;
vertical-align: middle;
line-height: 40px;
background: #10b981;
border: 1px solid;
margin-right: 10px;
margin-bottom: 10px;
border-radius: 6px;
font-weight: bold;
}
</style>
<div>
<p class="package-title">lancet功能模块</p>
<div class="package-container">
<div class="package-cell">algorithm</div>
<div class="package-cell">compare</div>
<div class="package-cell">concurrency</div>
<div class="package-cell">condition</div>
<div class="package-cell">convertor</div>
<div class="package-cell">cryptor</div>
<div class="package-cell">datastructure</div>
<div class="package-cell">datetime</div>
<div class="package-cell">fileutil</div>
<div class="package-cell">formatter</div>
<div class="package-cell">function</div>
<div class="package-cell">iterator</div>
<div class="package-cell">maputil</div>
<div class="package-cell">mathutil</div>
<div class="package-cell">netutil</div>
<div class="package-cell">pointer</div>
<div class="package-cell">random</div>
<div class="package-cell">retry</div>
<div class="package-cell">slice</div>
<div class="package-cell">stream</div>
<div class="package-cell">structs</div>
<div class="package-cell">strutil</div>
<div class="package-cell">system</div>
<div class="package-cell">tuple</div>
<div class="package-cell">validator</div>
<div class="package-cell">xerror</div>
</div>
</div>

View File

@@ -43,15 +43,15 @@ import (
### <span id="BubbleSort">BubbleSort</span> ### <span id="BubbleSort">BubbleSort</span>
<p>冒泡排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>冒泡排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) func BubbleSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
```go ```go
package main package main
@@ -91,15 +91,15 @@ func main() {
### <span id="InsertionSort">InsertionSort</span> ### <span id="InsertionSort">InsertionSort</span>
<p>插入排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>插入排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) func InsertionSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G5LJiWgJJW6)</span></b>
```go ```go
package main package main
@@ -117,7 +117,7 @@ type people struct {
// PeopleAageComparator sort people slice by age field // PeopleAageComparator sort people slice by age field
type peopleAgeComparator struct{} type peopleAgeComparator struct{}
// Compare implements github.com/duke-git/lancet/lancetconstraints/constraints.go/Comparator // Compare implements github.com/duke-git/lancet/constraints/constraints.go/Comparator
func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int { func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
p1, _ := v1.(people) p1, _ := v1.(people)
p2, _ := v2.(people) p2, _ := v2.(people)
@@ -154,15 +154,15 @@ func main() {
### <span id="SelectionSort">SelectionSort</span> ### <span id="SelectionSort">SelectionSort</span>
<p>选择排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>选择排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) func SelectionSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oXovbkekayS)</span></b>
```go ```go
package main package main
@@ -202,15 +202,15 @@ func main() {
### <span id="ShellSort">ShellSort</span> ### <span id="ShellSort">ShellSort</span>
<p>希尔排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>希尔排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) func ShellSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3ibkszpJEu3)</span></b>
```go ```go
package main package main
@@ -250,15 +250,15 @@ func main() {
### <span id="QuickSort">QuickSort</span> ### <span id="QuickSort">QuickSort</span>
<p>快速排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>快速排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator) func QuickSort[T any](slice []T comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7Y7c1Elk3ax)</span></b>
```go ```go
package main package main
@@ -298,15 +298,15 @@ func main() {
### <span id="HeapSort">HeapSort</span> ### <span id="HeapSort">HeapSort</span>
<p>堆排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>堆排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) func HeapSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/u6Iwa1VZS_f)</span></b>
```go ```go
package main package main
@@ -346,15 +346,15 @@ func main() {
### <span id="MergeSort">MergeSort</span> ### <span id="MergeSort">MergeSort</span>
<p>归并排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>归并排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) func MergeSort[T any](slice []T, comparator constraints.Comparator)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ydinn9YzUJn)</span></b>
```go ```go
package main package main
@@ -394,15 +394,15 @@ func main() {
### <span id="CountSort">CountSort</span> ### <span id="CountSort">CountSort</span>
<p>计数排序参数comparator需要实现包lancetconstraints.Comparator。</p> <p>计数排序参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func CountSort[T any](slice []T, comparator constraints.Comparator) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tB-Umgm0DrP)</span></b>
```go ```go
package main package main
@@ -443,15 +443,15 @@ func main() {
### <span id="BinarySearch">BinarySearch</span> ### <span id="BinarySearch">BinarySearch</span>
<p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator。</p> <p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int func BinarySearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/t6MeGiUSN47)</span></b>
```go ```go
package main package main
@@ -494,15 +494,15 @@ func main() {
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span> ### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator。</p> <p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包constraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int func BinaryIterativeSearch[T any](sortedSlice []T, target T, lowIndex, highIndex int, comparator constraints.Comparator) int
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Anozfr8ZLH3)</span></b>
```go ```go
package main package main
@@ -553,7 +553,7 @@ func main() {
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IsS7rgn5s3x)</span></b>
```go ```go
package main package main
@@ -596,7 +596,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int func (l *LRUCache[K, V]) Len() int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/-EZjgOURufP)</span></b>
```go ```go
package main package main

View File

@@ -30,10 +30,12 @@ import (
- [GreaterThan](#GreaterThan) - [GreaterThan](#GreaterThan)
- [LessOrEqual](#LessOrEqual) - [LessOrEqual](#LessOrEqual)
- [GreaterOrEqual](#GreaterOrEqual) - [GreaterOrEqual](#GreaterOrEqual)
- [InDelta](#InDelta)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## 文档
### <span id="Equal">Equal</span> ### <span id="Equal">Equal</span>
@@ -45,7 +47,7 @@ import (
func Equal(left, right any) bool func Equal(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wmVxR-to4lz)</span></b>
```go ```go
package main package main
@@ -94,7 +96,7 @@ func main() {
func EqualValue(left, right any) bool func EqualValue(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fxnna_LLD9u)</span></b>
```go ```go
package main package main
@@ -133,7 +135,7 @@ func main() {
func LessThan(left, right any) bool func LessThan(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cYh7FQQj0ne)</span></b>
```go ```go
package main package main
@@ -182,7 +184,7 @@ func main() {
func GreaterThan(left, right any) bool func GreaterThan(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9-NYDFZmIMp)</span></b>
```go ```go
package main package main
@@ -234,7 +236,7 @@ func main() {
func LessOrEqual(left, right any) bool func LessOrEqual(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/e4T_scwoQzp)</span></b>
```go ```go
package main package main
@@ -283,7 +285,7 @@ func main() {
func GreaterOrEqual(left, right any) bool func GreaterOrEqual(left, right any) bool
``` ```
<b>示例:</b> <b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vx8mP0U8DFk)</span></b>
```go ```go
package main package main
@@ -324,3 +326,50 @@ func main() {
// false // false
} }
``` ```
### <span id="InDelta">InDelta</span>
<p>检查增量内两个值是否相等。</p>
<b>函数签名:</b>
```go
func InDelta[T constraints.Integer | constraints.Float](left, right T, delta float64) bool
```
<b>示例: <span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TuDdcNtMkjo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := InDelta(1, 1, 0)
result2 := InDelta(1, 2, 0)
result3 := InDelta(2.0/3.0, 0.66667, 0.001)
result4 := InDelta(2.0/3.0, 0.0, 0.001)
result5 := InDelta(float64(74.96)-float64(20.48), 54.48, 0)
result6 := InDelta(float64(74.96)-float64(20.48), 54.48, 1e-14)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// false
// true
// false
// false
// true
}
```

View File

@@ -1,15 +1,17 @@
# Concurrency # Concurrency
并发包包含一些支持并发编程的功能。例如goroutine, channel等。
并发包包含一些支持并发编程的功能。例如goroutine, channel 等。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go) - [https://github.com/duke-git/lancet/blob/main/concurrency/channel.go](https://github.com/duke-git/lancet/blob/main/concurrency/channel.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/concurrency" "github.com/duke-git/lancet/v2/concurrency"
@@ -19,25 +21,28 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
### Channel ### Channel
- [NewChannel](#NewChannel)
- [Bridge](#Bridge) - [NewChannel](#NewChannel)
- [FanIn](#FanIn) - [Bridge](#Bridge)
- [Generate](#Generate) - [FanIn](#FanIn)
- [Or](#Or) - [Generate](#Generate)
- [OrDone](#OrDone) - [Or](#Or)
- [Repeat](#Repeat) - [OrDone](#OrDone)
- [RepeatFn](#RepeatFn) - [Repeat](#Repeat)
- [Take](#Take) - [RepeatFn](#RepeatFn)
- [Tee](#Tee) - [Take](#Take)
- [Tee](#Tee)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### Channel ### Channel
### <span id="NewChannel">NewChannel</span> ### <span id="NewChannel">NewChannel</span>
<p>返回一个Channel指针实例</p> <p>返回一个Channel指针实例</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -46,7 +51,8 @@ import (
type Channel[T any] struct type Channel[T any] struct
func NewChannel[T any]() *Channel[T] func NewChannel[T any]() *Channel[T]
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go ```go
package main package main
@@ -70,7 +76,8 @@ func main() {
```go ```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qmWSy1NVF-Y)</span></b>
```go ```go
package main package main
@@ -122,7 +129,8 @@ func main() {
```go ```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2VYFMexEvTm)</span></b>
```go ```go
package main package main
@@ -161,7 +169,8 @@ func main() {
```go ```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7aB4KyMMp9A)</span></b>
```go ```go
package main package main
@@ -199,7 +208,8 @@ func main() {
```go ```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/k5N_ALVmYjE)</span></b>
```go ```go
package main package main
@@ -238,7 +248,8 @@ func main() {
```go ```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4J1zAWttP85)</span></b>
```go ```go
package main package main
@@ -279,7 +290,8 @@ func main() {
```go ```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Wqz9rwioPww)</span></b>
```go ```go
package main package main
@@ -322,7 +334,8 @@ func main() {
```go ```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lm_GoS6aDjo)</span></b>
```go ```go
package main package main
@@ -360,7 +373,8 @@ func main() {
```go ```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9Utt-1pDr2J)</span></b>
```go ```go
package main package main
@@ -406,7 +420,8 @@ func main() {
```go ```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3TQPKnCirrP)</span></b>
```go ```go
package main package main
@@ -436,4 +451,4 @@ func main() {
// 1 // 1
// 1 // 1
} }
``` ```

View File

@@ -18,7 +18,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## 目录
- [Bool](#Bool) - [Bool](#Bool)
- [And](#And) - [And](#And)
@@ -31,7 +31,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 文档
### <span id="Bool">Bool</span> ### <span id="Bool">Bool</span>
<p>返回传入参数的bool值.<br/> <p>返回传入参数的bool值.<br/>
@@ -45,7 +45,7 @@ slices和map的length大于0时返回true否则返回false<br/>
```go ```go
func Bool[T any](value T) bool func Bool[T any](value T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ETzeDJRSvhm)</span></b>
```go ```go
package main package main
@@ -109,7 +109,7 @@ func main() {
```go ```go
func And[T, U any](a T, b U) bool func And[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/W1SSUmt6pvr)</span></b>
```go ```go
package main package main
@@ -135,7 +135,7 @@ func main() {
```go ```go
func Or[T, U any](a T, b U) bool func Or[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UlQTxHaeEkq)</span></b>
```go ```go
package main package main
@@ -161,7 +161,7 @@ func main() {
```go ```go
func Xor[T, U any](a T, b U) bool func Xor[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gObZrW7ZbG8)</span></b>
```go ```go
package main package main
@@ -187,7 +187,7 @@ func main() {
```go ```go
func Nor[T, U any](a T, b U) bool func Nor[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g2j08F_zZky)</span></b>
```go ```go
package main package main
@@ -213,7 +213,7 @@ func main() {
```go ```go
func Xnor[T, U any](a T, b U) bool func Xnor[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OuDB9g51643)</span></b>
```go ```go
package main package main
@@ -239,7 +239,7 @@ func main() {
```go ```go
func Nand[T, U any](a T, b U) bool func Nand[T, U any](a T, b U) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vSRMLxLIbq8)</span></b>
```go ```go
package main package main
@@ -265,7 +265,7 @@ func main() {
```go ```go
func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U func TernaryOperator[T, U any](isTrue T, ifValue U, elseValue U) U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ElllPZY0guT)</span></b>
```go ```go
package main package main

View File

@@ -41,6 +41,12 @@ import (
- [DeepClone](#DeepClone) - [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties) - [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface) - [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
- [ToStdBase64](#ToStdBase64)
- [ToUrlBase64](#ToUrlBase64)
- [ToRawStdBase64](#ToRawStdBase64)
- [ToRawUrlBase64](#ToRawUrlBase64)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -56,7 +62,7 @@ import (
func ColorHexToRGB(colorHex string) (red, green, blue int) func ColorHexToRGB(colorHex string) (red, green, blue int)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/o7_ft-JCJBV)</span></b>
```go ```go
package main package main
@@ -87,7 +93,7 @@ func main() {
func ColorRGBToHex(red, green, blue int) string func ColorRGBToHex(red, green, blue int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nzKS2Ro87J1)</span></b>
```go ```go
package main package main
@@ -120,7 +126,7 @@ func main() {
func ToBool(s string) (bool, error) func ToBool(s string) (bool, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ARht2WnGdIN)</span></b>
```go ```go
package main package main
@@ -161,7 +167,7 @@ func main() {
func ToBytes(data any) ([]byte, error) func ToBytes(data any) ([]byte, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fAMXYFDvOvr)</span></b>
```go ```go
package main package main
@@ -194,7 +200,7 @@ func main() {
func ToChar(s string) []string func ToChar(s string) []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JJ1SvbFkVdM)</span></b>
```go ```go
package main package main
@@ -230,7 +236,7 @@ func main() {
func ToChannel[T any](array []T) <-chan T func ToChannel[T any](array []T) <-chan T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hOx_oYZbAnL)</span></b>
```go ```go
package main package main
@@ -267,7 +273,7 @@ func main() {
func ToFloat(value any) (float64, error) func ToFloat(value any) (float64, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4YTmPCibqHJ)</span></b>
```go ```go
package main package main
@@ -312,7 +318,7 @@ func main() {
func ToInt(value any) (int64, error) func ToInt(value any) (int64, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9_h9vIt-QZ_b)</span></b>
```go ```go
package main package main
@@ -354,7 +360,7 @@ func main() {
func ToJson(value any) (string, error) func ToJson(value any) (string, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2rLIkMmXWvR)</span></b>
```go ```go
package main package main
@@ -389,7 +395,7 @@ func main() {
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tVFy7E-t24l)</span></b>
```go ```go
package main package main
@@ -430,7 +436,7 @@ func main() {
func ToPointer[T any](value T) *T func ToPointer[T any](value T) *T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ASf_etHNlw1)</span></b>
```go ```go
package main package main
@@ -459,7 +465,7 @@ func main() {
func ToString(value any) string func ToString(value any) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nF1zOOslpQq)</span></b>
```go ```go
package main package main
@@ -507,7 +513,7 @@ func main() {
func StructToMap(value any) (map[string]any, error) func StructToMap(value any) (map[string]any, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KYGYJqNUBOI)</span></b>
```go ```go
package main package main
@@ -545,7 +551,7 @@ func main() {
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dmX4Ix5V6Wl)</span></b>
```go ```go
package main package main
@@ -575,7 +581,7 @@ func main() {
func EncodeByte(data any) ([]byte, error) func EncodeByte(data any) ([]byte, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DVmM1G5JfuP)</span></b>
```go ```go
package main package main
@@ -604,7 +610,7 @@ func main() {
func DecodeByte(data []byte, target any) error func DecodeByte(data []byte, target any) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
```go ```go
package main package main
@@ -640,7 +646,7 @@ func main() {
func DeepClone[T any](src T) T func DeepClone[T any](src T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/j4DP5dquxnk)</span></b>
```go ```go
package main package main
@@ -704,7 +710,7 @@ func main() {
func CopyProperties[T, U any](dst T, src U) (err error) func CopyProperties[T, U any](dst T, src U) (err error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/oZujoB5Sgg5)</span></b>
```go ```go
package main package main
@@ -783,7 +789,7 @@ func main() {
func ToInterface(v reflect.Value) (value interface{}, ok bool) func ToInterface(v reflect.Value) (value interface{}, ok bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/syqw0-WG7Xd)</span></b>
```go ```go
package main package main
@@ -795,15 +801,351 @@ import (
func main() { func main() {
val := reflect.ValueOf("abc") val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val) iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal) fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal) fmt.Printf("%v\n", iVal)
fmt.Println(ok) fmt.Println(ok)
// Output: // Output:
// string // string
// abc // abc
// true // true
} }
``` ```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>utf8编码转GBK编码。</p>
<b>函数签名:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9FlIaFLArIL)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>GBK编码转utf8编码。</p>
<b>函数签名:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OphmHCN_9u8)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
```
### <span id="ToStdBase64">ToStdBase64</span>
<p>将值转换为StdBase64编码的字符串。error类型的数据也会把error的原因进行编码复杂的结构会转为JSON格式的字符串</p>
<b>函数签名:</b>
```go
func ToStdBase64(value any) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_fLJqJD3NMo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
afterEncode := convertor.ToStdBase64(nil)
fmt.Println(afterEncode)
afterEncode = convertor.ToStdBase64("")
fmt.Println(afterEncode)
stringVal := "hello"
afterEncode = convertor.ToStdBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = convertor.ToStdBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = convertor.ToStdBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = convertor.ToStdBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = convertor.ToStdBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = convertor.ToStdBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = convertor.ToStdBase64(errVal)
fmt.Println(afterEncode)
// Output:
//
//
// aGVsbG8=
// aGVsbG8=
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
// MTIzLjQ1Ng==
// dHJ1ZQ==
// ZXJy
}
```
### <span id="ToUrlBase64">ToUrlBase64</span>
<p>值转换为 ToUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
<b>函数签名:</b>
```go
func ToUrlBase64(value any) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C_d0GlvEeUR)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
afterEncode := convertor.ToUrlBase64(nil)
fmt.Println(afterEncode)
stringVal := "hello"
afterEncode = convertor.ToUrlBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = convertor.ToUrlBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = convertor.ToUrlBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = convertor.ToUrlBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = convertor.ToUrlBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = convertor.ToUrlBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = convertor.ToUrlBase64(errVal)
fmt.Println(afterEncode)
// Output:
//
// aGVsbG8=
// aGVsbG8=
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ==
// MTIzLjQ1Ng==
// dHJ1ZQ==
// ZXJy
}
```
### <span id="ToRawStdBase64">ToRawStdBase64</span>
<p>值转换为 ToRawStdBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
<b>函数签名:</b>
```go
func ToRawStdBase64(value any) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wSAr3sfkDcv)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
stringVal := "hello"
afterEncode = convertor.ToRawStdBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = convertor.ToRawStdBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = convertor.ToRawStdBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = convertor.ToRawStdBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode := convertor.ToRawStdBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = convertor.ToRawStdBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = convertor.ToRawStdBase64(errVal)
fmt.Println(afterEncode)
// Output:
// aGVsbG8
// aGVsbG8
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
// MTIzLjQ1Ng
// dHJ1ZQ
// ZXJy
}
```
### <span id="ToRawUrlBase64">ToRawUrlBase64</span>
<p>值转换为 ToRawUrlBase64 编码的字符串。error 类型的数据也会把 error 的原因进行编码,复杂的结构会转为 JSON 格式的字符串</p>
<b>函数签名:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HwdDPFcza1O)</span></b>
```go
func ToRawUrlBase64(value any) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
stringVal := "hello"
afterEncode := convertor.ToRawUrlBase64(stringVal)
fmt.Println(afterEncode)
byteSliceVal := []byte("hello")
afterEncode = convertor.ToRawUrlBase64(byteSliceVal)
fmt.Println(afterEncode)
intVal := 123
afterEncode = convertor.ToRawUrlBase64(intVal)
fmt.Println(afterEncode)
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
A string
B int
}{"hello", 3}}
afterEncode = convertor.ToRawUrlBase64(mapVal)
fmt.Println(afterEncode)
floatVal := 123.456
afterEncode = convertor.ToRawUrlBase64(floatVal)
fmt.Println(afterEncode)
boolVal := true
afterEncode = convertor.ToRawUrlBase64(boolVal)
fmt.Println(afterEncode)
errVal := errors.New("err")
afterEncode = convertor.ToRawUrlBase64(errVal)
fmt.Println(afterEncode)
// Output:
// aGVsbG8
// aGVsbG8
// MTIz
// eyJhIjoiaGkiLCJiIjoyLCJjIjp7IkEiOiJoZWxsbyIsIkIiOjN9fQ
// MTIzLjQ1Ng
// dHJ1ZQ
// ZXJy
}
```

View File

@@ -1,16 +1,18 @@
# Cryptor # Cryptor
cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。
cryptor 包包含数据加密和解密功能。支持 base64, md5, hmac, hash, aes, des, rsa。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go) - [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go) - [https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/main/cryptor/crypto.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/cryptor" "github.com/duke-git/lancet/v2/cryptor"
@@ -20,46 +22,57 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [AesEcbEncrypt](#AesEcbEncrypt)
- [AesEcbDecrypt](#AesEcbDecrypt)
- [AesCbcEncrypt](#AesCbcEncrypt)
- [AesCbcDecrypt](#AesCbcDecrypt)
- [AesCtrCrypt](#AesCtrCrypt)
- [AesCfbEncrypt](#AesCfbEncrypt)
- [AesCfbDecrypt](#AesCfbDecrypt)
- [AesOfbEncrypt](#AesOfbEncrypt)
- [AesOfbDecrypt](#AesOfbDecrypt)
- [Base64StdEncode](#Base64StdEncode)
- [Base64StdDecode](#Base64StdDecode)
- [DesEcbEncrypt](#DesEcbEncrypt)
- [DesEcbDecrypt](#DesEcbDecrypt)
- [DesCbcEncrypt](#DesCbcEncrypt)
- [DesCbcDecrypt](#DesCbcDecrypt)
- [DesCtrCrypt](#DesCtrCrypt)
- [DesCfbEncrypt](#DesCfbEncrypt)
- [DesCfbDecrypt](#DesCfbDecrypt)
- [DesOfbEncrypt](#DesOfbEncrypt)
- [DesOfbDecrypt](#DesOfbDecrypt)
- [HmacMd5](#HmacMd5)
- [HmacSha1](#HmacSha1)
- [HmacSha256](#HmacSha256)
- [HmacSha512](#HmacSha512)
- [Md5String](#Md5String)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha256](#Sha256)
- [Sha512](#Sha512)
- [GenerateRsaKey](#GenerateRsaKey)
- [RsaEncrypt](#RsaEncrypt)
- [RsaDecrypt](#RsaDecrypt)
- [AesEcbEncrypt](#AesEcbEncrypt)
- [AesEcbDecrypt](#AesEcbDecrypt)
- [AesCbcEncrypt](#AesCbcEncrypt)
- [AesCbcDecrypt](#AesCbcDecrypt)
- [AesCtrCrypt](#AesCtrCrypt)
- [AesCfbEncrypt](#AesCfbEncrypt)
- [AesCfbDecrypt](#AesCfbDecrypt)
- [AesOfbEncrypt](#AesOfbEncrypt)
- [AesOfbDecrypt](#AesOfbDecrypt)
- [Base64StdEncode](#Base64StdEncode)
- [Base64StdDecode](#Base64StdDecode)
- [DesEcbEncrypt](#DesEcbEncrypt)
- [DesEcbDecrypt](#DesEcbDecrypt)
- [DesCbcEncrypt](#DesCbcEncrypt)
- [DesCbcDecrypt](#DesCbcDecrypt)
- [DesCtrCrypt](#DesCtrCrypt)
- [DesCfbEncrypt](#DesCfbEncrypt)
- [DesCfbDecrypt](#DesCfbDecrypt)
- [DesOfbEncrypt](#DesOfbEncrypt)
- [DesOfbDecrypt](#DesOfbDecrypt)
- [HmacMd5](#HmacMd5)
- [HmacMd5WithBase64](#HmacMd5WithBase64)
- [HmacSha1](#HmacSha1)
- [HmacSha1WithBase64](#HmacSha1WithBase64)
- [HmacSha256](#HmacSha256)
- [HmacSha256WithBase64](#HmacSha256WithBase64)
- [HmacSha512](#HmacSha512)
- [HmacSha512WithBase64](#HmacSha512WithBase64)
- [Md5String](#Md5String)
- [Md5StringWithBase64](#Md5StringWithBase64)
- [Md5Byte](#Md5Byte)
- [Md5ByteWithBase64](#Md5ByteWithBase64)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha1WithBase64](#Sha1WithBase64)
- [Sha256](#Sha256)
- [Sha256WithBase64](#Sha256WithBase64)
- [Sha512](#Sha512)
- [Sha512WithBase64](#Sha512WithBase64)
- [GenerateRsaKey](#GenerateRsaKey)
- [RsaEncrypt](#RsaEncrypt)
- [RsaDecrypt](#RsaDecrypt)
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
- [RsaEncryptOAEP](#RsaEncryptOAEP)
- [RsaDecryptOAEP](#RsaDecryptOAEP)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="AesEcbEncrypt">AesEcbEncrypt</span> ### <span id="AesEcbEncrypt">AesEcbEncrypt</span>
<p>使用AES ECB算法模式加密数据. 参数`key`的长度是16, 24 or 32。</p> <p>使用AES ECB算法模式加密数据. 参数`key`的长度是16, 24 or 32。</p>
@@ -69,7 +82,8 @@ import (
```go ```go
func AesEcbEncrypt(data, key []byte) []byte func AesEcbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
```go ```go
package main package main
@@ -102,7 +116,8 @@ func main() {
```go ```go
func AesEcbDecrypt(encrypted, key []byte) []byte func AesEcbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zI6xsmuQRbn)</span></b>
```go ```go
package main package main
@@ -135,7 +150,8 @@ func main() {
```go ```go
func AesCbcEncrypt(data, key []byte) []byte func AesCbcEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOq_g8_lKZD)</span></b>
```go ```go
package main package main
@@ -169,7 +185,7 @@ func main() {
func AesCbcDecrypt(encrypted, key []byte) []byte func AesCbcDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOq_g8_lKZD)</span></b>
```go ```go
package main package main
@@ -203,7 +219,7 @@ func main() {
func AesCtrCrypt(data, key []byte) []byte func AesCtrCrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/SpaZO0-5Nsp)</span></b>
```go ```go
package main package main
@@ -237,7 +253,7 @@ func main() {
func AesCfbEncrypt(data, key []byte) []byte func AesCfbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tfkF10B13kH)</span></b>
```go ```go
package main package main
@@ -271,7 +287,7 @@ func main() {
func AesCfbDecrypt(encrypted, key []byte) []byte func AesCfbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tfkF10B13kH)</span></b>
```go ```go
package main package main
@@ -305,7 +321,7 @@ func main() {
func AesOfbEncrypt(data, key []byte) []byte func AesOfbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VtHxtkUj-3F)</span></b>
```go ```go
package main package main
@@ -328,6 +344,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="AesCfbDecrypt">AesOfbDecrypt</span> ### <span id="AesCfbDecrypt">AesOfbDecrypt</span>
<p>使用AES OFB算法模式解密数据参数`key`的长度是16, 24 or 32。</p> <p>使用AES OFB算法模式解密数据参数`key`的长度是16, 24 or 32。</p>
@@ -338,7 +355,7 @@ func main() {
func AesOfbDecrypt(encrypted, key []byte) []byte func AesOfbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VtHxtkUj-3F)</span></b>
```go ```go
package main package main
@@ -371,7 +388,8 @@ func main() {
```go ```go
func Base64StdEncode(s string) string func Base64StdEncode(s string) string
``` ```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VOaUyQUreoK)</span></b>
```go ```go
package main package main
@@ -389,6 +407,7 @@ func main() {
// aGVsbG8= // aGVsbG8=
} }
``` ```
### <span id="Base64StdDecode">Base64StdDecode</span> ### <span id="Base64StdDecode">Base64StdDecode</span>
<p>解码base64字符串。</p> <p>解码base64字符串。</p>
@@ -399,7 +418,7 @@ func main() {
func Base64StdDecode(s string) string func Base64StdDecode(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RWQylnJVgIe)</span></b>
```go ```go
package main package main
@@ -428,7 +447,7 @@ func main() {
func DesEcbEncrypt(data, key []byte) []byte func DesEcbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8qivmPeZy4P)</span></b>
```go ```go
package main package main
@@ -452,6 +471,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="DesEcbDecrypt">DesEcbDecrypt</span> ### <span id="DesEcbDecrypt">DesEcbDecrypt</span>
<p>使用DES ECB算法模式解决密数据参数`key`的长度是8。</p> <p>使用DES ECB算法模式解决密数据参数`key`的长度是8。</p>
@@ -462,7 +482,7 @@ func main() {
func DesEcbDecrypt(encrypted, key []byte) []byte func DesEcbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8qivmPeZy4P)</span></b>
```go ```go
package main package main
@@ -497,7 +517,7 @@ func main() {
func DesCbcEncrypt(data, key []byte) []byte func DesCbcEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4cC4QvWfe3_1)</span></b>
```go ```go
package main package main
@@ -531,7 +551,7 @@ func main() {
func DesCbcDecrypt(encrypted, key []byte) []byte func DesCbcDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4cC4QvWfe3_1)</span></b>
```go ```go
package main package main
@@ -554,6 +574,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="DesCtrCrypt">DesCtrCrypt</span> ### <span id="DesCtrCrypt">DesCtrCrypt</span>
<p>使用DES CTR算法模式加密/解密数据,参数`key`的长度是8</p> <p>使用DES CTR算法模式加密/解密数据,参数`key`的长度是8</p>
@@ -564,7 +585,7 @@ func main() {
func DesCtrCrypt(data, key []byte) []byte func DesCtrCrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9-T6OjKpcdw)</span></b>
```go ```go
package main package main
@@ -598,7 +619,7 @@ func main() {
func DesCfbEncrypt(data, key []byte) []byte func DesCfbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/y-eNxcFBlxL)</span></b>
```go ```go
package main package main
@@ -621,6 +642,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="DesCfbDecrypt">DesCfbDecrypt</span> ### <span id="DesCfbDecrypt">DesCfbDecrypt</span>
<p>使用DES CFB算法模式解决密数据参数`key`的长度是8。</p> <p>使用DES CFB算法模式解决密数据参数`key`的长度是8。</p>
@@ -631,7 +653,7 @@ func main() {
func DesCfbDecrypt(encrypted, key []byte) []byte func DesCfbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/y-eNxcFBlxL)</span></b>
```go ```go
package main package main
@@ -654,6 +676,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="DesOfbEncrypt">DesOfbEncrypt</span> ### <span id="DesOfbEncrypt">DesOfbEncrypt</span>
<p>使用DES OFB算法模式加密数据参数`key`的长度是8。</p> <p>使用DES OFB算法模式加密数据参数`key`的长度是8。</p>
@@ -664,7 +687,7 @@ func main() {
func DesOfbEncrypt(data, key []byte) []byte func DesOfbEncrypt(data, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/74KmNadjN1J)</span></b>
```go ```go
package main package main
@@ -687,6 +710,7 @@ func main() {
// hello // hello
} }
``` ```
### <span id="DesOfbDecrypt">DesOfbDecrypt</span> ### <span id="DesOfbDecrypt">DesOfbDecrypt</span>
<p>使用DES OFB算法模式解密数据参数`key`的长度是8。</p> <p>使用DES OFB算法模式解密数据参数`key`的长度是8。</p>
@@ -697,7 +721,7 @@ func main() {
func DesOfbDecrypt(encrypted, key []byte) []byte func DesOfbDecrypt(encrypted, key []byte) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/74KmNadjN1J)</span></b>
```go ```go
package main package main
@@ -728,10 +752,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HmacMd5(data, key string) string func HmacMd5(str, key string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
```go ```go
package main package main
@@ -742,7 +766,7 @@ import (
) )
func main() { func main() {
str := "hello" str := "hello"
key := "12345" key := "12345"
hms := cryptor.HmacMd5(str, key) hms := cryptor.HmacMd5(str, key)
@@ -752,17 +776,50 @@ func main() {
// e834306eab892d872525d4918a7a639a // e834306eab892d872525d4918a7a639a
} }
``` ```
### <span id="HmacSha1">HmacSha1</span>
<p>获取字符串sha1 hmac值。</p> ### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
<p>获取字符串md5 hmac base64字符串值。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HmacSha1(data, key string) string func HmacMd5WithBase64(str, key string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UY0ng2AefFC)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacMd5WithBase64(str, key)
fmt.Println(hms)
// Output:
// 6DQwbquJLYclJdSRinpjmg==
}
```
### <span id="HmacSha1">HmacSha1</span>
<p>获取字符串的sha1 hmac值。</p>
<b>函数签名:</b>
```go
func HmacSha1(str, key string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1UI4oQ4WXKM)</span></b>
```go ```go
package main package main
@@ -783,6 +840,39 @@ func main() {
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0 // 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
} }
``` ```
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
<p>获取字符串的sha1 base64值。</p>
<b>函数签名:</b>
```go
func HmacSha1WithBase64(str, key string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/47JmmGrnF7B)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha1WithBase64(str, key)
fmt.Println(hms)
// Output:
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
}
```
### <span id="HmacSha256">HmacSha256</span> ### <span id="HmacSha256">HmacSha256</span>
<p>获取字符串sha256 hmac值。</p> <p>获取字符串sha256 hmac值。</p>
@@ -790,10 +880,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HmacSha256(data, key string) string func HmacSha256(str, key string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HhpwXxFhhC0)</span></b>
```go ```go
package main package main
@@ -815,6 +905,38 @@ func main() {
} }
``` ```
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
<p>获取字符串sha256 hmac base64值。</p>
<b>函数签名:</b>
```go
func HmacSha256WithBase64(str, key string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EKbkUvPTLwO)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha256WithBase64(str, key)
fmt.Println(hms)
// Output:
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
}
```
### <span id="HmacSha512">HmacSha512</span> ### <span id="HmacSha512">HmacSha512</span>
<p>获取字符串sha512 hmac值。</p> <p>获取字符串sha512 hmac值。</p>
@@ -822,10 +944,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HmacSha512(data, key string) string func HmacSha512(str, key string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/59Od6m4A0Ud)</span></b>
```go ```go
package main package main
@@ -847,6 +969,37 @@ func main() {
} }
``` ```
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
<p>获取字符串sha512 hmac base64值。</p>
<b>函数签名:</b>
```go
func HmacSha512WithBase64(str, key string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/c6dSe3E2ydU)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
str := "hello"
key := "12345"
hms := cryptor.HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
```
### <span id="Md5String">Md5String</span> ### <span id="Md5String">Md5String</span>
@@ -855,10 +1008,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Md5String(s string) string func Md5String(str string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1bLcVetbTOI)</span></b>
```go ```go
package main package main
@@ -879,6 +1032,93 @@ func main() {
} }
``` ```
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
<p>获取字符串md5 base64值。</p>
<b>函数签名:</b>
```go
func Md5StringWithBase64(s string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Tcb-Z7LN2ax)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5StringWithBase64("hello")
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5Byte">Md5Byte</span>
<p>获取byte slice的md5值。</p>
<b>函数签名:</b>
```go
func Md5Byte(data []byte) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/suraalH8lyC)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5Byte([]byte{'a'})
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
```
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
<p>获取byte slice的md5 base64值。</p>
<b>函数签名:</b>
```go
func Md5ByteWithBase64(data []byte) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Lx4gH7Vdr5_y)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
### <span id="Md5File">Md5File</span> ### <span id="Md5File">Md5File</span>
<p>获取文件md5值。</p> <p>获取文件md5值。</p>
@@ -912,10 +1152,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Sha1(data string) string func Sha1(str string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_m_uoD1deMT)</span></b>
```go ```go
package main package main
@@ -936,6 +1176,35 @@ func main() {
} }
``` ```
### <span id="Sha1WithBase64">Sha1WithBase64</span>
<p>获取字符串sha1 base64值。</p>
<b>函数签名:</b>
```go
func Sha1WithBase64(str string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fSyx-Gl2l2-)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha1WithBase64("hello")
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
```
### <span id="Sha256">Sha256</span> ### <span id="Sha256">Sha256</span>
<p>获取字符串sha256值。</p> <p>获取字符串sha256值。</p>
@@ -943,10 +1212,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Sha256(data string) string func Sha256(str string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tU9tfBMIAr1)</span></b>
```go ```go
package main package main
@@ -967,6 +1236,35 @@ func main() {
} }
``` ```
### <span id="Sha256WithBase64">Sha256WithBase64</span>
<p>获取字符串sha256 base64值。</p>
<b>函数签名:</b>
```go
func Sha256WithBase64(str string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/85IXJHIal1k)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha256WithBase64("hello")
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
```
### <span id="Sha512">Sha512</span> ### <span id="Sha512">Sha512</span>
<p>获取字符串sha512值。</p> <p>获取字符串sha512值。</p>
@@ -974,10 +1272,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Sha512(data string) string func Sha512(str string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3WsvLYZxsHa)</span></b>
```go ```go
package main package main
@@ -998,6 +1296,35 @@ func main() {
} }
``` ```
### <span id="Sha512WithBase64">Sha512WithBase64</span>
<p>获取字符串sha512 base64值。</p>
<b>函数签名:</b>
```go
func Sha512WithBase64(str string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q_fY2rA-k5I)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
result := cryptor.Sha512WithBase64("hello")
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}
```
### <span id="GenerateRsaKey">GenerateRsaKey</span> ### <span id="GenerateRsaKey">GenerateRsaKey</span>
<p>在当前目录下创建rsa私钥文件和公钥文件。</p> <p>在当前目录下创建rsa私钥文件和公钥文件。</p>
@@ -1008,7 +1335,7 @@ func main() {
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zutRHrDqs0X)</span></b>
```go ```go
package main package main
@@ -1036,7 +1363,7 @@ func main() {
func RsaEncrypt(data []byte, pubKeyFileName string) []byte func RsaEncrypt(data []byte, pubKeyFileName string) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
```go ```go
package main package main
@@ -1051,11 +1378,11 @@ func main() {
if err != nil { if err != nil {
return return
} }
data := []byte("hello") data := []byte("hello")
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem") encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem") decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted)) fmt.Println(string(decrypted))
// Output: // Output:
@@ -1063,7 +1390,6 @@ func main() {
} }
``` ```
### <span id="RsaDecrypt">RsaDecrypt</span> ### <span id="RsaDecrypt">RsaDecrypt</span>
<p>用私钥文件rsa解密数据。</p> <p>用私钥文件rsa解密数据。</p>
@@ -1074,7 +1400,7 @@ func main() {
func RsaDecrypt(data []byte, privateKeyFileName string) []byte func RsaDecrypt(data []byte, privateKeyFileName string) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uef0q1fz53I)</span></b>
```go ```go
package main package main
@@ -1089,14 +1415,125 @@ func main() {
if err != nil { if err != nil {
return return
} }
data := []byte("hello") data := []byte("hello")
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem") encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem") decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted)) fmt.Println(string(decrypted))
// Output: // Output:
// hello // hello
} }
``` ```
### <span id="GenerateRsaKeyPair">GenerateRsaKeyPair</span>
<p>创建rsa公钥私钥和key。</p>
<b>函数签名:</b>
```go
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
pri, pub := cryptor.GenerateRsaKeyPair(1024)
}
```
### <span id="RsaEncryptOAEP">RsaEncryptOAEP</span>
<p>rsa OAEP加密。</p>
<b>函数签名:</b>
```go
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
pri, pub := cryptor.GenerateRsaKeyPair(1024)
data := []byte("hello world")
label := []byte("123456")
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
if err != nil {
return
}
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
if err != nil {
return
}
fmt.Println(string(decrypted))
// Output:
// hello world
}
```
### <span id="RsaDecryptOAEP">RsaDecryptOAEP</span>
<p>rsa OAEP解密。</p>
<b>函数签名:</b>
```go
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
pri, pub := cryptor.GenerateRsaKeyPair(1024)
data := []byte("hello world")
label := []byte("123456")
encrypted, err := cryptor.RsaEncryptOAEP(data, label, *pub)
if err != nil {
return
}
decrypted, err := cryptor.RsaDecryptOAEP([]byte(encrypted), label, *pri)
if err != nil {
return
}
fmt.Println(string(decrypted))
// Output:
// hello world
}
```

View File

@@ -0,0 +1,525 @@
# CopyOnWriteList
CopyOnWriteList 是一个线程安全的 List 实现,底层使用 go 切片。写入时,会复制一份新的切片,写入完成后,再将新的切片赋值给原来的切片。读取时,直接读取原来的切片。
## 源码
- [https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go](https://github.com/duke-git/lancet/blob/main/datastructure/list/copyonwritelist.go)
## 用法
```go
import (
"github.com/duke-git/lancet/datastructure/list"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [NewCopyOnWriteList](#NewCopyOnWriteList)
- [Size](#Size)
- [Get](#Get)
- [Set](#Set)
- [Remove](#Remove)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [IndexOfFunc](#IndexOfFunc)
- [LastIndexOfFunc](#LastIndexOfFunc)
- [IsEmpty](#IsEmpty)
- [Contain](#Contain)
- [ValueOf](#ValueOf)
- [Add](#Add)
- [AddAll](#AddAll)
- [AddByIndex](#AddByIndex)
- [DeleteAt](#DeleteAt)
- [DeleteIf](#DeleteIf)
- [DeleteBy](#DeleteBy)
- [DeleteRange](#DeleteRange)
- [Equal](#Equal)
## 文档
### NewCopyOnWriteList
返回一个具有空切片的 CopyOnWriteList。
```go
type CopyOnWriteList[T any] struct {
data []T
lock sync.Locker
}
func NewCopyOnWriteList() *CopyOnWriteList
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l)
}
```
### Size
返回 CopyOnWriteList 的长度。
```go
func (l *CopyOnWriteList[T]) Size() int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Size())
}
```
### Get
返回列表中指定位置的元素
```go
func (c *CopyOnWriteList[T]) Get(index int) *T
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Get(2))
}
```
### Set
将此列表中指定位置的元素替换为指定元素。
```go
func (c *CopyOnWriteList[T]) Set(index int, e T) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Set(2, 4))
}
```
### Remove
### IndexOf
返回列表中值的索引,如果没有找到返回-1。
```go
func (c *CopyOnWriteList[T]) IndexOf(e T) int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.IndexOf(1))
}
```
### LastIndexOf
返回指定元素在此列表中最后出现的索引,如果此列表不包含该元素,则返回-1。
```go
func (c *CopyOnWriteList[T]) LastIndexOf(e T) int
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,1})
fmt.Println(l.LastIndexOf(1))
}
```
### <span id="IndexOfFunc">IndexOfFunc</span>
<p>返回第一个满足判断函数f(v)的元素的索引,如果找不到则返回-1。</p>
<b>函数签名:</b>
```go
func (l *CopyOnWriteList[T]) IndexOfFunc(f func(T) bool) int
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1, 2, 3})
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 1 })) //0
fmt.Println(l.IndexOfFunc(func(a int) bool { return a == 0 })) //-1
}
```
### <span id="LastIndexOfFunc">LastIndexOfFunc</span>
<p>返回最后一个满足判断函数f(v)的元素的索引,如果找不到则返回-1。</p>
<b>函数签名:</b>
```go
func (l *CopyOnWriteList[T]) LastIndexOfFunc(f func(T) bool) int
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1, 2, 3, 1})
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 1 })) // 3
fmt.Println(l.LastIndexOfFunc(func(a int) bool { return a == 0 })) //-1
}
```
### IsEmpty
如果此列表不包含任何元素,则返回 true。
```go
func (c *CopyOnWriteList[T]) IsEmpty() bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{})
fmt.Println(l.IsEmpty())
}
```
### Contain
判断 CopyOnWriteList 是否包含某个元素
```go
func (c *CopyOnWriteList[T]) Contain(e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.Contain(1))
}
```
### ValueOf
返回列表中索引处的值指针
```go
func (c *CopyOnWriteList[T]) ValueOf(index int) []T
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
fmt.Println(l.ValueOf(2))
}
```
### Add
将指定的元素追加到此列表的末尾。
```go
func (c *CopyOnWriteList[T]) Add(e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.Add(4)
fmt.Println(l.getList())
}
```
### AddAll
将指定集合中的所有元素追加到此列表的末尾
```go
func (c *CopyOnWriteList[T]) AddAll(e []T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
l.AddAll([]int{4,5,6})
fmt.Println(l.getList())
}
```
### AddByIndex
将指定元素插入此列表中的指定位置。
```go
func (c *CopyOnWriteList[T]) AddByIndex(index int, e T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.AddByIndex(2, 6)
fmt.Println(l.getList())
}
```
### DeleteAt
移除此列表中指定位置的元素。
```go
func (c *CopyOnWriteList[T]) DeleteAt(index int) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteAt(2)
fmt.Println(l.getList())
}
```
### DeleteIf
从此列表中删除第一个出现的指定元素(如果该元素存在)。
```go
func (c *CopyOnWriteList[T]) DeleteIf(f func(T) bool) (oldValue *T, ok bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteIf(func(i int) bool {
return i == 2
})
fmt.Println(l.getList())
}
```
### DeleteBy
从此列表中删除第一个出现的指定元素(如果该元素存在)。
```go
func (c *CopyOnWriteList[T]) DeleteBy(e T) (*T bool)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3})
list.DeleteBy(2)
fmt.Println(l.getList())
}
```
### DeleteRange
从该列表中删除索引介于 fromIndex(包含)和 toIndex(不包含)之间的所有元素。
(左闭右开)。
```go
func (c *CopyOnWriteList[T]) DeleteRange(start int, end int)
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
list.DeleteRange(2, 5)
fmt.Println(l.getList())
}
```
### Equal
如果指定的对象等于此列表,则返回 true。
```go
func (c *CopyOnWriteList[T]) Equal(e []T) bool
```
#### 示例
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/datastructure/list"
)
func main() {
l := list.NewCopyOnWriteList([]int{1,2,3,4,5,6,7,8,9})
fmt.Println(l.Equal([]int{1,2,3,4,5,6,7,8,9}))
}
```

View File

@@ -31,6 +31,7 @@ import (
- [Iterate](#Iterate) - [Iterate](#Iterate)
- [Keys](#Keys) - [Keys](#Keys)
- [Values](#Values) - [Values](#Values)
- [FilterByValue](#FilterByValue)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -38,7 +39,7 @@ import (
### <span id="NewHashMap">NewHashMap</span> ### <span id="NewHashMap">NewHashMap</span>
<p>新建默认容量1 << 10的HashMap指针实例</p> <p>新建默认容量1 &lt&lt 10的HashMap指针实例</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -276,7 +277,7 @@ func main() {
### <span id="Values">Values</span> ### <span id="Values">Values</span>
<p>返回hashmap所有值的切片 (随机顺序).</p> <p>返回hashmap所有值的切片 (随机顺序)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -306,3 +307,40 @@ func main() {
``` ```
### <span id="FilterByValue">FilterByValue</span>
<p>返回一个过滤后的HashMap。 如果任何值与 perdicate 函数不匹配,则返回 nil否则返回包含选定值的 HashMap。</p>
<b>函数签名:</b>
```go
func (hm *HashMap) FilterByValue(perdicate func(value any) bool) *HashMap
```
<b>示例:</b>
```go
package main
import (
"fmt"
hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
)
func main() {
hm := hashmap.NewHashMap()
hm.Put("a", 1)
hm.Put("b", 2)
hm.Put("c", 3)
hm.Put("d", 4)
hm.Put("e", 5)
hm.Put("f", 6)
filteredHM := hm.FilterByValue(func(value any) bool {
return value.(int) == 1 || value.(int) == 3
})
fmt.Println(filteredHM.Size()) //2
}
```

View File

@@ -44,9 +44,9 @@ MaxHeap是通过slice实现的二叉堆树根节点的key既大于等于左
```go ```go
type MaxHeap[T any] struct { type MaxHeap[T any] struct {
data []T data []T
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] func NewMaxHeap[T any](comparator constraints.Comparator) *MaxHeap[T]
``` ```
<b>示例:</b> <b>示例:</b>

View File

@@ -0,0 +1,412 @@
# Optional
Optional类型代表一个可选的值它要么包含一个实际值要么为空。
<div STYLE="page-break-after: always;"></div>
## 源码
- [https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go](https://github.com/duke-git/lancet/blob/main/datastructure/optional/optional.go)
<div STYLE="page-break-after: always;"></div>
## 用法
```go
import (
"github.com/duke-git/lancet/v2/datastructure/optional"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Of](#Of)
- [FromNillable](#FromNillable)
- [Default](#Default)
- [IsNotNil](#IsNotNil)
- [IsNil](#IsNil)
- [IsNotNil](#IsNotNil)
- [IfNotNilOrElse](#IfNotNilOrElse)
- [Umwarp](#Umwarp)
- [OrElse](#OrElse)
- [OrElseGet](#OrElseGet)
- [OrElseTrigger](#OrElseTrigger)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Of">Of</span>
<p>返回一个包含非空值的Optional。</p>
<b>函数签名:</b>
```go
func Of[T any](value T) Optional[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
value := 42
opt := optional.Of(value)
fmt.Println(opt.Get())
// Output:
// 42
}
```
### <span id="FromNillable">FromNillable</span>
<p>返回一个包含给定值的Optional该值可能为空 (nil)。</p>
<b>函数签名:</b>
```go
func FromNillable[T any](value *T) Optional[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
var value *int = nil
opt := optional.FromNillable(value)
fmt.Println(opt.IsNotNil())
value = new(int)
*value = 42
opt = optional.FromNillable(value)
fmt.Println(opt.IsNotNil())
// Output:
// false
// true
}
```
### <span id="Default">Default</span>
<p>返回一个空Optional实例。</p>
<b>函数签名:</b>
```go
func Default[T any]() Optional[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
optDefault := optional.Default[int]()
fmt.Println(optDefault.IsNil())
// Output:
// true
}
```
### <span id="IsNil">IsNil</span>
<p>验证Optional是否为空。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) IsNil() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
optDefault := optional.Default[int]()
fmt.Println(optDefault.IsNil())
// Output:
// true
}
```
### <span id="IsNotNil">IsNotNil</span>
<p>检查当前Optional内是否存在值。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) IsNotNil() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
var value *int = nil
opt := optional.FromNillable(value)
fmt.Println(opt.IsNotNil())
value = new(int)
*value = 42
opt = optional.FromNillable(value)
fmt.Println(opt.IsNotNil())
// Output:
// false
// true
}
```
### <span id="IfNotNil">IfNotNil</span>
<p>如果值存在则使用action方法执行给定的操作。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) IfNotNil(action func(value T))
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
called := false
action := func(value int) { called = true }
optDefault := optional.Default[int]()
optDefault.IfNotNil(action)
fmt.Println(called)
called = false // Reset for next test
optWithValue := optional.Of(42)
optWithValue.IfNotNil(action)
fmt.Println(optWithValue.IsNotNil())
// Output:
// false
// true
}
```
### <span id="IfNotNilOrElse">IfNotNilOrElse</span>
<p>根据是否存在值执行相应的操作:有值则执行指定操作,没有值则执行默认操作。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) IfNotNilOrElse(action func(value T), fallbackAction func())
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
calledWithValue := false
valueAction := func(value int) { calledWithValue = true }
emptyAction := func() { t.Errorf("Empty action should not be called when value is present") }
optWithValue := optional.Of(42)
optWithValue.IfNotNilOrElse(valueAction, emptyAction)
fmt.Println(calledWithValue)
calledWithEmpty := false
valueAction = func(value int) { t.Errorf("Value action should not be called when value is not present") }
emptyAction = func() { calledWithEmpty = true }
optDefault := optional.Default[int]()
optDefault.IfNotNilOrElse(valueAction, emptyAction)
fmt.Println(calledWithEmpty)
// Output:
// true
// true
}
```
### <span id="Unwrap">Unwrap</span>
<p>如果存在返回该值否则引发panic。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) Unwrap() T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
value := 42
opt := optional.Of(value)
fmt.Println(opt.Unwrap())
// Output:
// 42
}
```
### <span id="OrElse">OrElse</span>
<p>检查Optional值是否存在如果存在则直接返回该值。如果不存在返回参数other值。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) OrElse(other T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
optDefault := optional.Empty[int]()
val := optDefault.OrElse(100)
fmt.Println(val)
optWithValue := optional.Of(42)
val = optWithValue.OrElse(100)
fmt.Println(val)
// Output:
// 100
// 42
}
```
### <span id="OrElseGet">OrElseGet</span>
<p>检查Optional值是否存在如果存在则直接返回该值。如果不存在则调用一个提供的函数 (supplier),并返回该函数的执行结果。</p>
<b>函数签名:</b>
```go
func (o Optional[T]) OrElseGet(action func() T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
optDefault := optional.Default[int]()
action := func() int { return 100 }
val := optDefault.OrElseGet(action)
fmt.Println(val)
// Output:
// 100
}
```
### <span id="OrElseTrigger">OrElseTrigger</span>
<p>检查Optional值是否存在如果存在则直接返回该值否则返回错误。</p>
<b>函数签名:</b>
```go
OrElseTrigger(errorHandler func() error) (T, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datastructure/optional"
)
func main() {
optDefault := optional.Default[int]()
_, err := optDefault.OrElseTrigger(func() error { return errors.New("no value") })
fmt.Println(err.Error())
optWithValue := optional.Of(42)
val, err := optWithValue.OrElseTrigger(func() error { return errors.New("no value") })
fmt.Println(val)
fmt.Println(err)
// Output:
// no value
// 42
// nil
}
```

View File

@@ -1100,12 +1100,12 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func NewPriorityQueue[T any](capacity int, comparator lancetconstraints.Comparator) *PriorityQueue[T] func NewPriorityQueue[T any](capacity int, comparator constraints.Comparator) *PriorityQueue[T]
type PriorityQueue[T any] struct { type PriorityQueue[T any] struct {
items []T items []T
size int size int
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
``` ```
<b>示例:</b> <b>示例:</b>

View File

@@ -1,6 +1,6 @@
# Set # Set
Set 集合数据结构类似列表。Set 中元素不重复。 集合数据结构类似列表。Set中元素不重复。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -22,8 +22,8 @@ import (
## 目录 ## 目录
- [NewSet](#NewSet) - [New](#New)
- [NewSetFromSlice](#NewSetFromSlice) - [FromSlice](#FromSlice)
- [Values](#Values) - [Values](#Values)
- [Add](#Add) - [Add](#Add)
- [AddIfNotExist](#AddIfNotExist) - [AddIfNotExist](#AddIfNotExist)
@@ -40,20 +40,23 @@ import (
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [SymmetricDifference](#SymmetricDifference) - [SymmetricDifference](#SymmetricDifference)
- [Minus](#Minus) - [Minus](#Minus)
- [Pop](#Pop)
- [ToSlice](#ToSlice)
- [ToSortedSlice](#ToSortedSlice)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="NewSet">NewSet</span> ### <span id="New">New</span>
<p>返回Set结构体对象</p> <p>返回Set结构体对象</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
type Set[T comparable] map[T]bool type Set[T comparable] map[T]struct{}
func NewSet[T comparable](items ...T) Set[T] func New[T comparable](items ...T) Set[T]
``` ```
<b>示例:</b> <b>示例:</b>
@@ -67,19 +70,19 @@ import (
) )
func main() { func main() {
st := set.NewSet[int](1,2,2,3) st := set.New[int](1,2,2,3)
fmt.Println(st.Values()) //1,2,3 fmt.Println(st.Values()) //1,2,3
} }
``` ```
### <span id="NewSetFromSlice">NewSetFromSlice</span> ### <span id="FromSlice">FromSlice</span>
<p>基于切片创建集合</p> <p>基于切片创建集合</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func NewSetFromSlice[T comparable](items []T) Set[T] func FromSlice[T comparable](items []T) Set[T]
``` ```
<b>示例:</b> <b>示例:</b>
@@ -93,14 +96,15 @@ import (
) )
func main() { func main() {
st := set.NewSetFromSlice([]int{1, 2, 2, 3}) st := set.FromSlice([]int{1, 2, 2, 3})
fmt.Println(st.Values()) //1,2,3 fmt.Println(st.Values()) //1,2,3
} }
``` ```
### <span id="Values">Values</span> ### <span id="Values">Values<sup>deprecated</sup></span>
<p>获取集合中所有元素的切片</p> <p>获取集合中所有元素的切片<br>
<a href='#ToSlice'>ToSlice()</a> 方法提供与 Values 方法相同的功能</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -119,7 +123,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int](1,2,2,3) st := set.New[int](1,2,2,3)
fmt.Println(st.Values()) //1,2,3 fmt.Println(st.Values()) //1,2,3
} }
``` ```
@@ -145,7 +149,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int]() st := set.New[int]()
st.Add(1, 2, 3) st.Add(1, 2, 3)
fmt.Println(st.Values()) //1,2,3 fmt.Println(st.Values()) //1,2,3
@@ -173,7 +177,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int]() st := set.New[int]()
st.Add(1, 2, 3) st.Add(1, 2, 3)
r1 := st.AddIfNotExist(1) r1 := st.AddIfNotExist(1)
@@ -206,7 +210,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int]() st := set.New[int]()
st.Add(1, 2) st.Add(1, 2)
ok := st.AddIfNotExistBy(3, func(val int) bool { ok := st.AddIfNotExistBy(3, func(val int) bool {
@@ -245,7 +249,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int]() st := set.New[int]()
st.Add(1, 2, 3) st.Add(1, 2, 3)
set.Delete(3) set.Delete(3)
@@ -274,7 +278,7 @@ import (
) )
func main() { func main() {
st := set.NewSet[int]() st := set.New[int]()
st.Add(1, 2, 3) st.Add(1, 2, 3)
fmt.Println(st.Contain(1)) //true fmt.Println(st.Contain(1)) //true
@@ -303,9 +307,9 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(1, 2) set2 := set.New(1, 2)
set3 := set.NewSet(1, 2, 3, 4) set3 := set.New(1, 2, 3, 4)
fmt.Println(set1.ContainAll(set2)) //true fmt.Println(set1.ContainAll(set2)) //true
fmt.Println(set1.ContainAll(set3)) //false fmt.Println(set1.ContainAll(set3)) //false
@@ -333,7 +337,7 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
fmt.Println(set1.Size()) //3 fmt.Println(set1.Size()) //3
} }
@@ -360,7 +364,7 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set1.Clone() set2 := set1.Clone()
fmt.Println(set1.Size() == set2.Size()) //true fmt.Println(set1.Size() == set2.Size()) //true
@@ -389,9 +393,9 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(1, 2, 3) set2 := set.New(1, 2, 3)
set3 := set.NewSet(1, 2, 3, 4) set3 := set.New(1, 2, 3, 4)
fmt.Println(set1.Equal(set2)) //true fmt.Println(set1.Equal(set2)) //true
fmt.Println(set1.Equal(set3)) //false fmt.Println(set1.Equal(set3)) //false
@@ -419,7 +423,7 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
arr := []int{} arr := []int{}
set.Iterate(func(item int) { set.Iterate(func(item int) {
arr = append(arr, item) arr = append(arr, item)
@@ -450,7 +454,7 @@ import (
) )
func main() { func main() {
s := set.NewSet(1, 2, 3, 4, 5) s := set.New(1, 2, 3, 4, 5)
var sum int var sum int
@@ -487,8 +491,8 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet() set2 := set.New()
fmt.Println(set1.IsEmpty()) //false fmt.Println(set1.IsEmpty()) //false
fmt.Println(set2.IsEmpty()) //true fmt.Println(set2.IsEmpty()) //true
@@ -516,8 +520,8 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(2, 3, 4, 5) set2 := set.New(2, 3, 4, 5)
set3 := set1.Union(set2) set3 := set1.Union(set2)
fmt.Println(set3.Values()) //1,2,3,4,5 fmt.Println(set3.Values()) //1,2,3,4,5
@@ -545,8 +549,8 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(2, 3, 4, 5) set2 := set.New(2, 3, 4, 5)
set3 := set1.Intersection(set2) set3 := set1.Intersection(set2)
fmt.Println(set3.Values()) //2,3 fmt.Println(set3.Values()) //2,3
@@ -574,8 +578,8 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(2, 3, 4, 5) set2 := set.New(2, 3, 4, 5)
set3 := set1.SymmetricDifference(set2) set3 := set1.SymmetricDifference(set2)
fmt.Println(set3.Values()) //1,4,5 fmt.Println(set3.Values()) //1,4,5
@@ -603,9 +607,9 @@ import (
) )
func main() { func main() {
set1 := set.NewSet(1, 2, 3) set1 := set.New(1, 2, 3)
set2 := set.NewSet(2, 3, 4, 5) set2 := set.New(2, 3, 4, 5)
set3 := set.NewSet(2, 3) set3 := set.New(2, 3)
res1 := set1.Minus(set2) res1 := set1.Minus(set2)
fmt.Println(res1.Values()) //1 fmt.Println(res1.Values()) //1
@@ -636,7 +640,7 @@ import (
) )
func main() { func main() {
s := set.NewSet[int]() s := set.New[int]()
s.Add(1) s.Add(1)
s.Add(2) s.Add(2)
s.Add(3) s.Add(3)
@@ -647,3 +651,58 @@ func main() {
fmt.Println(ok) // true fmt.Println(ok) // true
} }
``` ```
### <span id="ToSlice">ToSlice</span>
<p>以切片的形式返回集合中所有的元素(无序)</p>
<b>函数签名:</b>
```go
func (s Set[T]) ToSlice() (v T, ok bool)
```
<b>示例:</b>
```go
func main() {
s := set.New(1, 2, 3, 4, 5)
val := s.ToSlice()
fmt.Println(val) // [2 3 4 5 1]
}
```
### <span id="ToSortedSlice">ToSortedSlice</span>
<p>以切片的形式返回集合中所有的元素(按给定的规则排序)</p>
<b>函数签名:</b>
```go
func (s Set[T]) ToSortedSlice() (v T, ok bool)
```
<b>示例:</b>
```go
func main() {
s1 := set.New(1, 2, 3, 4, 5)
type Person struct {
Name string
Age int
}
s2 := FromSlice([]Person{{"Tom", 20}, {"Jerry", 18}, {"Spike", 25}})
res1 := s1.ToSortedSlice(func(v1, v2 int) bool {
return v1 < v2
})
res2 := s2.ToSortedSlice(func(v1, v2 Person) bool {
return v1.Age < v2.Age
})
fmt.Println(res1) // [1 2 3 4 5]
fmt.Println(res2) // [{Jerry 18} {Tom 20} {Spike 25}]
}
```

View File

@@ -41,7 +41,7 @@ import (
## 文档 ## 文档
## 1. BSTree ## 1. BSTree
BSTree是一种二叉搜索树数据结构其中每个节点有两个孩子分别称为左孩子和右孩子。 在 BSTree 中leftNode < rootNode < rightNode。 T类型应该实现lancetconstraints.Comparator。 BSTree是一种二叉搜索树数据结构其中每个节点有两个孩子分别称为左孩子和右孩子。 在 BSTree 中leftNode < rootNode < rightNode。 T类型应该实现constraints.Comparator。
### <span id="NewBSTree">NewBSTree</span> ### <span id="NewBSTree">NewBSTree</span>
<p>返回BSTree指针实例</p> <p>返回BSTree指针实例</p>
@@ -49,11 +49,11 @@ BSTree是一种二叉搜索树数据结构其中每个节点有两个孩子
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func NewBSTree[T any](rootData T, comparator lancetconstraints.Comparator) *BSTree[T] func NewBSTree[T any](rootData T, comparator constraints.Comparator) *BSTree[T]
type BSTree[T any] struct { type BSTree[T any] struct {
root *datastructure.TreeNode[T] root *datastructure.TreeNode[T]
comparator lancetconstraints.Comparator comparator constraints.Comparator
} }
type TreeNode[T any] struct { type TreeNode[T any] struct {

View File

@@ -41,6 +41,8 @@ import (
- [GetNowDate](#GetNowDate) - [GetNowDate](#GetNowDate)
- [GetNowTime](#GetNowTime) - [GetNowTime](#GetNowTime)
- [GetNowDateTime](#GetNowDateTime) - [GetNowDateTime](#GetNowDateTime)
- [GetTodayStartTime](#GetTodayStartTime)
- [GetTodayEndTime](#GetTodayEndTime)
- [GetZeroHourTimestamp](#GetZeroHourTimestamp) - [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp) - [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr) - [FormatTimeToStr](#FormatTimeToStr)
@@ -54,6 +56,14 @@ import (
- [ToFormatForTpl](#ToFormatForTpl) - [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601) - [ToIso8601](#ToIso8601)
- [IsLeapYear](#IsLeapYear) - [IsLeapYear](#IsLeapYear)
- [BetweenSeconds](#BetweenSeconds)
- [DayOfYear](#DayOfYear)
- [IsWeekend<sup>deprecated</sup>](#IsWeekend)
- [NowDateOrTime](#NowDateOrTime)
- [Timestamp](#Timestamp)
- [TimestampMilli](#TimestampMilli)
- [TimestampMicro](#TimestampMicro)
- [TimestampNano](#TimestampNano)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -61,7 +71,7 @@ import (
## 注: ## 注:
1. 方法 FormatTimeToStr 和 FormatStrToTime 中的 format 参数值需要传以下类型之一: 1. 函数中`format`参数值需要传以下值之一 (忽略大小写):
- yyyy-mm-dd hh:mm:ss - yyyy-mm-dd hh:mm:ss
- yyyy-mm-dd hh:mm - yyyy-mm-dd hh:mm
@@ -72,14 +82,18 @@ import (
- dd-mm-yy hh:mm:ss - dd-mm-yy hh:mm:ss
- yyyy/mm/dd hh:mm:ss - yyyy/mm/dd hh:mm:ss
- yyyy/mm/dd hh:mm - yyyy/mm/dd hh:mm
- yyyy-mm-dd hh - yyyy/mm/dd hh
- yyyy/mm/dd - yyyy/mm/dd
- yyyy/mm - yyyy/mm
- mm/dd - mm/dd
- dd/mm/yy hh:mm:ss - dd/mm/yy hh:mm:ss
- yyyymmdd
- mmddyy
- yyyy - yyyy
- yy
- mm - mm
- hh:mm:ss - hh:mm:ss
- hh:mm
- mm:ss - mm:ss
### <span id="AddDay">AddDay</span> ### <span id="AddDay">AddDay</span>
@@ -92,7 +106,7 @@ import (
func AddDay(t time.Time, day int64) time.Time func AddDay(t time.Time, day int64) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dIGbs_uTdFa)</span></b>
```go ```go
package main package main
@@ -131,7 +145,7 @@ func main() {
func AddHour(t time.Time, hour int64) time.Time func AddHour(t time.Time, hour int64) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rcMjd7OCsi5)</span></b>
```go ```go
package main package main
@@ -170,7 +184,7 @@ func main() {
func AddMinute(t time.Time, minute int64) time.Time func AddMinute(t time.Time, minute int64) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nT1heB1KUUK)</span></b>
```go ```go
package main package main
@@ -209,7 +223,7 @@ func main() {
func AddYear(t time.Time, year int64) time.Time func AddYear(t time.Time, year int64) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MqW2ujnBx10)</span></b>
```go ```go
package main package main
@@ -223,18 +237,18 @@ import (
func main() { func main() {
now := time.Now() now := time.Now()
after1Year := AddYear(now, 1) after1Year := datetime.AddYear(now, 1)
diff1 := after1Year.Sub(now) diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1) before1Year := datetime.AddYear(now, -1)
diff2 := before1Year.Sub(now) diff2 := before1Year.Sub(now)
fmt.Println(diff1) fmt.Println(diff1)
fmt.Println(diff2) fmt.Println(diff2)
// Output: // Output:
// 8760h0m0s // 8760h0m0s
// -8760h0m0s // -8760h0m0s
} }
``` ```
@@ -248,7 +262,7 @@ func main() {
func BeginOfMinute(t time.Time) time.Time func BeginOfMinute(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ieOLVJ9CiFT)</span></b>
```go ```go
package main package main
@@ -280,7 +294,7 @@ func main() {
func BeginOfHour(t time.Time) time.Time func BeginOfHour(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GhdGFnDWpYs)</span></b>
```go ```go
package main package main
@@ -312,7 +326,7 @@ func main() {
func BeginOfDay(t time.Time) time.Time func BeginOfDay(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/94m_UT6cWs9)</span></b>
```go ```go
package main package main
@@ -344,7 +358,7 @@ func main() {
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ynjoJPz7VNV)</span></b>
```go ```go
package main package main
@@ -376,7 +390,7 @@ func main() {
func BeginOfMonth(t time.Time) time.Time func BeginOfMonth(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bWXVFsmmzwL)</span></b>
```go ```go
package main package main
@@ -408,7 +422,7 @@ func main() {
func BeginOfYear(t time.Time) time.Time func BeginOfYear(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/i326DSwLnV8)</span></b>
```go ```go
package main package main
@@ -440,7 +454,7 @@ func main() {
func EndOfMinute(t time.Time) time.Time func EndOfMinute(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yrL5wGzPj4z)</span></b>
```go ```go
package main package main
@@ -472,7 +486,7 @@ func main() {
func EndOfHour(t time.Time) time.Time func EndOfHour(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6ce3j_6cVqN)</span></b>
```go ```go
package main package main
@@ -504,7 +518,7 @@ func main() {
func EndOfDay(t time.Time) time.Time func EndOfDay(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eMBOvmq5Ih1)</span></b>
```go ```go
package main package main
@@ -536,7 +550,7 @@ func main() {
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/i08qKXD9flf)</span></b>
```go ```go
package main package main
@@ -568,7 +582,7 @@ func main() {
func EndOfMonth(t time.Time) time.Time func EndOfMonth(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_GWh10B3Nqi)</span></b>
```go ```go
package main package main
@@ -600,7 +614,7 @@ func main() {
func EndOfYear(t time.Time) time.Time func EndOfYear(t time.Time) time.Time
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G01cKlMCvNm)</span></b>
```go ```go
package main package main
@@ -632,21 +646,18 @@ func main() {
func GetNowDate() string func GetNowDate() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/PvfkPpcpBBf)</span></b>
```go ```go
package main package main
import ( import (
"fmt" "fmt"
"time"
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
now := time.Now()
currentDate := datetime.GetNowDate() currentDate := datetime.GetNowDate()
fmt.Println(currentDate) fmt.Println(currentDate)
// Output: // Output:
@@ -664,22 +675,19 @@ func main() {
func GetNowTime() string func GetNowTime() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/l7BNxCkTmJS)</span></b>
```go ```go
package main package main
import ( import (
"fmt" "fmt"
"time"
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
now := time.Now()
currentTime := datetime.GetNowTime() currentTime := datetime.GetNowTime()
fmt.Println(currentTime)
fmt.Println(currentTime) // 15:57:33
// Output: // Output:
// 15:57:33 // 15:57:33
@@ -696,21 +704,18 @@ func main() {
func GetNowDateTime() string func GetNowDateTime() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pI4AqngD0al)</span></b>
```go ```go
package main package main
import ( import (
"fmt" "fmt"
"time"
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
now := time.Now()
current := datetime.GetNowDateTime() current := datetime.GetNowDateTime()
fmt.Println(current) fmt.Println(current)
// Output: // Output:
@@ -718,6 +723,64 @@ func main() {
} }
``` ```
### <span id="GetTodayStartTime">GetTodayStartTime</span>
<p>返回当天开始时间, 格式: yyyy-mm-dd 00:00:00。</p>
<b>函数签名:</b>
```go
func GetTodayStartTime() string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/84siyYF7t99)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
startTime := datetime.GetTodayStartTime()
fmt.Println(startTime)
// Output:
// 2023-06-29 00:00:00
}
```
### <span id="GetTodayEndTime">GetTodayEndTime</span>
<p>返回当天结束时间,格式: yyyy-mm-dd 23:59:59。</p>
<b>函数签名:</b>
```go
func GetTodayEndTime() string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jjrLnfoqgn3)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
endTime := datetime.GetTodayEndTime()
fmt.Println(endTime)
// Output:
// 2023-06-29 23:59:59
}
```
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span> ### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>获取零点时间戳(timestamp of 00:00)</p> <p>获取零点时间戳(timestamp of 00:00)</p>
@@ -728,21 +791,18 @@ func main() {
func GetZeroHourTimestamp() int64 func GetZeroHourTimestamp() int64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/QmL2oIaGE3q)</span></b>
```go ```go
package main package main
import ( import (
"fmt" "fmt"
"time"
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
now := time.Now()
zeroTime := datetime.GetZeroHourTimestamp() zeroTime := datetime.GetZeroHourTimestamp()
fmt.Println(zeroTime) fmt.Println(zeroTime)
// Output: // Output:
@@ -760,21 +820,18 @@ func main() {
func GetNightTimestamp() int64 func GetNightTimestamp() int64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UolysR3MYP1)</span></b>
```go ```go
package main package main
import ( import (
"fmt" "fmt"
"time"
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func main() { func main() {
now := time.Now()
nightTime := datetime.GetNightTimestamp() nightTime := datetime.GetNightTimestamp()
fmt.Println(nightTime) fmt.Println(nightTime)
// Output: // Output:
@@ -789,10 +846,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func FormatTimeToStr(t time.Time, format string) string func FormatTimeToStr(t time.Time, format string, timezone ...string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_Ia7M8H_OvE)</span></b>
```go ```go
package main package main
@@ -828,10 +885,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func FormatStrToTime(str, format string) (time.Time, error) func FormatStrToTime(str, format string, timezone ...string) (time.Time, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1h9FwdU8ql4)</span></b>
```go ```go
package main package main
@@ -870,7 +927,7 @@ type theTime struct {
func NewUnixNow() *theTime func NewUnixNow() *theTime
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/U4PPx-9D0oz)</span></b>
```go ```go
package main package main
@@ -902,7 +959,7 @@ type theTime struct {
func NewUnix(unix int64) *theTime func NewUnix(unix int64) *theTime
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/psoSuh_kLRt)</span></b>
```go ```go
package main package main
@@ -934,7 +991,7 @@ type theTime struct {
func NewFormat(t string) (*theTime, error) func NewFormat(t string) (*theTime, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VkW08ZOaXPZ)</span></b>
```go ```go
package main package main
@@ -966,7 +1023,7 @@ type theTime struct {
func NewISO8601(iso8601 string) (*theTime, error) func NewISO8601(iso8601 string) (*theTime, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mkhOHQkdeA2)</span></b>
```go ```go
package main package main
@@ -995,7 +1052,7 @@ func main() {
func (t *theTime) ToUnix() int64 func (t *theTime) ToUnix() int64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_LUiwAdocjy)</span></b>
```go ```go
package main package main
@@ -1024,7 +1081,7 @@ func main() {
func (t *theTime) ToFormat() string func (t *theTime) ToFormat() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VkW08ZOaXPZ)</span></b>
```go ```go
package main package main
@@ -1053,7 +1110,7 @@ func main() {
func (t *theTime) ToFormatForTpl(tpl string) string func (t *theTime) ToFormatForTpl(tpl string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nyXxXcQJ8L5)</span></b>
```go ```go
package main package main
@@ -1083,7 +1140,7 @@ func main() {
func (t *theTime) ToIso8601() string func (t *theTime) ToIso8601() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mkhOHQkdeA2)</span></b>
```go ```go
package main package main
@@ -1103,7 +1160,6 @@ func main() {
} }
``` ```
### <span id="IsLeapYear">IsLeapYear</span> ### <span id="IsLeapYear">IsLeapYear</span>
<p>验证是否是闰年。</p> <p>验证是否是闰年。</p>
@@ -1114,7 +1170,7 @@ func main() {
func IsLeapYear(year int) bool func IsLeapYear(year int) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xS1eS2ejGew)</span></b>
```go ```go
package main package main
@@ -1136,3 +1192,276 @@ func main() {
// false // false
} }
``` ```
### <span id="BetweenSeconds">BetweenSeconds</span>
<p>返回两个时间的间隔秒数。</p>
<b>函数签名:</b>
```go
func BetweenSeconds(t1 time.Time, t2 time.Time) int64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/n3YDRyfyXJu)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
today := time.Now()
tomorrow := datetime.AddDay(today, 1)
yesterday := datetime.AddDay(today, -1)
result1 := datetime.BetweenSeconds(today, tomorrow)
result2 := datetime.BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
```
### <span id="DayOfYear">DayOfYear</span>
<p>返回参数日期是一年中的第几天。</p>
<b>函数签名:</b>
```go
func DayOfYear(t time.Time) int
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0hjqhTwFNlH)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := datetime.DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := datetime.DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := datetime.DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
```
### <span id="IsWeekend">IsWeekend已废弃, 使用 '== Weekday'</span>
<p>判断日期是否是周末。</p>
<b>函数签名:</b>
```go
func IsWeekend(t time.Time) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cupRM5aZOIY)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := datetime.IsWeekend(date1)
result2 := datetime.IsWeekend(date2)
result3 := datetime.IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```
### <span id="NowDateOrTime">NowDateOrTime</span>
<p>根据指定的格式和时区返回当前时间字符串。</p>
<b>函数签名:</b>
```go
func NowDateOrTime(format string, timezone ...string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EZ-begEjtT0)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 2023-07-26 15:01:30
// 2023-07-26 02:01:30
}
```
### <span id="Timestamp">Timestamp</span>
<p>返回当前秒级时间戳。</p>
<b>函数签名:</b>
```go
func Timestamp(timezone ...string) int64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iU5b7Vvjx6x)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.Timestamp()
fmt.Println(ts)
// Output:
// 1690363051
}
```
### <span id="TimestampMilli">TimestampMilli</span>
<p>返回当前毫秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampMilli(timezone ...string) int64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4gvEusOTu1T)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMilli()
fmt.Println(ts)
// Output:
// 1690363051331
}
```
### <span id="TimestampMicro">TimestampMicro</span>
<p>返回当前微秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampMicro(timezone ...string) int64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2maANglKHQE)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampMicro()
fmt.Println(ts)
// Output:
// 1690363051331784
}
```
### <span id="TimestampNano">TimestampNano</span>
<p>返回当前纳秒级时间戳。</p>
<b>函数签名:</b>
```go
func TimestampNano(timezone ...string) int64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/A9Oq_COrcCF)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
ts := datetime.TimestampNano()
fmt.Println(ts)
// Output:
// 1690363051331788000
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@ import (
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
```go ```go
package main package main
@@ -81,7 +81,7 @@ func main() {
func Pretty(v any) (string, error) func Pretty(v any) (string, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YsciGj3FH2x)</span></b>
```go ```go
package main package main
@@ -120,7 +120,7 @@ func main() {
func PrettyToWriter(v any, out io.Writer) error func PrettyToWriter(v any, out io.Writer) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/LPLZ3lDi5ma)</span></b>
```go ```go
package main package main
@@ -163,7 +163,7 @@ func main() {
func DecimalBytes(size float64, precision ...int) string func DecimalBytes(size float64, precision ...int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FPXs1suwRcs)</span></b>
```go ```go
package main package main
@@ -202,7 +202,7 @@ func main() {
func BinaryBytes(size float64, precision ...int) string func BinaryBytes(size float64, precision ...int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/G9oHHMCAZxP)</span></b>
```go ```go
package main package main
@@ -241,7 +241,7 @@ func main() {
func ParseDecimalBytes(size string) (uint64, error) func ParseDecimalBytes(size string) (uint64, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Am98ybWjvjj)</span></b>
```go ```go
package main package main
@@ -280,7 +280,7 @@ func main() {
func ParseBinaryBytes(size string) (uint64, error) func ParseBinaryBytes(size string) (uint64, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/69v1tTT62x8)</span></b>
```go ```go
package main package main

View File

@@ -0,0 +1,693 @@
# Function
function 函数包控制函数执行流程,包含部分函数式编程。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
- [https://github.com/duke-git/lancet/blob/main/function/predicate.go](https://github.com/duke-git/lancet/blob/main/function/predicate.go)
- [https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/function"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [After](#After)
- [Before](#Before)
- [CurryFn](#CurryFn)
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
- [Schedule](#Schedule)
- [Pipeline](#Pipeline)
- [Watcher](#Watcher)
- [And](#And)
- [Or](#Or)
- [Negate](#Negate)
- [Nor](#Nor)
- [Xnor](#Xnor)
- [Nand](#Nand)
- [AcceptIf](#AcceptIf)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="After">After</span>
<p>创建一个函数当他被调用n或更多次之后将马上触发fn</p>
<b>函数签名:</b>
```go
func After(n int, fn any) func(args ...any) []reflect.Value
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
fn := function.After(2, func() {
fmt.Println("hello")
})
fn()
fn()
// Output:
// hello
}
```
### <span id="Before">Before</span>
<p>创建一个函数调用次数不超过n次之后再调用这个函数将返回一次最后调用fn的结果</p>
<b>函数签名:</b>
```go
func Before(n int, fn any) func(args ...any) []reflect.Value
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0HqUDIFZ3IL)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
fn := function.Before(2, func() {
fmt.Println("hello")
})
fn()
fn()
fn()
fn()
// Output:
// hello
// hello
}
```
### <span id="CurryFn">CurryFn</span>
<p>创建柯里化函数</p>
<b>函数签名:</b>
```go
type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/5HopfDwANKX)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
add := func(a, b int) int {
return a + b
}
var addCurry function.CurryFn[int] = func(values ...int) int {
return add(values[0], values[1])
}
add1 := addCurry.New(1)
result := add1(2)
fmt.Println(result)
// Output:
// 3
}
```
### <span id="Compose">Compose</span>
<p>从右至左组合函数列表fnList返回组合后的函数</p>
<b>函数签名:</b>
```go
func Compose[T any](fnList ...func(...T) T) func(...T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KKfugD4PKYF)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
toUpper := func(strs ...string) string {
return strings.ToUpper(strs[0])
}
toLower := func(strs ...string) string {
return strings.ToLower(strs[0])
}
transform := function.Compose(toUpper, toLower)
result := transform("aBCde")
fmt.Println(result)
// Output:
// ABCDE
}
```
### <span id="Debounced">Debounced</span>
<p>创建一个debounced函数该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。</p>
<b>函数签名:</b>
```go
func Debounced(fn func(), duration time.Duration) func()
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/absuEGB_GN7)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
count := 0
add := func() {
count++
}
debouncedAdd := function.Debounced(add, 50*time.Microsecond)
debouncedAdd()
debouncedAdd()
debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond)
fmt.Println(count)
// Output:
// 1
// 2
}
```
### <span id="Delay">Delay</span>
<p>延迟delay时间后调用函数</p>
<b>函数签名:</b>
```go
func Delay(delay time.Duration, fn any, args ...any)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ivtc2ZE-Tye)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
var print = func(s string) {
fmt.Println(s)
}
function.Delay(2*time.Second, print, "hello")
// Output:
// hello
}
```
### <span id="Schedule">Schedule</span>
<p>每次持续时间调用函数,直到关闭返回的 bool chan</p>
<b>函数签名:</b>
```go
func Schedule(d time.Duration, fn any, args ...any) chan bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hbON-Xeyn5N)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
count := 0
increase := func() {
count++
}
stop := function.Schedule(2*time.Second, increase)
time.Sleep(2 * time.Second)
close(stop)
fmt.Println(count)
// Output:
// 2
}
```
### <span id="Pipeline">Pipeline</span>
<p>执行函数pipeline.</p>
<b>函数签名:</b>
```go
func Pipeline[T any](funcs ...func(T) T) func(T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mPdUVvj6HD6)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
addOne := func(x int) int {
return x + 1
}
double := func(x int) int {
return 2 * x
}
square := func(x int) int {
return x * x
}
fn := function.Pipeline(addOne, double, square)
result := fn(2)
fmt.Println(result)
// Output:
// 36
}
```
### <span id="Watcher">Watcher</span>
<p>Watcher用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。</p>
<b>函数签名:</b>
```go
type Watcher struct {
startTime int64
stopTime int64
excuting bool
}
func NewWatcher() *Watcher
func (w *Watcher) Start()
func (w *Watcher) Stop()
func (w *Watcher) Reset()
func (w *Watcher) GetElapsedTime() time.Duration
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/l2yrOpCLd1I)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
w := function.NewWatcher()
w.Start()
longRunningTask()
fmt.Println(w.excuting) //true
w.Stop()
eapsedTime := w.GetElapsedTime().Milliseconds()
fmt.Println(eapsedTime)
w.Reset()
}
func longRunningTask() {
var slice []int64
for i := 0; i < 10000000; i++ {
slice = append(slice, int64(i))
}
}
```
### <span id="And">And</span>
<p>返回一个复合谓词判断函数该判断函数表示一组谓词的逻辑and操作。只有当所有谓词判断函数对于给定的值都返回true时返回true, 否则返回false。</p>
<b>函数签名:</b>
```go
func And[T any](predicates ...func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dTBHJMQ0zD2)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
isNumericAndLength5 := function.And(
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
func(s string) bool { return len(s) == 5 },
)
fmt.Println(isNumericAndLength5("12345"))
fmt.Println(isNumericAndLength5("1234"))
fmt.Println(isNumericAndLength5("abcde"))
// Output:
// true
// false
// false
}
```
### <span id="Or">Or</span>
<p>返回一个复合谓词判断函数该判断函数表示一组谓词的逻辑or操作。只有当所有谓词判断函数对于给定的值都返回false时返回false, 否则返回true。</p>
<b>函数签名:</b>
```go
func Or[T any](predicates ...func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/LitCIsDFNDA)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
containsDigitOrSpecialChar := function.Or(
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
func(s string) bool { return strings.ContainsAny(s, "!@#$%") },
)
fmt.Println(containsDigitOrSpecialChar("hello!"))
fmt.Println(containsDigitOrSpecialChar("hello"))
// Output:
// true
// false
}
```
### <span id="Negate">Negate</span>
<p>返回一个谓词函数,该谓词函数表示当前谓词的逻辑否定。</p>
<b>函数签名:</b>
```go
func Negate[T any](predicate func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jbI8BtgFnVE)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
// Define some simple predicates for demonstration
isUpperCase := func(s string) bool {
return strings.ToUpper(s) == s
}
isLowerCase := func(s string) bool {
return strings.ToLower(s) == s
}
isMixedCase := function.Negate(function.Or(isUpperCase, isLowerCase))
fmt.Println(isMixedCase("ABC"))
fmt.Println(isMixedCase("AbC"))
// Output:
// false
// true
}
```
### <span id="Nor">Nor</span>
<p>返回一个组合谓词函数,表示给定值上所有谓词逻辑非或 (nor) 的结果。只有当所有谓词函数对给定值都返回false时该组合谓词函数才返回true。</p>
<b>函数签名:</b>
```go
func Nor[T any](predicates ...func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2KdCoBEOq84)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
match := function.Nor(
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
func(s string) bool { return len(s) == 5 },
)
fmt.Println(match("dbcdckkeee"))
match = function.Nor(
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
func(s string) bool { return len(s) == 5 },
)
fmt.Println(match("0123456789"))
// Output:
// true
// false
}
```
### <span id="Nand">Nand</span>
<p>返回一个复合谓词函数,表示给定谓词函数列表的逻辑非与 (NAND)。仅当列表中所有函数对给定参数返回false时才返回true否则返回false。</p>
<b>函数签名:</b>
```go
func Nand[T any](predicates ...func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rb-FdNGpgSO)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
isNumericAndLength5 := function.Nand(
func(s string) bool { return strings.ContainsAny(s, "0123456789") },
func(s string) bool { return len(s) == 5 },
)
fmt.Println(isNumericAndLength5("12345"))
fmt.Println(isNumericAndLength5("1234"))
fmt.Println(isNumericAndLength5("abcdef"))
// Output:
// false
// false
// true
}
```
### <span id="Xnor">Xnor</span>
<p>返回一个复合谓词函数,表示给定一组谓词函数的逻辑异或 (XNOR)。只有当所有 谓词函数对给参数都返回true或false时该谓词函数才返回true。</p>
<b>函数签名:</b>
```go
func Xnor[T any](predicates ...func(T) bool) func(T) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FJxko8SFbqc)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
isEven := func(i int) bool { return i%2 == 0 }
isPositive := func(i int) bool { return i > 0 }
match := function.Xnor(isEven, isPositive)
fmt.Println(match(2))
fmt.Println(match(-3))
fmt.Println(match(3))
// Output:
// true
// true
// false
}
```
### <span id="AcceptIf">AcceptIf</span>
<p>AcceptIf函数会返回另一个函数该函数的签名与 apply 函数相同,但同时还会包含一个布尔值来表示成功或失败。</p>
<b>函数签名:</b>
```go
func AcceptIf[T any](predicate func(T) bool, apply func(T) T) func(T) (T, bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XlXHHtzCf7d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/function"
)
func main() {
adder := function.AcceptIf(
function.And(
func(x int) bool {
return x > 10
}, func(x int) bool {
return x%2 == 0
}),
func(x int) int {
return x + 1
},
)
result, ok := adder(20)
fmt.Println(result)
fmt.Println(ok)
result, ok = adder(21)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 21
// true
// 0
// false
}
```

View File

@@ -43,6 +43,17 @@ import (
- [Merge](#Merge) - [Merge](#Merge)
- [Minus](#Minus) - [Minus](#Minus)
- [IsDisjoint](#IsDisjoint) - [IsDisjoint](#IsDisjoint)
- [HasKey](#HasKey)
- [ToSortedSlicesDefault](#ToSortedSlicesDefault)
- [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator)
- [NewConcurrentMap](#NewConcurrentMap)
- [ConcurrentMap_Get](#ConcurrentMap_Get)
- [ConcurrentMap_Set](#ConcurrentMap_Set)
- [ConcurrentMap_GetOrSet](#ConcurrentMap_GetOrSet)
- [ConcurrentMap_Delete](#ConcurrentMap_Delete)
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
- [ConcurrentMap_Has](#ConcurrentMap_Has)
- [ConcurrentMap_Range](#ConcurrentMap_Range)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -58,7 +69,7 @@ import (
func MapTo(src any, dst any) error func MapTo(src any, dst any) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4K7KBEPgS5M)</span></b>
```go ```go
package main package main
@@ -115,7 +126,7 @@ func main() {
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OaThj6iNVXK)</span></b>
```go ```go
package main package main
@@ -156,7 +167,7 @@ func main() {
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fSvF3wxuNG7)</span></b>
```go ```go
package main package main
@@ -201,7 +212,7 @@ func main() {
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7ov6BJHbVqh)</span></b>
```go ```go
package main package main
@@ -239,7 +250,7 @@ func main() {
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P3-9MdcXegR)</span></b>
```go ```go
package main package main
@@ -277,7 +288,7 @@ func main() {
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YJM4Hj5hNwm)</span></b>
```go ```go
package main package main
@@ -318,7 +329,7 @@ func main() {
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jXGrWDBfSRp)</span></b>
```go ```go
package main package main
@@ -356,7 +367,7 @@ func main() {
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XB7Y10uw20_U)</span></b>
```go ```go
package main package main
@@ -394,7 +405,7 @@ func main() {
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Zld0oj3sjcC)</span></b>
```go ```go
package main package main
@@ -449,7 +460,7 @@ func main() {
func Keys[K comparable, V any](m map[K]V) []K func Keys[K comparable, V any](m map[K]V) []K
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xNB5bTb97Wd)</span></b>
```go ```go
package main package main
@@ -488,7 +499,7 @@ func main() {
func Merge[K comparable, V any](maps ...map[K]V) map[K]V func Merge[K comparable, V any](maps ...map[K]V) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/H95LENF1uB-)</span></b>
```go ```go
package main package main
@@ -527,7 +538,7 @@ func main() {
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3u5U9K7YZ9m)</span></b>
```go ```go
package main package main
@@ -569,7 +580,7 @@ func main() {
func Values[K comparable, V any](m map[K]V) []V func Values[K comparable, V any](m map[K]V) []V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CBKdUc5FTW6)</span></b>
```go ```go
package main package main
@@ -606,7 +617,7 @@ func main() {
func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hI371iB8Up8)</span></b>
```go ```go
package main package main
@@ -647,7 +658,7 @@ func main() {
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sg9-oRidh8f)</span></b>
```go ```go
package main package main
@@ -696,7 +707,7 @@ func main() {
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8scDxWeBDKd)</span></b>
```go ```go
package main package main
@@ -735,7 +746,7 @@ func main() {
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g92aY3fc7Iw)</span></b>
```go ```go
package main package main
@@ -778,7 +789,7 @@ type Entry[K comparable, V any] struct {
func Entries[K comparable, V any](m map[K]V) []Entry[K, V] func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ltb11LNcElY)</span></b>
```go ```go
package main package main
@@ -823,7 +834,7 @@ type Entry[K comparable, V any] struct {
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C8L4ul9TVwf)</span></b>
```go ```go
package main package main
@@ -857,7 +868,7 @@ func main() {
func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2 func Transform[K1 comparable, V1 any, K2 comparable, V2 any](m map[K1]V1, iteratee func(key K1, value V1) (K2, V2)) map[K2]V2
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P6ovfToM3zj)</span></b>
```go ```go
package main package main
@@ -896,7 +907,7 @@ func main() {
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/N9qgYg_Ho6f)</span></b>
```go ```go
package main package main
@@ -932,3 +943,507 @@ func main() {
// false // false
} }
``` ```
### <span id="HasKey">HasKey</span>
<p>检查map是否包含某个key。用于代替以下样板代码:</p>
```go
_, haskey := amap["baz"];
if haskey {
fmt.Println("map has key baz")
}
```
<b>函数签名:</b>
```go
func HasKey[K comparable, V any](m map[K]V, key K) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/isZZHOsDhFc)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
}
result1 := maputil.HasKey(m, "a")
result2 := maputil.HasKey(m, "c")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="ToSortedSlicesDefault">ToSortedSlicesDefault</span>
<p>将map的key和value转化成两个根据key的值从小到大排序的切片value切片中元素的位置与key对应。</p>
<b>函数签名:</b>
```go
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
3: "c",
2: "b",
}
keys, values := ToSortedSlicesDefault(m)
fmt.Println(keys)
fmt.Println(values)
// Output:
// [1 2 3]
// [a b c]
}
```
### <span id="ToSortedSlicesWithComparator">ToSortedSlicesWithComparator</span>
<p>将map的key和value转化成两个使用比较器函数根据key的值自定义排序规则的切片value切片中元素的位置与key对应。</p>
<b>函数签名:</b>
```go
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[time.Time]string{
time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today",
time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday",
time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow",
}
keys1, values1 := ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool {
return a.Before(b)
})
m2 := map[int]string{
1: "a",
3: "c",
2: "b",
}
keys2, values2 := ToSortedSlicesWithComparator(m2, func(a, b int) bool {
return a > b
})
fmt.Println(keys2)
fmt.Println(values2)
fmt.Println(keys1)
fmt.Println(values1)
// Output:
// [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC]
// [yesterday today tomorrow]
// [3 2 1]
// [c b a]
}
```
### <span id="NewConcurrentMap">NewConcurrentMap</span>
<p>ConcurrentMap协程安全的map结构。</p>
<b>函数签名:</b>
```go
// NewConcurrentMap create a ConcurrentMap with specific shard count.
func NewConcurrentMap[K comparable, V any](shardCount int) *ConcurrentMap[K, V]
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
// create a ConcurrentMap whose key type is string, value type is int
cm := maputil.NewConcurrentMap[string, int](100)
}
```
### <span id="ConcurrentMap_Set">ConcurrentMap_Set</span>
<p>在map中设置key和value。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Set(key K, value V)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_Get">ConcurrentMap_Get</span>
<p>根据key获取value, 如果不存在key,返回零值。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Get(key K) (V, bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/3PenTPETJT0)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok)
wg2.Done()
}(j)
}
wg2.Wait()
// output: (order may change)
// 1 true
// 3 true
// 2 true
// 0 true
// 4 true
}
```
### <span id="ConcurrentMap_GetOrSet">ConcurrentMap_GetOrSet</span>
<p>返回键的现有值如果存在否则设置key并返回给定值。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) GetOrSet(key K, value V) (actual V, ok bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aDcDApOK01a)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
val, ok := cm.GetOrSet(fmt.Sprintf("%d", n), n)
fmt.Println(val, ok)
wg.Done()
}(i)
}
wg.Wait()
// output: (order may change)
// 1 false
// 3 false
// 2 false
// 0 false
// 4 false
}
```
### <span id="ConcurrentMap_Delete">ConcurrentMap_Delete</span>
<p>删除key。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Delete(key K)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uTIJZYhpVMS)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
cm.Delete(fmt.Sprintf("%d", n))
wg2.Done()
}(i)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_GetAndDelete">ConcurrentMap_GetAndDelete</span>
<p>获取key然后删除。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) GetAndDelete(key K) (actual V, ok bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZyxeIXSZUiM)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //n, true
_, ok = cm.Get(fmt.Sprintf("%d", n))
fmt.Println(val, ok) //false
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Has">ConcurrentMap_Has</span>
<p>验证是否包含key。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Has(key K) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C8L4ul9TVwf)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
var wg2 sync.WaitGroup
wg2.Add(5)
for j := 0; j < 5; j++ {
go func(n int) {
ok := cm.Has(fmt.Sprintf("%d", n))
fmt.Println(ok) // true
wg2.Done()
}(j)
}
wg2.Wait()
}
```
### <span id="ConcurrentMap_Range">ConcurrentMap_Range</span>
<p>为map中每个键和值顺序调用迭代器。 如果iterator返回false则停止迭代。</p>
<b>函数签名:</b>
```go
func (cm *ConcurrentMap[K, V]) Range(iterator func(key K, value V) bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iqcy7P8P0Pr)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
cm := maputil.NewConcurrentMap[string, int](100)
var wg1 sync.WaitGroup
wg1.Add(5)
for i := 0; i < 5; i++ {
go func(n int) {
cm.Set(fmt.Sprintf("%d", n), n)
wg1.Done()
}(i)
}
wg1.Wait()
cm.Range(func(key string, value int) bool {
fmt.Println(value)
return true
})
}
```

View File

@@ -34,6 +34,10 @@ import (
- [RoundToFloat](#RoundToFloat) - [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString) - [RoundToString](#RoundToString)
- [TruncRound](#TruncRound) - [TruncRound](#TruncRound)
- [CeilToFloat](#CeilToFloat)
- [CeilToString](#CeilToString)
- [FloorToFloat](#FloorToFloat)
- [FloorToString](#FloorToString)
- [Range](#Range) - [Range](#Range)
- [RangeWithStep](#RangeWithStep) - [RangeWithStep](#RangeWithStep)
- [AngleToRadian](#AngleToRadian) - [AngleToRadian](#AngleToRadian)
@@ -42,10 +46,16 @@ import (
- [IsPrime](#IsPrime) - [IsPrime](#IsPrime)
- [GCD](#GCD) - [GCD](#GCD)
- [LCM](#LCM) - [LCM](#LCM)
- [Cos](#Cos)
- [Sin](#Sin)
- [Log](#Log)
- [Sum](#Sum)
- [Abs](#Abs)
- [Div](#Div)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## 文档
### <span id="Average">Average</span> ### <span id="Average">Average</span>
@@ -57,7 +67,7 @@ import (
func Average[T constraints.Integer | constraints.Float](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
```go ```go
package main package main
@@ -92,7 +102,7 @@ func main() {
func Exponent(x, n int64) int64 func Exponent(x, n int64) int64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Vv7LBwER-pz)</span></b>
```go ```go
package main package main
@@ -128,7 +138,7 @@ func main() {
func Fibonacci(first, second, n int) int func Fibonacci(first, second, n int) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IscseUNMuUc)</span></b>
```go ```go
package main package main
@@ -164,7 +174,7 @@ func main() {
func Factorial(x uint) uint func Factorial(x uint) uint
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tt6LdOK67Nx)</span></b>
```go ```go
package main package main
@@ -200,7 +210,7 @@ func main() {
func Max[T constraints.Integer | constraints.Float](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cN8DHI0rTkH)</span></b>
```go ```go
package main package main
@@ -233,7 +243,7 @@ func main() {
func MaxBy[T any](slice []T, comparator func(T, T) bool) T func MaxBy[T any](slice []T, comparator func(T, T) bool) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pbe2MT-7DV2)</span></b>
```go ```go
package main package main
@@ -277,7 +287,7 @@ func main() {
func Min[T constraints.Integer | constraints.Float](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pbe2MT-7DV2)</span></b>
```go ```go
package main package main
@@ -310,7 +320,7 @@ func main() {
func MinBy[T any](slice []T, comparator func(T, T) bool) T func MinBy[T any](slice []T, comparator func(T, T) bool) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/N9qgYg_Ho6f)</span></b>
```go ```go
package main package main
@@ -354,7 +364,7 @@ func main() {
func Percent(val, total float64, n int) float64 func Percent(val, total float64, n int) float64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/s0NdFCtwuyd)</span></b>
```go ```go
package main package main
@@ -365,18 +375,18 @@ import (
) )
func main() { func main() {
result1 := Percent(1, 2, 2) result1 := mathutil.Percent(1, 2, 2)
result2 := Percent(0.1, 0.3, 2) result2 := mathutil.Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2) result3 := mathutil.Percent(-30305, 408420, 2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
// Output: // Output:
// 50 // 50
// 33.33 // 33.33
// -7.42 // -7.42
} }
``` ```
@@ -387,10 +397,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func RoundToFloat(x float64, n int) float64 func RoundToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ghyb528JRJL)</span></b>
```go ```go
package main package main
@@ -423,10 +433,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func RoundToString(x float64, n int) string func RoundToString[T constraints.Float | constraints.Integer](x T, n int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kZwpBRAcllO)</span></b>
```go ```go
package main package main
@@ -459,10 +469,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func TruncRound(x float64, n int) float64 func TruncRound[T constraints.Float | constraints.Integer](x T, n int) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/aumarSHIGzP)</span></b>
```go ```go
package main package main
@@ -488,6 +498,150 @@ func main() {
} }
``` ```
### <span id="CeilToFloat">CeilToFloat</span>
<p>向上舍入进一法保留n位小数。</p>
<b>函数签名:</b>
```go
func CeilToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8hOeSADZPCo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.CeilToFloat(3.14159, 1)
result2 := mathutil.CeilToFloat(3.14159, 2)
result3 := mathutil.CeilToFloat(5, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3.2
// 3.15
// 5
}
```
### <span id="CeilToString">CeilToString</span>
<p>向上舍入进一法保留n位小数返回字符串。</p>
<b>函数签名:</b>
```go
func CeilToString[T constraints.Float | constraints.Integer](x T, n int) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wy5bYEyUKKG)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.CeilToString(3.14159, 1)
result2 := mathutil.CeilToString(3.14159, 2)
result3 := mathutil.CeilToString(5, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3.2
// 3.15
// 5.0000
}
```
### <span id="FloorToFloat">FloorToFloat</span>
<p>向下舍入去尾法保留n位小数。</p>
<b>函数签名:</b>
```go
func FloorToFloat[T constraints.Float | constraints.Integer](x T, n int) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vbCBrQHZEED)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.FloorToFloat(3.14159, 1)
result2 := mathutil.FloorToFloat(3.14159, 2)
result3 := mathutil.FloorToFloat(5, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3.1
// 3.14
// 5
}
```
### <span id="FloorToString">FloorToString</span>
<p>向下舍入去尾法保留n位小数返回字符串。</p>
<b>函数签名:</b>
```go
func FloorToString[T constraints.Float | constraints.Integer](x T, n int) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Qk9KPd2IdDb)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.FloorToString(3.14159, 1)
result2 := mathutil.FloorToString(3.14159, 2)
result3 := mathutil.FloorToString(5, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3.1
// 3.14
// 5.0000
}
```
### <span id="Range">Range</span> ### <span id="Range">Range</span>
<p>根据指定的起始值和数量,创建一个数字切片。</p> <p>根据指定的起始值和数量,创建一个数字切片。</p>
@@ -498,7 +652,7 @@ func main() {
func Range[T constraints.Integer | constraints.Float](start T, count int) []T func Range[T constraints.Integer | constraints.Float](start T, count int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9ke2opxa8ZP)</span></b>
```go ```go
package main package main
@@ -537,7 +691,7 @@ func main() {
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/akLWz0EqOSM)</span></b>
```go ```go
package main package main
@@ -576,7 +730,7 @@ func main() {
func AngleToRadian(angle float64) float64 func AngleToRadian(angle float64) float64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CIvlICqrHql)</span></b>
```go ```go
package main package main
@@ -612,7 +766,7 @@ func main() {
func RadianToAngle(radian float64) float64 func RadianToAngle(radian float64) float64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dQtmOTUOMgi)</span></b>
```go ```go
package main package main
@@ -648,7 +802,7 @@ func main() {
func PointDistance(x1, y1, x2, y2 float64) float64 func PointDistance(x1, y1, x2, y2 float64) float64
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RrG4JIaziM8)</span></b>
```go ```go
package main package main
@@ -668,8 +822,6 @@ func main() {
} }
``` ```
### <span id="IsPrime">IsPrime</span> ### <span id="IsPrime">IsPrime</span>
<p>判断质数。</p> <p>判断质数。</p>
@@ -680,7 +832,7 @@ func main() {
func IsPrime(n int) bool func IsPrime(n int) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rdd8UTHZJ7u)</span></b>
```go ```go
package main package main
@@ -692,20 +844,20 @@ import (
func main() { func main() {
result1 := mathutil.IsPrime(-1) result1 := mathutil.IsPrime(-1)
result2 := mathutil.IsPrime(0) result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1) result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2) result4 := mathutil.IsPrime(2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4) fmt.Println(result4)
// Output: // Output:
// false // false
// false // false
// false // false
// true // true
} }
``` ```
@@ -719,7 +871,7 @@ func main() {
func GCD[T constraints.Integer](integers ...T) T func GCD[T constraints.Integer](integers ...T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CiEceLSoAKB)</span></b>
```go ```go
package main package main
@@ -731,27 +883,26 @@ import (
func main() { func main() {
result1 := mathutil.GCD(1, 1) result1 := mathutil.GCD(1, 1)
result2 := mathutil.GCD(1, -1) result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1) result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1) result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9) result5 := mathutil.GCD(3, 6, 9)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4) fmt.Println(result4)
fmt.Println(result5) fmt.Println(result5)
// Output: // Output:
// 1 // 1
// 1 // 1
// -1 // -1
// -1 // -1
// 3 // 3
} }
``` ```
### <span id="LCM">LCM</span> ### <span id="LCM">LCM</span>
<p>计算最小公倍数。</p> <p>计算最小公倍数。</p>
@@ -762,7 +913,7 @@ func main() {
func LCM[T constraints.Integer](integers ...T) T func LCM[T constraints.Integer](integers ...T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EjcZxfY7G_g)</span></b>
```go ```go
package main package main
@@ -774,16 +925,241 @@ import (
func main() { func main() {
result1 := mathutil.LCM(1, 1) result1 := mathutil.LCM(1, 1)
result2 := mathutil.LCM(1, 2) result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9) result3 := mathutil.LCM(3, 6, 9)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
// Output: // Output:
// 1 // 1
// 2 // 2
// 18 // 18
}
```
### <span id="Cos">Cos</span>
<p>计算弧度的余弦值</p>
<b>函数签名:</b>
```go
func Cos(radian float64, precision ...int) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Sm89LoIfvFq)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Cos(0)
result2 := mathutil.Cos(90)
result3 := mathutil.Cos(180)
result4 := mathutil.Cos(math.Pi)
result5 := mathutil.Cos(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// -0.447
// -0.598
// -1
// 0
}
```
### <span id="Sin">Sin</span>
<p>计算弧度的正弦值</p>
<b>函数签名:</b>
```go
func Sin(radian float64, precision ...int) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TWMQlMywDsP)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sin(0)
result2 := mathutil.Sin(90)
result3 := mathutil.Sin(180)
result4 := mathutil.Sin(math.Pi)
result5 := mathutil.Sin(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 0
// 0.894
// -0.801
// 0
// 1
}
```
### <span id="Log">Log</span>
<p>计算以base为底n的对数。</p>
<b>函数签名:</b>
```go
func Log(n, base float64) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_d4bi8oyhat)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
```
### <span id="Sum">Sum</span>
<p>求传入参数之和。</p>
<b>函数签名:</b>
```go
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1To2ImAMJA7)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sum(1, 2)
result2 := mathutil.Sum(0.1, float64(1))
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.1
}
```
### <span id="Abs">Abs</span>
<p>求绝对值。</p>
<b>函数签名:</b>
```go
func Abs[T constraints.Integer | constraints.Float](x T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fsyBh1Os-1d)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := Abs(-1)
result2 := Abs(-0.1)
result3 := Abs(float32(0.2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 0.1
// 0.2
}
```
### <span id="Div">Div</span>
<p>除法运算。</p>
<b>函数签名:</b>
```go
func Div[T constraints.Float | constraints.Integer](x T, y T) float64
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WLxDdGXXYat)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Div(9, 4)
result2 := mathutil.Div(1, 2)
result3 := mathutil.Div(0, 666)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2.25
// 0.5
// 0
} }
``` ```

View File

@@ -63,7 +63,7 @@ import (
func ConvertMapToQueryString(param map[string]any) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jnNt_qoSnRi)</span></b>
```go ```go
package main package main
@@ -98,7 +98,7 @@ func main() {
func EncodeUrl(urlStr string) (string, error) func EncodeUrl(urlStr string) (string, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bsZ6BRC4uKI)</span></b>
```go ```go
package main package main
@@ -133,7 +133,7 @@ func main() {
func GetInternalIp() string func GetInternalIp() string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fxnna_LLD9u)</span></b>
```go ```go
package main package main
@@ -165,7 +165,7 @@ func main() {
func GetIps() []string func GetIps() []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/NUFfcEmukx1)</span></b>
```go ```go
package main package main
@@ -195,7 +195,7 @@ func main() {
func GetMacAddrs() []string { func GetMacAddrs() []string {
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Rq9UUBS_Xp1)</span></b>
```go ```go
package main package main
@@ -239,7 +239,7 @@ type PublicIpInfo struct {
} }
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YDxIfozsRHR)</span></b>
```go ```go
package main package main
@@ -269,7 +269,7 @@ func main() {
func GetRequestPublicIp(req *http.Request) string func GetRequestPublicIp(req *http.Request) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kxU-YDc_eBo)</span></b>
```go ```go
package main package main
@@ -307,7 +307,7 @@ func main() {
func IsPublicIP(IP net.IP) bool func IsPublicIP(IP net.IP) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nmktSQpJZnn)</span></b>
```go ```go
package main package main
@@ -344,7 +344,7 @@ func main() {
func IsInternalIP(IP net.IP) bool func IsInternalIP(IP net.IP) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sYGhXbgO4Cb)</span></b>
```go ```go
package main package main
@@ -388,7 +388,7 @@ type HttpRequest struct {
} }
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
```go ```go
package main package main
@@ -445,7 +445,7 @@ func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
```go ```go
package main package main
@@ -476,7 +476,7 @@ func main() {
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
```go ```go
package main package main
@@ -530,7 +530,7 @@ func main() {
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jUSgynekH7G)</span></b>
```go ```go
package main package main
@@ -584,7 +584,7 @@ func main() {
func StructToUrlValues(targetStruct any) url.Values func StructToUrlValues(targetStruct any) url.Values
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pFqMkM40w9z)</span></b>
```go ```go
package main package main
@@ -622,9 +622,9 @@ func main() {
} }
``` ```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpGet">HttpGet</span>
<p>发送http get请求</p> <p>发送http get请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -664,9 +664,9 @@ func main() {
} }
``` ```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPost">HttpPost</span>
<p>发送http post请求</p> <p>发送http post请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -694,16 +694,14 @@ import (
func main() { func main() {
url := "https://jsonplaceholder.typicode.com/todos" url := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{ header := map[string]string{
"Content-Type": "application/json", "Content-Type": "application/x-www-form-urlencoded",
} }
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, "TestAddToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := netutil.HttpPost(url, header, nil, bodyParams) postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestToDo")
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -713,9 +711,9 @@ func main() {
} }
``` ```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPut">HttpPut</span>
<p>发送http put请求</p> <p>发送http put请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -763,9 +761,9 @@ func main() {
} }
``` ```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpDelete">HttpDelete</span>
<p>发送http delete请求</p> <p>发送http delete请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -802,9 +800,9 @@ func main() {
} }
``` ```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span> ### <span id="HttpPatch">HttpPatch</span>
<p>发送http patch请求</p> <p>发送http patch请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -968,7 +966,7 @@ func main() {
func IsPingConnected(host string) bool func IsPingConnected(host string) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q8OzTijsA87)</span></b>
```go ```go
package main package main
@@ -1001,7 +999,7 @@ func main() {
func IsTelnetConnected(host string, port string) bool func IsTelnetConnected(host string, port string) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yiLCGtQv_ZG)</span></b>
```go ```go
package main package main

View File

@@ -0,0 +1,227 @@
# Pointer
pointer 包支持一些指针类型的操作。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/pointer/pointer.go](https://github.com/duke-git/lancet/blob/main/pointer/pointer.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/pointer"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Of](#Of)
- [Unwrap](#Unwrap)
- [ExtractPointer](#ExtractPointer)
- [UnwarpOr](#UnwarpOr)
- [UnwarpOrDefault](#UnwarpOrDefault)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Of">Of</span>
<p>返回传入参数的指针值。</p>
<b>函数签名:</b>
```go
func Of[T any](v T) *T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HFd70x4DrMj)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
result1 := pointer.Of(123)
result2 := pointer.Of("abc")
fmt.Println(*result1)
fmt.Println(*result2)
// Output:
// 123
// abc
}
```
### <span id="Unwrap">Unwrap</span>
<p>返回传入指针指向的值。</p>
<b>函数签名:</b>
```go
func Unwrap[T any](p *T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cgeu3g7cjWb)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
result1 := pointer.Unwrap(&a)
result2 := pointer.Unwrap(&b)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 123
// abc
}
```
### <span id="ExtractPointer">ExtractPointer</span>
<p>返回传入interface的底层值。</p>
<b>函数签名:</b>
```go
func ExtractPointer(value any) any
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/D7HFjeWU2ZP)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 1
b := &a
c := &b
d := &c
result := pointer.ExtractPointer(d)
fmt.Println(result)
// Output:
// 1
}
```
### <span id="UnwarpOr">UnwarpOr</span>
<p>返回指针的值如果指针为零值则返回fallback。</p>
<b>函数签名:</b>
```go
UnwarpOr[T any](p *T, fallback T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/mmNaLC38W8C)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOr(&a, 456)
result2 := pointer.UnwarpOr(&b, "abc")
result3 := pointer.UnwarpOr(c, 456)
result4 := pointer.UnwarpOr(d, "def")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 456
// def
}
```
### <span id="UnwarpOrDefault">UnwarpOrDefault</span>
<p>返回指针的值,如果指针为零值,则返回相应零值。</p>
<b>函数签名:</b>
```go
UnwarpOrDefault[T any](p *T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZnGIHf8_o4E)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
var c *int
var d *string
result1 := pointer.UnwarpOrDefault(&a)
result2 := pointer.UnwarpOrDefault(&b)
result3 := pointer.UnwarpOrDefault(c)
result4 := pointer.UnwarpOrDefault(d)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 123
// abc
// 0
//
}
```

View File

@@ -29,7 +29,11 @@ import (
- [RandLower](#RandLower) - [RandLower](#RandLower)
- [RandNumeral](#RandNumeral) - [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter) - [RandNumeralOrLetter](#RandNumeralOrLetter)
- [RandSymbolChar](#RandSymbolChar)
- [UUIdV4](#UUIdV4) - [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
- [RandFloat](#RandFloat)
- [RandFloats](#RandFloats)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -45,7 +49,7 @@ import (
func RandBytes(length int) []byte func RandBytes(length int) []byte
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EkiLESeXf8d)</span></b>
```go ```go
package main package main
@@ -71,7 +75,7 @@ func main() {
func RandInt(min, max int) int func RandInt(min, max int) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pXyyAAI5YxD)</span></b>
```go ```go
package main package main
@@ -97,7 +101,7 @@ func main() {
func RandString(length int) string func RandString(length int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/W2xvRUXA7Mi)</span></b>
```go ```go
package main package main
@@ -123,7 +127,7 @@ func main() {
func RandUpper(length int) string func RandUpper(length int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/29QfOh0DVuh)</span></b>
```go ```go
package main package main
@@ -149,7 +153,7 @@ func main() {
func RandLower(length int) string func RandLower(length int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XJtZ471cmtI)</span></b>
```go ```go
package main package main
@@ -175,7 +179,7 @@ func main() {
func RandNumeral(length int) string func RandNumeral(length int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/g4JWVpHsJcf)</span></b>
```go ```go
package main package main
@@ -201,7 +205,7 @@ func main() {
func RandNumeralOrLetter(length int) string func RandNumeralOrLetter(length int) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/19CEQvpx2jD)</span></b>
```go ```go
package main package main
@@ -217,6 +221,32 @@ func main() {
} }
``` ```
### <span id="RandSymbolChar">RandSymbolChar</span>
<p>生成给定长度的随机符号字符串。</p>
<b>函数签名:</b>
```go
func RandSymbolChar(length int) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Im6ZJxAykOm)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
randStr := random.RandSymbolChar(6)
fmt.Println(randStr) // 随机特殊字符字符串,例如: @#(_")
}
```
### <span id="UUIdV4">UUIdV4</span> ### <span id="UUIdV4">UUIdV4</span>
<p>生成UUID v4字符串</p> <p>生成UUID v4字符串</p>
@@ -227,7 +257,7 @@ func main() {
func UUIdV4() (string, error) func UUIdV4() (string, error)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_Z9SFmr28ft)</span></b>
```go ```go
package main package main
@@ -245,3 +275,81 @@ func main() {
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>生成一个不重复的长度为n的随机int切片。</p>
<b>函数签名:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uBkRSOz73Ec)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
result := random.RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```
### <span id="RandFloat">RandFloat</span>
<p>生成随机float64数字可以指定范围和精度。</p>
<b>函数签名:</b>
```go
func RandFloat(min, max float64, precision int) float64
```
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zbD_tuobJtr)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
floatNumber := random.RandFloat(1.0, 5.0, 2)
fmt.Println(floatNumber) //2.14 (random number)
}
```
### <span id="RandFloats">RandFloats</span>
<p>生成随机float64数字切片指定长度范围和精度.</p>
<b>函数签名:</b>
```go
func RandFloats(n int, min, max float64, precision int) []float64
```
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/I3yndUQ-rhh)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
floatNumbers := random.RandFloats(5, 1.0, 5.0, 2)
fmt.Println(floatNumber) //[3.42 3.99 1.3 2.38 4.23] (random)
}
```

464
docs/api/packages/retry.md Normal file
View File

@@ -0,0 +1,464 @@
# Retry
retry 重试执行函数直到函数运行成功或被 context cancel。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [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>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/retry"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Context](#Context)
- [Retry](#Retry)
- [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes)
- [BackoffStrategy](#BackoffStrategy)
- [RetryWithCustomBackoff](#RetryWithCustomBackoff)
- [RetryWithLinearBackoff](#RetryWithLinearBackoff)
- [RetryWithExponentialWithJitterBackoff](#RetryWithExponentialWithJitterBackoff)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Context">Context</span>
<p>设置重试context参数</p>
<b>函数签名:</b>
```go
func Context(ctx context.Context)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xnAOOXv9GkS)</span></b>
```go
import (
"context"
"errors"
"fmt"
"lancet-demo/retry"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.TODO())
number := 0
increaseNumber := func() error {
number++
if number > 3 {
cancel()
}
return errors.New("error occurs")
}
duration := retry.RetryDuration(time.Microsecond*50)
retry.Retry(increaseNumber,
duration,
retry.Context(ctx),
)
fmt.Println(number)
// Output:
// 4
}
```
### <span id="RetryFunc">RetryFunc</span>
<p>被重试执行的函数</p>
<b>函数签名:</b>
```go
type RetryFunc func() error
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
var increaseNumber retry.RetryFunc = func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryTimes">RetryTimes</span>
<p>设置重试次数默认5</p>
<b>函数签名:</b>
```go
func RetryTimes(n uint)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ssfVeU2SwLO)</span></b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil {
fmt.Println(err)
}
// Output:
// function main.main.func1 run failed after 2 times retry
}
```
### <span id="RetryDuration">RetryDuration</span>
<p>设置重试间隔时间默认3秒</p>
<b>函数签名:</b>
```go
func RetryDuration(d time.Duration)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="Retry">Retry</span>
<p>重试执行函数retryFunc直到函数运行成功或被context停止</p>
<b>函数签名:</b>
```go
func Retry(retryFunc RetryFunc, opts ...Option) error
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nk2XRmagfVF)</span></b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="BackoffStrategy">BackoffStrategy</span>
<p>定义计算退避间隔的方法的接口。</p>
<b>函数签名:</b>
```go
// BackoffStrategy is an interface that defines a method for calculating backoff intervals.
type BackoffStrategy interface {
// CalculateInterval returns the time.Duration after which the next retry attempt should be made.
CalculateInterval() time.Duration
}
```
<b>示例:</b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
type ExampleCustomBackoffStrategy struct {
interval time.Duration
}
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
return c.interval + 1
}
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry,Retry(increaseNumber, retry.RetryWithCustomBackoff(&示例CustomBackoffStrategy{interval: time.Microsecond * 50}))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryWithCustomBackoff">RetryWithCustomBackoff</span>
<p>设置自定义退避策略。</p>
<b>函数签名:</b>
```go
func RetryWithCustomBackoff(backoffStrategy BackoffStrategy) Option
```
<b>示例:</b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
type ExampleCustomBackoffStrategy struct {
interval time.Duration
}
func (c *ExampleCustomBackoffStrategy) CalculateInterval() time.Duration {
return c.interval + 1
}
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry,Retry(increaseNumber, retry.RetryWithCustomBackoff(&示例CustomBackoffStrategy{interval: time.Microsecond * 50}))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryWithLinearBackoff">RetryWithLinearBackoff</span>
<p>设置线性策略退避。</p>
<b>函数签名:</b>
```go
func RetryWithLinearBackoff(interval time.Duration) Option
```
<b>示例:</b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryWithLinearBackoff(time.Microsecond*50))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```
### <span id="RetryWithExponentialWithJitterBackoff">RetryWithExponentialWithJitterBackoff</span>
<p>设置指数策略退避。</p>
<b>函数签名:</b>
```go
func RetryWithExponentialWithJitterBackoff(interval time.Duration, base uint64, maxJitter time.Duration) Option
```
<b>示例:</b>
```go
package main
import (
"fmt"
"errors"
"log"
"github.com/duke-git/lancet/v2/retry"
)
func main() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryWithExponentialWithJitterBackoff(time.Microsecond*50, 2, time.Microsecond*25))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
```

View File

@@ -35,6 +35,7 @@ import (
- [DifferenceBy](#DifferenceBy) - [DifferenceBy](#DifferenceBy)
- [DifferenceWith](#DifferenceWith) - [DifferenceWith](#DifferenceWith)
- [DeleteAt](#DeleteAt) - [DeleteAt](#DeleteAt)
- [DeleteRange](#DeleteRange)
- [Drop](#Drop) - [Drop](#Drop)
- [DropRight](#DropRight) - [DropRight](#DropRight)
- [DropWhile](#DropWhile) - [DropWhile](#DropWhile)
@@ -77,7 +78,7 @@ import (
- [IsSortedByKey](#IsSortedByKey) - [IsSortedByKey](#IsSortedByKey)
- [Sort](#Sort) - [Sort](#Sort)
- [SortBy](#SortBy) - [SortBy](#SortBy)
- [SortByField<sup>deprecated</sup>](#SortByField) - [SortByField](#SortByField)
- [Some](#Some) - [Some](#Some)
- [StringSlice<sup>deprecated</sup>](#StringSlice) - [StringSlice<sup>deprecated</sup>](#StringSlice)
- [SymmetricDifference](#SymmetricDifference) - [SymmetricDifference](#SymmetricDifference)
@@ -90,9 +91,16 @@ import (
- [UpdateAt](#UpdateAt) - [UpdateAt](#UpdateAt)
- [Without](#Without) - [Without](#Without)
- [KeyBy](#KeyBy) - [KeyBy](#KeyBy)
- [Join](#Join)
- [Partition](#Partition)
- [SetToDefaultIf](#SetToDefaultIf)
- [Break](#Break)
- [RightPadding](#RightPadding)
- [LeftPadding](#LeftPadding)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="AppendIfAbsent">AppendIfAbsent</span> ### <span id="AppendIfAbsent">AppendIfAbsent</span>
@@ -105,7 +113,7 @@ import (
func AppendIfAbsent[T comparable](slice []T, item T) []T func AppendIfAbsent[T comparable](slice []T, item T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GNdv7Jg2Taj)</span></b>
```go ```go
import ( import (
@@ -136,7 +144,7 @@ func main() {
func Contain[T comparable](slice []T, target T) bool func Contain[T comparable](slice []T, target T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_454yEHcNjf)</span></b>
```go ```go
import ( import (
@@ -167,7 +175,7 @@ func main() {
func ContainBy[T any](slice []T, predicate func(item T) bool) bool func ContainBy[T any](slice []T, predicate func(item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/49tkHfX4GNc)</span></b>
```go ```go
import ( import (
@@ -212,7 +220,7 @@ func main() {
func ContainSubSlice[T comparable](slice, subSlice []T) bool func ContainSubSlice[T comparable](slice, subSlice []T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bcuQ3UT6Sev)</span></b>
```go ```go
import ( import (
@@ -243,7 +251,7 @@ func main() {
func Chunk[T any](slice []T, size int) [][]T func Chunk[T any](slice []T, size int) [][]T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/b4Pou5j2L_C)</span></b>
```go ```go
import ( import (
@@ -285,7 +293,7 @@ func main() {
func Compact[T comparable](slice []T) []T func Compact[T comparable](slice []T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pO5AnxEr3TK)</span></b>
```go ```go
import ( import (
@@ -322,7 +330,7 @@ func main() {
func Concat[T any](slice []T, slices ...[]T) []T func Concat[T any](slice []T, slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
```go ```go
import ( import (
@@ -353,7 +361,7 @@ func main() {
func Count[T comparable](slice []T, item T) int func Count[T comparable](slice []T, item T) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Mj4oiEnQvRJ)</span></b>
```go ```go
import ( import (
@@ -386,7 +394,7 @@ func main() {
func CountBy[T any](slice []T, predicate func(index int, item T) bool) int func CountBy[T any](slice []T, predicate func(index int, item T) bool) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tHOccTMDZCC)</span></b>
```go ```go
import ( import (
@@ -420,7 +428,7 @@ func main() {
func Difference[T comparable](slice, comparedSlice []T) []T func Difference[T comparable](slice, comparedSlice []T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/VXvadzLzhDa)</span></b>
```go ```go
import ( import (
@@ -451,7 +459,7 @@ func main() {
func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DiivgwM5OnC)</span></b>
```go ```go
import ( import (
@@ -486,7 +494,7 @@ func main() {
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/v2U2deugKuV)</span></b>
```go ```go
import ( import (
@@ -513,15 +521,15 @@ func main() {
### <span id="DeleteAt">DeleteAt</span> ### <span id="DeleteAt">DeleteAt</span>
<p>删除切片中指定开始索引到结束索引的元素</p> <p>删除切片中指定索引的元素(不修改原切片)。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func DeleteAt[T any](slice []T, start int, end ...int) func DeleteAt[T any](slice []T, index int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/800B1dPBYyd)</span></b>
```go ```go
import ( import (
@@ -530,18 +538,66 @@ import (
) )
func main() { func main() {
result1 := slice.DeleteAt([]string{"a", "b", "c"}, -1) chars := []string{"a", "b", "c", "d", "e"}
result2 := slice.DeleteAt([]string{"a", "b", "c"}, 0)
result3 := slice.DeleteAt([]string{"a", "b", "c"}, 0, 2) result1 := slice.DeleteAt(chars, 0)
result2 := slice.DeleteAt(chars, 4)
result3 := slice.DeleteAt(chars, 5)
result4 := slice.DeleteAt(chars, 6)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4)
// Output: // Output:
// [a b c] // [b c d e]
// [b c] // [a b c d]
// [c] // [a b c d]
// [a b c d]
}
```
### <span id="DeleteRange">DeleteRange</span>
<p>删除切片中指定索引范围的元素(不修改原切片)。</p>
<b>函数签名:</b>
```go
func DeleteRange[T any](slice []T, start, end int) []T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/945HwiNrnle)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
chars := []string{"a", "b", "c", "d", "e"}
result1 := DeleteRange(chars, 0, 0)
result2 := DeleteRange(chars, 0, 1)
result3 := DeleteRange(chars, 0, 3)
result4 := DeleteRange(chars, 0, 4)
result5 := DeleteRange(chars, 0, 5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// [a b c d e]
// [b c d e]
// [d e]
// [e]
// []
} }
``` ```
@@ -556,7 +612,7 @@ func main() {
func Drop[T any](slice []T, n int) []T func Drop[T any](slice []T, n int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jnPO2yQsT8H)</span></b>
```go ```go
import ( import (
@@ -593,7 +649,7 @@ func main() {
func DropRight[T any](slice []T, n int) []T func DropRight[T any](slice []T, n int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8bcXvywZezG)</span></b>
```go ```go
import ( import (
@@ -630,7 +686,7 @@ func main() {
func DropWhile[T any](slice []T, predicate func(item T) bool) []T func DropWhile[T any](slice []T, predicate func(item T) bool) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4rt252UV_qs)</span></b>
```go ```go
import ( import (
@@ -670,7 +726,7 @@ func main() {
func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6wyK3zMY56e)</span></b>
```go ```go
import ( import (
@@ -712,7 +768,7 @@ func main() {
func Every[T any](slice []T, predicate func(index int, item T) bool) bool func Every[T any](slice []T, predicate func(index int, item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/R8U6Sl-j8cD)</span></b>
```go ```go
import ( import (
@@ -746,7 +802,7 @@ func main() {
func Equal[T comparable](slice1, slice2 []T) bool func Equal[T comparable](slice1, slice2 []T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WcRQJ37ifPa)</span></b>
```go ```go
import ( import (
@@ -781,7 +837,7 @@ func main() {
func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/b9iygtgsHI1)</span></b>
```go ```go
import ( import (
@@ -816,7 +872,7 @@ func main() {
func Filter[T any](slice []T, predicate func(index int, item T) bool) []T func Filter[T any](slice []T, predicate func(index int, item T) bool) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/SdPna-7qK4T)</span></b>
```go ```go
import ( import (
@@ -850,7 +906,7 @@ func main() {
func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CBKeBoHVLgq)</span></b>
```go ```go
import ( import (
@@ -886,7 +942,7 @@ func main() {
func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/n1lysBYl-GB)</span></b>
```go ```go
import ( import (
@@ -897,18 +953,18 @@ import (
func main() { func main() {
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool { isEven := func(i, num int) bool {
return num%2 == 0 return num%2 == 0
} }
result, ok := slice.FindBy(nums, isEven) result, ok := slice.FindBy(nums, isEven)
fmt.Println(result) fmt.Println(result)
fmt.Println(ok) fmt.Println(ok)
// Output: // Output:
// 2 // 2
// true // true
} }
``` ```
@@ -922,7 +978,7 @@ func main() {
func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool) func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FFDPV_j7URd)</span></b>
```go ```go
import ( import (
@@ -958,7 +1014,7 @@ func main() {
func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8iqomzyCl_s)</span></b>
```go ```go
import ( import (
@@ -969,18 +1025,18 @@ import (
func main() { func main() {
nums := []int{1, 2, 3, 4, 5} nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool { isEven := func(i, num int) bool {
return num%2 == 0 return num%2 == 0
} }
result, ok := slice.FindLastBy(nums, isEven) result, ok := slice.FindLastBy(nums, isEven)
fmt.Println(result) fmt.Println(result)
fmt.Println(ok) fmt.Println(ok)
// Output: // Output:
// 4 // 4
// true // true
} }
``` ```
@@ -994,7 +1050,7 @@ func main() {
func Flatten(slice any) any func Flatten(slice any) any
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hYa3cBEevtm)</span></b>
```go ```go
import ( import (
@@ -1024,7 +1080,7 @@ func main() {
func FlattenDeep(slice any) any func FlattenDeep(slice any) any
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yjYNHPyCFaF)</span></b>
```go ```go
import ( import (
@@ -1054,7 +1110,7 @@ func main() {
func ForEach[T any](slice []T, iteratee func(index int, item T)) func ForEach[T any](slice []T, iteratee func(index int, item T))
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DrPaa4YsHRF)</span></b>
```go ```go
import ( import (
@@ -1089,7 +1145,7 @@ func main() {
func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool) func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qScs39f3D9W)</span></b>
```go ```go
import ( import (
@@ -1127,7 +1183,7 @@ func main() {
func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T) func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/QVkPxzPR0iA)</span></b>
```go ```go
import ( import (
@@ -1163,7 +1219,7 @@ func main() {
func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ApCvMNTLO8a)</span></b>
```go ```go
import ( import (
@@ -1197,7 +1253,7 @@ func main() {
func IntSlice(slice any) []int func IntSlice(slice any) []int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UQDj-on9TGN)</span></b>
```go ```go
import ( import (
@@ -1226,7 +1282,7 @@ func main() {
func InterfaceSlice(slice any) []any func InterfaceSlice(slice any) []any
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/FdQXF0Vvqs-)</span></b>
```go ```go
import ( import (
@@ -1255,7 +1311,7 @@ func main() {
func Intersection[T comparable](slices ...[]T) []T func Intersection[T comparable](slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/anJXfB5wq_t)</span></b>
```go ```go
import ( import (
@@ -1286,7 +1342,7 @@ func main() {
func InsertAt[T any](slice []T, index int, value any) []T func InsertAt[T any](slice []T, index int, value any) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hMLNxPEGJVE)</span></b>
```go ```go
import ( import (
@@ -1326,7 +1382,7 @@ func main() {
func IndexOf[T comparable](slice []T, item T) int func IndexOf[T comparable](slice []T, item T) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MRN1f0FpABb)</span></b>
```go ```go
import ( import (
@@ -1359,7 +1415,7 @@ func main() {
func LastIndexOf[T comparable](slice []T, item T) int func LastIndexOf[T comparable](slice []T, item T) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DokM4cf1IKH)</span></b>
```go ```go
import ( import (
@@ -1392,7 +1448,7 @@ func main() {
func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/biaTefqPquw)</span></b>
```go ```go
import ( import (
@@ -1426,7 +1482,7 @@ func main() {
func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/J94SZ_9MiIe)</span></b>
```go ```go
import ( import (
@@ -1463,7 +1519,7 @@ func main() {
func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_QARWlWs1N_F)</span></b>
```go ```go
import ( import (
@@ -1496,7 +1552,7 @@ func main() {
func Merge[T any](slices ...[]T) []T func Merge[T any](slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lbjFp784r9N)</span></b>
```go ```go
import ( import (
@@ -1527,7 +1583,7 @@ func main() {
func Reverse[T any](slice []T) func Reverse[T any](slice []T)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8uI8f1lwNrQ)</span></b>
```go ```go
import ( import (
@@ -1557,7 +1613,7 @@ func main() {
func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/_RfXJJWIsIm)</span></b>
```go ```go
import ( import (
@@ -1591,7 +1647,7 @@ func main() {
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YKDpLi7gtee)</span></b>
```go ```go
import ( import (
@@ -1627,7 +1683,7 @@ func main() {
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qT9dZC03A1K)</span></b>
```go ```go
import ( import (
@@ -1657,7 +1713,7 @@ func main() {
func Replace[T comparable](slice []T, old T, new T, n int) []T func Replace[T comparable](slice []T, old T, new T, n int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/P5mZp7IhOFo)</span></b>
```go ```go
import ( import (
@@ -1699,7 +1755,7 @@ func main() {
func ReplaceAll[T comparable](slice []T, old T, new T) []T func ReplaceAll[T comparable](slice []T, old T, new T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CzqXMsuYUrx)</span></b>
```go ```go
import ( import (
@@ -1727,7 +1783,7 @@ func main() {
func Repeat[T any](item T, n int) []T func Repeat[T any](item T, n int) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1CbOmtgILUU)</span></b>
```go ```go
import ( import (
@@ -1755,7 +1811,7 @@ func main() {
func Shuffle[T any](slice []T) []T func Shuffle[T any](slice []T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YHvhnWGU3Ge)</span></b>
```go ```go
import ( import (
@@ -1784,7 +1840,7 @@ func main() {
func IsAscending[T constraints.Ordered](slice []T) bool func IsAscending[T constraints.Ordered](slice []T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9CtsFjet4SH)</span></b>
```go ```go
import ( import (
@@ -1818,7 +1874,7 @@ func main() {
func IsDescending[T constraints.Ordered](slice []T) bool func IsDescending[T constraints.Ordered](slice []T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/U_LljFXma14)</span></b>
```go ```go
import ( import (
@@ -1852,7 +1908,7 @@ func main() {
func IsSorted[T constraints.Ordered](slice []T) bool func IsSorted[T constraints.Ordered](slice []T) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/nCE8wPLwSA-)</span></b>
```go ```go
import ( import (
@@ -1886,7 +1942,7 @@ func main() {
func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tUoGB7DOHI4)</span></b>
```go ```go
import ( import (
@@ -1926,7 +1982,7 @@ func main() {
func Sort[T constraints.Ordered](slice []T, sortOrder ...string) func Sort[T constraints.Ordered](slice []T, sortOrder ...string)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/V9AVjzf_4Fk)</span></b>
```go ```go
import ( import (
@@ -1963,7 +2019,7 @@ func main() {
func SortBy[T any](slice []T, less func(a, b T) bool) func SortBy[T any](slice []T, less func(a, b T) bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/DAhLQSZEumm)</span></b>
```go ```go
import ( import (
@@ -2000,9 +2056,9 @@ func main() {
} }
``` ```
### <span id="SortByField">SortByField (已弃用: 请使用 Sort 或 SortBy 代替该方法)</span> ### <span id="SortByField">SortByField</span>
<p>按字段对结构切片进行排序。slice元素应为struct字段类型应为int、uint、string或bool。 默认排序类型是升序asc如果是降序设置 sortType 为 desc</p> <p>按字段对结构切片进行排序。slice元素应为struct排序字段field类型应为int、uint、string或bool。 默认排序类型是升序asc如果是降序设置 sortType 为 desc</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -2010,7 +2066,7 @@ func main() {
func SortByField(slice any, field string, sortType ...string) error func SortByField(slice any, field string, sortType ...string) error
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fU1prOBP9p1)</span></b>
```go ```go
import ( import (
@@ -2051,7 +2107,7 @@ func main() {
func Some[T any](slice []T, predicate func(index int, item T) bool) bool func Some[T any](slice []T, predicate func(index int, item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4pO9Xf9NDGS)</span></b>
```go ```go
import ( import (
@@ -2085,7 +2141,7 @@ func main() {
func StringSlice(slice any) []string func StringSlice(slice any) []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/W0TZDWCPFcI)</span></b>
```go ```go
import ( import (
@@ -2114,7 +2170,7 @@ func main() {
func SymmetricDifference[T comparable](slices ...[]T) []T func SymmetricDifference[T comparable](slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1CbOmtgILUU)</span></b>
```go ```go
import ( import (
@@ -2145,7 +2201,7 @@ func main() {
func ToSlice[T any](items ...T) []T func ToSlice[T any](items ...T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/YzbzVq5kscN)</span></b>
```go ```go
import ( import (
@@ -2173,7 +2229,7 @@ func main() {
func ToSlicePointer[T any](items ...T) []*T func ToSlicePointer[T any](items ...T) []*T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gx4tr6_VXSF)</span></b>
```go ```go
import ( import (
@@ -2208,7 +2264,7 @@ func main() {
func Unique[T comparable](slice []T) []T func Unique[T comparable](slice []T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/AXw0R3ZTE6a)</span></b>
```go ```go
import ( import (
@@ -2235,7 +2291,7 @@ func main() {
func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UR323iZLDpv)</span></b>
```go ```go
import ( import (
@@ -2266,7 +2322,7 @@ func main() {
func Union[T comparable](slices ...[]T) []T func Union[T comparable](slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/hfXV1iRIZOf)</span></b>
```go ```go
import ( import (
@@ -2297,7 +2353,7 @@ func main() {
func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HGKHfxKQsFi)</span></b>
```go ```go
import ( import (
@@ -2322,7 +2378,7 @@ func main() {
### <span id="UpdateAt">UpdateAt</span> ### <span id="UpdateAt">UpdateAt</span>
<p>更新索引处的切片元素。 如果index < 0或 index >= len(slice),将返回错误</p> <p>更新索引处的切片元素。 如果index &lt 0或 index &lt= len(slice),将返回错误</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -2330,7 +2386,7 @@ func main() {
func UpdateAt[T any](slice []T, index int, value T) []T func UpdateAt[T any](slice []T, index int, value T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/f3mh2KloWVm)</span></b>
```go ```go
import ( import (
@@ -2370,7 +2426,7 @@ func main() {
func Without[T comparable](slice []T, items ...T) []T func Without[T comparable](slice []T, items ...T) []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bwhEXEypThg)</span></b>
```go ```go
import ( import (
@@ -2390,7 +2446,7 @@ func main() {
### <span id="KeyBy">KeyBy</span> ### <span id="KeyBy">KeyBy</span>
<p>将切片每个元素调用函数后转为map</p> <p>将切片每个元素调用函数后转为map</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -2398,7 +2454,7 @@ func main() {
func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uXod2LWD1Kg)</span></b>
```go ```go
import ( import (
@@ -2417,3 +2473,221 @@ func main() {
// map[1:a 2:ab 3:abc] // map[1:a 2:ab 3:abc]
} }
``` ```
### <span id="Join">Join</span>
<p>用指定的分隔符链接切片元素。</p>
<b>函数签名:</b>
```go
func Join[T any](s []T, separator string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/huKzqwNDD7V)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
result1 := slice.Join(nums, ",")
result2 := slice.Join(nums, "-")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1,2,3,4,5
// 1-2-3-4-5
}
```
### <span id="Partition">Partition</span>
<p>根据给定的predicate判断函数分组切片元素。</p>
<b>函数签名:</b>
```go
func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/lkQ3Ri2NQhV)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
result1 := slice.Partition(nums)
result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// [[1 2 3 4 5]]
// [[2 4] [1 3 5]]
// [[1 2] [3 4] [5]]
}
```
### <span id="Random">Random</span>
<p>随机返回切片中元素以及下标, 当切片长度为0时返回下标-1</p>
<b>函数签名:</b>
```go
func Random[T any](slice []T) (val T, idx int)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UzpGQptWppw)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
val, idx := slice.Random(nums)
if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
fmt.Println("okk")
}
// Output:
// okk
}
```
### <span id="SetToDefaultIf">SetToDefaultIf</span>
<p>根据给定给定的predicate判定函数来修改切片中的元素。对于满足的元素将其替换为指定的默认值同时保持元素在切片中的位置不变。函数返回修改后的切片以及被修改的元素个数。</p>
<b>函数签名:</b>
```go
func SetToDefaultIf[T any](slice []T, predicate func(T) bool) ([]T, int)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9AXGlPRC0-A)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
strs := []string{"a", "b", "a", "c", "d", "a"}
modifiedStrs, count := slice.SetToDefaultIf(strs, func(s string) bool { return "a" == s })
fmt.Println(modifiedStrs)
fmt.Println(count)
// Output:
// [ b c d ]
// 3
}
```
### <span id="Break">Break</span>
<p>根据判断函数将切片分成两部分。它开始附加到与函数匹配的第一个元素之后的第二个切片。第一个匹配之后的所有元素都包含在第二个切片中,无论它们是否与函数匹配。</p>
<b>函数签名:</b>
```go
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
even := func(n int) bool { return n%2 == 0 }
resultEven, resultAfterFirstEven := slice.Break(nums, even)
fmt.Println(resultEven)
fmt.Println(resultAfterFirstEven)
// Output:
// [1]
// [2 3 4 5]
}
```
<span id="RightPadding">RightPadding</span>
<p>在切片的右部添加元素。</p>
<b>函数签名:</b>
```go
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
padded := slice.RightPadding(nums, 0, 3)
fmt.Println(padded)
// Output:
// [1 2 3 4 5 0 0 0]
}
```
<span id="LeftPadding">LeftPadding</span>
<p>在切片的左部添加元素。</p>
<b>函数签名:</b>
```go
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
padded := slice.LeftPadding(nums, 0, 3)
fmt.Println(padded)
// Output:
// [0 0 0 1 2 3 4 5]
}
```

View File

@@ -63,7 +63,7 @@ import (
func Of[T any](elems ...T) stream[T] func Of[T any](elems ...T) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jI6_iZZuVFE)</span></b>
```go ```go
import ( import (
@@ -93,7 +93,7 @@ func main() {
func FromSlice[T any](source []T) stream[T] func FromSlice[T any](source []T) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wywTO0XZtI4)</span></b>
```go ```go
import ( import (
@@ -123,7 +123,7 @@ func main() {
func FromChannel[T any](source <-chan T) stream[T] func FromChannel[T any](source <-chan T) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9TZYugGMhXZ)</span></b>
```go ```go
import ( import (
@@ -161,7 +161,7 @@ func main() {
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9Ex1-zcg-B-)</span></b>
```go ```go
import ( import (
@@ -190,7 +190,7 @@ func main() {
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rkOWL1yA3j9)</span></b>
```go ```go
import ( import (
@@ -230,7 +230,7 @@ func main() {
func Concat[T any](a, b stream[T]) stream[T] func Concat[T any](a, b stream[T]) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HM4OlYk_OUC)</span></b>
```go ```go
import ( import (
@@ -263,7 +263,7 @@ func main() {
func (s stream[T]) Distinct() stream[T] func (s stream[T]) Distinct() stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eGkOSrm64cB)</span></b>
```go ```go
import ( import (
@@ -297,7 +297,7 @@ func main() {
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/MFlSANo-buc)</span></b>
```go ```go
import ( import (
@@ -331,7 +331,7 @@ func main() {
func (s stream[T]) Map(mapper func(item T) T) stream[T] func (s stream[T]) Map(mapper func(item T) T) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OtNQUImdYko)</span></b>
```go ```go
import ( import (
@@ -365,7 +365,7 @@ func main() {
func (s stream[T]) Peek(consumer func(item T)) stream[T] func (s stream[T]) Peek(consumer func(item T)) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/u1VNzHs6cb2)</span></b>
```go ```go
import ( import (
@@ -402,7 +402,7 @@ func main() {
func (s stream[T]) Skip(n int) stream[T] func (s stream[T]) Skip(n int) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fNdHbqjahum)</span></b>
```go ```go
import ( import (
@@ -441,7 +441,7 @@ func main() {
func (s stream[T]) Limit(maxSize int) stream[T] func (s stream[T]) Limit(maxSize int) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qsO4aniDcGf)</span></b>
```go ```go
import ( import (
@@ -480,7 +480,7 @@ func main() {
func (s stream[T]) Reverse() stream[T] func (s stream[T]) Reverse() stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/A8_zkJnLHm4)</span></b>
```go ```go
import ( import (
@@ -510,7 +510,7 @@ func main() {
func (s stream[T]) Range(start, end int) stream[T] func (s stream[T]) Range(start, end int) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/indZY5V2f4j)</span></b>
```go ```go
import ( import (
@@ -549,7 +549,7 @@ func main() {
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/XXtng5uonFj)</span></b>
```go ```go
import ( import (
@@ -581,7 +581,7 @@ func main() {
func (s stream[T]) ForEach(action func(item T)) func (s stream[T]) ForEach(action func(item T))
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Dsm0fPqcidk)</span></b>
```go ```go
import ( import (
@@ -614,7 +614,7 @@ func main() {
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6uzZjq_DJLU)</span></b>
```go ```go
import ( import (
@@ -646,7 +646,7 @@ func main() {
func (s stream[T]) FindFirst() (T, bool) func (s stream[T]) FindFirst() (T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9xEf0-6C1e3)</span></b>
```go ```go
import ( import (
@@ -678,7 +678,7 @@ func main() {
func (s stream[T]) FindLast() (T, bool) func (s stream[T]) FindLast() (T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/WZD2rDAW-2h)</span></b>
```go ```go
import ( import (
@@ -687,16 +687,16 @@ import (
) )
func main() { func main() {
original := FromSlice([]int{3, 2, 1}) original := stream.FromSlice([]int{3, 2, 1})
result, ok := original.FindLast() result, ok := original.FindLast()
fmt.Println(result) fmt.Println(result)
fmt.Println(ok) fmt.Println(ok)
// Output: // Output:
// 1 // 1
// true // true
} }
``` ```
@@ -710,7 +710,7 @@ func main() {
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/fm-1KOPtGzn)</span></b>
```go ```go
import ( import (
@@ -734,7 +734,7 @@ func main() {
### <span id="Min">Min</span> ### <span id="Min">Min</span>
<p>根据提供的less函数返回stream的最小元素。less函数: a < b</p> <p>根据提供的less函数返回stream的最小元素。less函数: a &lt b</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -742,7 +742,7 @@ func main() {
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/vZfIDgGNRe_0)</span></b>
```go ```go
import ( import (
@@ -774,7 +774,7 @@ func main() {
func (s stream[T]) AllMatch(predicate func(item T) bool) bool func (s stream[T]) AllMatch(predicate func(item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/V5TBpVRs-Cx)</span></b>
```go ```go
import ( import (
@@ -812,7 +812,7 @@ func main() {
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/PTCnWn4OxSn)</span></b>
```go ```go
import ( import (
@@ -850,7 +850,7 @@ func main() {
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iWS64pL1oo3)</span></b>
```go ```go
import ( import (
@@ -888,7 +888,7 @@ func main() {
func (s stream[T]) Count() int func (s stream[T]) Count() int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/r3koY6y_Xo-)</span></b>
```go ```go
import ( import (
@@ -919,7 +919,7 @@ func main() {
func (s stream[T]) ToSlice() []T func (s stream[T]) ToSlice() []T
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jI6_iZZuVFE)</span></b>
```go ```go
import ( import (

576
docs/api/packages/struct.md Normal file
View File

@@ -0,0 +1,576 @@
# Structs
structs 包封装了一个抽象的`Struct`结构体,提供了操作`struct`的相关函数
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/structs/struct.go](https://github.com/duke-git/lancet/blob/main/structs/struct.go)
- [https://github.com/duke-git/lancet/blob/main/structs/field.go](https://github.com/duke-git/lancet/blob/main/structs/field.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/structs"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录:
- [New](#New)
- [ToMap](#ToMap)
- [Fields](#Fields)
- [Field](#Field)
- [IsStruct](#IsStruct)
- [Tag](#Tag)
- [Name](#Name)
- [Value](#Value)
- [Kind](#Kind)
- [IsEmbedded](#IsEmbedded)
- [IsExported](#IsExported)
- [IsZero](#IsZero)
- [IsSlice](#IsSlice)
- [IsTargetType](#IsTargetType)
<div STYLE="page-break-after: always;"></div>
## API 文档:
### <span id="New">New</span>
<p>`Struct`结构体的构造函数</p>
<b>函数签名:</b>
```go
func New(value any, tagName ...string) *Struct
```
<b>示例:</b>
```go
package main
import (
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
// to do something
}
```
### <span id="ToMap">ToMap</span>
<p>将一个合法的struct对象转换为map[string]any</p>
<b>函数签名:</b>
```go
func (s *Struct) ToMap() (map[string]any, error)
```
<b>除此之外,提供一个便捷的静态方法 ToMap</b>
```go
func ToMap(v any) (map[string]any, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s1 := structs.New(p1)
m1, _ := s1.ToMap()
fmt.Println(m1)
// 如果不需要Struct更多的方法可以直接使用ToMap
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
}
```
### <span id="Fields">Fields</span>
<p>获取一个struct对象的属性列表</p>
<b>函数签名:</b>
```go
func (s *Struct) Fields() []*Field
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fields := s.Fields()
fmt.Println(len(fields))
// Output:
// 1
}
```
### <span id="Field">Field</span>
<p>根据属性名获取一个struct对象的属性</p>
<b>函数签名:</b>
```go
func (s *Struct) Field(name string) *Field
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
f := s.Field("Name")
fmt.Println(f.Value())
// Output:
// 11
}
```
### <span id="IsStruct">IsStruct</span>
<p>判断是否为一个合法的struct对象</p>
<b>函数签名:</b>
```go
func (s *Struct) IsStruct() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fmt.Println(s.IsStruct())
// Output:
// true
}
```
### <span id="Tag">Tag</span>
<p>获取`Field``Tag`默认的tag key是json</p>
<b>函数签名:</b>
```go
func (f *Field) Tag() *Tag
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
tag := n.Tag()
fmt.Println(tag.Name)
// Output:
// name
}
```
### <span id="Value">Value</span>
<p>获取`Field`属性的值</p>
<b>函数签名:</b>
```go
func (f *Field) Value() any
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
fmt.Println(n.Value())
// Output:
// 111
}
```
### <span id="IsEmbedded">IsEmbedded</span>
<p>判断属性是否为嵌入</p>
<b>函数签名:</b>
```go
func (f *Field) IsEmbedded() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
c1 := &Child{}
c1.Name = "111"
c1.Age = 11
s := structs.New(c1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsEmbedded())
fmt.Println(a.IsEmbedded())
// Output:
// true
// false
}
```
### <span id="IsExported">IsExported</span>
<p>判断属性是否导出</p>
<b>函数签名:</b>
```go
func (f *Field) IsExported() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
age int
}
p1 := &Parent{Name: "11", age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("age")
fmt.Println(n.IsExported())
fmt.Println(a.IsExported())
// Output:
// true
// false
}
```
### <span id="IsZero">IsZero</span>
<p>判断属性是否为零值</p>
<b>函数签名:</b>
```go
func (f *Field) IsZero() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsZero())
fmt.Println(a.IsZero())
// Output:
// true
// false
}
```
### <span id="Name">Name</span>
<p>获取属性名</p>
<b>函数签名:</b>
```go
func (f *Field) Name() string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Name())
fmt.Println(a.Name())
// Output:
// Name
// Age
}
```
### <span id="Kind">Kind</span>
<p>获取属性Kind</p>
<b>函数签名:</b>
```go
func (f *Field) Kind() reflect.Kind
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Kind())
fmt.Println(a.Kind())
// Output:
// string
// int
}
```
### <span id="IsSlice">IsSlice</span>
<p>判断属性是否是切片</p>
<b>函数签名:</b>
```go
func (f *Field) IsSlice() bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
arr []int
}
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
a, _ := s.Field("arr")
fmt.Println(a.IsSlice())
// Output:
// true
}
```
### <span id="IsTargetType">IsTargetType</span>
<p>判断属性是否是目标类型</p>
<b>函数签名:</b>
```go
func (f *Field) IsTargetType(targetType reflect.Kind) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"reflect"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
arr []int
}
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("arr")
fmt.Println(n.IsTargetType(reflect.String))
fmt.Println(a.IsTargetType(reflect.Slice))
// Output:
// true
// true
}
```

View File

@@ -49,16 +49,24 @@ import (
- [StringToBytes](#StringToBytes) - [StringToBytes](#StringToBytes)
- [BytesToString](#BytesToString) - [BytesToString](#BytesToString)
- [IsBlank](#IsBlank) - [IsBlank](#IsBlank)
- [IsNotBlank](#IsNotBlank)
- [HasPrefixAny](#HasPrefixAny) - [HasPrefixAny](#HasPrefixAny)
- [HasSuffixAny](#HasSuffixAny) - [HasSuffixAny](#HasSuffixAny)
- [IndexOffset](#IndexOffset) - [IndexOffset](#IndexOffset)
- [ReplaceWithMap](#ReplaceWithMap) - [ReplaceWithMap](#ReplaceWithMap)
- [Trim](#Trim) - [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim) - [SplitAndTrim](#SplitAndTrim)
- [HideString](#HideString)
- [ContainsAll](#ContainsAll)
- [ContainsAny](#ContainsAny)
- [RemoveWhiteSpace](#RemoveWhiteSpace)
- [SubInBetween](#SubInBetween)
- [HammingDistance](#HammingDistance)
- [Concat](#Concat)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation 文档 ## 文档
### <span id="After">After</span> ### <span id="After">After</span>
@@ -70,7 +78,7 @@ import (
func After(s, char string) string func After(s, char string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/RbCOQqCDA7m)</span></b>
```go ```go
import ( import (
@@ -110,7 +118,7 @@ func main() {
func AfterLast(s, char string) string func AfterLast(s, char string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/1TegARrb8Yn)</span></b>
```go ```go
import ( import (
@@ -150,7 +158,7 @@ func main() {
func Before(s, char string) string func Before(s, char string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/JAWTZDS4F5w)</span></b>
```go ```go
import ( import (
@@ -187,7 +195,7 @@ func main() {
func BeforeLast(s, char string) string func BeforeLast(s, char string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pJfXXAoG_Te)</span></b>
```go ```go
import ( import (
@@ -224,7 +232,7 @@ func main() {
func CamelCase(s string) string func CamelCase(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9eXP3tn2tUy)</span></b>
```go ```go
import ( import (
@@ -259,7 +267,7 @@ func main() {
func KebabCase(s string) string func KebabCase(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dcZM9Oahw-Y)</span></b>
```go ```go
import ( import (
@@ -294,7 +302,7 @@ func main() {
func UpperKebabCase(s string) string func UpperKebabCase(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/zDyKNneyQXk)</span></b>
```go ```go
import ( import (
@@ -329,7 +337,7 @@ func main() {
func Capitalize(s string) string func Capitalize(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2OAjgbmAqHZ)</span></b>
```go ```go
import ( import (
@@ -364,7 +372,7 @@ func main() {
func IsString(v any) bool func IsString(v any) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/IOgq7oF9ERm)</span></b>
```go ```go
import ( import (
@@ -404,7 +412,7 @@ func main() {
func LowerFirst(s string) string func LowerFirst(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CbzAyZmtJwL)</span></b>
```go ```go
import ( import (
@@ -438,7 +446,7 @@ func main() {
func UpperFirst(s string) string func UpperFirst(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sBbBxRbs8MM)</span></b>
```go ```go
import ( import (
@@ -472,7 +480,7 @@ func main() {
func Pad(source string, size int, padStr string) string func Pad(source string, size int, padStr string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/NzImQq-VF8q)</span></b>
```go ```go
import ( import (
@@ -517,7 +525,7 @@ func main() {
func PadEnd(source string, size int, padStr string) string func PadEnd(source string, size int, padStr string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/9xP8rN0vz--)</span></b>
```go ```go
import ( import (
@@ -563,7 +571,7 @@ func main() {
func PadStart(source string, size int, padStr string) string func PadStart(source string, size int, padStr string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/xpTfzArDfvT)</span></b>
```go ```go
import ( import (
@@ -609,7 +617,7 @@ func main() {
func Reverse(s string) string func Reverse(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/adfwalJiecD)</span></b>
```go ```go
import ( import (
@@ -640,7 +648,7 @@ func main() {
func SnakeCase(s string) string func SnakeCase(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tgzQG11qBuN)</span></b>
```go ```go
import ( import (
@@ -672,10 +680,10 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func SnakeCase(s string) string func UpperSnakeCase(s string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4COPHpnLx38)</span></b>
```go ```go
import ( import (
@@ -710,7 +718,7 @@ func main() {
func SplitEx(s, sep string, removeEmptyString bool) []string func SplitEx(s, sep string, removeEmptyString bool) []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Us-ySSbWh-3)</span></b>
```go ```go
import ( import (
@@ -751,7 +759,7 @@ func main() {
func Substring(s string, offset int, length uint) string func Substring(s string, offset int, length uint) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/q3sM6ehnPDp)</span></b>
```go ```go
import ( import (
@@ -794,7 +802,7 @@ func main() {
func Wrap(str string, wrapWith string) string func Wrap(str string, wrapWith string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KoZOlZDDt9y)</span></b>
```go ```go
import ( import (
@@ -821,7 +829,7 @@ func main() {
} }
``` ```
### <span id="Wrap">Wrap</span> ### <span id="Unwrap">Unwrap</span>
<p>用另一个字符串解开包裹一个字符串。</p> <p>用另一个字符串解开包裹一个字符串。</p>
@@ -831,7 +839,7 @@ func main() {
func Unwrap(str string, wrapToken string) string func Unwrap(str string, wrapToken string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Ec2q4BzCpG-)</span></b>
```go ```go
import ( import (
@@ -871,7 +879,7 @@ func main() {
func SplitWords(s string) []string func SplitWords(s string) []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KLiX4WiysMM)</span></b>
```go ```go
import ( import (
@@ -914,7 +922,7 @@ func main() {
func WordCount(s string) int func WordCount(s string) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/bj7_odx3vRf)</span></b>
```go ```go
import ( import (
@@ -957,7 +965,7 @@ func main() {
func RemoveNonPrintable(str string) string func RemoveNonPrintable(str string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/og47F5x_jTZ)</span></b>
```go ```go
import ( import (
@@ -971,7 +979,7 @@ func main() {
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
// Output: // Output:
// hello world // hello world
// 你好😄 // 你好😄
@@ -988,7 +996,7 @@ func main() {
func StringToBytes(str string) (b []byte) func StringToBytes(str string) (b []byte)
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7OyFBrf9AxA)</span></b>
```go ```go
import ( import (
@@ -998,13 +1006,13 @@ import (
func main() { func main() {
result1 := strutil.StringToBytes("abc") result1 := strutil.StringToBytes("abc")
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'}) result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
// Output: // Output:
// [97 98 99] // [97 98 99]
// true // true
} }
``` ```
@@ -1018,7 +1026,7 @@ func main() {
func BytesToString(bytes []byte) string func BytesToString(bytes []byte) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6c68HRvJecH)</span></b>
```go ```go
import ( import (
@@ -1028,12 +1036,12 @@ import (
func main() { func main() {
bytes := []byte{'a', 'b', 'c'} bytes := []byte{'a', 'b', 'c'}
result := strutil.BytesToString(bytes) result := strutil.BytesToString(bytes)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// abc // abc
} }
``` ```
@@ -1047,7 +1055,7 @@ func main() {
func IsBlank(str string) bool func IsBlank(str string) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6zXRH_c0Qd3)</span></b>
```go ```go
import ( import (
@@ -1057,17 +1065,56 @@ import (
func main() { func main() {
result1 := strutil.IsBlank("") result1 := strutil.IsBlank("")
result2 := strutil.IsBlank("\t\v\f\n") result2 := strutil.IsBlank("\t\v\f\n")
result3 := strutil.IsBlank(" 中文") result3 := strutil.IsBlank(" 中文")
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
// Output: // Output:
// true // true
// true // true
// false // false
}
```
### <span id="IsNotBlank">IsNotBlank</span>
<p>Checks if a string is not whitespace or not empty.</p>
<b>函数签名:</b>
```go
func IsNotBlank(str string) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/e_oJW0RAquA)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.IsNotBlank("")
result2 := strutil.IsNotBlank(" ")
result3 := strutil.IsNotBlank("\t\v\f\n")
result4 := strutil.IsNotBlank(" 中文")
result5 := strutil.IsNotBlank(" world ")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// false
// false
// false
// true
// true
} }
``` ```
@@ -1081,7 +1128,7 @@ func main() {
func HasPrefixAny(str string, prefixes []string) bool func HasPrefixAny(str string, prefixes []string) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8UUTl2C5slo)</span></b>
```go ```go
import ( import (
@@ -1091,14 +1138,14 @@ import (
func main() { func main() {
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"}) result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"}) result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
// Output: // Output:
// true // true
// false // false
} }
``` ```
@@ -1112,7 +1159,7 @@ func main() {
func HasSuffixAny(str string, suffixes []string) bool func HasSuffixAny(str string, suffixes []string) bool
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sKWpCQdOVkx)</span></b>
```go ```go
import ( import (
@@ -1122,14 +1169,14 @@ import (
func main() { func main() {
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"}) result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"}) result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
// Output: // Output:
// true // true
// false // false
} }
``` ```
@@ -1143,7 +1190,7 @@ func main() {
func IndexOffset(str string, substr string, idxFrom int) int func IndexOffset(str string, substr string, idxFrom int) int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qZo4lV2fomB)</span></b>
```go ```go
import ( import (
@@ -1154,28 +1201,27 @@ import (
func main() { func main() {
str := "foo bar hello world" str := "foo bar hello world"
result1 := strutil.IndexOffset(str, "o", 5) result1 := strutil.IndexOffset(str, "o", 5)
result2 := strutil.IndexOffset(str, "o", 0) result2 := strutil.IndexOffset(str, "o", 0)
result3 := strutil.IndexOffset(str, "d", len(str)-1) result3 := strutil.IndexOffset(str, "d", len(str)-1)
result4 := strutil.IndexOffset(str, "d", len(str)) result4 := strutil.IndexOffset(str, "d", len(str))
result5 := strutil.IndexOffset(str, "f", -1) result5 := strutil.IndexOffset(str, "f", -1)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4) fmt.Println(result4)
fmt.Println(result5) fmt.Println(result5)
// Output: // Output:
// 12 // 12
// 1 // 1
// 18 // 18
// -1 // -1
// -1 // -1
} }
``` ```
### <span id="ReplaceWithMap">ReplaceWithMap</span> ### <span id="ReplaceWithMap">ReplaceWithMap</span>
<p>返回`str`的副本以无序的方式被map替换区分大小写。</p> <p>返回`str`的副本以无序的方式被map替换区分大小写。</p>
@@ -1186,7 +1232,7 @@ func main() {
func ReplaceWithMap(str string, replaces map[string]string) string func ReplaceWithMap(str string, replaces map[string]string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/h3t7CNj2Vvu)</span></b>
```go ```go
import ( import (
@@ -1196,16 +1242,16 @@ import (
func main() { func main() {
str := "ac ab ab ac" str := "ac ab ab ac"
replaces := map[string]string{ replaces := map[string]string{
"a": "1", "a": "1",
"b": "2", "b": "2",
} }
result := strutil.ReplaceWithMap(str, replaces) result := strutil.ReplaceWithMap(str, replaces)
fmt.Println(result) fmt.Println(result)
// Output: // Output:
// 1c 12 12 1c // 1c 12 12 1c
} }
``` ```
@@ -1219,7 +1265,7 @@ func main() {
func Trim(str string, characterMask ...string) string func Trim(str string, characterMask ...string) string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Y0ilP0NRV3j)</span></b>
```go ```go
import ( import (
@@ -1230,23 +1276,22 @@ import (
func main() { func main() {
result1 := strutil.Trim("\nabcd") result1 := strutil.Trim("\nabcd")
str := "$ ab cd $ " str := "$ ab cd $ "
result2 := strutil.Trim(str) result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$") result3 := strutil.Trim(str, "$")
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
// Output: // Output:
// abcd // abcd
// $ ab cd $ // $ ab cd $
// ab cd // ab cd
} }
``` ```
### <span id="SplitAndTrim">SplitAndTrim</span> ### <span id="SplitAndTrim">SplitAndTrim</span>
<p>将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p> <p>将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p>
@@ -1257,7 +1302,7 @@ func main() {
func SplitAndTrim(str, delimiter string, characterMask ...string) []string func SplitAndTrim(str, delimiter string, characterMask ...string) []string
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ZNL6o4SkYQ7)</span></b>
```go ```go
import ( import (
@@ -1268,14 +1313,254 @@ import (
func main() { func main() {
str := " a,b, c,d,$1 " str := " a,b, c,d,$1 "
result1 := strutil.SplitAndTrim(str, ",") result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$") result2 := strutil.SplitAndTrim(str, ",", "$")
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
// Output: // Output:
// [a b c d $1] // [a b c d $1]
// [a b c d 1] // [a b c d 1]
} }
``` ```
### <span id="HideString">HideString</span>
<p>使用参数`replaceChar`隐藏源字符串中的一些字符。替换范围是 origin[start : end]。</p>
<b>函数签名:</b>
```go
func HideString(origin string, start, end int, replaceChar string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/pzbaIVCTreZ)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "13242658976"
result1 := strutil.HideString(str, 3, 3, "*")
result2 := strutil.HideString(str, 3, 4, "*")
result3 := strutil.HideString(str, 3, 7, "*")
result4 := strutil.HideString(str, 7, 11, "*")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 13242658976
// 132*2658976
// 132****8976
// 1324265****
}
```
### <span id="ContainsAll">ContainsAll</span>
<p>判断字符串是否包括全部给定的子字符串切片。</p>
<b>函数签名:</b>
```go
func ContainsAll(str string, substrs []string) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/KECtK2Os4zq)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="ContainsAny">ContainsAny</span>
<p>判断字符串是否包括给定的子字符串切片中任意一个子字符串。</p>
<b>函数签名:</b>
```go
func ContainsAny(str string, substrs []string) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dZGSSMB3LXE)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
<p>删除字符串中的空格当设置repalceAll为true时删除全部空格为false时替换多个空格为1个空格。</p>
<b>函数签名:</b>
```go
func RemoveWhiteSpace(str string, repalceAll bool) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HzLC9vsTwkf)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := " hello \r\n \t world"
result1 := strutil.RemoveWhiteSpace(str, true)
result2 := strutil.RemoveWhiteSpace(str, false)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// helloworld
// hello world
}
```
### <span id="SubInBetween">SubInBetween</span>
<p>获取字符串中指定的起始字符串start和终止字符串end直接的子字符串。</p>
<b>函数签名:</b>
```go
func SubInBetween(str string, start string, end string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/EDbaRvjeNsv)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "abcde"
result1 := strutil.SubInBetween(str, "", "de")
result2 := strutil.SubInBetween(str, "a", "d")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// abc
// bc
}
```
### <span id="HammingDistance">HammingDistance</span>
<p>计算两个字符串之间的汉明距离。汉明距离是指对应符号不同的位置数。</p>
<b>函数签名:</b>
```go
func HammingDistance(a, b string) (int, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/glNdQEA9HUi)</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1, _ := strutil.HammingDistance("de", "de")
result2, _ := strutil.HammingDistance("a", "d")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// 1
}
```
### <span id="Concat">Concat</span>
<p>拼接字符串。length是拼接后字符串的长度如果不确定则传0或负数。</p>
<b>函数签名:</b>
```go
func Concat(length int, str ...string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
result2 := strutil.Concat(11, "Go", " ", "Language")
result3 := strutil.Concat(0, "An apple a ", "day", "keeps the", " doctor away")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// Hello World!
// Go Language
// An apple a daykeeps the doctor away
}
```

View File

@@ -34,19 +34,19 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation 文档 ## 文档
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p> <p>检查当前操作系统是否是windows</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zIflQgZNuxD)</span></b>
```go ```go
import ( import (
@@ -64,13 +64,13 @@ func main() {
<p>检查当前操作系统是否是linux</p> <p>检查当前操作系统是否是linux</p>
<b>Signature:</b> <b>函数签名:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/zIflQgZNuxD)</span></b>
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>示例:</b>
```go ```go
import ( import (
@@ -88,13 +88,13 @@ func main() {
<p>检查当前操作系统是否是macos</p> <p>检查当前操作系统是否是macos</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/Mg4Hjtyq7Zc)</span></b>
```go ```go
import ( import (
@@ -112,13 +112,13 @@ func main() {
<p>获取key命名的环境变量的值</p> <p>获取key命名的环境变量的值</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/D88OYVCyjO-)</span></b>
```go ```go
import ( import (
@@ -142,13 +142,13 @@ func main() {
<p>设置由key命名的环境变量的值</p> <p>设置由key命名的环境变量的值</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/D88OYVCyjO-)</span></b>
```go ```go
import ( import (
@@ -172,13 +172,13 @@ func main() {
<p>删除单个环境变量</p> <p>删除单个环境变量</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/fqyq4b3xUFQ)</span></b>
```go ```go
import ( import (
@@ -210,13 +210,13 @@ func main() {
<p>获取key命名的环境变量值并与compareEnv进行比较</p> <p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/BciHrKYOHbp)</span></b>
```go ```go
import ( import (
@@ -243,7 +243,7 @@ func main() {
<p>执行shell命令返回命令的stdout和stderr字符串如果出现错误则返回错误。参数`command`是一个完整的命令字符串如ls-alinuxdirwindowsping 127.0.0.1。在linux中使用/bin/bash-c执行命令在windows中使用powershell.exe执行命令。</p> <p>执行shell命令返回命令的stdout和stderr字符串如果出现错误则返回错误。参数`command`是一个完整的命令字符串如ls-alinuxdirwindowsping 127.0.0.1。在linux中使用/bin/bash-c执行命令在windows中使用powershell.exe执行命令。</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
type ( type (
@@ -252,7 +252,7 @@ type (
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error) func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/n-2fLyZef-4)</span></b>
```go ```go
import ( import (
@@ -292,7 +292,7 @@ func main() {
func GetOsBits() int func GetOsBits() int
``` ```
<b>示例:</b> <b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/ml-_XH3gJbW)</span></b>
```go ```go
import ( import (

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