1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

Compare commits

...

290 Commits

Author SHA1 Message Date
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
dudaodong
3beb769f09 release v2.2.0 2023-05-18 10:53:02 +08:00
dudaodong
8af02ff95b doc: update readme file 2023-05-18 10:51:33 +08:00
dudaodong
ba4485d8c0 merge main 2023-05-18 10:32:36 +08:00
dudaodong
8a1dd40738 doc: add doc for AddYear function 2023-05-18 10:27:37 +08:00
dudaodong
85e2806531 doc: add doc for FindLast 2023-05-18 10:21:24 +08:00
will
1616d3d1be feat:addFindLast for stream (#95)
Co-authored-by: sunyaoyao <sunyaoyao@kezaihui.com>
2023-05-18 10:17:15 +08:00
tlei995
aa8e0d5c12 feat:add AddYear func (#96)
Co-authored-by: leitao <leitao@kezaihui.com>
2023-05-18 10:14:23 +08:00
dudaodong
f05477d9cf fix: update logic of Percent function 2023-05-18 10:11:48 +08:00
dudaodong
cd91e16b26 doc: update document for strutil and convertor package 2023-05-11 10:06:32 +08:00
dudaodong
9fcf046fb3 feat: add Trim and SplitAndTrim 2023-05-10 10:53:17 +08:00
dudaodong
c3f1bc39d7 feat: add ReplaceWithMap 2023-05-10 10:29:26 +08:00
dudaodong
f5784b0f46 feat: add ReplaceByMap 2023-05-10 10:03:13 +08:00
dudaodong
c86a8a479d feat: add ToInterface 2023-05-09 12:01:57 +08:00
dudaodong
e2aeb8ec07 doc: add document for GCD and LCM function 2023-05-06 11:28:38 +08:00
dudaodong
654ba15aaf feat: add GCD and LCM function 2023-05-06 11:02:00 +08:00
dudaodong
945c59896b feat: add IsLeapYear 2023-04-28 14:42:25 +08:00
dudaodong
219e31d929 fix: fix format issue 2023-04-27 15:49:58 +08:00
dudaodong
82cb86b35c doc: add go playground demo for compare package 2023-04-27 14:15:25 +08:00
dudaodong
f93c561f5d doc: update go playground demo 2023-04-27 12:03:15 +08:00
dudaodong
4888909208 fix: fix IsPingConnected failed in windows 2023-04-26 19:53:53 +08:00
dudaodong
33c8875d14 test: update TestWordCount 2023-04-26 19:35:28 +08:00
dudaodong
99cb1b13a3 test: remove unstable test item 2023-04-26 18:14:27 +08:00
dudaodong
42ec189995 release v2.1.20 2023-04-26 18:03:52 +08:00
dudaodong
424c291813 test: add TestExecCommandWithOption 2023-04-26 17:53:20 +08:00
dudaodong
4311b9ac66 test: remove t.Log() 2023-04-26 14:59:45 +08:00
dudaodong
581e338889 doc: add new function to readme file 2023-04-26 14:31:47 +08:00
dudaodong
f399425c2a doc: add document for compare package 2023-04-26 11:02:11 +08:00
dudaodong
dcdb29334d doc: update fileutils package document 2023-04-26 10:44:12 +08:00
dudaodong
4859f3ca23 test: add examples for compare package 2023-04-26 10:19:42 +08:00
dudaodong
9f2528842e feat: add unit test for compare package 2023-04-26 10:05:09 +08:00
dudaodong
6066d6669f feat: add compare package 2023-04-25 18:01:05 +08:00
dudaodong
e3804e9534 test: add test.csv file 2023-04-25 11:34:09 +08:00
dudaodong
2f51397d2c feat: add ReadCsvFile 2023-04-25 11:28:43 +08:00
dudaodong
11217a11c7 feat: add FileSize, MTime, Sha 2023-04-25 11:16:00 +08:00
dudaodong
fa81ee143e refactor: update param name CopyFile 2023-04-25 10:49:12 +08:00
dudaodong
62891f20f8 feat: add IsZipFile 2023-04-24 14:00:53 +08:00
dudaodong
5e79eaa9dd feat: add IsZipFile 2023-04-24 11:00:58 +08:00
dudaodong
aaf45012e4 fix: refact CopyProperties 2023-04-22 14:14:13 +08:00
dudaodong
48c17ea1ce fix: update params in TestIsPingConnected 2023-04-19 17:40:55 +08:00
dudaodong
e90283c3f9 fix: update params in TestIsPingConnected 2023-04-19 17:35:17 +08:00
dudaodong
f82c4a305d fix: update params in TestIsPingConnected 2023-04-19 17:32:30 +08:00
dudaodong
05997603a9 doc: add document for DownloadFile and UploadFile 2023-04-19 16:16:47 +08:00
dudaodong
6d5ec807f7 test: comment some test case 2023-04-19 16:04:35 +08:00
dudaodong
f73c7e7e86 doc: add document and example for IsPingConnected and IsTelnetConnected 2023-04-19 11:48:28 +08:00
dudaodong
c137428b9e feat: add IsPingConnected and IsTelnetConnected 2023-04-19 11:14:10 +08:00
dudaodong
9f68620b37 feat: add IsPingConnected and IsTelnetConnected 2023-04-19 11:13:21 +08:00
dudaodong
2cdbba56a4 feat: add UploadFile and DownloadFile 2023-04-18 20:09:56 +08:00
dudaodong
01a3b139c0 doc: add document for new functions in slice and strutil package 2023-04-18 15:49:09 +08:00
dudaodong
fcb3b97b45 doc: add docment and playground demo for v2.1.19 2023-04-18 15:21:03 +08:00
dudaodong
52ea64bc33 feat: add FindLastBy function 2023-04-17 20:17:26 +08:00
燕归来
14bc08c6d6 feat: add FindBy that a result will be without unrefrence #88 (#90)
feat: add example for FindBy

chore: reduce code duplication
2023-04-17 20:11:56 +08:00
dudaodong
47bdd6718a fix: ExecCommand can't compile in macos 2023-04-17 17:03:46 +08:00
dudaodong
18d27604e6 update mod file 2023-04-17 17:00:53 +08:00
dudaodong
66bd339e3a doc: add example for strutil new functions 2023-04-17 16:35:26 +08:00
燕归来
04abb7a3ea feat: add some function for strutil package #88 (#89) 2023-04-17 16:07:14 +08:00
dudaodong
975c303a31 fix: ExampleListFileNames 2023-04-17 15:35:17 +08:00
dudaodong
3b8dd94a5c fix: TestListFileNames 2023-04-17 15:32:59 +08:00
dudaodong
815791c0b6 Merge branch 'main' into v2 2023-04-17 15:28:37 +08:00
dudaodong
a12a691ee6 release v2.1.19 2023-04-17 15:28:01 +08:00
Nothin
247cf89947 [FEATURE] system add option (#87) 2023-04-17 14:06:49 +08:00
dudaodong
c3fad62d8c doc: update stream package document 2023-04-17 13:53:47 +08:00
dudaodong
a8a96be21b doc: update doc for new added functions 2023-04-17 11:34:17 +08:00
dudaodong
8e297769b2 fix: fix example comment of MapTo function 2023-04-17 11:06:03 +08:00
dudaodong
98cdf1c040 Merge branch 'main' into v2 2023-04-17 10:38:28 +08:00
dudaodong
d7976e31a4 refactor: move typemap.go to maputil package and add document for it 2023-04-17 10:37:56 +08:00
dudaodong
5b11a8b457 refactor: move typemap.go to maputil package and add document for it 2023-04-17 10:36:59 +08:00
Nothin
d4a16534f2 add typemap (#85)
* [FEATURE] typemap, quick map any type to specified type

* [DOC] add more test case

---------

Co-authored-by: zhijian.chen <zhijian.chen@longsys.com>
2023-04-17 10:04:31 +08:00
dudaodong
ecf0688788 update readme file 2023-04-07 17:39:54 +08:00
dudaodong
90f9cad1ea update readme file 2023-04-07 15:23:34 +08:00
dudaodong
4a298876e9 doc: add docment and example for byte.go 2023-04-07 14:53:48 +08:00
dudaodong
74474cd9ef feat: add feature for humanize byte unit 2023-04-07 14:18:28 +08:00
dudaodong
f23f18457e feat: add Pretty and PrettyToWriter 2023-04-06 16:30:38 +08:00
dudaodong
18f01ffd75 doc: update doc and example for validator 2023-04-06 10:46:31 +08:00
dudaodong
c53d541a6b doc: add document for stream package 2023-04-05 20:17:41 +08:00
dudaodong
5b9b4c4344 test: add example for stream package 2023-04-05 18:52:27 +08:00
dudaodong
6e7300bbbf feat: add CurrentPath 2023-04-05 15:55:55 +08:00
dudaodong
3685aee02b fix: fix bug of Comma function 2023-04-05 14:26:42 +08:00
dudaodong
046f3e0bf9 feat: add IsInt, IsFloat, IsNumber 2023-04-05 14:07:23 +08:00
dudaodong
c01c9d14b4 feat: add ReduceRight 2023-04-04 17:54:54 +08:00
dudaodong
f198191063 feat: add ReduceBy 2023-04-04 17:41:37 +08:00
dudaodong
8bdd46bda4 doc: add play ground demo 2023-04-03 10:33:57 +08:00
dudaodong
e29b56c3c3 release v2.1.18 2023-04-03 10:12:50 +08:00
dudaodong
c357fc68c8 doc: update readme file for new feature 2023-04-03 10:12:13 +08:00
dudaodong
bc25e7a037 feat: add IsPrintable 2023-03-31 12:00:32 +08:00
dudaodong
217350042b feat: add RemoveNonPrintable 2023-03-30 14:52:32 +08:00
dudaodong
e56a8a1ef5 feat: add IsASCII 2023-03-30 14:41:32 +08:00
dudaodong
6453f755a6 doc: add doc for IsPrime 2023-03-30 14:09:05 +08:00
dudaodong
027abd6ad5 feat: add IsPrime 2023-03-30 11:54:20 +08:00
dudaodong
91503b1656 comment TestEachWithBreak 2023-03-29 10:31:38 +08:00
dudaodong
e2522cd29b fix: fix TestEachWithBreak case 2023-03-29 10:24:41 +08:00
dudaodong
da69b77892 Merge branch 'main' of github.com:duke-git/lancet 2023-03-29 10:15:56 +08:00
dudaodong
05772d8d7d comment TestEachWithBreak 2023-03-28 20:08:05 +08:00
Mickls
3b497532f3 fix: The LastIndexOf method can never return the index of the first element (#83)
Co-authored-by: JiangCheng <jiangcheng@kezaihui.com>
2023-03-28 20:02:57 +08:00
dudaodong
1cd3be508c refactor rename async package name to 2023-03-24 11:43:56 +08:00
dudaodong
a41d461910 doc: update mathutil package doc 2023-03-24 11:23:45 +08:00
dudaodong
cde5946bf0 feat: add PointDistance 2023-03-23 17:49:07 +08:00
dudaodong
c28803b25e feat: add AngleToRadian and RadianToAngle 2023-03-23 17:41:31 +08:00
dudaodong
f09e521783 doc: add go playground demo 2023-03-22 21:06:01 +08:00
dudaodong
0aa41f337d fix: test failed 2023-03-20 16:39:56 +08:00
dudaodong
48814a720a fix: test failed in promise test 2023-03-20 16:26:21 +08:00
dudaodong
04b79b3dfe release v2.1.17 2023-03-20 16:17:52 +08:00
dudaodong
302007ebdf doc: update readme file for new feature 2023-03-20 16:12:58 +08:00
dudaodong
965e5fbcda feat: add Pop for set 2023-03-20 11:10:35 +08:00
dudaodong
70d0adde42 feat: add EachWithBreak for set 2023-03-20 10:49:14 +08:00
dudaodong
0b80074bb7 refactor: remove unused code 2023-03-20 10:35:37 +08:00
dudaodong
90945a0399 Merge branch 'main' into v2 2023-03-18 19:35:48 +08:00
zm
47dccd63af add the struct package english docs (#82) 2023-03-18 19:33:07 +08:00
dudaodong
4ae7e59829 feat: add example for promise 2023-03-17 16:03:35 +08:00
dudaodong
8f0c60cade test: add unit test for promise Race and Any function 2023-03-17 13:59:18 +08:00
dudaodong
3f6aef1432 fix: fix bug of IsNotNil function 2023-03-16 19:15:36 +08:00
dudaodong
a714e04470 test: add unit test for promise.All function 2023-03-16 19:11:30 +08:00
dudaodong
7456621153 fix: fix bug of IsNil function 2023-03-16 17:01:28 +08:00
dudaodong
73ac9825e9 test: add unit test for Promise 2023-03-16 16:55:32 +08:00
dudaodong
930bb9c839 feat: complete promise Any function 2023-03-16 15:59:06 +08:00
dudaodong
3d8f1be212 feat: add error_join.go to support join error under go1.19, for internal use. 2023-03-16 15:56:54 +08:00
dudaodong
13a4ed59fa doc: update comment for concurrency package 2023-03-16 15:35:26 +08:00
dudaodong
c799d10ce9 feat: add promise All, Race, Any methods 2023-03-16 15:34:28 +08:00
dudaodong
5ab322ade2 feat: add async package, promise implemention 2023-03-16 14:49:07 +08:00
dudaodong
d0ffc61842 doc: fix doc error 2023-03-16 10:36:06 +08:00
zm
5e66bc6227 [structs] change package structutil to structs (#81)
* refactor package structutil to structs

* add structs package zh-CN docs
2023-03-15 19:14:19 +08:00
dudaodong
7261b281ad refactor: add function comment for tag.go 2023-03-15 17:43:47 +08:00
dudaodong
f79693804b refactor: make package variable defaultTagName unexported 2023-03-15 15:08:56 +08:00
dudaodong
534c7a0abc refactor: make errInvalidStruct exported, change error.go to struct_internal.go 2023-03-15 14:58:34 +08:00
dudaodong
4eaff47d38 Merge branch 'main' into v2 2023-03-15 14:43:48 +08:00
dudaodong
3e019522c7 doc: add doc for ForEachWithBreak 2023-03-15 14:42:22 +08:00
dudaodong
0734f220b3 feat: add ForEachWithBreak support break for each loop 2023-03-15 14:38:33 +08:00
zm
2d2c277090 [StructUtil] add support that the Struct can nest any type to transform (#80)
* add support json tag attribute for StructToMap function

* add the structutil to provide more rich functions and fixed #77

* add support that the nested struct to map for structutil

* recover code

* add structutil unit test

* [StructUtil] add unit test
2023-03-15 14:26:34 +08:00
dudaodong
ef1e548dfc merge main 2023-03-13 19:44:44 +08:00
zm
924589d2da Add StructUtil for provide more rich functions (#79)
* add support json tag attribute for StructToMap function

* add the structutil to provide more rich functions and fixed #77
2023-03-13 19:28:37 +08:00
dudaodong
77f32f4cc6 Merge branch 'main' into v2 2023-03-11 20:14:32 +08:00
zm
1755dd249b add support json tag attribute for StructToMap function (#78) 2023-03-11 20:08:41 +08:00
dudaodong
7a25688ec1 doc: add doc for Range and RangeWithStep 2023-03-09 17:13:51 +08:00
dudaodong
51a6912eb3 feat: add RangeWithStep function 2023-03-06 18:05:58 +08:00
dudaodong
28d0428b50 feat: add Range function 2023-03-06 17:49:56 +08:00
dudaodong
6a9eb645bb fix: fix StructToUrlValues failed when tag contain omitempty 2023-03-06 17:07:57 +08:00
dudaodong
3857b342f6 fix: fix ExampleContext failed 2023-03-01 11:45:02 +08:00
dudaodong
71aa91a58d doc: add go playground demo 2023-03-01 11:39:27 +08:00
dudaodong
081908bce3 fix: fix goline error 2023-03-01 11:10:12 +08:00
dudaodong
66efe61834 release v2.1.16 2023-03-01 10:08:53 +08:00
dudaodong
94f7f3e0e5 doc: add new function docs 2023-02-28 15:03:02 +08:00
dudaodong
9d2c9806d1 feat: add ContainBy function 2023-02-24 14:19:10 +08:00
dudaodong
e523d4af6e doc: add doc for FilterMap and FlatMap 2023-02-24 11:23:02 +08:00
dudaodong
f3801bcd8f feat: add FlatMap 2023-02-24 11:14:59 +08:00
dudaodong
5767aad303 feat: add FilterMap 2023-02-24 10:55:27 +08:00
dudaodong
f7aaa1ed2a fix: fix issue #75 2023-02-23 11:43:41 +08:00
dudaodong
ef19a414bc doc: fix doc error 2023-02-23 10:58:43 +08:00
dudaodong
65704dea06 doc: fix doc error 2023-02-23 10:57:48 +08:00
dudaodong
5eac358bb0 doc: format code in doc file 2023-02-22 17:00:46 +08:00
dudaodong
8e36ef5cef doc: add doc for new map functions 2023-02-22 16:59:01 +08:00
dudaodong
21b0d2ec0e doc: add doc for WordCount and SplitWords function 2023-02-22 16:13:41 +08:00
dudaodong
32ca975204 feat: add OmitBy, OmitByKeys, OmitByValues 2023-02-21 14:52:10 +08:00
dudaodong
ec740e442c feat: add WordCount 2023-02-21 14:27:00 +08:00
dudaodong
ed98ad53ec feat: add SplitWords 2023-02-21 14:16:36 +08:00
dudaodong
af7b9d2710 doc: add doc for CopyProperties function 2023-02-20 14:10:55 +08:00
dudaodong
f08b368001 fix: update param type of CopyProperties 2023-02-20 14:04:45 +08:00
dudaodong
be8a0558f8 test: add examples for CopyProperties function 2023-02-20 12:00:49 +08:00
dudaodong
46de539e22 feat: add CopyProperties for merge properties between structs 2023-02-20 11:48:30 +08:00
dudaodong
36fb3abe9e test: add examples for maputil package function 2023-02-19 16:59:21 +08:00
dudaodong
fee8d325b7 doc: add doc for Pad function 2023-02-19 12:58:14 +08:00
dudaodong
8784be1583 feat: add Pad function 2023-02-19 12:37:26 +08:00
dudaodong
84cd68de7f fix: fix bugs of PadEnd and PadStart 2023-02-19 12:34:39 +08:00
dudaodong
a774c060ce feat: add MapKeys and MapValues 2023-02-17 15:41:58 +08:00
dudaodong
730f061b95 feat: add Entries FromEntries Transform 2023-02-17 15:24:46 +08:00
dudaodong
2eb08f3404 feat: add FilterByValues function 2023-02-17 11:59:44 +08:00
dudaodong
4c1496b648 feat: add FilterByKeys function 2023-02-17 11:57:09 +08:00
dudaodong
c2ae784f27 feat: add ValuesBy function 2023-02-17 11:48:11 +08:00
dudaodong
e71cecefea feat: add KeysBy function 2023-02-17 11:40:20 +08:00
dudaodong
572e53aa14 doc: add go playground demo for xerror package 2023-02-16 14:28:50 +08:00
dudaodong
ca9ecb9c8a update go playground demo 2023-02-16 14:10:24 +08:00
dudaodong
8bf0786abe release v2.1.15 2023-02-16 12:02:34 +08:00
dudaodong
61cb8395e3 doc: update doc for xerror package 2023-02-15 14:41:56 +08:00
dudaodong
dde8a41daf doc: update doc for xerror package 2023-02-15 14:41:41 +08:00
dudaodong
d7518e01af doc: fix ExampleXError_StackTrace bug 2023-02-15 12:04:14 +08:00
dudaodong
be9fa7acaa doc: update doc for xerror package 2023-02-15 11:58:33 +08:00
dudaodong
2629a731cc doc: update doc for xerror package 2023-02-15 11:53:21 +08:00
dudaodong
54c7f90b7f test: add examples for xerror package 2023-02-15 10:39:51 +08:00
dudaodong
770bc88b88 doc: update doc for xerror package 2023-02-15 10:14:26 +08:00
dudaodong
4cc1722f81 feat: fix AesEcbEncrypt and AesEcbDecrypt 2023-02-14 16:42:25 +08:00
dudaodong
d0260b2841 feat: add XError to support more contextual error handling 2023-02-14 16:32:57 +08:00
dudaodong
57bd64cae7 feat: add stack 2023-02-14 10:21:38 +08:00
dudaodong
c383719496 doc: add doc for DeepClone function 2023-02-12 19:24:56 +08:00
dudaodong
4b196a72b1 feat: add DeepClone 2023-02-10 15:50:28 +08:00
dudaodong
888381a06c doc: add drop and sort related function doc 2023-02-10 10:53:41 +08:00
dudaodong
a554eb7ef4 doc: add doc for sort function 2023-02-10 10:42:38 +08:00
dudaodong
26ff90122b doc: add doc for Drop function 2023-02-10 10:31:02 +08:00
dudaodong
75b27c6540 feat: add IsSortedByKey 2023-02-10 10:10:57 +08:00
dudaodong
a7e77fa98d feat: add IsSorted 2023-02-09 19:30:11 +08:00
dudaodong
abf392117a feat: add IsAscending, Isdescending 2023-02-09 19:25:58 +08:00
dudaodong
d231d9f572 feat: add DropRightWhile 2023-02-09 17:53:26 +08:00
dudaodong
97447d058e test: add test and example for DropWhile 2023-02-09 17:46:40 +08:00
dudaodong
040e112aa6 feat: add DropRight and DropWhile 2023-02-09 17:38:31 +08:00
dudaodong
afb021b4b5 feat: add Max, Min for stream 2023-02-08 15:20:29 +08:00
dudaodong
5075774000 feat: add Sorted for stream 2023-02-08 15:07:09 +08:00
dudaodong
6bba44dc50 feat: add Concat for stream 2023-02-07 10:47:28 +08:00
dudaodong
422022c74d feat: add Range for stream 2023-02-07 10:36:07 +08:00
dudaodong
87fcf97e2d feat: add FindFirst, Reverse for stream 2023-02-07 10:24:19 +08:00
dudaodong
05d1f348d4 refactor: update constant names 2023-02-06 19:39:31 +08:00
dudaodong
6f2f1f3004 fix: IsZeroValue support pointer 2023-02-06 19:36:36 +08:00
dudaodong
9cd9d1aeb5 release v2.1.14 2023-02-06 17:42:13 +08:00
dudaodong
71b27c0aa9 feat: add ForEach, Reduce for stream 2023-02-06 17:40:54 +08:00
dudaodong
09a379ec6d feat: add ForEach, Reduce for stream 2023-02-06 17:38:33 +08:00
dudaodong
b4b9b03835 feat: add NoneMatch, AllMatch, AnyMatch for stream 2023-02-06 17:24:17 +08:00
dudaodong
48c7794b01 feat: add Limit method of stream 2023-02-06 17:08:36 +08:00
dudaodong
8e3911833d doc: normalize documents 2023-02-06 11:42:03 +08:00
dudaodong
ebe494051b doc: add doc for some new methods of list 2023-02-06 11:35:32 +08:00
dudaodong
c35bda6a65 feat: add ListToMap for list 2023-02-06 11:06:46 +08:00
dudaodong
1fe4cdc429 feat: add Difference and SymmetricDifference for list 2023-02-06 10:55:42 +08:00
dudaodong
6a79e322e3 Merge branch 'main' into v2 2023-02-06 10:00:02 +08:00
Cai Zhijiang
17e8d2bb6d 部分城市有4位区号+8位号码 (#69) 2023-02-06 09:47:21 +08:00
燕归来
325be0d6a1 feat: add func Iterator, ForEach, RetainAll and DeleteAll for List structure (#71) 2023-02-06 09:46:25 +08:00
dudaodong
ea0f96a8c0 feat: add Skip for stream 2023-01-30 16:56:33 +08:00
dudaodong
82cbb54787 feat: add FromChannel for create stream 2023-01-17 16:47:20 +08:00
dudaodong
585d33cafa feat: add Generate for create stream 2023-01-17 16:31:44 +08:00
dudaodong
bc4cf35e15 feat: add Filter, Map, Count for stream 2023-01-17 14:59:47 +08:00
dudaodong
a3bc20af1d feat: add Distinct 2023-01-17 11:39:05 +08:00
dudaodong
61338b6b46 feat: add Stream package 2023-01-17 11:25:15 +08:00
dudaodong
bc3c080ac3 doc: normalize document 2023-01-15 12:43:00 +08:00
dudaodong
d3fab15af3 refactor: clean structure for netutil package 2023-01-14 14:39:06 +08:00
dudaodong
6e3e411d46 doc: normalize document 2023-01-14 12:48:39 +08:00
dudaodong
f976941e36 doc: normalize document 2023-01-14 12:32:27 +08:00
dudaodong
4c5524354c doc: normalize documents 2023-01-13 14:36:33 +08:00
dudaodong
2c6e9a3fb9 doc: format document 2023-01-13 11:01:22 +08:00
dudaodong
5f2c3edff4 doc: format document 2023-01-13 10:57:40 +08:00
dudaodong
b422d98702 doc: format document 2023-01-13 10:48:21 +08:00
dudaodong
6f27e0bfbf doc: format document 2023-01-13 10:47:47 +08:00
dudaodong
ce3b6b461e doc: format document 2023-01-13 10:43:16 +08:00
dudaodong
0d6ad4f0d2 doc: format document 2023-01-13 10:41:47 +08:00
dudaodong
c875a7f8b8 doc: format document 2023-01-13 10:39:39 +08:00
dudaodong
0c62d117a1 doc: format document 2023-01-13 10:12:37 +08:00
dudaodong
c260ce493d doc: normalize documents 2023-01-12 15:44:34 +08:00
dudaodong
9ffe96d3ef update readme file 2023-01-12 11:32:43 +08:00
dudaodong
d4bba76dc8 fix: fix ExampleSchedule failed 2023-01-09 11:25:14 +08:00
168 changed files with 32557 additions and 7147 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ fileutil/*.link
fileutil/unzip/* fileutil/unzip/*
slice/testdata/* slice/testdata/*
cryptor/*.pem cryptor/*.pem
test

545
README.md
View File

@@ -1,10 +1,10 @@
<div align=center> <div align=center>
<a href="https://uvdream.github.io/lancet-docs/en/"><img src="./logo.png" width="200" height="200"/></a> <img src="./logo.png" width="200" height="200"/>
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.2.2-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -24,8 +24,8 @@ English | [简体中文](./README_zh-CN.md)
## Feature ## Feature
- 👏 Comprehensive, efficient and reusable. - 👏 Comprehensive, efficient and reusable.
- 💪 300+ go util functions, support string, slice, datetime, net, crypt... - 💪 500+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library. - 💅 Only depends on two kinds of libraries: go standard library and golang.org/x.
- 🌍 Unit test for every exported function. - 🌍 Unit test for every exported function.
## Installation ## Installation
@@ -38,10 +38,10 @@ English | [简体中文](./README_zh-CN.md)
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
``` ```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.5. </b> 2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.0. </b>
```go ```go
go get github.com/duke-git/lancet@v1.3.5 // below go1.18, install latest version of v1.x.x go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
``` ```
## Usage ## Usage
@@ -118,7 +118,34 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)] [[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async. ### 2. Compare package provides a lightweight comparison function on any type.
```go
import "github.com/duke-git/lancet/v2/compare"
```
#### Function list:
- **<big>Equal</big>** : Checks if two values are equal or not. (check both type and value)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#Equal)]
[[play](https://go.dev/play/p/wmVxR-to4lz)]
- **<big>EqualValue</big>** : Checks if two values are equal or not. (check value only)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#EqualValue)]
[[play](https://go.dev/play/p/fxnna_LLD9u)]
- **<big>LessThan</big>** : Checks if value `left` less than value `right`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#LessThan)]
[[play](https://go.dev/play/p/cYh7FQQj0ne)]
- **<big>GreaterThan</big>** : Checks if value `left` greater than value `right`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterThan)]
[[play](https://go.dev/play/p/9-NYDFZmIMp)]
- **<big>LessOrEqual</big>** : Checks if value `left` less than or equal than value `right`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#LessOrEqual)]
[[play](https://go.dev/play/p/e4T_scwoQzp)]
- **<big>GreaterOrEqual</big>** : Checks if value `left` less greater or equal than value `right`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
### 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
```go ```go
import "github.com/duke-git/lancet/v2/concurrency" import "github.com/duke-git/lancet/v2/concurrency"
@@ -157,7 +184,7 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)] [[play](https://go.dev/play/p/3TQPKnCirrP)]
### 3. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator... ### 4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...
```go ```go
import "github.com/duke-git/lancet/v2/condition" import "github.com/duke-git/lancet/v2/condition"
@@ -173,13 +200,13 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/W1SSUmt6pvr)] [[play](https://go.dev/play/p/W1SSUmt6pvr)]
- **<big>Or</big>** : returns false if neither a nor b is truthy. - **<big>Or</big>** : returns false if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)]
[[play](https://go.dev/play/p/UlQTxHaeEkq)]] [[play](https://go.dev/play/p/UlQTxHaeEkq)]
- **<big>Xor</big>** : returns true if a or b but not both is truthy. - **<big>Xor</big>** : returns true if a or b but not both is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)]
[[play](https://go.dev/play/p/gObZrW7ZbG8)] [[play](https://go.dev/play/p/gObZrW7ZbG8)]
- **<big>Nor</big>** : returns true if neither a nor b is truthy. - **<big>Nor</big>** : returns true if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)]
[[play](https://go.dev/play/p/g2j08F_zZky) [[play](https://go.dev/play/p/g2j08F_zZky)]
- **<big>Xnor</big>** : returns true if both a and b or neither a nor b are truthy. - **<big>Xnor</big>** : returns true if both a and b or neither a nor b are truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xnor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)] [[play](https://go.dev/play/p/OuDB9g51643)]
@@ -190,7 +217,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)] [[play](https://go.dev/play/p/ElllPZY0guT)]
### 4. Convertor package contains some functions for data convertion. ### 5. Convertor package contains some functions for data convertion.
```go ```go
import "github.com/duke-git/lancet/v2/convertor" import "github.com/duke-git/lancet/v2/convertor"
@@ -246,8 +273,21 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>DecodeByte</big>** : decode byte slice data to target object. - **<big>DecodeByte</big>** : decode byte slice data to target object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DecodeByte)]
[[play](https://go.dev/play/p/zI6xsmuQRbn)] [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- **<big>DeepClone</big>** : creates a deep copy of passed item, can't clone unexported field of struct.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#DeepClone)]
[[play](https://go.dev/play/p/j4DP5dquxnk)]
- **<big>CopyProperties</big>** : copies each field from the source struct into the destination struct.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#CopyProperties)]
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : converts reflect value to its interface type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInterface)]
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
- **<big>Utf8ToGbk</big>** : converts utf8 encoding data to GBK encoding data
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#Utf8ToGbk)]
- **<big>GbkToUtf8</big>** : converts GBK encoding data to utf8 encoding data.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#GbkToUtf8)]
### 5. Cryptor package is for data encryption and decryption. ### 6. Cryptor package is for data encryption and decryption.
```go ```go
import "github.com/duke-git/lancet/v2/cryptor" import "github.com/duke-git/lancet/v2/cryptor"
@@ -351,7 +391,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)] [[play](https://go.dev/play/p/uef0q1fz53I)]
### 6. Datetime package supports date and time format and compare. ### 7. Datetime package supports date and time format and compare.
```go ```go
import "github.com/duke-git/lancet/v2/datetime" import "github.com/duke-git/lancet/v2/datetime"
@@ -368,6 +408,9 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>AddMinute</big>** : add or sub day to the time. - **<big>AddMinute</big>** : add or sub day to the time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)]
[[play](https://go.dev/play/p/nT1heB1KUUK)] [[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : add or sub year to the time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddYear)]
[[play](https://go.dev/play/p/MqW2ujnBx10)]
- **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date. - **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)] [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -449,11 +492,21 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>ToIso8601</big>** : return iso8601 time string. - **<big>ToIso8601</big>** : return iso8601 time string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)] [[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>BetweenSeconds</big>** : returns the number of seconds between two times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
[[play](https://go.dev/play/p/n3YDRyfyXJu)]
- **<big>DayOfYear</big>** : returns which day of the year the parameter date `t` is.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#DayOfYear)]
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
- **<big>IsWeekend</big>** : checks if passed time is weekend or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
### 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
```go ```go
import list "github.com/duke-git/lancet/v2/datastructure/list" import list "github.com/duke-git/lancet/v2/datastructure/list"
@@ -485,7 +538,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : hash map structure. - **<big>Hashmap</big>** : hash map structure.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)]
### 8. Fileutil package implements some basic functions for file operations. ### 9. Fileutil package implements some basic functions for file operations.
```go ```go
import "github.com/duke-git/lancet/v2/fileutil" import "github.com/duke-git/lancet/v2/fileutil"
@@ -532,14 +585,43 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ReadFileByLine</big>** : read file line by line, return string slice of file content. - **<big>ReadFileByLine</big>** : read file line by line, return string slice of file content.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)]
[[play](https://go.dev/play/p/svJP_7ZrBrD)] [[play](https://go.dev/play/p/svJP_7ZrBrD)]
- **<big>Zip</big>** : create zip file. - **<big>Zip</big>** : create a zip file of fpath, fpath could be a file or a directory.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)] [[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>ZipAppendEntry</big>** : append a single file or directory by fpath to an existing zip file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ZipAppendEntry)]
- **<big>UnZip</big>** : unzip the zip file and save it to dest path. - **<big>UnZip</big>** : unzip the zip file and save it to dest path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)] [[play](https://go.dev/play/p/g0w34kS7B8m)]
- **<big>CurrentPath</big>** : return current absolute path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CurrentPath)]
[[play](https://go.dev/play/p/s74a9iBGcSw)]
- **<big>IsZipFile</big>** : checks if file is zip file or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsZipFile)]
[[play](https://go.dev/play/p/9M0g2j_uF_e)]
- **<big>FileSize</big>** : return file size in bytes.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileSize)]
[[play](https://go.dev/play/p/H9Z05uD-Jjc)]
- **<big>MTime</big>** : return file modified time(unix timestamp).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MTime)]
[[play](https://go.dev/play/p/s_Tl7lZoAaY)]
- **<big>Sha</big>** : return file sha value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Sha)]
[[play](https://go.dev/play/p/VfEEcO2MJYf)]
- **<big>ReadCsvFile</big>** : read file content into slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadCsvFile)]
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
- **<big>WriteCsvFile</big>** : write content to target csv file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteCsvFile)]
- **<big>WriteBytesToFile</big>** : write bytes to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteBytesToFile)]
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
- **<big>WriteStringToFile</big>** : write string to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
### 9. Formatter contains some functions for data formatting.
### 10. Formatter contains some functions for data formatting.
```go ```go
import "github.com/duke-git/lancet/v2/formatter" import "github.com/duke-git/lancet/v2/formatter"
@@ -550,8 +632,26 @@ import "github.com/duke-git/lancet/v2/formatter"
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char. - **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)]
[[play](https://go.dev/play/p/eRD5k2vzUVX)] [[play](https://go.dev/play/p/eRD5k2vzUVX)]
- **<big>Pretty</big>** : pretty print data to JSON string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Pretty)]
[[play](https://go.dev/play/p/YsciGj3FH2x)]
- **<big>PrettyToWriter</big>** : pretty encode data to writer.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#PrettyToWriter)]
[[play](https://go.dev/play/p/LPLZ3lDi5ma)]
- **<big>DecimalBytes</big>** : returns a human readable byte size under decimal standard (base 1000).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#DecimalBytes)]
[[play](https://go.dev/play/p/FPXs1suwRcs)]
- **<big>BinaryBytes</big>** : returns a human-readable byte size under binary standard (base 1024).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#BinaryBytes)]
[[play](https://go.dev/play/p/G9oHHMCAZxP)]
- **<big>ParseDecimalBytes</big>** : return the human readable bytes size string into the amount it represents(base 1000).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseDecimalBytes)]
[[play](https://go.dev/play/p/Am98ybWjvjj)]
- **<big>ParseBinaryBytes</big>** : return the human readable bytes size string into the amount it represents(base 1024).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
### 10. Function package can control the flow of function execution and support part of functional programming ### 11. Function package can control the flow of function execution and support part of functional programming
```go ```go
import "github.com/duke-git/lancet/v2/function" import "github.com/duke-git/lancet/v2/function"
@@ -587,8 +687,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)] [[play](https://go.dev/play/p/l2yrOpCLd1I)]
### 12. Maputil package includes some functions to manipulate map.
### 11. Maputil package includes some functions to manipulate map.
```go ```go
import "github.com/duke-git/lancet/v2/maputil" import "github.com/duke-git/lancet/v2/maputil"
@@ -596,18 +695,39 @@ import "github.com/duke-git/lancet/v2/maputil"
#### Function list: #### Function list:
- **<big>MapTo</big>** : quick map any value to struct or any base type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapTo)]
[[play](https://go.dev/play/p/4K7KBEPgS5M)]
- **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map. - **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)]
[[play](https://go.dev/play/p/OaThj6iNVXK)] [[play](https://go.dev/play/p/OaThj6iNVXK)]
- **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function. - **<big>Filter</big>** : iterates over map, return a new map contains all key and value pairs pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)]
[[play](https://go.dev/play/p/fSvF3wxuNG7)] [[play](https://go.dev/play/p/fSvF3wxuNG7)]
- **<big>FilterByKeys</big>** : iterates over map, return a new map whose keys are all given keys
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FilterByKeys)]
[[play](https://go.dev/play/p/7ov6BJHbVqh)]
- **<big>FilterByValues</big>** : iterates over map, return a new map whose values are all given values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FilterByValues)]
[[play](https://go.dev/play/p/P3-9MdcXegR)]
- **<big>OmitBy</big>** : the opposite of Filter, removes all the map elements for which the predicate function returns true.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitBy)]
[[play](https://go.dev/play/p/YJM4Hj5hNwm)]
- **<big>OmitByKeys</big>** : the opposite of FilterByKeys, extracts all the map elements which keys are not omitted.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitByKeys)]
[[play](https://go.dev/play/p/jXGrWDBfSRp)]
- **<big>OmitByValues</big>** : the opposite of FilterByValues. remov all elements whose value are in the give slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#OmitByValues)]
[[play](https://go.dev/play/p/XB7Y10uw20_U)]
- **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps. - **<big>Intersect</big>** : iterates over maps, return a new map of key and value pairs in all given maps.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)]
[[play](https://go.dev/play/p/Zld0oj3sjcC)] [[play](https://go.dev/play/p/Zld0oj3sjcC)]
- **<big>Keys</big>** : returns a slice of the map's keys. - **<big>Keys</big>** : returns a slice of the map's keys.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)]
[[play](https://go.dev/play/p/xNB5bTb97Wd)] [[play](https://go.dev/play/p/xNB5bTb97Wd)]
- **<big>KeysBy</big>** : creates a slice whose element is the result of function mapper invoked by every map's key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#KeysBy)]
[[play](https://go.dev/play/p/hI371iB8Up8)]
- **<big>Merge</big>** : merge maps, next key will overwrite previous key. - **<big>Merge</big>** : merge maps, next key will overwrite previous key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)]
[[play](https://go.dev/play/p/H95LENF1uB-)] [[play](https://go.dev/play/p/H95LENF1uB-)]
@@ -617,11 +737,29 @@ import "github.com/duke-git/lancet/v2/maputil"
- **<big>Values</big>** : returns a slice of the map's values. - **<big>Values</big>** : returns a slice of the map's values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)]
[[play](https://go.dev/play/p/CBKdUc5FTW6)] [[play](https://go.dev/play/p/CBKdUc5FTW6)]
- **<big>ValuesBy</big>** : creates a slice whose element is the result of function mapper invoked by every map's value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ValuesBy)]
[[play](https://go.dev/play/p/sg9-oRidh8f)]
- **<big>MapKeys</big>** : transforms a map to other type map by manipulating it's keys.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapKeys)]
[[play](https://go.dev/play/p/8scDxWeBDKd)]
- **<big>MapValues</big>** : transforms a map to other type map by manipulating it's values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapValues)]
[[play](https://go.dev/play/p/g92aY3fc7Iw)]
- **<big>Entries</big>** : transforms a map into array of key/value pairs.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Entries)]
[[play](https://go.dev/play/p/Ltb11LNcElY)]
- **<big>FromEntries</big>** : creates a map based on a slice of key/value pairs.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#FromEntries)]
[[play](https://go.dev/play/p/fTdu4sCNjQO)]
- **<big>Transform</big>** : transform a map to another type map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Transform)]
[[play](https://go.dev/play/p/P6ovfToM3zj)]
- **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common. - **<big>IsDisjoint</big>** : check two map are disjoint if they have no keys in common.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)] [[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 12. Mathutil package implements some functions for math calculation. ### 13. Mathutil package implements some functions for math calculation.
```go ```go
import "github.com/duke-git/lancet/v2/mathutil" import "github.com/duke-git/lancet/v2/mathutil"
@@ -655,7 +793,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/N9qgYg_Ho6f)] [[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : calculate the percentage of value to total. - **<big>Percent</big>** : calculate the percentage of value to total.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)]
[[play](https://go.dev/play/p/QQM9B13coSP)] [[play](https://go.dev/play/p/s0NdFCtwuyd)]
- **<big>RoundToFloat</big>** : round up to n decimal places for float64. - **<big>RoundToFloat</big>** : round up to n decimal places for float64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)] [[play](https://go.dev/play/p/ghyb528JRJL)]
@@ -665,8 +803,42 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<big>TruncRound</big>** : round off n decimal places for int64. - **<big>TruncRound</big>** : round off n decimal places for int64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)]
[[play](https://go.dev/play/p/aumarSHIGzP)] [[play](https://go.dev/play/p/aumarSHIGzP)]
- **<big>Range</big>** : Creates a slice of numbers from start with specified count, element step is 1.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Range)]
[[play](https://go.dev/play/p/9ke2opxa8ZP)]
- **<big>RangeWithStep</big>** : Creates a slice of numbers from start to end with specified step.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Range)]
[[play](https://go.dev/play/p/akLWz0EqOSM)]
- **<big>AngleToRadian</big>** : converts angle value to radian value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#AngleToRadian)]
[[play](https://go.dev/play/p/CIvlICqrHql)]
- **<big>RadianToAngle</big>** : converts radian value to angle value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RadianToAngle)]
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
- **<big>PointDistance</big>** : get two points distance.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#PointDistance)]
[[play](https://go.dev/play/p/RrG4JIaziM8)]
- **<big>IsPrime</big>** : checks if number is prime number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : return greatest common divisor (GCD) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#GCD)]
[[play](https://go.dev/play/p/CiEceLSoAKB)]
- **<big>LCM</big>** : return Least Common Multiple (LCM) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#LCM)]
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
- **<big>Cos</big>** : return the cosine of the radian argument.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Cos)]
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
- **<big>Sin</big>** : return the sine of the radian argument.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sin)]
[[play](https://go.dev/play/p/TWMQlMywDsP)]
- **<big>Log</big>** : returns the logarithm of base n.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Log)]
- **<big>Sum</big>** : return sum of passed numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sum)]
### 13. Netutil package contains functions to get net information and send http request. ### 14. Netutil package contains functions to get net information and send http request.
```go ```go
import "github.com/duke-git/lancet/v2/netutil" import "github.com/duke-git/lancet/v2/netutil"
@@ -716,22 +888,30 @@ import "github.com/duke-git/lancet/v2/netutil"
- **<big>StructToUrlValues</big>** : convert struct to url valuse. - **<big>StructToUrlValues</big>** : convert struct to url valuse.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)]
[[play](https://go.dev/play/p/pFqMkM40w9z)] [[play](https://go.dev/play/p/pFqMkM40w9z)]
- **<big>HttpGet<sup>deprecated</sup></big>** : send get http request. - **<big>HttpGet<sup>deprecated</sup></big>** : send http get request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)]
- **<big>HttpDelete<sup>deprecated</sup></big>** : send delete http request. - **<big>HttpDelete<sup>deprecated</sup></big>** : send http delete request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)]
- **<big>HttpPost<sup>deprecated</sup></big>** : send post http request. - **<big>HttpPost<sup>deprecated</sup></big>** : send http post request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)]
- **<big>HttpPut<sup>deprecated</sup></big>** : send put http request. - **<big>HttpPut<sup>deprecated</sup></big>** : send http put request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)]
- **<big>HttpPatch<sup>deprecated</sup></big>** : send patch http request. - **<big>HttpPatch<sup>deprecated</sup></big>** : send http patch request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)]
- **<big>ParseHttpResponse</big>** : decode http response into target object. - **<big>ParseHttpResponse</big>** : decode http response into target object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
- **<big>DownloadFile</big>** : download the file exist in url to a local file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DownloadFile)]
- **<big>UploadFile</big>** : upload the file to a server.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#UploadFile)]
- **<big>IsPingConnected</big>** : checks if can ping the specified host or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPingConnected)]
[[play](https://go.dev/play/p/q8OzTijsA87)]
- **<big>IsTelnetConnected</big>** : checks if can if can telnet the specified host or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
### 15. Random package implements some basic functions to generate random int and string.
### 14. Random package implements some basic functions to generate random int and string.
```go ```go
import "github.com/duke-git/lancet/v2/random" import "github.com/duke-git/lancet/v2/random"
@@ -763,8 +943,10 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122. - **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)] [[play](https://go.dev/play/p/_Z9SFmr28ft)]
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUniqueIntSlice)]
### 15. Retry package is for executing a function repeatedly until it was successful or canceled by the context. ### 16. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
```go ```go
import "github.com/duke-git/lancet/v2/retry" import "github.com/duke-git/lancet/v2/retry"
@@ -788,7 +970,7 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)] [[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 16. Slice contains some functions to manipulate slice. ### 17. Slice contains some functions to manipulate slice.
```go ```go
import "github.com/duke-git/lancet/v2/slice" import "github.com/duke-git/lancet/v2/slice"
@@ -802,6 +984,9 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Contain</big>** : check if the value is in the slice or not. - **<big>Contain</big>** : check if the value is in the slice or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)]
[[play](https://go.dev/play/p/_454yEHcNjf)] [[play](https://go.dev/play/p/_454yEHcNjf)]
- **<big>ContainBy</big>** : returns true if predicate function return true.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainBy)]
[[play](https://go.dev/play/p/49tkHfX4GNc)]
- **<big>ContainSubSlice</big>** : check if the slice contain a given subslice or not. - **<big>ContainSubSlice</big>** : check if the slice contain a given subslice or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)]
[[play](https://go.dev/play/p/bcuQ3UT6Sev)] [[play](https://go.dev/play/p/bcuQ3UT6Sev)]
@@ -832,9 +1017,18 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>DeleteAt</big>** : delete the element of slice from specific start index to end index - 1. - **<big>DeleteAt</big>** : delete the element of slice from specific start index to end index - 1.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteAt)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)] [[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Drop</big>** : creates a slice with `n` elements dropped from the beginning when n > 0, or `n` elements dropped from the ending when n < 0. - **<big>Drop</big>** : drop n elements from the start of a slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)] [[play](https://go.dev/play/p/jnPO2yQsT8H)]
- **<big>DropRight</big>** : drop n elements from the end of a slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRight)]
[[play](https://go.dev/play/p/8bcXvywZezG)]
- **<big>DropWhile</big>** : drop n elements from the start of a slice while predicate function returns true.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropWhile)]
[[play](https://go.dev/play/p/4rt252UV_qs)]
- **<big>DropRightWhile</big>** : drop n elements from the end of a slice while predicate function returns true.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DropRightWhile)]
[[play](https://go.dev/play/p/6wyK3zMY56e)]
- **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal. - **<big>Equal</big>** : checks if two slices are equal: the same length and all elements' order and value are equal.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)]
[[play](https://go.dev/play/p/WcRQJ37ifPa)] [[play](https://go.dev/play/p/WcRQJ37ifPa)]
@@ -847,21 +1041,36 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Filter</big>** : iterates over elements of slice, returning an slice of all elements pass the predicate function. - **<big>Filter</big>** : iterates over elements of slice, returning an slice of all elements pass the predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)]
[[play](https://go.dev/play/p/SdPna-7qK4T)] [[play](https://go.dev/play/p/SdPna-7qK4T)]
- **<big>Find</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function. - **<big>FilterMap</big>** : returns a slice which apply both filtering and mapping to the given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FilterMap)]
[[play](https://go.dev/play/p/J94SZ_9MiIe)]
- **<big>Find<sup>deprecated</sup></big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)]
[[play](https://go.dev/play/p/CBKeBoHVLgq)] [[play](https://go.dev/play/p/CBKeBoHVLgq)]
- **<big>FindLast</big>** : return the last item that passes a truth test on predicate function. - **<big>FindBy</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindBy)]
[[play](https://go.dev/play/p/n1lysBYl-GB)]
- **<big>FindLast<sup>deprecated</sup></big>** : return the last item that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)]
[[play](https://go.dev/play/p/FFDPV_j7URd)] [[play](https://go.dev/play/p/FFDPV_j7URd)]
- **<big>FindLastBy</big>** : iterates over elements of slice, returning the last one that passes a truth test on predicate function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLastBy)]
[[play](https://go.dev/play/p/8iqomzyCl_s)]
- **<big>Flatten</big>** : flattens slice one level. - **<big>Flatten</big>** : flattens slice one level.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)]
[[play](https://go.dev/play/p/hYa3cBEevtm)] [[play](https://go.dev/play/p/hYa3cBEevtm)]
- **<big>FlattenDeep</big>** : flattens slice recursive to one level. - **<big>FlattenDeep</big>** : flattens slice recursive to one level.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)]
[[play](https://go.dev/play/p/yjYNHPyCFaF)] [[play](https://go.dev/play/p/yjYNHPyCFaF)]
- **<big>FlatMap</big>** : manipulates a slice and transforms and flattens it to a slice of another type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlatMap)]
[[play](https://go.dev/play/p/_QARWlWs1N_F)]
- **<big>ForEach</big>** : iterates over elements of slice and invokes function for each element. - **<big>ForEach</big>** : iterates over elements of slice and invokes function for each element.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)]
[[play](https://go.dev/play/p/DrPaa4YsHRF)] [[play](https://go.dev/play/p/DrPaa4YsHRF)]
- **<big>ForEachWithBreak</big>** : iterates over elements of slice and invokes function for each element, when iteratee return false, will break the for each loop.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEachWithBreak)]
[[play](https://go.dev/play/p/qScs39f3D9W)]
- **<big>GroupBy</big>** : iterate over elements of the slice, each element will be group by criteria, returns two slices. - **<big>GroupBy</big>** : iterate over elements of the slice, each element will be group by criteria, returns two slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)]
[[play](https://go.dev/play/p/QVkPxzPR0iA)] [[play](https://go.dev/play/p/QVkPxzPR0iA)]
@@ -895,9 +1104,15 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Reverse</big>** : return slice of element order is reversed to the given slice. - **<big>Reverse</big>** : return slice of element order is reversed to the given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)]
[[play](https://go.dev/play/p/8uI8f1lwNrQ)] [[play](https://go.dev/play/p/8uI8f1lwNrQ)]
- **<big>Reduce</big>** : creates an slice of values by running each element of slice thru iteratee function. - **<big>Reduce<sup>deprecated</sup></big>** : creates an slice of values by running each element of slice thru iteratee function.(Deprecated: use ReduceBy)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)]
[[play](https://go.dev/play/p/_RfXJJWIsIm)] [[play](https://go.dev/play/p/_RfXJJWIsIm)]
- **<big>ReduceBy</big>** : produces a value from slice by accumulating the result of each element as passed through the reducer function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReduceBy)]
[[play](https://go.dev/play/p/YKDpLi7gtee)]
- **<big>ReduceRight</big>** : ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReduceRight)]
[[play](https://go.dev/play/p/qT9dZC03A1K)]
- **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new. - **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)] [[play](https://go.dev/play/p/P5mZp7IhOFo)]
@@ -910,6 +1125,18 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Shuffle</big>** : shuffle the slice. - **<big>Shuffle</big>** : shuffle the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Shuffle)]
[[play](https://go.dev/play/p/YHvhnWGU3Ge)] [[play](https://go.dev/play/p/YHvhnWGU3Ge)]
- **<big>IsAscending</big>** : Checks if a slice is ascending order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsAscending)]
[[play](https://go.dev/play/p/9CtsFjet4SH)]
- **<big>IsDescending</big>** : Checks if a slice is descending order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsDescending)]
[[play](https://go.dev/play/p/U_LljFXma14)]
- **<big>IsSorted</big>** : Checks if a slice is sorted (ascending or descending).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSorted)]
[[play](https://go.dev/play/p/nCE8wPLwSA-)]
- **<big>IsSortedByKey</big>** : Checks if a slice is sorted by iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IsSortedByKey)]
[[play](https://go.dev/play/p/tUoGB7DOHI4)]
- **<big>Sort</big>** : sorts a slice of any ordered type(number or string). - **<big>Sort</big>** : sorts a slice of any ordered type(number or string).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Sort)]
[[play](https://go.dev/play/p/V9AVjzf_4Fk)] [[play](https://go.dev/play/p/V9AVjzf_4Fk)]
@@ -956,7 +1183,127 @@ import "github.com/duke-git/lancet/v2/slice"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)] [[play](https://go.dev/play/p/uXod2LWD1Kg)]
### 17. Strutil package contains some functions to manipulate string. ### 18. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited.
```go
import "github.com/duke-git/lancet/v2/stream"
```
#### Function list:
- **<big>Of</big>** : creates a stream whose elements are the specified values.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Of)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
- **<big>FromSlice</big>** : creates a stream from slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromSlice)]
[[play](https://go.dev/play/p/wywTO0XZtI4)]
- **<big>FromChannel</big>** : creates a stream from channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromChannel)]
[[play](https://go.dev/play/p/9TZYugGMhXZ)]
- **<big>FromRange</big>** : creates a number stream from start to end. both start and end are included. [start, end]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromRange)]
[[play](https://go.dev/play/p/9Ex1-zcg-B-)]
- **<big>Generate</big>** : creates a stream where each element is generated by the provided generater function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Generate)]
[[play](https://go.dev/play/p/rkOWL1yA3j9)]
- **<big>Concat</big>** : creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Concat)]
[[play](https://go.dev/play/p/HM4OlYk_OUC)]
- **<big>Distinct</big>** : creates returns a stream that removes the duplicated items.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Distinct)]
[[play](https://go.dev/play/p/eGkOSrm64cB)]
- **<big>Filter</big>** : returns a stream consisting of the elements of this stream that match the given predicate.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Filter)]
[[play](https://go.dev/play/p/MFlSANo-buc)]
- **<big>Map</big>** : returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Map)]
[[play](https://go.dev/play/p/OtNQUImdYko)]
- **<big>Peek</big>** : returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Peek)]
[[play](https://go.dev/play/p/u1VNzHs6cb2)]
- **<big>Skip</big>** : returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Skip)]
[[play](https://go.dev/play/p/fNdHbqjahum)]
- **<big>Limit</big>** : returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Limit)]
[[play](https://go.dev/play/p/qsO4aniDcGf)]
- **<big>Reverse</big>** : returns a stream whose elements are reverse order of given stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Reverse)]
[[play](https://go.dev/play/p/A8_zkJnLHm4)]
- **<big>Range</big>** : returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Range)]
[[play](https://go.dev/play/p/indZY5V2f4j)]
- **<big>Sorted</big>** : returns a stream consisting of the elements of this stream, sorted according to the provided less function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Sorted)]
[[play](https://go.dev/play/p/XXtng5uonFj)]
- **<big>ForEach</big>** : performs an action for each element of this stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ForEach)]
[[play](https://go.dev/play/p/Dsm0fPqcidk)]
- **<big>Reduce</big>** : performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Reduce)]
[[play](https://go.dev/play/p/6uzZjq_DJLU)]
- **<big>FindFirst</big>** : returns the first element of this stream and true, or zero value and false if the stream is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindFirst)]
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : returns the last element of this stream and true, or zero value and false if the stream is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindLast)]
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less fuction: a > b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
- **<big>Min</big>** : returns the minimum element of this stream according to the provided less function. less fuction: a < b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Min)]
[[play](https://go.dev/play/p/vZfIDgGNRe_0)]
- **<big>AllMatch</big>** : returns whether all elements of this stream match the provided predicate.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#AllMatch)]
[[play](https://go.dev/play/p/V5TBpVRs-Cx)]
- **<big>AnyMatch</big>** : returns whether any elements of this stream match the provided predicate.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#AnyMatch)]
[[play](https://go.dev/play/p/PTCnWn4OxSn)]
- **<big>NoneMatch</big>** : returns whether no elements of this stream match the provided predicate.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#NoneMatch)]
[[play](https://go.dev/play/p/iWS64pL1oo3)]
- **<big>Count</big>** : returns the count of elements in the stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Count)]
[[play](https://go.dev/play/p/r3koY6y_Xo-)]
- **<big>ToSlice</big>** : returns the elements in the stream.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
### 19. Structs package provides several high level functions to manipulate struct, tag, and field.
```go
import "github.com/duke-git/lancet/v2/structs"
```
#### Function list:
- **<big>New</big>** : creates a `Struct` instance.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#New)]
- **<big>ToMap</big>** : converts a valid struct to a map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#ToMap)]
- **<big>Fields</big>** : get all fields of a given struct, that the fields are abstract struct field.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#Fields)]
- **<big>IsStruct</big>** : check if the struct is valid.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#IsStruct)]
- **<big>Tag</big>** : get a `Tag` of the `Field`, `Tag` is a abstract struct field tag
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#Tag)]
- **<big>Name</big>** : get the field name.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#Name)]
- **<big>Value</big>** : get the `Field` underlying value.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#Value)]
- **<big>Kind</big>** : get the field's kind
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#Kind)]
- **<big>IsEmbedded</big>** : check if the field is an embedded field.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsEmbedded)]
- **<big>IsExported</big>** : check if the field is exporte
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsExported)]
- **<big>IsZero</big>** : check if the field is zero value
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsZero)]
- **<big>IsSlice</big>** : check if the field is a slice
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsSlice)]
### 20. Strutil package contains some functions to manipulate string.
```go ```go
import "github.com/duke-git/lancet/v2/strutil" import "github.com/duke-git/lancet/v2/strutil"
@@ -981,6 +1328,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Capitalize</big>** : converts the first character of source string to upper case and the remaining to lower case. - **<big>Capitalize</big>** : converts the first character of source string to upper case and the remaining to lower case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)] [[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>ContainsAll</big>** : return true if target string contains all the substrings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAll)]
[[play](https://go.dev/play/p/KECtK2Os4zq)]
- **<big>ContainsAny</big>** : return true if target string contains any one of the substrings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAny)]
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
- **<big>IsString</big>** : checks if the parameter value data type is string or not. - **<big>IsString</big>** : checks if the parameter value data type is string or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)] [[play](https://go.dev/play/p/IOgq7oF9ERm)]
@@ -996,6 +1349,9 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>UpperFirst</big>** : converts the first character of string to upper case. - **<big>UpperFirst</big>** : converts the first character of string to upper case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)]
[[play](https://go.dev/play/p/sBbBxRbs8MM)] [[play](https://go.dev/play/p/sBbBxRbs8MM)]
- **<big>Pad</big>** : pads string on the left and right side if it's shorter than size.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Pad)]
[[play](https://go.dev/play/p/NzImQq-VF8q)]
- **<big>PadEnd</big>** : pads string with given characters on the right side if it's shorter than limit size. Padding characters are truncated if they exceed size. - **<big>PadEnd</big>** : pads string with given characters on the right side if it's shorter than limit size. Padding characters are truncated if they exceed size.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)]
[[play](https://go.dev/play/p/9xP8rN0vz--)] [[play](https://go.dev/play/p/9xP8rN0vz--)]
@@ -1023,8 +1379,49 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Unwrap</big>** : unwrap a given string from anther string. will change source string. - **<big>Unwrap</big>** : unwrap a given string from anther string. will change source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)]
[[play](https://go.dev/play/p/Ec2q4BzCpG-)] [[play](https://go.dev/play/p/Ec2q4BzCpG-)]
- **<big>SplitWords</big>** : splits a string into words, word only contains alphabetic characters.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitWords)]
[[play](https://go.dev/play/p/KLiX4WiysMM)]
- **<big>WordCount</big>** : return the number of meaningful word of a string, word only contains alphabetic characters.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#WordCount)]
[[play](https://go.dev/play/p/bj7_odx3vRf)]
- **<big>RemoveNonPrintable</big>** : remove non-printable characters from a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveNonPrintable)]
[[play](https://go.dev/play/p/og47F5x_jTZ)]
- **<big>StringToBytes</big>** : converts a string to byte slice without a memory allocation.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#StringToBytes)]
[[play](https://go.dev/play/p/7OyFBrf9AxA)]
- **<big>BytesToString</big>** : converts a byte slice to string without a memory allocation.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BytesToString)]
[[play](https://go.dev/play/p/6c68HRvJecH)]
- **<big>IsBlank</big>** : checks if a string is whitespace or empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsBlank)]
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
- **<big>HasPrefixAny</big>** : checks if a string starts with any of an array of specified strings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HasPrefixAny)]
[[play](https://go.dev/play/p/8UUTl2C5slo)]
- **<big>HasSuffixAny</big>** : checks if a string ends with any of an array of specified strings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HasSuffixAny)]
[[play](https://go.dev/play/p/sKWpCQdOVkx)]
- **<big>IndexOffset</big>** : returns the index of the first instance of substr in string after offsetting the string by `idxFrom`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IndexOffset)]
[[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReplaceWithMap)]
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
- **<big>Trim</big>** : strips whitespace (or other characters) from the beginning and end of a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Trim)]
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
- **<big>SplitAndTrim</big>** : splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitAndTrim)]
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
- **<big>HideString</big>** : Hide some chars in source string with param `replaceChar`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HideString)]
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
- **<big>RemoveWhiteSpace</big>** : remove whitespace characters from a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveWhiteSpace)]
### 19. System package contain some functions about os, runtime, shell command. ### 21. System package contain some functions about os, runtime, shell command.
```go ```go
import "github.com/duke-git/lancet/v2/system" import "github.com/duke-git/lancet/v2/system"
@@ -1060,7 +1457,7 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)] [[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 19. Validator package contains some functions for data validation. ### 22. Validator package contains some functions for data validation.
```go ```go
import "github.com/duke-git/lancet/v2/validator" import "github.com/duke-git/lancet/v2/validator"
@@ -1113,18 +1510,27 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsEmptyString</big>** : check if the string is empty. - **<big>IsEmptyString</big>** : check if the string is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)]
[[play](https://go.dev/play/p/dpzgUjFnBCX)] [[play](https://go.dev/play/p/dpzgUjFnBCX)]
- **<big>IsFloat</big>** : check if the value is float(float32, float34) or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloat)]
[[play](https://go.dev/play/p/vsyG-sxr99_Z)]
- **<big>IsFloatStr</big>** : check if the string can convert to a float. - **<big>IsFloatStr</big>** : check if the string can convert to a float.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#LOYwS_Oyl7U)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)]
[[play](https://go.dev/play/p/LOYwS_Oyl7U)] [[play](https://go.dev/play/p/LOYwS_Oyl7U)]
- **<big>IsNumber</big>** : check if the value is number(integer, float) or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumber)]
[[play](https://go.dev/play/p/mdJHOAvtsvF)]
- **<big>IsNumberStr</big>** : check if the string can convert to a number. - **<big>IsNumberStr</big>** : check if the string can convert to a number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)] [[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsJSON</big>** : check if the string is valid JSON. - **<big>IsJSON</big>** : check if the string is valid JSON.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)]
[[play](https://go.dev/play/p/sRS6c4K8jGk)] [[play](https://go.dev/play/p/8Kip1Itjiil)]
- **<big>IsRegexMatch</big>** : check if the string match the regexp. - **<big>IsRegexMatch</big>** : check if the string match the regexp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)]
[[play](https://go.dev/play/p/z_XeZo_litG)] [[play](https://go.dev/play/p/z_XeZo_litG)]
- **<big>IsInt</big>** : check if the string can convert to a number.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsInt)]
[[play](https://go.dev/play/p/eFoIHbgzl-z)]
- **<big>IsIntStr</big>** : check if the string can convert to a integer. - **<big>IsIntStr</big>** : check if the string can convert to a integer.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)]
[[play](https://go.dev/play/p/jQRtFv-a0Rk)] [[play](https://go.dev/play/p/jQRtFv-a0Rk)]
@@ -1152,8 +1558,14 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsGBK</big>** : check if data encoding is gbk. - **<big>IsGBK</big>** : check if data encoding is gbk.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsGBK)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsGBK)]
[[play](https://go.dev/play/p/E2nt3unlmzP)] [[play](https://go.dev/play/p/E2nt3unlmzP)]
- **<big>IsASCII</big>** : checks if string is all ASCII char.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsASCII)]
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
- **<big>IsPrintable</big>** : checks if string is all printable chars.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
### 20. xerror package implements helpers for errors. ### 23. xerror package implements helpers for errors.
```go ```go
import "github.com/duke-git/lancet/v2/xerror" import "github.com/duke-git/lancet/v2/xerror"
@@ -1161,10 +1573,45 @@ import "github.com/duke-git/lancet/v2/xerror"
#### Function list: #### Function list:
- **<big>Unwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err. - **<big>New</big>** : creates a new XError pointer instance with message.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#New)]
[[play](https://go.dev/play/p/w4oWZts7q7f)]
- **<big>Wrap</big>** : creates a new XError pointer instance based on error object, and add message.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Wrap)]
[[play](https://go.dev/play/p/5385qT2dCi4)]
- **<big>Unwrap</big>** : returns unwrapped XError from err by errors.As. If no XError, returns nil.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)]
[[play](https://go.dev/play/p/w84d7Mb3Afk)] [[play](https://go.dev/play/p/LKMLep723tu)]
- **<big>XError_Wrap</big>** : creates a new XError and copy message and id to new one.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Wrap)]
[[play](https://go.dev/play/p/5385qT2dCi4)]
- **<big>XError_Unwrap</big>** : Compatible with github.com/pkg/errors.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Unwrap)]
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
- **<big>XError_With</big>** : adds key and value related to the XError object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_With)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_Id</big>** : sets XError object id to check equality in XError.Is.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Id)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Is</big>** : checks if target error is XError and Error.id of two errors are matched.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Is)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Values</big>** : returns map of key and value that is set by XError.With function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Values)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_StackTrace</big>** : returns stack trace which is compatible with pkg/errors.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_StackTrace)]
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
- **<big>XError_Info</big>** : returns information of xerror, which can be printed.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Info)]
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
- **<big>XError_Error</big>** : implements standard error interface.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#XError_Error)]
[[play](https://go.dev/play/p/w4oWZts7q7f)]
- **<big>TryUnwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, TryUnwrap panics with err.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#TryUnwrap)]
[[play](https://go.dev/play/p/acyZVkNZEeW)]
## How to Contribute ## How to Contribute

View File

@@ -1,10 +1,10 @@
<div align=center> <div align=center>
<a href="https://uvdream.github.io/lancet-docs/"><img src="./logo.png" width="200" height="200"/><a/> <img src="./logo.png" width="200" height="200"/>
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.2.2-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -22,10 +22,10 @@
## 特性 ## 特性
- 👏 全面、高效、可复用 - 👏 全面、高效、可复用
- 💪 300+常用 go 工具函数,支持 string、slice、datetime、net、crypt... - 💪 500+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
- 💅 只依赖 go 标准库 - 💅 只依赖 go 标准库和 golang.org/x。
- 🌍 所有导出函数单元测试覆盖率 100% - 🌍 所有导出函数单元测试覆盖率 100%
## 安装 ## 安装
@@ -37,10 +37,10 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
``` ```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.5。</b> 2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.0。</b>
```go ```go
go get github.com/duke-git/lancet@v1.3.5 // 使用go1.18以下版本, 必须安装v1.x.x版本 go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
``` ```
## 用法 ## 用法
@@ -51,7 +51,7 @@ lancet 是以包的结构组织代码的,使用时需要导入相应的包名
import "github.com/duke-git/lancet/v2/strutil" import "github.com/duke-git/lancet/v2/strutil"
``` ```
## 例 ##
此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包: 此处以字符串工具函数 Reverse逆序字符串为例需要导入 strutil 包:
@@ -117,7 +117,34 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)] [[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等 ### 2. compare 包提供几个轻量级的类型比较函数
```go
import "github.com/duke-git/lancet/v2/compare"
```
#### Function list:
- **<big>Equal</big>** : 检查两个值是否相等(检查类型和值)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#Equal)]
[[play](https://go.dev/play/p/wmVxR-to4lz)]
- **<big>EqualValue</big>** : 检查两个值是否相等(只检查值)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#EqualValue)]
[[play](https://go.dev/play/p/fxnna_LLD9u)]
- **<big>LessThan</big>** : 验证参数`left`的值是否小于参数`right`的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#LessThan)]
[[play](https://go.dev/play/p/cYh7FQQj0ne)]
- **<big>GreaterThan</big>** : 验证参数`left`的值是否大于参数`right`的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterThan)]
[[play](https://go.dev/play/p/9-NYDFZmIMp)]
- **<big>LessOrEqual</big>** : 验证参数`left`的值是否小于或等于参数`right`的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#LessOrEqual)]
[[play](https://go.dev/play/p/e4T_scwoQzp)]
- **<big>GreaterOrEqual</big>** : 验证参数`left`的值是否大于或等于参数`right`的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
### 3. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。
```go ```go
import "github.com/duke-git/lancet/v2/concurrency" import "github.com/duke-git/lancet/v2/concurrency"
@@ -156,7 +183,7 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)] [[play](https://go.dev/play/p/3TQPKnCirrP)]
### 3. condition 包含一些用于条件判断的函数。 ### 4. condition 包含一些用于条件判断的函数。
```go ```go
import "github.com/duke-git/lancet/v2/condition" import "github.com/duke-git/lancet/v2/condition"
@@ -178,10 +205,10 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/gObZrW7ZbG8)] [[play](https://go.dev/play/p/gObZrW7ZbG8)]
- **<big>Nor</big>** : 异或的取反操作。 - **<big>Nor</big>** : 异或的取反操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nor)]
[[play](https://go.dev/play/p/g2j08F_zZky) [[play](https://go.dev/play/p/g2j08F_zZky)]
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。 - **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)]] [[play](https://go.dev/play/p/OuDB9g51643)]
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true - **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
[[play](https://go.dev/play/p/vSRMLxLIbq8)] [[play](https://go.dev/play/p/vSRMLxLIbq8)]
@@ -189,7 +216,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)] [[play](https://go.dev/play/p/ElllPZY0guT)]
### 4. convertor 转换器包支持一些常见的数据类型转换。 ### 5. convertor 转换器包支持一些常见的数据类型转换。
```go ```go
import "github.com/duke-git/lancet/v2/convertor" import "github.com/duke-git/lancet/v2/convertor"
@@ -245,8 +272,21 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>DecodeByte</big>** : 解码字节切片到目标对象,目标对象需要传入一个指针实例。 - **<big>DecodeByte</big>** : 解码字节切片到目标对象,目标对象需要传入一个指针实例。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DecodeByte)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DecodeByte)]
[[play](https://go.dev/play/p/zI6xsmuQRbn)] [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- **<big>DeepClone</big>** : 创建一个传入值的深拷贝, 无法克隆结构体的非导出字段。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#DeepClone)]
[[play](https://go.dev/play/p/j4DP5dquxnk)]
- **<big>CopyProperties</big>** : 拷贝不同结构体之间的同名字段。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#CopyProperties)]
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : 将反射值转换成对应的 interface 类型。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInterface)]
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
- **<big>Utf8ToGbk</big>** : utf8 编码转 GBK 编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#Utf8ToGbk)]
- **<big>GbkToUtf8</big>** : GBK 编码转 utf8 编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#GbkToUtf8)]
### 5. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。 ### 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。
```go ```go
import "github.com/duke-git/lancet/v2/cryptor" import "github.com/duke-git/lancet/v2/cryptor"
@@ -350,9 +390,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)] [[play](https://go.dev/play/p/uef0q1fz53I)]
### 7. datetime 日期时间处理包,格式化日期,比较日期。
### 6. datetime 日期时间处理包,格式化日期,比较日期。
```go ```go
import "github.com/duke-git/lancet/v2/datetime" import "github.com/duke-git/lancet/v2/datetime"
@@ -369,6 +407,9 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>AddMinute</big>** : 将日期加/减分钟数。 - **<big>AddMinute</big>** : 将日期加/减分钟数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)]
[[play](https://go.dev/play/p/nT1heB1KUUK)] [[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : 将日期加/减分年数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddYear)]
[[play](https://go.dev/play/p/MqW2ujnBx10)]
- **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。 - **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)] [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -450,10 +491,23 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>ToIso8601</big>** : 返回 iso8601 日期字符串。 - **<big>ToIso8601</big>** : 返回 iso8601 日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)] [[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>IsLeapYear</big>** :验证是否是闰年。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BetweenSeconds)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
- **<big>DayOfYear</big>** : 返回参数日期是一年中的第几天。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#DayOfYear)]
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
- **<big>IsWeekend</big>** : 判断日期是否是周末。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
### 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph.
### 7. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph.
```go ```go
import list "github.com/duke-git/lancet/v2/datastructure/list" import list "github.com/duke-git/lancet/v2/datastructure/list"
@@ -485,10 +539,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : 哈希映射。 - **<big>Hashmap</big>** : 哈希映射。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
### 9. fileutil 包含文件基本操作。
### 8. fileutil 包含文件基本操作。
```go ```go
import "github.com/duke-git/lancet/v2/fileutil" import "github.com/duke-git/lancet/v2/fileutil"
@@ -538,11 +589,39 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>Zip</big>** : zip 压缩文件, 参数可以是文件或目录。 - **<big>Zip</big>** : zip 压缩文件, 参数可以是文件或目录。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)] [[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>ZipAppendEntry</big>** : 通过将单个文件或目录追加到现有的 zip 文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ZipAppendEntry)]
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。 - **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)] [[play](https://go.dev/play/p/g0w34kS7B8m)]
- **<big>CurrentPath</big>** : 返回当前位置的绝对路径。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CurrentPath)]
[[play](https://go.dev/play/p/s74a9iBGcSw)]
- **<big>IsZipFile</big>** : 判断文件是否是 zip 压缩文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsZipFile)]
[[play](https://go.dev/play/p/9M0g2j_uF_e)]
- **<big>FileSize</big>** : 返回文件字节大小。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileSize)]
[[play](https://go.dev/play/p/H9Z05uD-Jjc)]
- **<big>MTime</big>** : 返回文件修改时间(unix timestamp)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MTime)]
[[play](https://go.dev/play/p/s_Tl7lZoAaY)]
- **<big>Sha</big>** : 返回文件 sha 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Sha)]
[[play](https://go.dev/play/p/VfEEcO2MJYf)]
- **<big>ReadCsvFile</big>** : 读取 csv 文件内容到切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadCsvFile)]
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
- **<big>WriteCsvFile</big>** : 向 csv 文件写入内容。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteCsvFile)]
- **<big>WriteBytesToFile</big>** : 将 bytes 写入文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteBytesToFile)]
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
- **<big>WriteStringToFile</big>** : 将字符串写入文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
### 9. formatter 格式化器包含一些数据格式化处理方法。 ### 10. formatter 格式化器包含一些数据格式化处理方法。
```go ```go
import "github.com/duke-git/lancet/v2/formatter" import "github.com/duke-git/lancet/v2/formatter"
@@ -553,8 +632,26 @@ import "github.com/duke-git/lancet/v2/formatter"
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。 - **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)]
[[play](https://go.dev/play/p/eRD5k2vzUVX)] [[play](https://go.dev/play/p/eRD5k2vzUVX)]
- **<big>Pretty</big>** : 返回 pretty JSON 字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Pretty)]
[[play](https://go.dev/play/p/YsciGj3FH2x)]
- **<big>PrettyToWriter</big>** : Pretty encode 数据到 writer。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#PrettyToWriter)]
[[play](https://go.dev/play/p/LPLZ3lDi5ma)]
- **<big>DecimalBytes</big>** : 返回十进制标准(以 1000 为基数下的可读字节单位字符串。precision 参数指定小数点后的位数,默认为 4。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#DecimalBytes)]
[[play](https://go.dev/play/p/FPXs1suwRcs)]
- **<big>BinaryBytes</big>** : 返回 binary 标准(以 1024 为基数下的可读字节单位字符串。precision 参数指定小数点后的位数,默认为 4。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#BinaryBytes)]
[[play](https://go.dev/play/p/G9oHHMCAZxP)]
- **<big>ParseDecimalBytes</big>** : 将字节单位字符串转换成其所表示的字节数(以 1000 为基数)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseDecimalBytes)]
[[play](https://go.dev/play/p/Am98ybWjvjj)]
- **<big>ParseBinaryBytes</big>** : 将字节单位字符串转换成其所表示的字节数(以 1024 为基数)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
### 10. function 函数包控制函数执行流程,包含部分函数式编程。 ### 11. function 函数包控制函数执行流程,包含部分函数式编程。
```go ```go
import "github.com/duke-git/lancet/v2/function" import "github.com/duke-git/lancet/v2/function"
@@ -590,8 +687,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)] [[play](https://go.dev/play/p/l2yrOpCLd1I)]
### 12. maputil 包括一些操作 map 的函数.
### 11. maputil 包括一些操作 map 的函数.
```go ```go
import "github.com/duke-git/lancet/v2/maputil" import "github.com/duke-git/lancet/v2/maputil"
@@ -599,18 +695,39 @@ import "github.com/duke-git/lancet/v2/maputil"
#### 函数列表: #### 函数列表:
- **<big>MapTo</big>** : 快速将 map 或者其他类型映射到结构体或者指定类型。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#MapTo)]
[[play](https://go.dev/play/p/4K7KBEPgS5M)]
- **<big>ForEach</big>** : 对 map 中的每对 key 和 value 执行 iteratee 函数。 - **<big>ForEach</big>** : 对 map 中的每对 key 和 value 执行 iteratee 函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)]
[[play](https://go.dev/play/p/OaThj6iNVXK)] [[play](https://go.dev/play/p/OaThj6iNVXK)]
- **<big>Filter</big>** : 迭代 map 中的每对 key 和 value返回 map其中的 key 和 value 符合 predicate 函数。 - **<big>Filter</big>** : 迭代 map 中的每对 key 和 value返回 map其中的 key 和 value 符合 predicate 函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)]
[[play](https://go.dev/play/p/fSvF3wxuNG7)] [[play](https://go.dev/play/p/fSvF3wxuNG7)]
- **<big>FilterByKeys</big>** : 迭代 map, 返回一个新 map其 key 都是给定的 key 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FilterByKeys)]
[[play](https://go.dev/play/p/7ov6BJHbVqh)]
- **<big>FilterByValues</big>** : 迭代 map, 返回一个新 map其 value 都是给定的 value 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FilterByValues)]
[[play](https://go.dev/play/p/P3-9MdcXegR)]
- **<big>OmitBy</big>** : Filter 的反向操作, 迭代 map 中的每对 key 和 value, 删除符合 predicate 函数的 key, value, 返回新 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitBy)]
[[play](https://go.dev/play/p/YJM4Hj5hNwm)]
- **<big>OmitByKeys</big>** : FilterByKeys 的反向操作, 迭代 map, 返回一个新 map其 key 不包括给定的 key 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitByKeys)]
[[play](https://go.dev/play/p/jXGrWDBfSRp)]
- **<big>OmitByValues</big>** : FilterByValues 的反向操作, 迭代 map, 返回一个新 map其 value 不包括给定的 value 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#OmitByValues)]
[[play](https://go.dev/play/p/XB7Y10uw20_U)]
- **<big>Intersect</big>** : 多个 map 的交集操作。 - **<big>Intersect</big>** : 多个 map 的交集操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)]
[[play](https://go.dev/play/p/Zld0oj3sjcC)] [[play](https://go.dev/play/p/Zld0oj3sjcC)]
- **<big>Keys</big>** : 返回 map 中所有 key 组成的切片。 - **<big>Keys</big>** : 返回 map 中所有 key 组成的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)]
[[play](https://go.dev/play/p/xNB5bTb97Wd)] [[play](https://go.dev/play/p/xNB5bTb97Wd)]
- **<big>KeysBy</big>** : 创建一个切片,其元素是每个 map 的 key 调用 mapper 函数的结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#KeysBy)]
[[play](https://go.dev/play/p/hI371iB8Up8)]
- **<big>Merge</big>** : 合并多个 map, 相同的 key 会被之后的 key 覆盖。 - **<big>Merge</big>** : 合并多个 map, 相同的 key 会被之后的 key 覆盖。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)]
[[play](https://go.dev/play/p/H95LENF1uB-)] [[play](https://go.dev/play/p/H95LENF1uB-)]
@@ -620,11 +737,29 @@ import "github.com/duke-git/lancet/v2/maputil"
- **<big>Values</big>** : 返回 map 中所有 values 组成的切片 - **<big>Values</big>** : 返回 map 中所有 values 组成的切片
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)]
[[play](https://go.dev/play/p/CBKdUc5FTW6)] [[play](https://go.dev/play/p/CBKdUc5FTW6)]
- **<big>ValuesBy</big>** : 创建一个切片,其元素是每个 map 的 value 调用 mapper 函数的结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#ValuesBy)]
[[play](https://go.dev/play/p/sg9-oRidh8f)]
- **<big>MapKeys</big>** : 操作 map 的每个 key然后转为新的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapKeys)]
[[play](https://go.dev/play/p/8scDxWeBDKd)]
- **<big>MapValues</big>** : 操作 map 的每个 value然后转为新的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#MapValues)]
[[play](https://go.dev/play/p/g92aY3fc7Iw)]
- **<big>Entries</big>** : 将 map 转换为键/值对切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Entries)]
[[play](https://go.dev/play/p/Ltb11LNcElY)]
- **<big>FromEntries</big>** : 基于键/值对的切片创建 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#FromEntries)]
[[play](https://go.dev/play/p/fTdu4sCNjQO)]
- **<big>Transform</big>** : 将 map 转换为其他类型的 map。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN#Transform)]
[[play](https://go.dev/play/p/P6ovfToM3zj)]
- **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。 - **<big>IsDisjoint</big>** : 验证两个 map 是否具有不同的 key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)] [[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 12. mathutil 包实现了一些数学计算的函数。 ### 13. mathutil 包实现了一些数学计算的函数。
```go ```go
import "github.com/duke-git/lancet/v2/mathutil" import "github.com/duke-git/lancet/v2/mathutil"
@@ -658,7 +793,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/N9qgYg_Ho6f)] [[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : 计算百分比,可以指定保留 n 位小数。 - **<big>Percent</big>** : 计算百分比,可以指定保留 n 位小数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)]
[[play](https://go.dev/play/p/QQM9B13coSP)] [[play](https://go.dev/play/p/s0NdFCtwuyd)]
- **<big>RoundToFloat</big>** : 四舍五入,保留 n 位小数,返回 float64。 - **<big>RoundToFloat</big>** : 四舍五入,保留 n 位小数,返回 float64。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)] [[play](https://go.dev/play/p/ghyb528JRJL)]
@@ -668,8 +803,42 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<big>TruncRound</big>** : 截短 n 位小数(不进行四舍五入)。 - **<big>TruncRound</big>** : 截短 n 位小数(不进行四舍五入)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)]
[[play](https://go.dev/play/p/aumarSHIGzP)] [[play](https://go.dev/play/p/aumarSHIGzP)]
- **<big>Range</big>** : 根据指定的起始值和数量,创建一个数字切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Range)]
[[play](https://go.dev/play/p/9ke2opxa8ZP)]
- **<big>RangeWithStep</big>** : 根据指定的起始值,结束值,步长,创建一个数字切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RangeWithStep)]
[[play](https://go.dev/play/p/akLWz0EqOSM)]
- **<big>AngleToRadian</big>** : 将角度值转为弧度值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#AngleToRadian)]
[[play](https://go.dev/play/p/CIvlICqrHql)]
- **<big>RadianToAngle</big>** : 将弧度值转为角度值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RadianToAngle)]
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
- **<big>PointDistance</big>** : 计算两个坐标点的距离。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#PointDistance)]
[[play](https://go.dev/play/p/RrG4JIaziM8)]
- **<big>IsPrime</big>** : 判断质数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : 求最大公约数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#GCD)]
[[play](https://go.dev/play/p/CiEceLSoAKB)]
- **<big>LCM</big>** : 求最小公倍数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#LCM)]
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
- **<big>Cos</big>** : 计算弧度的余弦值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Cos)]
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
- **<big>Sin</big>** : 计算弧度的正弦值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sin)]
[[play](https://go.dev/play/p/TWMQlMywDsP)]
- **<big>Log</big>** : 计算以 base 为底 n 的对数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Log)]
- **<big>Sum</big>** : 求传入参数之和。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sum)]
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。 ### 14. netutil 网络包支持获取 ip 地址,发送 http 请求。
```go ```go
import "github.com/duke-git/lancet/v2/netutil" import "github.com/duke-git/lancet/v2/netutil"
@@ -731,11 +900,18 @@ import "github.com/duke-git/lancet/v2/netutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)]
- **<big>ParseHttpResponse</big>** : 解析 http 响应体到目标结构体。 - **<big>ParseHttpResponse</big>** : 解析 http 响应体到目标结构体。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)]
- **<big>DownloadFile</big>** : 从指定的 server 地址下载文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DownloadFile)]
- **<big>UploadFile</big>** : 将文件上传指定的 server 地址。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#UploadFile)]
- **<big>IsPingConnected</big>** : 检查能否 ping 通主机。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPingConnected)]
[[play](https://go.dev/play/p/q8OzTijsA87)]
- **<big>IsTelnetConnected</big>** : 检查能否 telnet 到主机。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
### 15. random 随机数生成器包,可以生成随机[]bytes, int, string。
### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。
```go ```go
import "github.com/duke-git/lancet/v2/random" import "github.com/duke-git/lancet/v2/random"
@@ -767,10 +943,10 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>UUIdV4</big>** : 生成 UUID v4 字符串。 - **<big>UUIdV4</big>** : 生成 UUID v4 字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)] [[play](https://go.dev/play/p/_Z9SFmr28ft)]
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为n的随机int切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUniqueIntSlice)]
### 16. retry 重试执行函数直到函数运行成功或被 context cancel。
### 15. retry 重试执行函数直到函数运行成功或被 context cancel。
```go ```go
import "github.com/duke-git/lancet/v2/retry" import "github.com/duke-git/lancet/v2/retry"
@@ -794,21 +970,23 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)] [[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 17. slice 包含操作切片的方法集合。
### 16. slice 包含操作切片的方法集合。
```go ```go
import "github.com/duke-git/lancet/v2/slice" import "github.com/duke-git/lancet/v2/slice"
``` ```
#### 函数列表: #### 函数列表:
- **<big>AppendIfAbsent</big>** : 当前切片中不包含值时,将该值追加到切片中。 - **<big>AppendIfAbsent</big>** : 当前切片中不包含值时,将该值追加到切片中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)]
[[play](https://go.dev/play/p/GNdv7Jg2Taj)] [[play](https://go.dev/play/p/GNdv7Jg2Taj)]
- **<big>Contain</big>** : 判断 slice 是否包含 value。 - **<big>Contain</big>** : 判断 slice 是否包含 value。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)]
[[play](https://go.dev/play/p/_454yEHcNjf)] [[play](https://go.dev/play/p/_454yEHcNjf)]
- **<big>ContainBy</big>** : 根据 predicate 函数判断切片是否包含某个值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainBy)]
[[play](https://go.dev/play/p/49tkHfX4GNc)]
- **<big>ContainSubSlice</big>** : 判断 slice 是否包含 subslice。 - **<big>ContainSubSlice</big>** : 判断 slice 是否包含 subslice。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)]
[[play](https://go.dev/play/p/bcuQ3UT6Sev)] [[play](https://go.dev/play/p/bcuQ3UT6Sev)]
@@ -839,9 +1017,18 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。 - **<big>DeleteAt</big>** : 删除切片中指定开始索引到结束索引的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteAt)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)] [[play](https://go.dev/play/p/pJ-d6MUWcvK)]
- **<big>Drop</big>** : 创建一个切片当n > 0时从开头删除n个元素或者当n < 0时从结尾删除n个元素。 - **<big>Drop</big>** : 从切片头部删除 n 个元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)]
[[play](https://go.dev/play/p/pJ-d6MUWcvK)] [[play](https://go.dev/play/p/jnPO2yQsT8H)]
- **<big>DropRight</big>** : 从切片尾部删除 n 个元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRight)]
[[play](https://go.dev/play/p/8bcXvywZezG)]
- **<big>DropWhile</big>** : 从切片的头部删除 n 个元素,这个 n 个元素满足 predicate 函数返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropWhile)]
[[play](https://go.dev/play/p/4rt252UV_qs)]
- **<big>DropRightWhile</big>** : 从切片的尾部删除 n 个元素,这个 n 个元素满足 predicate 函数返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DropRightWhile)]
[[play](https://go.dev/play/p/6wyK3zMY56e)]
- **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。 - **<big>Equal</big>** : 检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)]
[[play](https://go.dev/play/p/WcRQJ37ifPa)] [[play](https://go.dev/play/p/WcRQJ37ifPa)]
@@ -854,21 +1041,36 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Filter</big>** : 返回切片中通过 predicate 函数真值测试的所有元素。 - **<big>Filter</big>** : 返回切片中通过 predicate 函数真值测试的所有元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)]
[[play](https://go.dev/play/p/SdPna-7qK4T)] [[play](https://go.dev/play/p/SdPna-7qK4T)]
- **<big>Find</big>** : 遍历切片的元素,返回一个通过predicate函数真值测试的元素 - **<big>FilterMap</big>** : 返回一个将 filter 和 map 操作应用于给定切片的切片
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FilterMap)]
[[play](https://go.dev/play/p/J94SZ_9MiIe)]
- **<big>Find<sup>deprecated</sup></big>** : 遍历切片的元素,返回第一个通过 predicate 函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)]
[[play](https://go.dev/play/p/CBKeBoHVLgq)] [[play](https://go.dev/play/p/CBKeBoHVLgq)]
- **<big>FindLast</big>** : 从头到尾遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。 - **<big>FindBy</big>** : 遍历切片的元素,返回一个通过 predicate 函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindBy)]
[[play](https://go.dev/play/p/n1lysBYl-GB)]
- **<big>FindLast<sup>deprecated</sup></big>** : 从头到尾遍历 slice 的元素,返回最后一个通过 predicate 函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)]
[[play](https://go.dev/play/p/FFDPV_j7URd)] [[play](https://go.dev/play/p/FFDPV_j7URd)]
- **<big>FindLastBy</big>** : 从遍历 slice 的元素,返回最后一个通过 predicate 函数真值测试的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLastBy)]
[[play](https://go.dev/play/p/8iqomzyCl_s)]
- **<big>Flatten</big>** : 将多维切片展平一层。 - **<big>Flatten</big>** : 将多维切片展平一层。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)]
[[play](https://go.dev/play/p/hYa3cBEevtm)] [[play](https://go.dev/play/p/hYa3cBEevtm)]
- **<big>FlattenDeep</big>** : 将多维切片递归展平到一层。 - **<big>FlattenDeep</big>** : 将多维切片递归展平到一层。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlattenDeep)]
[[play](https://go.dev/play/p/yjYNHPyCFaF)] [[play](https://go.dev/play/p/yjYNHPyCFaF)]
- **<big>FlatMap</big>** : 将切片转换为其它类型切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FlatMap)]
[[play](https://go.dev/play/p/_QARWlWs1N_F)]
- **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数。 - **<big>ForEach</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)]
[[play](https://go.dev/play/p/DrPaa4YsHRF)] [[play](https://go.dev/play/p/DrPaa4YsHRF)]
- **<big>ForEachWithBreak</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数,当 iteratee 函数返回 false 时,终止遍历。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEachWithBreak)]
[[play](https://go.dev/play/p/qScs39f3D9W)]
- **<big>GroupBy</big>** : 迭代切片的元素,每个元素将按条件分组,返回两个切片。 - **<big>GroupBy</big>** : 迭代切片的元素,每个元素将按条件分组,返回两个切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)]
[[play](https://go.dev/play/p/QVkPxzPR0iA)] [[play](https://go.dev/play/p/QVkPxzPR0iA)]
@@ -902,9 +1104,15 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Reverse</big>** : 反转切片中的元素顺序。 - **<big>Reverse</big>** : 反转切片中的元素顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
[[play](https://go.dev/play/p/8uI8f1lwNrQ)] [[play](https://go.dev/play/p/8uI8f1lwNrQ)]
- **<big>Reduce</big>** : 将切片中的元素依次运行iteratee函数返回运行结果。 - **<big>Reduce<sup>deprecated</sup></big>** : 将切片中的元素依次运行 iteratee 函数,返回运行结果。(废弃:建议使用 ReduceBy)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
[[play](https://go.dev/play/p/_RfXJJWIsIm)] [[play](https://go.dev/play/p/_RfXJJWIsIm)]
- **<big>ReduceBy</big>** : 对切片元素执行 reduce 操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReduceBy)]
[[play](https://go.dev/play/p/YKDpLi7gtee)]
- **<big>ReduceRight</big>** : 类似 ReduceBy 操作,迭代切片元素顺序从右至左。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReduceRight)]
[[play](https://go.dev/play/p/qT9dZC03A1K)]
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。 - **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)] [[play](https://go.dev/play/p/P5mZp7IhOFo)]
@@ -917,6 +1125,18 @@ import "github.com/duke-git/lancet/v2/slice"
- **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。 - **<big>Shuffle</big>** : 随机打乱切片中的元素顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Shuffle)]
[[play](https://go.dev/play/p/YHvhnWGU3Ge)] [[play](https://go.dev/play/p/YHvhnWGU3Ge)]
- **<big>IsAscending</big>** : 检查切片元素是否按升序排列。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsAscending)]
[[play](https://go.dev/play/p/9CtsFjet4SH)]
- **<big>IsDescending</big>** : 检查切片元素是否按降序排列。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsDescending)]
[[play](https://go.dev/play/p/U_LljFXma14)]
- **<big>IsSorted</big>** : 检查切片元素是否是有序的(升序或降序)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSorted)]
[[play](https://go.dev/play/p/nCE8wPLwSA-)]
- **<big>IsSortedByKey</big>** : 通过 iteratee 函数,检查切片元素是否是有序的。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IsSortedByKey)]
[[play](https://go.dev/play/p/tUoGB7DOHI4)]
- **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。 - **<big>Sort</big>** : 对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Sort)]
[[play](https://go.dev/play/p/V9AVjzf_4Fk)] [[play](https://go.dev/play/p/V9AVjzf_4Fk)]
@@ -963,8 +1183,129 @@ import "github.com/duke-git/lancet/v2/slice"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)] [[play](https://go.dev/play/p/uXod2LWD1Kg)]
### 18. Stream 流,该包仅验证简单的 stream 实现,功能有限。
### 17. strutil 包含字符串处理的相关函数。 ```go
import "github.com/duke-git/lancet/v2/stream"
```
#### Function list:
- **<big>Of</big>** : 创建元素为指定值的 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Of)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
- **<big>FromSlice</big>** : 从切片创建 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromSlice)]
[[play](https://go.dev/play/p/wywTO0XZtI4)]
- **<big>FromChannel</big>** : 从通道创建 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromChannel)]
[[play](https://go.dev/play/p/9TZYugGMhXZ)]
- **<big>FromRange</big>** : 指定一个数字范围创建 stream, 范围两端点值都包括在内。. [start, end]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromRange)]
[[play](https://go.dev/play/p/9Ex1-zcg-B-)]
- **<big>Generate</big>** : 创建一个 stream其中每个元素都由提供的生成器函数生成。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Generate)]
[[play](https://go.dev/play/p/rkOWL1yA3j9)]
- **<big>Concat</big>** : 创建一个延迟连接 stream其元素是第一个 stream 的所有元素,后跟第二个 stream 的全部元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Concat)]
[[play](https://go.dev/play/p/HM4OlYk_OUC)]
- **<big>Distinct</big>** : 创建并返回一个 stream用于删除重复的项。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Distinct)]
[[play](https://go.dev/play/p/eGkOSrm64cB)]
- **<big>Filter</big>** : 返回一个通过判定函数的 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Filter)]
[[play](https://go.dev/play/p/MFlSANo-buc)]
- **<big>Map</big>** : 返回一个 stream该 stream 由将给定函数应用于源 stream 元素的元素组成。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Map)]
[[play](https://go.dev/play/p/OtNQUImdYko)]
- **<big>Peek</big>** : 返回一个由源 stream 的元素组成的 stream并在从生成的 stream 中消耗元素时对每个元素执行所提供的操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Peek)]
[[play](https://go.dev/play/p/u1VNzHs6cb2)]
- **<big>Skip</big>** : 在丢弃 stream 的前 n 个元素后,返回由源 stream 的其余元素组成的 stream。如果此 stream 包含的元素少于 n 个,则将返回一个空 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Skip)]
[[play](https://go.dev/play/p/fNdHbqjahum)]
- **<big>Limit</big>** : 返回由源 stream 的元素组成的 stream该 stream 被截断为长度不超过 maxSize。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Limit)]
[[play](https://go.dev/play/p/qsO4aniDcGf)]
- **<big>Reverse</big>** : 返回元素与源 stream 的顺序相反的 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reverse)]
[[play](https://go.dev/play/p/A8_zkJnLHm4)]
- **<big>Range</big>** : 返回一个 stream该 stream 的元素在从源 stream 的开始(包含)到结束(排除)的范围内。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Range)]
[[play](https://go.dev/play/p/indZY5V2f4j)]
- **<big>Sorted</big>** : 返回一个 stream该 stream 由源 stream 的元素组成,并根据提供的 less 函数进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Sorted)]
[[play](https://go.dev/play/p/XXtng5uonFj)]
- **<big>ForEach</big>** : 对 stream 的每个元素执行一个操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ForEach)]
[[play](https://go.dev/play/p/Dsm0fPqcidk)]
- **<big>Reduce</big>** : 使用关联累加函数对 stream 的元素执行 reduce 操作,并 reduce 操作结果(如果有)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reduce)]
[[play](https://go.dev/play/p/6uzZjq_DJLU)]
- **<big>FindFirst</big>** : 返回此 stream 的第一个元素,如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindFirst)]
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : 返回此 stream 的最后一个元素,如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindLast)]
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
- **<big>Max</big>** : 根据提供的 less 函数返回 stream 的最大元素。less 函数: a > b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
- **<big>Min</big>** : 根据提供的 less 函数返回 stream 的最小元素。less 函数: a < b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Min)]
[[play](https://go.dev/play/p/vZfIDgGNRe_0)]
- **<big>AllMatch</big>** : 判断 stream 的所有元素是否全部匹配指定判定函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#AllMatch)]
[[play](https://go.dev/play/p/V5TBpVRs-Cx)]
- **<big>AnyMatch</big>** : 判断 stream 是否包含匹配指定判定函数的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#AnyMatch)]
[[play](https://go.dev/play/p/PTCnWn4OxSn)]
- **<big>NoneMatch</big>** : 判断 stream 的元素是否全部不匹配指定的判定函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#NoneMatch)]
[[play](https://go.dev/play/p/iWS64pL1oo3)]
- **<big>Count</big>** : 返回 stream 中元素的数量。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Count)]
[[play](https://go.dev/play/p/r3koY6y_Xo-)]
- **<big>ToSlice</big>** : 返回 stream 中的元素切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
### 19. structs 提供操作 struct, tag, field 的相关函数。
```go
import "github.com/duke-git/lancet/v2/structs"
```
#### Function list:
- **<big>New</big>** : `Struct`结构体的构造函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#New)]
- **<big>ToMap</big>** : 将一个合法的 struct 对象转换为 map[string]any。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#ToMap)]
- **<big>Fields</big>** : 获取一个 struct 对象的属性列表。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#Fields)]
- **<big>Field</big>** : 根据属性名获取一个 struct 对象的属性。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#Fields)]
- **<big>IsStruct</big>** : 判断是否为一个合法的 struct 对象。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#IsStruct)]
- **<big>Tag</big>** : 获取`Field``Tag`,默认的 tag key 是 json。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#Tag)]
- **<big>Name</big>** : 获取属性名。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#Name)]
- **<big>Value</big>** : 获取`Field`属性的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#Value)]
- **<big>Kind</big>** : 获取属性 Kind。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#Kind)]
- **<big>IsEmbedded</big>** : 判断属性是否为嵌入。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsEmbedded)]
- **<big>IsExported</big>** : 判断属性是否导出。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsExported)]
- **<big>IsZero</big>** : 判断属性是否为零值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsZero)]
- **<big>IsSlice</big>** : 判断属性是否是切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsSlice)]
### 20. strutil 包含字符串处理的相关函数。
```go ```go
import "github.com/duke-git/lancet/v2/strutil" import "github.com/duke-git/lancet/v2/strutil"
@@ -990,6 +1331,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Capitalize</big>** : 将字符串的第一个字符转换为大写。 - **<big>Capitalize</big>** : 将字符串的第一个字符转换为大写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)] [[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>ContainsAll</big>** : 判断字符串是否包括全部给定的子字符串切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAll)]
[[play](https://go.dev/play/p/KECtK2Os4zq)]
- **<big>ContainsAny</big>** : 判断字符串是否包括给定的子字符串切片中任意一个子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAny)]
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
- **<big>IsString</big>** : 判断传入参数的数据类型是否为字符串。 - **<big>IsString</big>** : 判断传入参数的数据类型是否为字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)] [[play](https://go.dev/play/p/IOgq7oF9ERm)]
@@ -1005,6 +1352,9 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>UpperFirst</big>** : 将字符串的第一个字符转换为大写形式。 - **<big>UpperFirst</big>** : 将字符串的第一个字符转换为大写形式。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)]
[[play](https://go.dev/play/p/sBbBxRbs8MM)] [[play](https://go.dev/play/p/sBbBxRbs8MM)]
- **<big>Pad</big>** : 如果字符串长度短于 size则在左右两侧填充字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Pad)]
[[play](https://go.dev/play/p/NzImQq-VF8q)]
- **<big>PadEnd</big>** : 如果字符串短于限制大小,则在右侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。 - **<big>PadEnd</big>** : 如果字符串短于限制大小,则在右侧用给定字符填充字符串。 如果填充字符超出大小,它们将被截断。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)]
[[play](https://go.dev/play/p/9xP8rN0vz--)] [[play](https://go.dev/play/p/9xP8rN0vz--)]
@@ -1032,8 +1382,49 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Unwrap</big>** : 从另一个字符串中解开一个给定的字符串。 将更改源字符串。 - **<big>Unwrap</big>** : 从另一个字符串中解开一个给定的字符串。 将更改源字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/Ec2q4BzCpG-)] [[play](https://go.dev/play/p/Ec2q4BzCpG-)]
- **<big>SplitWords</big>** : 将字符串拆分为单词,只支持字母字符单词。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitWords)]
[[play](https://go.dev/play/p/KLiX4WiysMM)]
- **<big>WordCount</big>** : 返回有意义单词的数量,只支持字母字符单词。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#WordCount)]
[[play](https://go.dev/play/p/bj7_odx3vRf)]
- **<big>RemoveNonPrintable</big>** : 删除字符串中不可打印的字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveNonPrintable)]
[[play](https://go.dev/play/p/og47F5x_jTZ)]
- **<big>StringToBytes</big>** : 在不分配内存的情况下将字符串转换为字节片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#StringToBytes)]
[[play](https://go.dev/play/p/7OyFBrf9AxA)]
- **<big>BytesToString</big>** : 在不分配内存的情况下将字节切片转换为字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BytesToString)]
[[play](https://go.dev/play/p/6c68HRvJecH)]
- **<big>IsBlank</big>** : 检查字符串是否为空格或空。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsBlank)]
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
- **<big>HasPrefixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个开头。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HasPrefixAny)]
[[play](https://go.dev/play/p/8UUTl2C5slo)]
- **<big>HasSuffixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个结尾。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HasSuffixAny)]
[[play](https://go.dev/play/p/sKWpCQdOVkx)]
- **<big>IndexOffset</big>** : 将字符串偏移 idxFrom 后,返回字符串中第一个 substr 实例的索引。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IndexOffset)]
[[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : 返回 string 的副本,以无序的方式被 map 替换,区分大小写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReplaceWithMap)]
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
- **<big>Trim</big>** : 从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Trim)]
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
- **<big>SplitAndTrim</big>** : 将字符串 str 按字符串 delimiter 拆分为一个切片,并对该数组的每个元素调用 Trim。忽略 Trim 后为空的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitAndTrim)]
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
- **<big>HideString</big>** : 隐藏源字符串中的一些字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HideString)]
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
- **<big>RemoveWhiteSpace</big>** : 删除字符串中的空格。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveWhiteSpace)]
### 18. system 包含 os, runtime, shell command 的相关函数。 ### 21. system 包含 os, runtime, shell command 的相关函数。
```go ```go
import "github.com/duke-git/lancet/v2/system" import "github.com/duke-git/lancet/v2/system"
@@ -1069,7 +1460,7 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)] [[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 19. validator 验证器包,包含常用字符串格式验证函数。 ### 22. validator 验证器包,包含常用字符串格式验证函数。
```go ```go
import "github.com/duke-git/lancet/v2/validator" import "github.com/duke-git/lancet/v2/validator"
@@ -1122,18 +1513,27 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsEmptyString</big>** : 验证字符串是否是空字符串。 - **<big>IsEmptyString</big>** : 验证字符串是否是空字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)]
[[play](https://go.dev/play/p/dpzgUjFnBCX)] [[play](https://go.dev/play/p/dpzgUjFnBCX)]
- **<big>IsFloat</big>** : 验证参数是否是浮点数((float32float34)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloat)]
[[play](https://go.dev/play/p/vsyG-sxr99_Z)]
- **<big>IsFloatStr</big>** : 验证字符串是否是可以转换为浮点数。 - **<big>IsFloatStr</big>** : 验证字符串是否是可以转换为浮点数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#LOYwS_Oyl7U)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)]
[[play](https://go.dev/play/p/LOYwS_Oyl7U)] [[play](https://go.dev/play/p/LOYwS_Oyl7U)]
- **<big>IsNumber</big>** : 验证参数是否是数字(integerfloat)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumber)]
[[play](https://go.dev/play/p/mdJHOAvtsvF)]
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。 - **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
[[play](https://go.dev/play/p/LzaKocSV79u)] [[play](https://go.dev/play/p/LzaKocSV79u)]
- **<big>IsJSON</big>** : 验证字符串是否是有效 json。 - **<big>IsJSON</big>** : 验证字符串是否是有效 json。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
[[play](https://go.dev/play/p/sRS6c4K8jGk)] [[play](https://go.dev/play/p/8Kip1Itjiil)]
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。 - **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)]
[[play](https://go.dev/play/p/z_XeZo_litG)] [[play](https://go.dev/play/p/z_XeZo_litG)]
- **<big>IsInt</big>** : 验证参数是否是整数(int, unit)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsInt)]
[[play](https://go.dev/play/p/eFoIHbgzl-z)]
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。 - **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
[[play](https://go.dev/play/p/jQRtFv-a0Rk)] [[play](https://go.dev/play/p/jQRtFv-a0Rk)]
@@ -1161,9 +1561,14 @@ import "github.com/duke-git/lancet/v2/validator"
- **<big>IsGBK</big>** : 检查数据编码是否为 gbk汉字内部代码扩展规范 - **<big>IsGBK</big>** : 检查数据编码是否为 gbk汉字内部代码扩展规范
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)]
[[play](https://go.dev/play/p/E2nt3unlmzP)] [[play](https://go.dev/play/p/E2nt3unlmzP)]
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsASCII)]
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
### 23. xerror 包实现一些错误处理函数
### 20. xerror 包实现一些错误处理函数
```go ```go
import "github.com/duke-git/lancet/v2/xerror" import "github.com/duke-git/lancet/v2/xerror"
@@ -1171,12 +1576,45 @@ import "github.com/duke-git/lancet/v2/xerror"
#### 函数列表: #### 函数列表:
- **<big>New</big>** : 创建 XError 对象实例。
- **<big>Unwrap</big>** : 检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。 [[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#New)]
[[play](https://go.dev/play/p/w4oWZts7q7f)]
- **<big>Wrap</big>** : 根据 error 对象创建 XError 对象实例,可添加 message。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Wrap)]
[[play](https://go.dev/play/p/5385qT2dCi4)]
- **<big>Unwrap</big>** : 从 error 对象中解构出 XError。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/w84d7Mb3Afk)] [[play](https://go.dev/play/p/LKMLep723tu)]
- **<big>XError_Wrap</big>** : 创建新的 XError 对象并将消息和 id 复制到新的对象中。
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap) [[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Wrap)]
[[play](https://go.dev/play/p/5385qT2dCi4)]
- **<big>XError_Unwrap</big>** : 解构 XEerror 为 error 对象。适配 github.com/pkg/errors。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Unwrap)]
[[play](https://go.dev/play/p/VUXJ8BST4c6)]
- **<big>XError_With</big>** : 添加与 XError 对象的键和值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_With)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_Id</big>** : 设置 XError 对象的 id。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Id)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Is</big>** : 检查目标 error 是否为 XError两个错误中的 error.id 是否匹配。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Is)]
[[play](https://go.dev/play/p/X6HBlsy58U9)]
- **<big>XError_Values</big>** : 返回由 With 设置的键和值的映射。将合并所有 XError 键和值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Values)]
[[play](https://go.dev/play/p/ow8UISXX_Dp)]
- **<big>XError_StackTrace</big>** : 返回与 pkg/error 兼容的堆栈信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_StackTrace)]
[[play](https://go.dev/play/p/6FAvSQpa7pc)]
- **<big>XError_Info</big>** : 返回可打印的 XError 对象信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Info)]
[[play](https://go.dev/play/p/1ZX0ME1F-Jb)]
- **<big>XError_Error</big>** : 实现标准库的 error 接口。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#XError_Error)]
[[play](https://go.dev/play/p/w4oWZts7q7f)]
- **<big>TryUnwrap</big>** : 检查 error, 如果 err 为 nil 则展开,则它返回一个有效值,如果 err 不是 nil 则 Unwrap 使用 err 发生 panic。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#TryUnwrap)]
[[play](https://go.dev/play/p/acyZVkNZEeW)]
## 如何贡献代码 ## 如何贡献代码

View File

@@ -200,7 +200,6 @@ func TestCountSort(t *testing.T) {
} }
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
sortedPeopleByAge := CountSort(peoples, comparator) sortedPeopleByAge := CountSort(peoples, comparator)
t.Log(sortedPeopleByAge)
expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]" expected := "[{d 8} {b 10} {c 17} {a 20} {e 28}]"
actual := fmt.Sprintf("%v", sortedPeopleByAge) actual := fmt.Sprintf("%v", sortedPeopleByAge)

64
compare/compare.go Normal file
View File

@@ -0,0 +1,64 @@
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
// Package compare provides a lightweight comparison function on any type.
// reference: https://github.com/stretchr/testify
package compare
import (
"reflect"
"time"
"github.com/duke-git/lancet/v2/convertor"
)
// operator type
const (
equal = "eq"
lessThan = "lt"
greaterThan = "gt"
lessOrEqual = "le"
greaterOrEqual = "ge"
)
var (
timeType = reflect.TypeOf(time.Time{})
bytesType = reflect.TypeOf([]byte{})
)
// Equal checks if two values are equal or not. (check both type and value)
// Play: https://go.dev/play/p/wmVxR-to4lz
func Equal(left, right any) bool {
return compareValue(equal, left, right)
}
// EqualValue checks if two values are equal or not. (check value only)
// Play: https://go.dev/play/p/fxnna_LLD9u
func EqualValue(left, right any) bool {
ls, rs := convertor.ToString(left), convertor.ToString(right)
return ls == rs
}
// LessThan checks if value `left` less than value `right`.
// Play: https://go.dev/play/p/cYh7FQQj0ne
func LessThan(left, right any) bool {
return compareValue(lessThan, left, right)
}
// GreaterThan checks if value `left` greater than value `right`.
// Play: https://go.dev/play/p/9-NYDFZmIMp
func GreaterThan(left, right any) bool {
return compareValue(greaterThan, left, right)
}
// LessOrEqual checks if value `left` less than or equal to value `right`.
// Play: https://go.dev/play/p/e4T_scwoQzp
func LessOrEqual(left, right any) bool {
return compareValue(lessOrEqual, left, right)
}
// GreaterOrEqual checks if value `left` greater than or equal to value `right`.
// Play: https://go.dev/play/p/vx8mP0U8DFk
func GreaterOrEqual(left, right any) bool {
return compareValue(greaterOrEqual, left, right)
}

View File

@@ -0,0 +1,170 @@
package compare
import (
"fmt"
"time"
)
func ExampleEqual() {
result1 := Equal(1, 1)
result2 := Equal("1", "1")
result3 := Equal([]int{1, 2, 3}, []int{1, 2, 3})
result4 := Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
result5 := Equal(1, "1")
result6 := Equal(1, int64(1))
result7 := Equal([]int{1, 2}, []int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
func ExampleEqualValue() {
result1 := EqualValue(1, 1)
result2 := EqualValue(int(1), int64(1))
result3 := EqualValue(1, "1")
result4 := EqualValue(1, "2")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
func ExampleLessThan() {
result1 := LessThan(1, 2)
result2 := LessThan(1.1, 2.2)
result3 := LessThan("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := LessThan(time1, time2)
result5 := LessThan(2, 1)
result6 := LessThan(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
func ExampleGreaterThan() {
result1 := GreaterThan(2, 1)
result2 := GreaterThan(2.2, 1.1)
result3 := GreaterThan("b", "a")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := GreaterThan(time2, time1)
result5 := GreaterThan(1, 2)
result6 := GreaterThan(int64(2), 1)
result7 := GreaterThan("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
func ExampleLessOrEqual() {
result1 := LessOrEqual(1, 1)
result2 := LessOrEqual(1.1, 2.2)
result3 := LessOrEqual("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := LessOrEqual(time1, time2)
result5 := LessOrEqual(2, 1)
result6 := LessOrEqual(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
func ExampleGreaterOrEqual() {
result1 := GreaterOrEqual(1, 1)
result2 := GreaterOrEqual(2.2, 1.1)
result3 := GreaterOrEqual("b", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := GreaterOrEqual(time2, time1)
result5 := GreaterOrEqual(1, 2)
result6 := GreaterOrEqual(int64(2), 1)
result7 := GreaterOrEqual("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}

323
compare/compare_internal.go Normal file
View File

@@ -0,0 +1,323 @@
package compare
import (
"bytes"
"encoding/json"
"reflect"
"time"
"github.com/duke-git/lancet/v2/convertor"
)
func compareValue(operator string, left, right any) bool {
leftType, rightType := reflect.TypeOf(left), reflect.TypeOf(right)
if leftType.Kind() != rightType.Kind() {
return false
}
switch leftType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.Bool, reflect.String:
return compareBasicValue(operator, left, right)
case reflect.Struct, reflect.Slice, reflect.Map:
return compareRefValue(operator, left, right, leftType.Kind())
}
return false
}
func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind) bool {
leftVal, rightVal := reflect.ValueOf(leftObj), reflect.ValueOf(rightObj)
switch kind {
case reflect.Struct:
// compare time
if leftVal.CanConvert(timeType) {
timeObj1, ok := leftObj.(time.Time)
if !ok {
timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
}
timeObj2, ok := rightObj.(time.Time)
if !ok {
timeObj2 = rightVal.Convert(timeType).Interface().(time.Time)
}
return compareBasicValue(operator, timeObj1.UnixNano(), timeObj2.UnixNano())
}
// for other struct type, only process equal operator
switch operator {
case equal:
return objectsAreEqualValues(leftObj, rightObj)
}
case reflect.Slice:
// compare []byte
if leftVal.CanConvert(bytesType) {
bytesObj1, ok := leftObj.([]byte)
if !ok {
bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
}
bytesObj2, ok := rightObj.([]byte)
if !ok {
bytesObj2 = rightVal.Convert(bytesType).Interface().([]byte)
}
switch operator {
case equal:
if bytes.Compare(bytesObj1, bytesObj2) == 0 {
return true
}
case lessThan:
if bytes.Compare(bytesObj1, bytesObj2) == -1 {
return true
}
case greaterThan:
if bytes.Compare(bytesObj1, bytesObj2) == 1 {
return true
}
case lessOrEqual:
if bytes.Compare(bytesObj1, bytesObj2) <= 0 {
return true
}
case greaterOrEqual:
if bytes.Compare(bytesObj1, bytesObj2) >= 0 {
return true
}
}
}
// for other type slice, only process equal operator
switch operator {
case equal:
return reflect.DeepEqual(leftObj, rightObj)
}
case reflect.Map:
// only process equal operator
switch operator {
case equal:
return reflect.DeepEqual(leftObj, rightObj)
}
}
return false
}
func objectsAreEqualValues(expected, actual interface{}) bool {
if objectsAreEqual(expected, actual) {
return true
}
actualType := reflect.TypeOf(actual)
if actualType == nil {
return false
}
expectedValue := reflect.ValueOf(expected)
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
// Attempt comparison after type conversion
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
}
return false
}
func objectsAreEqual(expected, actual interface{}) bool {
if expected == nil || actual == nil {
return expected == actual
}
exp, ok := expected.([]byte)
if !ok {
return reflect.DeepEqual(expected, actual)
}
act, ok := actual.([]byte)
if !ok {
return false
}
if exp == nil || act == nil {
return exp == nil && act == nil
}
return bytes.Equal(exp, act)
}
// compareBasic compare basic value: integer, float, string, bool
func compareBasicValue(operator string, leftValue, rightValue any) bool {
if leftValue == nil && rightValue == nil && operator == equal {
return true
}
switch leftVal := leftValue.(type) {
case json.Number:
if left, err := leftVal.Float64(); err == nil {
switch rightVal := rightValue.(type) {
case json.Number:
if right, err := rightVal.Float64(); err == nil {
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
left, err := convertor.ToFloat(leftValue)
if err != nil {
return false
}
switch rightVal := rightValue.(type) {
case json.Number:
if right, err := rightVal.Float64(); err == nil {
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
right, err := convertor.ToFloat(rightValue)
if err != nil {
return false
}
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case string:
left := leftVal
switch right := rightValue.(type) {
case string:
switch operator {
case equal:
if left == right {
return true
}
case lessThan:
if left < right {
return true
}
case greaterThan:
if left > right {
return true
}
case lessOrEqual:
if left <= right {
return true
}
case greaterOrEqual:
if left >= right {
return true
}
}
}
case bool:
left := leftVal
switch right := rightValue.(type) {
case bool:
switch operator {
case equal:
if left == right {
return true
}
}
}
}
return false
}

134
compare/compare_test.go Normal file
View File

@@ -0,0 +1,134 @@
package compare
import (
"testing"
"time"
"github.com/duke-git/lancet/v2/internal"
)
func TestEqual(t *testing.T) {
assert := internal.NewAssert(t, "TestEqual")
assert.Equal(true, Equal(1, 1))
assert.Equal(true, Equal(int64(1), int64(1)))
assert.Equal(true, Equal("a", "a"))
assert.Equal(true, Equal(true, true))
assert.Equal(true, Equal([]int{1, 2, 3}, []int{1, 2, 3}))
assert.Equal(true, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}))
assert.Equal(false, Equal(1, 2))
assert.Equal(false, Equal(1, int64(1)))
assert.Equal(false, Equal("a", "b"))
assert.Equal(false, Equal(true, false))
assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3}))
assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}))
time1 := time.Now()
time2 := time1.Add(time.Second)
time3 := time1.Add(time.Second)
assert.Equal(false, Equal(time1, time2))
assert.Equal(true, Equal(time2, time3))
st1 := struct {
A string
B string
}{
A: "a",
B: "b",
}
st2 := struct {
A string
B string
}{
A: "a",
B: "b",
}
st3 := struct {
A string
B string
}{
A: "a1",
B: "b",
}
assert.Equal(true, Equal(st1, st2))
assert.Equal(false, Equal(st1, st3))
}
func TestEqualValue(t *testing.T) {
assert := internal.NewAssert(t, "TestEqualValue")
assert.Equal(true, EqualValue(1, 1))
assert.Equal(true, EqualValue(int(1), int64(1)))
assert.Equal(true, EqualValue(1, "1"))
assert.Equal(false, EqualValue(1, "2"))
}
func TestLessThan(t *testing.T) {
assert := internal.NewAssert(t, "TestLessThan")
assert.Equal(true, LessThan(1, 2))
assert.Equal(true, LessThan(1.1, 2.2))
assert.Equal(true, LessThan("a", "b"))
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, LessThan(time1, time2))
assert.Equal(false, LessThan(1, 1))
assert.Equal(false, LessThan(1, int64(1)))
}
func TestGreaterThan(t *testing.T) {
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterThan(2, 1))
assert.Equal(true, GreaterThan(2.2, 1.1))
assert.Equal(true, GreaterThan("b", "a"))
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, GreaterThan(time2, time1))
assert.Equal(false, GreaterThan(1, 2))
assert.Equal(false, GreaterThan(int64(2), 1))
assert.Equal(false, GreaterThan("b", "c"))
}
func TestLessOrEqual(t *testing.T) {
assert := internal.NewAssert(t, "TestLessOrEqual")
assert.Equal(true, LessOrEqual(1, 2))
assert.Equal(true, LessOrEqual(1, 1))
assert.Equal(true, LessOrEqual(1.1, 2.2))
assert.Equal(true, LessOrEqual("a", "b"))
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, LessOrEqual(time1, time2))
assert.Equal(false, LessOrEqual(2, 1))
assert.Equal(false, LessOrEqual(1, int64(2)))
}
func TestGreaterOrEqual(t *testing.T) {
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterOrEqual(2, 1))
assert.Equal(true, GreaterOrEqual(1, 1))
assert.Equal(true, GreaterOrEqual(2.2, 1.1))
assert.Equal(true, GreaterOrEqual("b", "b"))
time1 := time.Now()
time2 := time1.Add(time.Second)
assert.Equal(true, GreaterOrEqual(time2, time1))
assert.Equal(false, GreaterOrEqual(1, 2))
assert.Equal(false, GreaterOrEqual(int64(2), 1))
assert.Equal(false, GreaterOrEqual("b", "c"))
}

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 concurrency contain some functions to support concurrent programming. eg, goroutine, channel, async. // Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel.
package concurrency package concurrency
import ( import (

View File

@@ -181,7 +181,6 @@ func TestBridge(t *testing.T) {
index := 0 index := 0
for val := range c.Bridge(ctx, genVals()) { for val := range c.Bridge(ctx, genVals()) {
// t.Logf("%v ", val) //0 1 2 3 4 5 6 7 8 9
assert.Equal(index, val) assert.Equal(index, val)
index++ index++
} }

View File

@@ -9,12 +9,17 @@ import (
"encoding/binary" "encoding/binary"
"encoding/gob" "encoding/gob"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io"
"math" "math"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
"github.com/duke-git/lancet/v2/structs"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
) )
// ToBool convert string to boolean. // ToBool convert string to boolean.
@@ -234,31 +239,7 @@ func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K
// map key is specified same as struct field tag `json` value. // map key is specified same as struct field tag `json` value.
// Play: https://go.dev/play/p/KYGYJqNUBOI // Play: https://go.dev/play/p/KYGYJqNUBOI
func StructToMap(value any) (map[string]any, error) { func StructToMap(value any) (map[string]any, error) {
v := reflect.ValueOf(value) return structs.ToMap(value)
t := reflect.TypeOf(value)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", value)
}
result := make(map[string]any)
fieldNum := t.NumField()
pattern := `^[A-Z]`
regex := regexp.MustCompile(pattern)
for i := 0; i < fieldNum; i++ {
name := t.Field(i).Name
tag := t.Field(i).Tag.Get("json")
if regex.MatchString(name) && tag != "" {
//result[name] = v.Field(i).Interface()
result[tag] = v.Field(i).Interface()
}
}
return result, nil
} }
// MapToSlice convert map to slice based on iteratee function. // MapToSlice convert map to slice based on iteratee function.
@@ -324,3 +305,92 @@ func DecodeByte(data []byte, target any) error {
decoder := gob.NewDecoder(buffer) decoder := gob.NewDecoder(buffer)
return decoder.Decode(target) return decoder.Decode(target)
} }
// DeepClone creates a deep copy of passed item.
// can't clone unexported field of struct
// Play: https://go.dev/play/p/j4DP5dquxnk
func DeepClone[T any](src T) T {
c := cloner{
ptrs: map[reflect.Type]map[uintptr]reflect.Value{},
}
result := c.clone(reflect.ValueOf(src))
if result.Kind() == reflect.Invalid {
var zeroValue T
return zeroValue
}
return result.Interface().(T)
}
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
// use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.
// Play: https://go.dev/play/p/oZujoB5Sgg5
func CopyProperties[T, U any](dst T, src U) error {
dstType, srcType := reflect.TypeOf(dst), reflect.TypeOf(src)
if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
return errors.New("CopyProperties: parameter dst should be struct pointer")
}
if srcType.Kind() == reflect.Ptr {
srcType = srcType.Elem()
}
if srcType.Kind() != reflect.Struct {
return errors.New("CopyProperties: parameter src should be a struct or struct pointer")
}
bytes, err := json.Marshal(src)
if err != nil {
return fmt.Errorf("CopyProperties: unable to marshal src: %s", err)
}
err = json.Unmarshal(bytes, dst)
if err != nil {
return fmt.Errorf("CopyProperties: unable to unmarshal into dst: %s", err)
}
return nil
}
// ToInterface converts reflect value to its interface type.
// Play: https://go.dev/play/p/syqw0-WG7Xd
func ToInterface(v reflect.Value) (value interface{}, ok bool) {
if v.IsValid() && v.CanInterface() {
return v.Interface(), true
}
switch v.Kind() {
case reflect.Bool:
return v.Bool(), true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int(), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint(), true
case reflect.Float32, reflect.Float64:
return v.Float(), true
case reflect.Complex64, reflect.Complex128:
return v.Complex(), true
case reflect.String:
return v.String(), true
case reflect.Ptr:
return ToInterface(v.Elem())
case reflect.Interface:
return ToInterface(v.Elem())
default:
return nil, false
}
}
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
// Play: todo
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: todo
func GbkToUtf8(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
b, err := io.ReadAll(r)
return b, err
}

View File

@@ -2,7 +2,11 @@ package convertor
import ( import (
"fmt" "fmt"
"reflect"
"strconv" "strconv"
"unicode/utf8"
"github.com/duke-git/lancet/v2/validator"
) )
func ExampleToBool() { func ExampleToBool() {
@@ -252,3 +256,138 @@ func ExampleDecodeByte() {
// Output: // Output:
// abc // abc
} }
func ExampleDeepClone() {
type Struct struct {
Str string
Int int
Float float64
Bool bool
Nil interface{}
// unexported string
}
cases := []interface{}{
true,
1,
0.1,
map[string]int{
"a": 1,
"b": 2,
},
&Struct{
Str: "test",
Int: 1,
Float: 0.1,
Bool: true,
Nil: nil,
// unexported: "can't be cloned",
},
}
for _, item := range cases {
cloned := DeepClone(item)
isPointerEqual := &cloned == &item
fmt.Println(cloned, isPointerEqual)
}
// Output:
// true false
// 1 false
// 0.1 false
// map[a:1 b:2] false
// &{test 1 0.1 true <nil>} false
}
func ExampleCopyProperties() {
type Disk struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type DiskVO struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type Indicator struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int `json:"cpu"`
Disk []Disk `json:"disk"`
Stop chan bool `json:"-"`
}
type IndicatorVO struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int64 `json:"cpu"`
Disk []DiskVO `json:"disk"`
}
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
}}
indicatorVO := IndicatorVO{}
CopyProperties(&indicatorVO, indicator)
fmt.Println(indicatorVO.Id)
fmt.Println(indicatorVO.Ip)
fmt.Println(len(indicatorVO.Disk))
// Output:
// 001
// 127.0.0.1
// 3
}
func ExampleToInterface() {
val := reflect.ValueOf("abc")
iVal, ok := ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}
func ExampleUtf8ToGbk() {
utf8Data := []byte("hello")
gbkData, _ := Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
func ExampleGbkToUtf8() {
gbkData, _ := Utf8ToGbk([]byte("hello"))
utf8Data, _ := GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}

View File

@@ -0,0 +1,216 @@
// Copyright 2023 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package convertor implements some functions to convert data.
package convertor
import "reflect"
type cloner struct {
ptrs map[reflect.Type]map[uintptr]reflect.Value
}
// clone return a duplicate of passed item.
func (c *cloner) clone(v reflect.Value) reflect.Value {
switch v.Kind() {
case reflect.Invalid:
return reflect.ValueOf(nil)
// bool
case reflect.Bool:
return reflect.ValueOf(v.Bool())
//int
case reflect.Int:
return reflect.ValueOf(int(v.Int()))
case reflect.Int8:
return reflect.ValueOf(int8(v.Int()))
case reflect.Int16:
return reflect.ValueOf(int16(v.Int()))
case reflect.Int32:
return reflect.ValueOf(int32(v.Int()))
case reflect.Int64:
return reflect.ValueOf(v.Int())
// uint
case reflect.Uint:
return reflect.ValueOf(uint(v.Uint()))
case reflect.Uint8:
return reflect.ValueOf(uint8(v.Uint()))
case reflect.Uint16:
return reflect.ValueOf(uint16(v.Uint()))
case reflect.Uint32:
return reflect.ValueOf(uint32(v.Uint()))
case reflect.Uint64:
return reflect.ValueOf(v.Uint())
// float
case reflect.Float32:
return reflect.ValueOf(float32(v.Float()))
case reflect.Float64:
return reflect.ValueOf(v.Float())
// complex
case reflect.Complex64:
return reflect.ValueOf(complex64(v.Complex()))
case reflect.Complex128:
return reflect.ValueOf(v.Complex())
// string
case reflect.String:
return reflect.ValueOf(v.String())
// array
case reflect.Array, reflect.Slice:
return c.cloneArray(v)
// map
case reflect.Map:
return c.cloneMap(v)
// Ptr
case reflect.Ptr:
return c.clonePtr(v)
// struct
case reflect.Struct:
return c.cloneStruct(v)
// func
case reflect.Func:
return v
// interface
case reflect.Interface:
return c.clone(v.Elem())
}
return reflect.Zero(v.Type())
}
func (c *cloner) cloneArray(v reflect.Value) reflect.Value {
if v.IsNil() {
return reflect.Zero(v.Type())
}
arr := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
for i := 0; i < v.Len(); i++ {
val := c.clone(v.Index(i))
if val.IsValid() {
continue
}
item := arr.Index(i)
if !item.CanSet() {
continue
}
item.Set(val.Convert(item.Type()))
}
return arr
}
func (c *cloner) cloneMap(v reflect.Value) reflect.Value {
if v.IsNil() {
return reflect.Zero(v.Type())
}
clonedMap := reflect.MakeMap(v.Type())
for _, key := range v.MapKeys() {
value := v.MapIndex(key)
clonedKey := c.clone(key)
clonedValue := c.clone(value)
if !isNillable(clonedKey) || !clonedKey.IsNil() {
clonedKey = clonedKey.Convert(key.Type())
}
if (!isNillable(clonedValue) || !clonedValue.IsNil()) && clonedValue.IsValid() {
clonedValue = clonedValue.Convert(value.Type())
}
if !clonedValue.IsValid() {
clonedValue = reflect.Zero(clonedMap.Type().Elem())
}
clonedMap.SetMapIndex(clonedKey, clonedValue)
}
return clonedMap
}
func isNillable(v reflect.Value) bool {
switch v.Kind() {
case reflect.Chan, reflect.Interface, reflect.Ptr, reflect.Func:
return true
}
return false
}
func (c *cloner) clonePtr(v reflect.Value) reflect.Value {
if v.IsNil() {
return reflect.Zero(v.Type())
}
var newVal reflect.Value
if v.Elem().CanAddr() {
ptrs, exists := c.ptrs[v.Type()]
if exists {
if newVal, exists := ptrs[v.Elem().UnsafeAddr()]; exists {
return newVal
}
}
}
newVal = c.clone(v.Elem())
if v.Elem().CanAddr() {
ptrs, exists := c.ptrs[v.Type()]
if exists {
if newVal, exists := ptrs[v.Elem().UnsafeAddr()]; exists {
return newVal
}
}
}
clonedPtr := reflect.New(newVal.Type())
clonedPtr.Elem().Set(newVal)
return clonedPtr
}
func (c *cloner) cloneStruct(v reflect.Value) reflect.Value {
clonedStructPtr := reflect.New(v.Type())
clonedStruct := clonedStructPtr.Elem()
if v.CanAddr() {
ptrs := c.ptrs[clonedStructPtr.Type()]
if ptrs == nil {
ptrs = make(map[uintptr]reflect.Value)
c.ptrs[clonedStructPtr.Type()] = ptrs
}
ptrs[v.UnsafeAddr()] = clonedStructPtr
}
for i := 0; i < v.NumField(); i++ {
newStructValue := clonedStruct.Field(i)
if !newStructValue.CanSet() {
continue
}
clonedVal := c.clone(v.Field(i))
if !clonedVal.IsValid() {
continue
}
newStructValue.Set(clonedVal.Convert(newStructValue.Type()))
}
return clonedStruct
}

View File

@@ -2,11 +2,14 @@ package convertor
import ( import (
"fmt" "fmt"
"reflect"
"strconv" "strconv"
"testing" "testing"
"unicode/utf8"
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
"github.com/duke-git/lancet/v2/slice" "github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/validator"
) )
func TestToChar(t *testing.T) { func TestToChar(t *testing.T) {
@@ -179,6 +182,7 @@ func TestToMap(t *testing.T) {
func TestStructToMap(t *testing.T) { func TestStructToMap(t *testing.T) {
assert := internal.NewAssert(t, "TestStructToMap") assert := internal.NewAssert(t, "TestStructToMap")
t.Run("StructToMap", func(_ *testing.T) {
type People struct { type People struct {
Name string `json:"name"` Name string `json:"name"`
age int age int
@@ -188,9 +192,26 @@ func TestStructToMap(t *testing.T) {
100, 100,
} }
pm, _ := StructToMap(p) pm, _ := StructToMap(p)
var expected = map[string]any{"name": "test"}
expected := map[string]any{"name": "test"}
assert.Equal(expected, pm) assert.Equal(expected, pm)
})
t.Run("StructToMapWithJsonAttr", func(_ *testing.T) {
type People struct {
Name string `json:"name,omitempty"` // json tag with attribute
Phone string `json:"phone"` // json tag without attribute
Sex string `json:"-"` // ignore
age int // no tag
}
p := People{
Phone: "1111",
Sex: "male",
age: 100,
}
pm, _ := StructToMap(p)
var expected = map[string]any{"phone": "1111"}
assert.Equal(expected, pm)
})
} }
func TestMapToSlice(t *testing.T) { func TestMapToSlice(t *testing.T) {
@@ -253,3 +274,149 @@ func TestDecodeByte(t *testing.T) {
assert.IsNil(err) assert.IsNil(err)
assert.Equal("abc", obj) assert.Equal("abc", obj)
} }
func TestDeepClone(t *testing.T) {
// assert := internal.NewAssert(t, "TestDeepClone")
type Struct struct {
Str string
Int int
Float float64
Bool bool
Nil interface{}
// unexported string
}
cases := []interface{}{
true,
1,
0.1,
map[string]int{
"a": 1,
"b": 2,
},
&Struct{
Str: "test",
Int: 1,
Float: 0.1,
Bool: true,
Nil: nil,
// unexported: "can't be cloned",
},
}
for i, item := range cases {
cloned := DeepClone(item)
if &cloned == &item {
t.Fatalf("[TestDeepClone case #%d failed]: equal pointer", i)
}
if !reflect.DeepEqual(item, cloned) {
t.Fatalf("[TestDeepClone case #%d failed] unequal objects", i)
}
}
}
func TestCopyProperties(t *testing.T) {
assert := internal.NewAssert(t, "TestCopyProperties")
type Disk struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type DiskVO struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type Indicator struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int `json:"cpu"`
Disk []Disk `json:"disk"`
Stop chan bool `json:"-"`
}
type IndicatorVO struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int64 `json:"cpu"`
Disk []DiskVO `json:"disk"`
}
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
}}
indicatorVO := IndicatorVO{}
err := CopyProperties(&indicatorVO, indicator)
assert.IsNil(err)
assert.Equal("001", indicatorVO.Id)
assert.Equal("127.0.0.1", indicatorVO.Ip)
assert.Equal(3, len(indicatorVO.Disk))
}
func TestToInterface(t *testing.T) {
assert := internal.NewAssert(t, "TestToInterface")
cases := []reflect.Value{
reflect.ValueOf("abc"),
reflect.ValueOf(int(0)), reflect.ValueOf(int8(1)), reflect.ValueOf(int16(-1)), reflect.ValueOf(int32(123)), reflect.ValueOf(int64(123)),
reflect.ValueOf(uint(123)), reflect.ValueOf(uint8(123)), reflect.ValueOf(uint16(123)), reflect.ValueOf(uint32(123)), reflect.ValueOf(uint64(123)),
reflect.ValueOf(float64(12.3)), reflect.ValueOf(float32(12.3)),
reflect.ValueOf(true), reflect.ValueOf(false),
}
expected := []interface{}{
"abc",
0, int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float64(12.3), float32(12.3),
true, false,
}
for i := 0; i < len(cases); i++ {
actual, _ := ToInterface(cases[i])
assert.Equal(expected[i], actual)
}
nilVal, ok := ToInterface(reflect.ValueOf(nil))
assert.EqualValues(nil, nilVal)
assert.Equal(false, ok)
}
func TestUtf8ToGbk(t *testing.T) {
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) {
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))
}

View File

@@ -2,11 +2,11 @@ package cryptor
import "bytes" import "bytes"
func generateAesKey(key []byte) []byte { func generateAesKey(key []byte, size int) []byte {
genKey := make([]byte, 16) genKey := make([]byte, size)
copy(genKey, key) copy(genKey, key)
for i := 16; i < len(key); { for i := size; i < len(key); {
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { for j := 0; j < size && i < len(key); j, i = j+1, i+1 {
genKey[j] ^= key[i] genKey[j] ^= key[i]
} }
} }

View File

@@ -23,6 +23,11 @@ import (
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j // Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbEncrypt(data, key []byte) []byte { func AesEcbEncrypt(data, key []byte) []byte {
size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
length := (len(data) + aes.BlockSize) / aes.BlockSize length := (len(data) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize) plain := make([]byte, length*aes.BlockSize)
@@ -34,7 +39,7 @@ func AesEcbEncrypt(data, key []byte) []byte {
} }
encrypted := make([]byte, len(plain)) encrypted := make([]byte, len(plain))
cipher, _ := aes.NewCipher(generateAesKey(key)) cipher, _ := aes.NewCipher(generateAesKey(key, size))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be]) cipher.Encrypt(encrypted[bs:be], plain[bs:be])
@@ -47,7 +52,11 @@ func AesEcbEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j // Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbDecrypt(encrypted, key []byte) []byte { func AesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := aes.NewCipher(generateAesKey(key)) size := len(key)
if size != 16 && size != 24 && size != 32 {
panic("key length shoud be 16 or 24 or 32")
}
cipher, _ := aes.NewCipher(generateAesKey(key, size))
decrypted := make([]byte, len(encrypted)) decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {

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. hashmap structure.
package datastructure package datastructure
import ( import (

View File

@@ -64,7 +64,6 @@ func TestHashMap_KeysValues(t *testing.T) {
keys := hm.Keys() keys := hm.Keys()
values := hm.Values() values := hm.Values()
t.Log(keys, values)
assert.Equal(3, len(values)) assert.Equal(3, len(values))
assert.Equal(3, len(keys)) assert.Equal(3, len(keys))

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. MaxHeap is a binary max heap.
package datastructure package datastructure
import ( import (

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

@@ -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

@@ -1,11 +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 contains some data structure. list is a linear table, implemented with slice.
package datastructure package datastructure
import ( import (
"reflect" "reflect"
"github.com/duke-git/lancet/v2/iterator"
) )
// List is a linear table, implemented with slice. // List is a linear table, implemented with slice.
@@ -316,6 +318,43 @@ func (l *List[T]) Intersection(other *List[T]) *List[T] {
return result return result
} }
// Difference returns the difference between two collections.
// return a list whose element in the original list, not in the given list.
func (l *List[T]) Difference(other *List[T]) *List[T] {
result := NewList(make([]T, 0))
intersectList := l.Intersection(other)
for _, v := range l.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
return result
}
// SymmetricDifference oppoiste operation of intersection function.
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T] {
result := NewList(make([]T, 0))
intersectList := l.Intersection(other)
for _, v := range l.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
for _, v := range other.data {
if !intersectList.Contain(v) {
result.data = append(result.data, v)
}
}
return result
}
// SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive. // SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] { func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
data := l.data[fromIndex:toIndex] data := l.data[fromIndex:toIndex]
@@ -323,3 +362,57 @@ func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] {
copy(subList, data) copy(subList, data)
return NewList(subList) return NewList(subList)
} }
// ForEach performs the given action for each element of the list.
func (l *List[T]) ForEach(consumer func(T)) {
for _, it := range l.data {
consumer(it)
}
}
// RetainAll retains only the elements in this list that are contained in the given list.
func (l *List[T]) RetainAll(list *List[T]) bool {
return l.batchRemove(list, true)
}
// DeleteAll removes from this list all of its elements that are contained in the given list.
func (l *List[T]) DeleteAll(list *List[T]) bool {
return l.batchRemove(list, false)
}
func (l *List[T]) batchRemove(list *List[T], complement bool) bool {
var (
w = 0
data = l.data
size = len(data)
)
for i := 0; i < size; i++ {
if list.Contain(data[i]) == complement {
data[w] = data[i]
w++
}
}
if w != size {
l.data = data[:w]
return true
}
return false
}
// Iterator returns an iterator over the elements in this list in proper sequence.
func (l *List[T]) Iterator() iterator.Iterator[T] {
return iterator.FromSlice(l.data)
}
// ListToMap convert a list to a map based on iteratee function.
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V {
result := make(map[K]V, list.Size())
for _, item := range list.data {
k, v := iteratee(item)
result[k] = v
}
return result
}

View File

@@ -328,6 +328,28 @@ func TestIntersection(t *testing.T) {
assert.Equal(true, expected.Equal(list3)) assert.Equal(true, expected.Equal(list3))
} }
func TestDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestDifference")
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
expected := NewList([]int{3})
list3 := list1.Difference(list2)
assert.Equal(true, expected.Equal(list3))
}
func TestSymmetricDifference(t *testing.T) {
assert := internal.NewAssert(t, "TestSymmetricDifference")
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
expected := NewList([]int{3, 4})
list3 := list1.SymmetricDifference(list2)
assert.Equal(true, expected.Equal(list3))
}
func TestSubSlice(t *testing.T) { func TestSubSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestSubSlice") assert := internal.NewAssert(t, "TestSubSlice")
@@ -357,3 +379,84 @@ func TestDeleteIf(t *testing.T) {
assert.Equal([]int{2, 3, 4}, list.Data()) assert.Equal([]int{2, 3, 4}, list.Data())
assert.Equal(0, count) assert.Equal(0, count)
} }
func TestForEach(t *testing.T) {
assert := internal.NewAssert(t, "TestForEach")
list := NewList([]int{1, 2, 3, 4})
rs := make([]int, 0)
list.ForEach(func(i int) {
rs = append(rs, i)
})
assert.Equal([]int{1, 2, 3, 4}, rs)
}
func TestRetainAll(t *testing.T) {
assert := internal.NewAssert(t, "TestRetainAll")
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
assert.Equal([]int{1, 2}, list.Data())
assert.Equal([]int{2, 3}, list1.Data())
assert.Equal([]int{1, 2}, list2.Data())
}
func TestDeleteAll(t *testing.T) {
assert := internal.NewAssert(t, "TestDeleteAll")
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
assert.Equal([]int{2, 3, 4}, list.Data())
assert.Equal([]int{1, 4}, list1.Data())
assert.Equal([]int{3, 4}, list2.Data())
}
func TestIterator(t *testing.T) {
assert := internal.NewAssert(t, "TestIterator")
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
rs := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
rs = append(rs, item)
}
assert.Equal([]int{1, 2, 3, 4}, rs)
}
func TestListToMap(t *testing.T) {
assert := internal.NewAssert(t, "ListToMap")
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -1,6 +1,10 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
package datastructure package datastructure
// Set is a data container, like slice, but element of set is not duplicate // Set is a data container, like slice, but element of set is not duplicate.
type Set[T comparable] map[T]struct{} type Set[T comparable] map[T]struct{}
// NewSet return a instance of set // NewSet return a instance of set
@@ -171,3 +175,25 @@ func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
return set return set
} }
// EachWithBreak iterates over elements of a set and invokes function for each element,
// when iteratee return false, will break the for each loop.
func (s Set[T]) EachWithBreak(iteratee func(item T) bool) {
for _, v := range s.Values() {
if !iteratee(v) {
break
}
}
}
// Pop delete the top element of set then return it, if set is empty, return nil-value of T and false.
func (s Set[T]) Pop() (v T, ok bool) {
if len(s) > 0 {
items := s.Values()
item := items[len(s)-1]
delete(s, item)
return item, true
}
return v, false
}

View File

@@ -192,3 +192,40 @@ func TestSet_Minus(t *testing.T) {
assert.Equal(NewSet(1), set1.Minus(set2)) assert.Equal(NewSet(1), set1.Minus(set2))
assert.Equal(NewSet(4, 5), set2.Minus(set3)) assert.Equal(NewSet(4, 5), set2.Minus(set3))
} }
func TestEachWithBreak(t *testing.T) {
// s := NewSet(1, 2, 3, 4, 5)
// var sum int
// s.EachWithBreak(func(n int) bool {
// if n > 3 {
// return false
// }
// sum += n
// return true
// })
// assert := internal.NewAssert(t, "TestEachWithBreak")
// assert.Equal(6, sum)
}
// func TestPop(t *testing.T) {
// assert := internal.NewAssert(t, "TestPop")
// s := NewSet[int]()
// val, ok := s.Pop()
// assert.Equal(0, val)
// assert.Equal(false, ok)
// s.Add(1)
// s.Add(2)
// s.Add(3)
// // s = NewSet(1, 2, 3, 4, 5)
// val, ok = s.Pop()
// assert.Equal(3, val)
// assert.Equal(true, ok)
// }

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

@@ -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

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

View File

@@ -40,7 +40,6 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
bstree.Insert(4) bstree.Insert(4)
acturl := bstree.PreOrderTraverse() acturl := bstree.PreOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 2, 4, 7}, acturl) assert.Equal([]int{6, 5, 2, 4, 7}, acturl)
} }
@@ -55,7 +54,6 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
bstree.Insert(4) bstree.Insert(4)
acturl := bstree.PostOrderTraverse() acturl := bstree.PostOrderTraverse()
t.Log(acturl)
assert.Equal([]int{5, 2, 4, 7, 6}, acturl) assert.Equal([]int{5, 2, 4, 7, 6}, acturl)
} }
@@ -70,7 +68,6 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
bstree.Insert(4) bstree.Insert(4)
acturl := bstree.InOrderTraverse() acturl := bstree.InOrderTraverse()
t.Log(acturl)
assert.Equal([]int{2, 4, 5, 6, 7}, acturl) assert.Equal([]int{2, 4, 5, 6, 7}, acturl)
} }
@@ -85,7 +82,6 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
bstree.Insert(4) bstree.Insert(4)
acturl := bstree.LevelOrderTraverse() acturl := bstree.LevelOrderTraverse()
t.Log(acturl)
assert.Equal([]int{6, 5, 7, 2, 4}, acturl) assert.Equal([]int{6, 5, 7, 2, 4}, acturl)
} }
@@ -102,14 +98,12 @@ func TestBSTree_Delete(t *testing.T) {
bstree.Delete(4) bstree.Delete(4)
acturl1 := bstree.InOrderTraverse() acturl1 := bstree.InOrderTraverse()
t.Log(acturl1)
assert.Equal([]int{2, 5, 6, 7}, acturl1) assert.Equal([]int{2, 5, 6, 7}, acturl1)
//todo //todo
// bstree.DeletetNode(6, comparator) // bstree.DeletetNode(6, comparator)
// bstree.Print() // bstree.Print()
// acturl2 := bstree.InOrderTraverse() // acturl2 := bstree.InOrderTraverse()
// t.Log(acturl2)
// assert.Equal([]int{2, 5, 7}, acturl2) // assert.Equal([]int{2, 5, 7}, acturl2)
} }

View File

@@ -20,9 +20,8 @@ func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat") assert := internal.NewAssert(t, "TestToFormat")
tm, err := NewFormat("2022-03-18 17:04:05") tm, err := NewFormat("2022-03-18 17:04:05")
t.Log("TestToFormat", tm.ToFormat())
assert.IsNil(err) assert.IsNil(err)
t.Log("ToFormat -> ", tm.ToFormat())
} }
func TestToFormatForTpl(t *testing.T) { func TestToFormatForTpl(t *testing.T) {
@@ -32,9 +31,9 @@ func TestToFormatForTpl(t *testing.T) {
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"))
assert.IsNil(err) assert.IsNil(err)
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
} }
func TestToIso8601(t *testing.T) { func TestToIso8601(t *testing.T) {
@@ -44,7 +43,7 @@ func TestToIso8601(t *testing.T) {
assert.IsNotNil(err) assert.IsNotNil(err)
tm, err := NewISO8601("2006-01-02T15:04:05.999Z") tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
t.Log("TestToIso8601", tm.ToIso8601())
// assert.Equal("2006-01-02T23:04:05+08:00", tm.ToIso8601())
assert.IsNil(err) assert.IsNil(err)
t.Log("ToIso8601 -> ", tm.ToIso8601())
} }

View File

@@ -35,7 +35,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",
@@ -72,6 +72,12 @@ func AddDay(t time.Time, day int64) time.Time {
return t.Add(24 * time.Hour * time.Duration(day)) return t.Add(24 * time.Hour * time.Duration(day))
} }
// AddYear add or sub year to the time.
// Play: https://go.dev/play/p/MqW2ujnBx10
func AddYear(t time.Time, year int64) time.Time {
return t.Add(365 * 24 * time.Hour * time.Duration(year))
}
// GetNowDate return format yyyy-mm-dd of current date. // GetNowDate return format yyyy-mm-dd of current date.
// Play: https://go.dev/play/p/PvfkPpcpBBf // Play: https://go.dev/play/p/PvfkPpcpBBf
func GetNowDate() string { func GetNowDate() string {
@@ -218,3 +224,32 @@ func BeginOfYear(t time.Time) time.Time {
func EndOfYear(t time.Time) time.Time { func EndOfYear(t time.Time) time.Time {
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond) return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
} }
// IsLeapYear check if param year is leap year or not.
// Play: https://go.dev/play/p/xS1eS2ejGew
func IsLeapYear(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
// BetweenSeconds returns the number of seconds between two times.
// Play: https://go.dev/play/p/n3YDRyfyXJu
func BetweenSeconds(t1 time.Time, t2 time.Time) int64 {
index := t2.Unix() - t1.Unix()
return index
}
// DayOfYear returns which day of the year the parameter date `t` is.
// Play: https://go.dev/play/p/0hjqhTwFNlH
func DayOfYear(t time.Time) int {
y, m, d := t.Date()
firstDay := time.Date(y, 1, 1, 0, 0, 0, 0, t.Location())
nowDate := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
return int(nowDate.Sub(firstDay).Hours() / 24)
}
// IsWeekend checks if passed time is weekend or not.
// Play: https://go.dev/play/p/cupRM5aZOIY
func IsWeekend(t time.Time) bool {
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
}

View File

@@ -57,6 +57,23 @@ func ExampleAddMinute() {
// -2m0s // -2m0s
} }
func ExampleAddYear() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
}
func ExampleGetNowDate() { func ExampleGetNowDate() {
result := GetNowDate() result := GetNowDate()
@@ -114,15 +131,18 @@ func ExampleFormatTimeToStr() {
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss") result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd") result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss") result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4)
// Output: // Output:
// 2021-01-02 16:04:08 // 2021-01-02 16:04:08
// 2021-01-02 // 2021-01-02
// 02-01-21 16:04:08 // 02-01-21 16:04:08
// 2021-01-02 16
} }
func ExampleFormatStrToTime() { func ExampleFormatStrToTime() {
@@ -321,3 +341,70 @@ func ExampleNewUnixNow() {
// // Output: // // Output:
// // 2006-01-02T23:04:05+08:00 // // 2006-01-02T23:04:05+08:00
// } // }
func ExampleIsLeapYear() {
result1 := IsLeapYear(2000)
result2 := IsLeapYear(2001)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
func ExampleBetweenSeconds() {
today := time.Now()
tomorrow := AddDay(today, 1)
yesterday := AddDay(today, -1)
result1 := BetweenSeconds(today, tomorrow)
result2 := BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
func ExampleDayOfYear() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
func ExampleIsWeekend() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := IsWeekend(date1)
result2 := IsWeekend(date2)
result3 := IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}

View File

@@ -7,6 +7,33 @@ import (
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAddYear(t *testing.T) {
assert := internal.NewAssert(t, "TestAddDay")
now := time.Now()
after2Years := AddYear(now, 1)
diff1 := after2Years.Sub(now)
assert.Equal(float64(8760), diff1.Hours())
before2Years := AddYear(now, -1)
diff2 := before2Years.Sub(now)
assert.Equal(float64(-8760), diff2.Hours())
}
func TestBetweenSeconds(t *testing.T) {
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) {
assert := internal.NewAssert(t, "TestAddDay") assert := internal.NewAssert(t, "TestAddDay")
@@ -71,12 +98,16 @@ func TestFormatTimeToStr(t *testing.T) {
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])
@@ -230,3 +261,44 @@ func TestEndOfYear(t *testing.T) {
assert.Equal(expected, actual) assert.Equal(expected, actual)
} }
func TestIsLeapYear(t *testing.T) {
assert := internal.NewAssert(t, "TestEndOfYear")
result1 := IsLeapYear(2000)
result2 := IsLeapYear(2001)
assert.Equal(true, result1)
assert.Equal(false, result2)
}
func TestDayOfYear(t *testing.T) {
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) {
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)
}

View File

@@ -1,4 +1,5 @@
# Algorithm # Algorithm
Package algorithm implements some basic algorithm. eg. sort, search. Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -12,6 +13,7 @@ Package algorithm implements some basic algorithm. eg. sort, search.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage ## Usage
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/algorithm" "github.com/duke-git/lancet/v2/algorithm"
@@ -35,14 +37,12 @@ import (
- [LinearSearch](#LinearSearch) - [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache) - [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="BubbleSort">BubbleSort</span> ### <span id="BubbleSort">BubbleSort</span>
<p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with bubble sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -50,6 +50,7 @@ import (
```go ```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -76,16 +77,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.BubbleSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="InsertionSort">InsertionSort</span> ### <span id="InsertionSort">InsertionSort</span>
<p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with insertion sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,6 +98,7 @@ func main() {
```go ```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -122,34 +128,32 @@ func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
} else if p1.Age > p2.Age { } else if p1.Age > p2.Age {
return 1 return 1
} }
return 0
//decending order return 0
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
} }
func main() { func main() {
var peoples = []people{ peoples := []people{
{Name: "a", Age: 20}, {Name: "a", Age: 20},
{Name: "b", Age: 10}, {Name: "b", Age: 10},
{Name: "c", Age: 17}, {Name: "c", Age: 17},
{Name: "d", Age: 8}, {Name: "d", Age: 8},
{Name: "e", Age: 28}, {Name: "e", Age: 28},
} }
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator) algorithm.InsertionSort(peoples, comparator)
fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}] fmt.Println(peoples)
// Output:
// [{d 8} {b 10} {c 17} {a 20} {e 28}]
} }
``` ```
### <span id="SelectionSort">SelectionSort</span> ### <span id="SelectionSort">SelectionSort</span>
<p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with selection sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -157,6 +161,7 @@ func main() {
```go ```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -183,16 +188,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.SelectionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="ShellSort">ShellSort</span> ### <span id="ShellSort">ShellSort</span>
<p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with shell sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -200,6 +209,7 @@ func main() {
```go ```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -226,16 +236,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.ShellSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="QuickSort">QuickSort</span> ### <span id="QuickSort">QuickSort</span>
<p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with quick sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -243,6 +257,7 @@ func main() {
```go ```go
func QuickSort[T any](slice []T comparator lancetconstraints.Comparator) func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -269,16 +284,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.QuickSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.QuickSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="HeapSort">HeapSort</span> ### <span id="HeapSort">HeapSort</span>
<p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with heap sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -286,6 +305,7 @@ func main() {
```go ```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -312,16 +332,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.HeapSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="MergeSort">MergeSort</span> ### <span id="MergeSort">MergeSort</span>
<p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with merge sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -329,6 +353,7 @@ func main() {
```go ```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -355,16 +380,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.MergeSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="CountSort">CountSort</span> ### <span id="CountSort">CountSort</span>
<p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p> <p>Sort slice with count sort algorithm. Param comparator should implements lancetconstraints.Comparator.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -372,6 +401,7 @@ func main() {
```go ```go
func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func CountSort[T any](slice []T, comparator lancetconstraints.Comparator) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -399,16 +429,20 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} sortedNums := algorithm.CountSort(numbers, comparator)
fmt.Println(sortedNums)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="BinarySearch">BinarySearch</span> ### <span id="BinarySearch">BinarySearch</span>
<p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p> <p>BinarySearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -416,6 +450,7 @@ func main() {
```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 lancetconstraints.Comparator) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -442,17 +477,23 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8} numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{} comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator) result1 := algorithm.BinarySearch(numbers, 5, 0, len(numbers)-1, comparator)
fmt.Println(notFoundIndex) //-1 result2 := algorithm.BinarySearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
} }
``` ```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span> ### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p> <p>BinaryIterativeSearch search for target within a sorted slice, recursive call itself. If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -460,6 +501,7 @@ func main() {
```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 lancetconstraints.Comparator) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -486,18 +528,23 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8} numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{} comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator) result1 := algorithm.BinaryIterativeSearch(numbers, 5, 0, len(numbers)-1, comparator)
fmt.Println(notFoundIndex) //-1 result2 := algorithm.BinaryIterativeSearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
} }
``` ```
### <span id="LinearSearch">LinearSearch</span> ### <span id="LinearSearch">LinearSearch</span>
<p>return the index of target in slice base on equal function.If a target is found, the index of the target is returned. Else the function return -1.</p> <p>return the index of target in slice base on equal function.If a target is found, the index of the target is returned. Else the function return -1.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -505,6 +552,7 @@ func main() {
```go ```go
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -534,8 +582,8 @@ func main() {
} }
``` ```
### <span id="LRUCache">LRUCache</span> ### <span id="LRUCache">LRUCache</span>
<p>LRUCache implements mem cache with lru.</p> <p>LRUCache implements mem cache with lru.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -547,6 +595,7 @@ func (l *LRUCache[K, V]) Put(key K, value V)
func (l *LRUCache[K, V]) Delete(key K) bool func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int func (l *LRUCache[K, V]) Len() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -562,14 +611,26 @@ func main() {
cache.Put(1, 1) cache.Put(1, 1)
cache.Put(2, 2) cache.Put(2, 2)
cache.Put(3, 3)
fmt.Println(cache.Len()) // 3 result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
v, ok := cache.Get(1) fmt.Println(result1, ok1)
fmt.Println(v, ok) // 1 true fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
ok = cache.Delete(1) fmt.Println(cache.Len())
fmt.Println(ok) // true
ok := cache.Delete(2)
fmt.Println(ok)
// Output:
// 1 true
// 2 true
// 0 false
// 2
// true
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Algorithm # Algorithm
algorithm 算法包实现一些基本算法sortsearchlrucache。 algorithm 算法包实现一些基本算法sortsearchlrucache。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -12,6 +13,7 @@ algorithm算法包实现一些基本算法sortsearchlrucache。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法 ## 用法
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/algorithm" "github.com/duke-git/lancet/v2/algorithm"
@@ -35,20 +37,21 @@ import (
- [LinearSearch](#LinearSearch) - [LinearSearch](#LinearSearch)
- [LRUCache](#LRUCache) - [LRUCache](#LRUCache)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="BubbleSort">BubbleSort</span> ### <span id="BubbleSort">BubbleSort</span>
<p>冒泡排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>冒泡排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator) func BubbleSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -74,24 +77,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.BubbleSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.BubbleSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="InsertionSort">InsertionSort</span> ### <span id="InsertionSort">InsertionSort</span>
<p>插入排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>插入排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator) func InsertionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -120,40 +128,41 @@ func (pc *peopleAgeComparator) Compare(v1 any, v2 any) int {
} else if p1.Age > p2.Age { } else if p1.Age > p2.Age {
return 1 return 1
} }
return 0
//decending order return 0
// if p1.Age > p2.Age {
// return -1
// } else if p1.Age < p2.Age {
// return 1
// }
} }
func main() { func main() {
var peoples = []people{ peoples := []people{
{Name: "a", Age: 20}, {Name: "a", Age: 20},
{Name: "b", Age: 10}, {Name: "b", Age: 10},
{Name: "c", Age: 17}, {Name: "c", Age: 17},
{Name: "d", Age: 8}, {Name: "d", Age: 8},
{Name: "e", Age: 28}, {Name: "e", Age: 28},
} }
comparator := &peopleAgeComparator{} comparator := &peopleAgeComparator{}
algorithm.InsertionSort(peoples, comparator) algorithm.InsertionSort(peoples, comparator)
fmt.Println(peoples) //[{d 8} {b 10} {c 17} {a 20} {e 28}] fmt.Println(peoples)
// Output:
// [{d 8} {b 10} {c 17} {a 20} {e 28}]
} }
``` ```
### <span id="SelectionSort">SelectionSort</span> ### <span id="SelectionSort">SelectionSort</span>
<p>选择排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>选择排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator) func SelectionSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -179,23 +188,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.SelectionSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.SelectionSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="ShellSort">ShellSort</span> ### <span id="ShellSort">ShellSort</span>
<p>希尔排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>希尔排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator) func ShellSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -221,24 +236,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.ShellSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.ShellSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="QuickSort">QuickSort</span> ### <span id="QuickSort">QuickSort</span>
<p>快速排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>快速排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func QuickSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func QuickSort[T any](slice []T comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -264,24 +284,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.QuickSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.QuickSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="HeapSort">HeapSort</span> ### <span id="HeapSort">HeapSort</span>
<p>堆排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>堆排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator) []T func HeapSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -307,24 +332,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.HeapSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.HeapSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="MergeSort">MergeSort</span> ### <span id="MergeSort">MergeSort</span>
<p>归并排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>归并排序参数comparator需要实现包lancetconstraints.Comparator。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator) func MergeSort[T any](slice []T, comparator lancetconstraints.Comparator)
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -350,24 +380,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
algorithm.MergeSort(intSlice, comparator)
fmt.Println(intSlice) //[]int{1, 2, 3, 4, 5, 6} algorithm.MergeSort(numbers, comparator)
fmt.Println(numbers)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="CountSort">CountSort</span> ### <span id="CountSort">CountSort</span>
<p>计数排序参数comparator需要实现包lancetconstraints.Comparator</p>
<p>计数排序参数comparator需要实现包lancetconstraints.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 lancetconstraints.Comparator) []T
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -377,6 +412,7 @@ import (
"github.com/duke-git/lancet/v2/algorithm" "github.com/duke-git/lancet/v2/algorithm"
) )
type intComparator struct{} type intComparator struct{}
func (c *intComparator) Compare(v1 any, v2 any) int { func (c *intComparator) Compare(v1 any, v2 any) int {
@@ -393,24 +429,29 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
intSlice := []int{2, 1, 5, 3, 6, 4} numbers := []int{2, 1, 5, 3, 6, 4}
comparator := &intComparator{} comparator := &intComparator{}
sortedSlice := algorithm.CountSort(intSlice, comparator)
fmt.Println(sortedSlice) //[]int{1, 2, 3, 4, 5, 6} sortedNums := algorithm.CountSort(numbers, comparator)
fmt.Println(sortedNums)
// Output:
// [1 2 3 4 5 6]
} }
``` ```
### <span id="BinarySearch">BinarySearch</span> ### <span id="BinarySearch">BinarySearch</span>
<p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<p>二分递归查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.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 lancetconstraints.Comparator) int
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -436,27 +477,32 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8} numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{} comparator := &intComparator{}
foundIndex := algorithm.BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator) result1 := algorithm.BinarySearch(numbers, 5, 0, len(numbers)-1, comparator)
fmt.Println(notFoundIndex) //-1 result2 := algorithm.BinarySearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
} }
``` ```
### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span> ### <span id="BinaryIterativeSearch">BinaryIterativeSearch</span>
<p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.Comparator</p>
<p>二分迭代查找,返回元素索引,未找到元素返回-1参数comparator需要实现包lancetconstraints.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 lancetconstraints.Comparator) int
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -482,28 +528,32 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
} }
func main() { func main() {
var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8} numbers := []int{1, 2, 3, 4, 5, 6, 7, 8}
comparator := &intComparator{} comparator := &intComparator{}
foundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)
fmt.Println(foundIndex) //4
notFoundIndex := algorithm.BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator) result1 := algorithm.BinaryIterativeSearch(numbers, 5, 0, len(numbers)-1, comparator)
fmt.Println(notFoundIndex) //-1 result2 := algorithm.BinaryIterativeSearch(numbers, 9, 0, len(numbers)-1, comparator)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 4
// -1
} }
``` ```
### <span id="LinearSearch">LinearSearch</span> ### <span id="LinearSearch">LinearSearch</span>
<p>基于传入的相等函数线性查找元素,返回元素索引,未找到元素返回-1</p>
<p>基于传入的相等函数线性查找元素,返回元素索引,未找到元素返回-1。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -532,9 +582,9 @@ func main() {
} }
``` ```
### <span id="LRUCache">LRUCache</span> ### <span id="LRUCache">LRUCache</span>
<p>lru实现缓存</p>
<p>lru算法实现缓存。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -545,7 +595,8 @@ func (l *LRUCache[K, V]) Put(key K, value V)
func (l *LRUCache[K, V]) Delete(key K) bool func (l *LRUCache[K, V]) Delete(key K) bool
func (l *LRUCache[K, V]) Len() int func (l *LRUCache[K, V]) Len() int
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -560,14 +611,26 @@ func main() {
cache.Put(1, 1) cache.Put(1, 1)
cache.Put(2, 2) cache.Put(2, 2)
cache.Put(3, 3)
fmt.Println(cache.Len()) // 3 result1, ok1 := cache.Get(1)
result2, ok2 := cache.Get(2)
result3, ok3 := cache.Get(3)
v, ok := cache.Get(1) fmt.Println(result1, ok1)
fmt.Println(v, ok) // 1 true fmt.Println(result2, ok2)
fmt.Println(result3, ok3)
ok = cache.Delete(1) fmt.Println(cache.Len())
fmt.Println(ok) // true
ok := cache.Delete(2)
fmt.Println(ok)
// Output:
// 1 true
// 2 true
// 0 false
// 2
// true
} }
``` ```

326
docs/compare.md Normal file
View File

@@ -0,0 +1,326 @@
# Compare
Package compare provides a lightweight comparison function on any type.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/compare/compare.go](https://github.com/duke-git/lancet/blob/main/compare/compare.go)
- [https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/condition"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Equal](#Equal)
- [EqualValue](#EqualValue)
- [LessThan](#LessThan)
- [GreaterThan](#GreaterThan)
- [LessOrEqual](#LessOrEqual)
- [GreaterOrEqual](#GreaterOrEqual)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Equal">Equal</span>
<p>Checks if two values are equal or not. (check both type and value)</p>
<b>Signature:</b>
```go
func Equal(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.Equal(1, 1)
result2 := compare.Equal("1", "1")
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
result5 := compare.Equal(1, "1")
result6 := compare.Equal(1, int64(1))
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```
### <span id="EqualValue">EqualValue</span>
<p>Checks if two values are equal or not. (check value only)</p>
<b>Signature:</b>
```go
func EqualValue(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.EqualValue(1, 1)
result2 := compare.EqualValue(int(1), int64(1))
result3 := compare.EqualValue(1, "1")
result4 := compare.EqualValue(1, "2")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
```
### <span id="LessThan">LessThan</span>
<p>Checks if value `left` less than value `right`.</p>
<b>Signature:</b>
```go
func LessThan(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.LessThan(1, 2)
result2 := compare.LessThan(1.1, 2.2)
result3 := compare.LessThan("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.LessThan(time1, time2)
result5 := compare.LessThan(2, 1)
result6 := compare.LessThan(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
```
### <span id="GreaterThan">GreaterThan</span>
<p>Checks if value `left` greater than value `right`.</p>
<b>Signature:</b>
```go
func GreaterThan(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.GreaterThan(2, 1)
result2 := compare.GreaterThan(2.2, 1.1)
result3 := compare.GreaterThan("b", "a")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.GreaterThan(time2, time1)
result5 := compare.GreaterThan(1, 2)
result6 := compare.GreaterThan(int64(2), 1)
result7 := compare.GreaterThan("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```
### <span id="LessOrEqual">LessOrEqual</span>
<p>Checks if value `left` less than or equal than value `right`.</p>
<b>Signature:</b>
```go
func LessOrEqual(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.LessOrEqual(1, 1)
result2 := compare.LessOrEqual(1.1, 2.2)
result3 := compare.LessOrEqual("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.LessOrEqual(time1, time2)
result5 := compare.LessOrEqual(2, 1)
result6 := compare.LessOrEqual(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
```
### <span id="GreaterOrEqual">GreaterOrEqual</span>
<p>Checks if value `left` less greater or equal than value `right`.</p>
<b>Signature:</b>
```go
func GreaterOrEqual(left, right any) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.GreaterOrEqual(1, 1)
result2 := compare.GreaterOrEqual(2.2, 1.1)
result3 := compare.GreaterOrEqual("b", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.GreaterOrEqual(time2, time1)
result5 := compare.GreaterOrEqual(1, 2)
result6 := compare.GreaterOrEqual(int64(2), 1)
result7 := compare.GreaterOrEqual("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```

326
docs/compare_zh-CN.md Normal file
View File

@@ -0,0 +1,326 @@
# Compare
compare包提供几个轻量级的类型比较函数。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/compare/compare.go](https://github.com/duke-git/lancet/blob/main/compare/compare.go)
- [https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/main/compare/compare_internal.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/condition"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Equal](#Equal)
- [EqualValue](#EqualValue)
- [LessThan](#LessThan)
- [GreaterThan](#GreaterThan)
- [LessOrEqual](#LessOrEqual)
- [GreaterOrEqual](#GreaterOrEqual)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Equal">Equal</span>
<p>检查两个值是否相等(检查类型和值)</p>
<b>函数签名:</b>
```go
func Equal(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.Equal(1, 1)
result2 := compare.Equal("1", "1")
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
result5 := compare.Equal(1, "1")
result6 := compare.Equal(1, int64(1))
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```
### <span id="EqualValue">EqualValue</span>
<p>检查两个值是否相等(只检查值)</p>
<b>函数签名:</b>
```go
func EqualValue(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.EqualValue(1, 1)
result2 := compare.EqualValue(int(1), int64(1))
result3 := compare.EqualValue(1, "1")
result4 := compare.EqualValue(1, "2")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// true
// true
// true
// false
}
```
### <span id="LessThan">LessThan</span>
<p>验证参数`left`的值是否小于参数`right`的值。</p>
<b>函数签名:</b>
```go
func LessThan(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.LessThan(1, 2)
result2 := compare.LessThan(1.1, 2.2)
result3 := compare.LessThan("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.LessThan(time1, time2)
result5 := compare.LessThan(2, 1)
result6 := compare.LessThan(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
```
### <span id="GreaterThan">GreaterThan</span>
<p>验证参数`left`的值是否大于参数`right`的值。</p>
<b>函数签名:</b>
```go
func GreaterThan(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.GreaterThan(2, 1)
result2 := compare.GreaterThan(2.2, 1.1)
result3 := compare.GreaterThan("b", "a")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.GreaterThan(time2, time1)
result5 := compare.GreaterThan(1, 2)
result6 := compare.GreaterThan(int64(2), 1)
result7 := compare.GreaterThan("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```
### <span id="LessOrEqual">LessOrEqual</span>
<p>验证参数`left`的值是否小于或等于参数`right`的值。</p>
<b>函数签名:</b>
```go
func LessOrEqual(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.LessOrEqual(1, 1)
result2 := compare.LessOrEqual(1.1, 2.2)
result3 := compare.LessOrEqual("a", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.LessOrEqual(time1, time2)
result5 := compare.LessOrEqual(2, 1)
result6 := compare.LessOrEqual(1, int64(2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// true
// true
// true
// true
// false
// false
}
```
### <span id="GreaterOrEqual">GreaterOrEqual</span>
<p>验证参数`left`的值是否大于或参数`right`的值。</p>
<b>函数签名:</b>
```go
func GreaterOrEqual(left, right any) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/compare"
)
func main() {
result1 := compare.GreaterOrEqual(1, 1)
result2 := compare.GreaterOrEqual(2.2, 1.1)
result3 := compare.GreaterOrEqual("b", "b")
time1 := time.Now()
time2 := time1.Add(time.Second)
result4 := compare.GreaterOrEqual(time2, time1)
result5 := compare.GreaterOrEqual(1, 2)
result6 := compare.GreaterOrEqual(int64(2), 1)
result7 := compare.GreaterOrEqual("b", "c")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
// true
// true
// true
// true
// false
// false
// false
}
```

View File

@@ -1,5 +1,5 @@
# Concurrency # Concurrency
Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, async. Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -61,8 +61,6 @@ func main() {
} }
``` ```
### <span id="Bridge">Bridge</span> ### <span id="Bridge">Bridge</span>
<p>Link multiple channels into one channel until cancel the context.</p> <p>Link multiple channels into one channel until cancel the context.</p>
@@ -105,6 +103,7 @@ func main() {
for v := range c.Bridge(ctx, genVals()) { for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -114,9 +113,6 @@ func main() {
} }
``` ```
### <span id="FanIn">FanIn</span> ### <span id="FanIn">FanIn</span>
<p>Merge multiple channels into one channel until cancel the context.</p> <p>Merge multiple channels into one channel until cancel the context.</p>
@@ -156,7 +152,6 @@ func main() {
} }
``` ```
### <span id="Repeat">Repeat</span> ### <span id="Repeat">Repeat</span>
<p>Create channel, put values into the channel repeatly until cancel the context.</p> <p>Create channel, put values into the channel repeatly until cancel the context.</p>
@@ -187,6 +182,7 @@ func main() {
for v := range intStream { for v := range intStream {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -195,8 +191,6 @@ func main() {
} }
``` ```
### <span id="Generate">Generate</span> ### <span id="Generate">Generate</span>
<p>Creates a channel, then put values into the channel.</p> <p>Creates a channel, then put values into the channel.</p>
@@ -269,6 +263,7 @@ func main() {
for v := range intStream { for v := range intStream {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// hello // hello
// hello // hello
@@ -276,8 +271,6 @@ func main() {
} }
``` ```
### <span id="Or">Or</span> ### <span id="Or">Or</span>
<p>Read one or more channels into one channel, will close when any readin channel is closed.</p> <p>Read one or more channels into one channel, will close when any readin channel is closed.</p>
@@ -321,9 +314,6 @@ func main() {
} }
``` ```
### <span id="OrDone">OrDone</span> ### <span id="OrDone">OrDone</span>
<p>Read a channel into another channel, will close until cancel context.</p> <p>Read a channel into another channel, will close until cancel context.</p>
@@ -354,6 +344,7 @@ func main() {
for v := range c.OrDone(ctx, intStream) { for v := range c.OrDone(ctx, intStream) {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 1 // 1
@@ -361,9 +352,6 @@ func main() {
} }
``` ```
### <span id="Take">Take</span> ### <span id="Take">Take</span>
<p>Create a channel whose values are taken from another channel with limit number.</p> <p>Create a channel whose values are taken from another channel with limit number.</p>
@@ -402,6 +390,7 @@ func main() {
for v := range intStream { for v := range intStream {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -409,8 +398,6 @@ func main() {
} }
``` ```
### <span id="Tee">Tee</span> ### <span id="Tee">Tee</span>
<p>Split one chanel into two channels, until cancel the context.</p> <p>Split one chanel into two channels, until cancel the context.</p>
@@ -444,6 +431,7 @@ func main() {
fmt.Println(v) fmt.Println(v)
fmt.Println(<-ch2) fmt.Println(<-ch2)
} }
// Output: // Output:
// 1 // 1
// 1 // 1

View File

@@ -1,5 +1,5 @@
# Concurrency # Concurrency
并发包包含一些支持并发编程的功能。例如goroutine, channel, async等。 并发包包含一些支持并发编程的功能。例如goroutine, channel等。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -46,7 +46,7 @@ import (
type Channel[T any] struct type Channel[T any] struct
func NewChannel[T any]() *Channel[T] func NewChannel[T any]() *Channel[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -61,8 +61,6 @@ func main() {
} }
``` ```
### <span id="Bridge">Bridge</span> ### <span id="Bridge">Bridge</span>
<p>将多个channel链接到一个channel直到取消上下文。</p> <p>将多个channel链接到一个channel直到取消上下文。</p>
@@ -72,7 +70,7 @@ func main() {
```go ```go
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -105,6 +103,7 @@ func main() {
for v := range c.Bridge(ctx, genVals()) { for v := range c.Bridge(ctx, genVals()) {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -114,9 +113,6 @@ func main() {
} }
``` ```
### <span id="FanIn">FanIn</span> ### <span id="FanIn">FanIn</span>
<p>将多个channel合并为一个channel直到取消上下文。</p> <p>将多个channel合并为一个channel直到取消上下文。</p>
@@ -126,7 +122,7 @@ func main() {
```go ```go
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -156,7 +152,6 @@ func main() {
} }
``` ```
### <span id="Generate">Generate</span> ### <span id="Generate">Generate</span>
<p>根据传入的值生成channel.</p> <p>根据传入的值生成channel.</p>
@@ -166,7 +161,7 @@ func main() {
```go ```go
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -204,7 +199,7 @@ func main() {
```go ```go
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -225,6 +220,7 @@ func main() {
for v := range intStream { for v := range intStream {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -233,9 +229,6 @@ func main() {
} }
``` ```
### <span id="RepeatFn">RepeatFn</span> ### <span id="RepeatFn">RepeatFn</span>
<p>返回一个channel重复执行函数fn并将结果放入返回的channel直到取消上下文。</p> <p>返回一个channel重复执行函数fn并将结果放入返回的channel直到取消上下文。</p>
@@ -245,7 +238,7 @@ func main() {
```go ```go
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -277,8 +270,6 @@ func main() {
} }
``` ```
### <span id="Or">Or</span> ### <span id="Or">Or</span>
<p>将一个或多个channel读取到一个channel中当任何读取channel关闭时将结束读取。</p> <p>将一个或多个channel读取到一个channel中当任何读取channel关闭时将结束读取。</p>
@@ -288,7 +279,7 @@ func main() {
```go ```go
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T func (c *Channel[T]) Or(channels ...<-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -322,9 +313,6 @@ func main() {
} }
``` ```
### <span id="OrDone">OrDone</span> ### <span id="OrDone">OrDone</span>
<p>将一个channel读入另一个channel直到取消上下文。</p> <p>将一个channel读入另一个channel直到取消上下文。</p>
@@ -334,7 +322,7 @@ func main() {
```go ```go
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -355,6 +343,7 @@ func main() {
for v := range c.OrDone(ctx, intStream) { for v := range c.OrDone(ctx, intStream) {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 1 // 1
@@ -362,9 +351,6 @@ func main() {
} }
``` ```
### <span id="Take">Take</span> ### <span id="Take">Take</span>
<p>返回一个channel其值从另一个channel获取直到取消上下文。</p> <p>返回一个channel其值从另一个channel获取直到取消上下文。</p>
@@ -374,7 +360,7 @@ func main() {
```go ```go
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -403,6 +389,7 @@ func main() {
for v := range intStream { for v := range intStream {
fmt.Println(v) fmt.Println(v)
} }
// Output: // Output:
// 1 // 1
// 2 // 2
@@ -410,8 +397,6 @@ func main() {
} }
``` ```
### <span id="Tee">Tee</span> ### <span id="Tee">Tee</span>
<p>将一个channel分成两个channel直到取消上下文。</p> <p>将一个channel分成两个channel直到取消上下文。</p>
@@ -421,7 +406,7 @@ func main() {
```go ```go
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -58,40 +58,51 @@ import (
func main() { func main() {
// bool // bool
fmt.Println(condition.Bool(false)) // false result1 := condition.Bool(false)
fmt.Println(condition.Bool(true)) // true result2 := condition.Bool(true)
fmt.Println(result1) // false
fmt.Println(result2) // true
// integer // integer
fmt.Println(condition.Bool(0)) // false result3 := condition.Bool(0)
fmt.Println(condition.Bool(1)) // true result4 := condition.Bool(1)
fmt.Println(result3) // false
// float fmt.Println(result4) // true
fmt.Println(condition.Bool(0.0)) // false
fmt.Println(condition.Bool(0.1)) // true
// string // string
fmt.Println(condition.Bool("")) // false result5 := condition.Bool("")
fmt.Println(condition.Bool(" ")) // true result6 := condition.Bool(" ")
fmt.Println(condition.Bool("0")) // true fmt.Println(result5) // false
fmt.Println(result6) // true
// slice // slice
var nums [2]int nums := []int{}
fmt.Println(condition.Bool(nums)) // false result7 := condition.Bool(nums)
nums = [2]int{0, 1}
fmt.Println(condition.Bool(nums)) // true
// map nums = append(nums, 1, 2)
fmt.Println(condition.Bool(map[string]string{})) // false result8 := condition.Bool(nums)
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true fmt.Println(result7) // false
fmt.Println(result8) // true
// struct // struct
fmt.Println(condition.Bool(struct{}{})) // false result9 = condition.Bool(struct{}{})
fmt.Println(condition.Bool(time.Now())) // true fmt.Println(result8) // false
// Output:
// false
// true
// false
// true
// false
// true
// false
// true
// false
} }
``` ```
### <span id="And">And</span> ### <span id="And">And</span>
<p>Returns true if both a and b are truthy.</p> <p>Returns true if both a and b are truthy.</p>
@@ -277,10 +288,18 @@ import (
) )
func main() { func main() {
trueValue := "1" conditionTrue := 2 > 1
falseValue := "0" result1 := condition.TernaryOperator(conditionTrue, 0, 1)
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1" conditionFalse := 2 > 3
result2 := condition.TernaryOperator(conditionFalse, 0, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// 1
} }
``` ```

View File

@@ -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>例:</b>
```go ```go
package main package main
@@ -57,40 +57,50 @@ import (
func main() { func main() {
// bool // bool
fmt.Println(condition.Bool(false)) // false result1 := condition.Bool(false)
fmt.Println(condition.Bool(true)) // true result2 := condition.Bool(true)
fmt.Println(result1) // false
fmt.Println(result2) // true
// integer // integer
fmt.Println(condition.Bool(0)) // false result3 := condition.Bool(0)
fmt.Println(condition.Bool(1)) // true result4 := condition.Bool(1)
fmt.Println(result3) // false
// float fmt.Println(result4) // true
fmt.Println(condition.Bool(0.0)) // false
fmt.Println(condition.Bool(0.1)) // true
// string // string
fmt.Println(condition.Bool("")) // false result5 := condition.Bool("")
fmt.Println(condition.Bool(" ")) // true result6 := condition.Bool(" ")
fmt.Println(condition.Bool("0")) // true fmt.Println(result5) // false
fmt.Println(result6) // true
// slice // slice
var nums [2]int nums := []int{}
fmt.Println(condition.Bool(nums)) // false result7 := condition.Bool(nums)
nums = [2]int{0, 1}
fmt.Println(condition.Bool(nums)) // true
// map nums = append(nums, 1, 2)
fmt.Println(condition.Bool(map[string]string{})) // false result8 := condition.Bool(nums)
fmt.Println(condition.Bool(map[string]string{"a": "a"})) // true fmt.Println(result7) // false
fmt.Println(result8) // true
// struct // struct
fmt.Println(condition.Bool(struct{}{})) // false result9 = condition.Bool(struct{}{})
fmt.Println(condition.Bool(time.Now())) // true fmt.Println(result8) // false
// Output:
// false
// true
// false
// true
// false
// true
// false
// true
// false
} }
``` ```
### <span id="And">And</span> ### <span id="And">And</span>
<p>逻辑且操作当切仅当a和b都为true时返回true</p> <p>逻辑且操作当切仅当a和b都为true时返回true</p>
@@ -99,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>例:</b>
```go ```go
package main package main
@@ -117,8 +127,6 @@ func main() {
} }
``` ```
### <span id="Or">Or</span> ### <span id="Or">Or</span>
<p>逻辑或操作当切仅当a和b都为false时返回false</p> <p>逻辑或操作当切仅当a和b都为false时返回false</p>
@@ -127,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>例:</b>
```go ```go
package main package main
@@ -145,8 +153,6 @@ func main() {
} }
``` ```
### <span id="Xor">Xor</span> ### <span id="Xor">Xor</span>
<p>逻辑异或操作a和b相同返回falsea和b不相同返回true</p> <p>逻辑异或操作a和b相同返回falsea和b不相同返回true</p>
@@ -155,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>例:</b>
```go ```go
package main package main
@@ -173,8 +179,6 @@ func main() {
} }
``` ```
### <span id="Nor">Nor</span> ### <span id="Nor">Nor</span>
<p>异或的取反操作</p> <p>异或的取反操作</p>
@@ -183,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>例:</b>
```go ```go
package main package main
@@ -201,8 +205,6 @@ func main() {
} }
``` ```
### <span id="Xnor">Xnor</span> ### <span id="Xnor">Xnor</span>
<p>如果a和b都是真的或a和b均是假的则返回true。</p> <p>如果a和b都是真的或a和b均是假的则返回true。</p>
@@ -211,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>例:</b>
```go ```go
package main package main
@@ -237,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>例:</b>
```go ```go
package main package main
@@ -255,8 +257,6 @@ func main() {
} }
``` ```
### <span id="TernaryOperator">TernaryOperator</span> ### <span id="TernaryOperator">TernaryOperator</span>
<p>三元运算符</p> <p>三元运算符</p>
@@ -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>例:</b>
```go ```go
package main package main
@@ -276,10 +276,18 @@ import (
) )
func main() { func main() {
trueValue := "1" conditionTrue := 2 > 1
falseValue := "0" result1 := condition.TernaryOperator(conditionTrue, 0, 1)
fmt.Println(condition.TernaryOperator(true, trueValue, falseValue)) // "1" conditionFalse := 2 > 3
result2 := condition.TernaryOperator(conditionFalse, 0, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 0
// 1
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Convertor # Convertor
Package convertor contains some functions for data type convertion. Package convertor contains some functions for data type convertion.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ Package convertor contains some functions for data type convertion.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/convertor" "github.com/duke-git/lancet/v2/convertor"
@@ -19,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [ColorHexToRGB](#ColorHexToRGB) - [ColorHexToRGB](#ColorHexToRGB)
- [ColorRGBToHex](#ColorRGBToHex) - [ColorRGBToHex](#ColorRGBToHex)
- [ToBool](#ToBool) - [ToBool](#ToBool)
@@ -35,14 +38,18 @@ import (
- [MapToSlice](#MapToSlice) - [MapToSlice](#MapToSlice)
- [EncodeByte](#EncodeByte) - [EncodeByte](#EncodeByte)
- [DecodeByte](#DecodeByte) - [DecodeByte](#DecodeByte)
- [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="ColorHexToRGB">ColorHexToRGB</span> ### <span id="ColorHexToRGB">ColorHexToRGB</span>
<p>Convert color hex to color rgb.</p> <p>Convert color hex to color rgb.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -50,6 +57,7 @@ import (
```go ```go
func ColorHexToRGB(colorHex string) (red, green, blue int) func ColorHexToRGB(colorHex string) (red, green, blue int)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -63,12 +71,14 @@ import (
func main() { func main() {
colorHex := "#003366" colorHex := "#003366"
r, g, b := convertor.ColorHexToRGB(colorHex) r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
fmt.Println(r, g, b)
// Output:
// 0 51 102
} }
``` ```
### <span id="ColorRGBToHex">ColorRGBToHex</span> ### <span id="ColorRGBToHex">ColorRGBToHex</span>
<p>Convert color rgb to color hex.</p> <p>Convert color rgb to color hex.</p>
@@ -78,6 +88,7 @@ func main() {
```go ```go
func ColorRGBToHex(red, green, blue int) string func ColorRGBToHex(red, green, blue int) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -92,14 +103,15 @@ func main() {
r := 0 r := 0
g := 51 g := 51
b := 102 b := 102
colorHex := convertor.ColorRGBToHex(r, g, b) colorHex := ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366 fmt.Println(colorHex)
// Output:
// #003366
} }
``` ```
### <span id="ToBool">ToBool</span> ### <span id="ToBool">ToBool</span>
<p>Convert string to bool. Use strconv.ParseBool.</p> <p>Convert string to bool. Use strconv.ParseBool.</p>
@@ -109,6 +121,7 @@ func main() {
```go ```go
func ToBool(s string) (bool, error) func ToBool(s string) (bool, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -120,22 +133,26 @@ import (
) )
func main() { func main() {
v1, _ := convertor.ToBool("1") cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
fmt.Println(v1) //true
v2, _ := convertor.ToBool("true") for i := 0; i < len(cases); i++ {
fmt.Println(v2) //true result, _ := convertor.ToBool(cases[i])
fmt.Println(result)
}
v3, _ := convertor.ToBool("True") // Output:
fmt.Println(v3) //true // true
// true
v4, _ := convertor.ToBool("123") // true
fmt.Println(v4) //false // false
// false
// false
// false
// false
// false
} }
``` ```
### <span id="ToBytes">ToBytes</span> ### <span id="ToBytes">ToBytes</span>
<p>Convert value to byte slice.</p> <p>Convert value to byte slice.</p>
@@ -145,6 +162,7 @@ func main() {
```go ```go
func ToBytes(data any) ([]byte, error) func ToBytes(data any) ([]byte, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -156,16 +174,18 @@ import (
) )
func main() { func main() {
bytesData, err := convertor.ToBytes("0") bytesData, err := convertor.ToBytes("abc")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
fmt.Println(bytesData)
// Output:
// [97 98 99]
} }
``` ```
### <span id="ToChar">ToChar</span> ### <span id="ToChar">ToChar</span>
<p>Convert string to char slice.</p> <p>Convert string to char slice.</p>
@@ -175,6 +195,7 @@ func main() {
```go ```go
func ToChar(s string) []string func ToChar(s string) []string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -186,18 +207,21 @@ import (
) )
func main() { func main() {
chars := convertor.ToChar("") result1 := convertor.ToChar("")
fmt.Println(chars) //[]string{""} result2 := convertor.ToChar("abc")
result3 := convertor.ToChar("1 2#3")
chars = convertor.ToChar("abc") fmt.Println(result1)
fmt.Println(chars) //[]string{"a", "b", "c"} fmt.Println(result2)
fmt.Println(result3)
chars = convertor.ToChar("1 2#3") // Output:
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"} // []
// [a b c]
// [1 2 # 3]
} }
``` ```
### <span id="ToChannel">ToChannel</span> ### <span id="ToChannel">ToChannel</span>
<p>Convert a collection of elements to a read-only channel.</p> <p>Convert a collection of elements to a read-only channel.</p>
@@ -207,6 +231,7 @@ func main() {
```go ```go
func ToChannel[T any](array []T) <-chan T func ToChannel[T any](array []T) <-chan T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -219,23 +244,21 @@ import (
func main() { func main() {
ch := convertor.ToChannel([]int{1, 2, 3}) ch := convertor.ToChannel([]int{1, 2, 3})
result1 := <-ch
result2 := <-ch
result3 := <-ch
val1, _ := <-ch fmt.Println(result1)
fmt.Println(val1) //1 fmt.Println(result2)
fmt.Println(result3)
val2, _ := <-ch // Output:
fmt.Println(val2) //2 // 1
// 2
val3, _ := <-ch // 3
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
} }
``` ```
### <span id="ToFloat">ToFloat</span> ### <span id="ToFloat">ToFloat</span>
<p>Convert value to a float64 value. If param is a invalid floatable, will return 0.0 and error. </p> <p>Convert value to a float64 value. If param is a invalid floatable, will return 0.0 and error. </p>
@@ -245,6 +268,7 @@ func main() {
```go ```go
func ToFloat(value any) (float64, error) func ToFloat(value any) (float64, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -256,19 +280,30 @@ import (
) )
func main() { func main() {
v, err := convertor.ToFloat("") result1, _ := convertor.ToFloat("")
if err != nil { result2, err := convertor.ToFloat("abc")
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax result3, _ := convertor.ToFloat("-1")
} result4, _ := convertor.ToFloat("-.11")
fmt.Println(v) //0 result5, _ := convertor.ToFloat("1.23e3")
result6, _ := convertor.ToFloat(true)
v, _ = convertor.ToFloat("-.11") fmt.Println(result1)
fmt.Println(v) //-0.11 fmt.Println(result2, err)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// 0
// 0 strconv.ParseFloat: parsing "": invalid syntax
// -1
// -0.11
// 1230
// 0
} }
``` ```
### <span id="ToInt">ToInt</span> ### <span id="ToInt">ToInt</span>
<p>Convert value to a int64 value. If param is a invalid intable, will return 0 and error. </p> <p>Convert value to a int64 value. If param is a invalid intable, will return 0 and error. </p>
@@ -278,6 +313,7 @@ func main() {
```go ```go
func ToInt(value any) (int64, error) func ToInt(value any) (int64, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -289,19 +325,27 @@ import (
) )
func main() { func main() {
v, err := convertor.ToInt("") result1, _ := convertor.ToInt("123")
if err != nil { result2, _ := convertor.ToInt("-123")
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax result3, _ := convertor.ToInt(float64(12.3))
} result4, err := convertor.ToInt("abc")
fmt.Println(v) //0 result5, _ := convertor.ToInt(true)
v, _ = convertor.ToFloat(1.12) fmt.Println(result1)
fmt.Println(v) //1 fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4, err)
fmt.Println(result5)
// Output:
// 123
// -123
// 12
// 0 strconv.ParseInt: parsing "": invalid syntax
// 0
} }
``` ```
### <span id="ToJson">ToJson</span> ### <span id="ToJson">ToJson</span>
<p>Convert interface to json string. If param can't be converted, will return "" and error. </p> <p>Convert interface to json string. If param can't be converted, will return "" and error. </p>
@@ -311,6 +355,7 @@ func main() {
```go ```go
func ToJson(value any) (string, error) func ToJson(value any) (string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -322,14 +367,20 @@ import (
) )
func main() { func main() {
var aMap = map[string]int{"a": 1, "b": 2, "c": 3} aMap := map[string]int{"a": 1, "b": 2, "c": 3}
jsonStr, _ := convertor.ToJson(aMap) result, err := ToJson(aMap)
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(result)
// Output:
// {"a":1,"b":2,"c":3}
} }
``` ```
### <span id="ToMap">ToMap</span> ### <span id="ToMap">ToMap</span>
<p>Convert a slice of structs to a map based on iteratee function. </p> <p>Convert a slice of structs to a map based on iteratee function. </p>
@@ -339,6 +390,7 @@ func main() {
```go ```go
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -358,16 +410,18 @@ func main() {
{name: "Hello", code: 100}, {name: "Hello", code: 100},
{name: "Hi", code: 101}, {name: "Hi", code: 101},
} }
result := convertor.ToMap(messages, func(msg Message) (int, string) { result := convertor.ToMap(messages, func(msg Message) (int, string) {
return msg.code, msg.name return msg.code, msg.name
}) })
fmt.Println(result) //{100: "Hello", 101: "Hi"} fmt.Println(result)
// Output:
// map[100:Hello 101:Hi]
} }
``` ```
### <span id="ToPointer">ToPointer</span> ### <span id="ToPointer">ToPointer</span>
<p>Returns a pointer to passed value. </p> <p>Returns a pointer to passed value. </p>
@@ -377,6 +431,7 @@ func main() {
```go ```go
func ToPointer[T any](value T) *T func ToPointer[T any](value T) *T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -389,11 +444,13 @@ import (
func main() { func main() {
result := convertor.ToPointer(123) result := convertor.ToPointer(123)
fmt.Println(*result) //123 fmt.Println(*result)
// Output:
// 123
} }
``` ```
### <span id="ToString">ToString</span> ### <span id="ToString">ToString</span>
<p>ToString convert value to string, for number, string, []byte, will convert to string. For other type (slice, map, array, struct) will call json.Marshal</p> <p>ToString convert value to string, for number, string, []byte, will convert to string. For other type (slice, map, array, struct) will call json.Marshal</p>
@@ -403,6 +460,7 @@ func main() {
```go ```go
func ToString(value any) string func ToString(value any) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -414,13 +472,33 @@ import (
) )
func main() { func main() {
fmt.Printf("%q", convertor.ToString(1)) //"1" result1 := convertor.ToString("")
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1" result2 := convertor.ToString(nil)
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]" result3 := convertor.ToString(0)
result4 := convertor.ToString(1.23)
result5 := convertor.ToString(true)
result6 := convertor.ToString(false)
result7 := convertor.ToString([]int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
//
//
// 0
// 1.23
// true
// false
// [1,2,3]
} }
``` ```
### <span id="StructToMap">StructToMap</span> ### <span id="StructToMap">StructToMap</span>
<p>Convert struct to map, only convert exported field, struct field tag `json` should be set.</p> <p>Convert struct to map, only convert exported field, struct field tag `json` should be set.</p>
@@ -430,6 +508,7 @@ func main() {
```go ```go
func StructToMap(value any) (map[string]any, error) func StructToMap(value any) (map[string]any, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -451,12 +530,13 @@ func main() {
} }
pm, _ := convertor.StructToMap(p) pm, _ := convertor.StructToMap(p)
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test] fmt.Println(pm)
// Output:
// map[name:test]
} }
``` ```
### <span id="MapToSlice">MapToSlice</span> ### <span id="MapToSlice">MapToSlice</span>
<p>Convert a map to a slice based on iteratee function.</p> <p>Convert a map to a slice based on iteratee function.</p>
@@ -466,6 +546,7 @@ func main() {
```go ```go
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -486,7 +567,6 @@ func main() {
} }
``` ```
### <span id="EncodeByte">EncodeByte</span> ### <span id="EncodeByte">EncodeByte</span>
<p>Encode data to byte slice.</p> <p>Encode data to byte slice.</p>
@@ -496,6 +576,7 @@ func main() {
```go ```go
func EncodeByte(data any) ([]byte, error) func EncodeByte(data any) ([]byte, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -508,12 +589,13 @@ import (
func main() { func main() {
byteData, _ := convertor.EncodeByte("abc") byteData, _ := convertor.EncodeByte("abc")
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99} fmt.Println(byteData)
// Output:
// [6 12 0 3 97 98 99]
} }
``` ```
### <span id="DecodeByte">DecodeByte</span> ### <span id="DecodeByte">DecodeByte</span>
<p>Decode byte data to target object. target should be a pointer instance.</p> <p>Decode byte data to target object. target should be a pointer instance.</p>
@@ -523,6 +605,7 @@ func main() {
```go ```go
func DecodeByte(data []byte, target any) error func DecodeByte(data []byte, target any) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -536,7 +619,260 @@ import (
func main() { func main() {
var result string var result string
byteData := []byte{6, 12, 0, 3, 97, 98, 99} byteData := []byte{6, 12, 0, 3, 97, 98, 99}
convertor.DecodeByte(byteData, &result)
fmt.Println(result) //"abc" err := convertor.DecodeByte(byteData, &result)
if err != nil {
return
}
fmt.Println(result)
// Output:
// abc
}
```
### <span id="DeepClone">DeepClone</span>
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
<b>Signature:</b>
```go
func DeepClone[T any](src T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
type Struct struct {
Str string
Int int
Float float64
Bool bool
Nil interface{}
unexported string
}
cases := []interface{}{
true,
1,
0.1,
map[string]int{
"a": 1,
"b": 2,
},
&Struct{
Str: "test",
Int: 1,
Float: 0.1,
Bool: true,
Nil: nil,
// unexported: "can't be cloned",
},
}
for _, item := range cases {
cloned := convertor.DeepClone(item)
isPointerEqual := &cloned == &item
fmt.Println(cloned, isPointerEqual)
}
// Output:
// true false
// 1 false
// 0.1 false
// map[a:1 b:2] false
// &{test 1 0.1 true <nil> } false
}
```
### <span id="CopyProperties">CopyProperties</span>
<p>Copies each field from the source struct into the destination struct. Use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.</p>
<b>Signature:</b>
```go
func CopyProperties[T, U any](dst T, src U) (err error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
type Disk struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type DiskVO struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type Indicator struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int `json:"cpu"`
Disk []Disk `json:"disk"`
Stop chan bool `json:"-"`
}
type IndicatorVO struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int64 `json:"cpu"`
Disk []DiskVO `json:"disk"`
}
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
}}
indicatorVO := IndicatorVO{}
err := convertor.CopyProperties(&indicatorVO, indicator)
if err != nil {
return
}
fmt.Println(indicatorVO.Id)
fmt.Println(indicatorVO.Ip)
fmt.Println(len(indicatorVO.Disk))
// Output:
// 001
// 127.0.0.1
// 3
}
```
### <span id="ToInterface">ToInterface</span>
<p>Converts reflect value to its interface type.</p>
<b>Signature:</b>
```go
func ToInterface(v reflect.Value) (value interface{}, ok bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}
```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>Converts utf8 encoding data to GBK encoding data.</p>
<b>Signature:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>Converts GBK encoding data to utf8 encoding data.</p>
<b>Signature:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Convertor # Convertor
convertor 转换器包支持一些常见的数据类型转换 convertor 转换器包支持一些常见的数据类型转换
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -37,22 +38,27 @@ import (
- [MapToSlice](#MapToSlice) - [MapToSlice](#MapToSlice)
- [EncodeByte](#EncodeByte) - [EncodeByte](#EncodeByte)
- [DecodeByte](#DecodeByte) - [DecodeByte](#DecodeByte)
- [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="ColorHexToRGB">ColorHexToRGB</span> ### <span id="ColorHexToRGB">ColorHexToRGB</span>
<p>颜色值十六进制转rgb</p>
<p>颜色值十六进制转rgb。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ColorHexToRGB(colorHex string) (red, green, blue int) func ColorHexToRGB(colorHex string) (red, green, blue int)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -65,22 +71,25 @@ import (
func main() { func main() {
colorHex := "#003366" colorHex := "#003366"
r, g, b := convertor.ColorHexToRGB(colorHex) r, g, b := convertor.ColorHexToRGB(colorHex)
fmt.Println(r, g, b) //0,51,102
fmt.Println(r, g, b)
// Output:
// 0 51 102
} }
``` ```
### <span id="ColorRGBToHex">ColorRGBToHex</span> ### <span id="ColorRGBToHex">ColorRGBToHex</span>
<p>颜色值rgb转十六进制</p> <p>颜色值rgb转十六进制</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ColorRGBToHex(red, green, blue int) string func ColorRGBToHex(red, green, blue int) string
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -94,24 +103,26 @@ func main() {
r := 0 r := 0
g := 51 g := 51
b := 102 b := 102
colorHex := convertor.ColorRGBToHex(r, g, b) colorHex := ColorRGBToHex(r, g, b)
fmt.Println(colorHex) //#003366 fmt.Println(colorHex)
// Output:
// #003366
} }
``` ```
### <span id="ToBool">ToBool</span> ### <span id="ToBool">ToBool</span>
<p>字符串转布尔类型使用strconv.ParseBool</p> <p>字符串转布尔类型使用strconv.ParseBool</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToBool(s string) (bool, error) func ToBool(s string) (bool, error)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -122,32 +133,37 @@ import (
) )
func main() { func main() {
v1, _ := convertor.ToBool("1") cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
fmt.Println(v1) //true
v2, _ := convertor.ToBool("true") for i := 0; i < len(cases); i++ {
fmt.Println(v2) //true result, _ := convertor.ToBool(cases[i])
fmt.Println(result)
}
v3, _ := convertor.ToBool("True") // Output:
fmt.Println(v3) //true // true
// true
v4, _ := convertor.ToBool("123") // true
fmt.Println(v4) //false // false
// false
// false
// false
// false
// false
} }
``` ```
### <span id="ToBytes">ToBytes</span> ### <span id="ToBytes">ToBytes</span>
<p>interface转字节切片.</p> <p>Interface转字节切片</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToBytes(data any) ([]byte, error) func ToBytes(data any) ([]byte, error)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -158,26 +174,29 @@ import (
) )
func main() { func main() {
bytesData, err := convertor.ToBytes("0") bytesData, err := convertor.ToBytes("abc")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(bytesData) //[]bytes{3, 4, 0, 0}
fmt.Println(bytesData)
// Output:
// [97 98 99]
} }
``` ```
### <span id="ToChar">ToChar</span> ### <span id="ToChar">ToChar</span>
<p>字符串转字符切片</p> <p>字符串转字符切片</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToChar(s string) []string func ToChar(s string) []string
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -188,29 +207,32 @@ import (
) )
func main() { func main() {
chars := convertor.ToChar("") result1 := convertor.ToChar("")
fmt.Println(chars) //[]string{""} result2 := convertor.ToChar("abc")
result3 := convertor.ToChar("1 2#3")
chars = convertor.ToChar("abc") fmt.Println(result1)
fmt.Println(chars) //[]string{"a", "b", "c"} fmt.Println(result2)
fmt.Println(result3)
chars = convertor.ToChar("1 2#3") // Output:
fmt.Println(chars) //[]string{"1", " ", "2", "#", "3"} // []
// [a b c]
// [1 2 # 3]
} }
``` ```
### <span id="ToChannel">ToChannel</span> ### <span id="ToChannel">ToChannel</span>
<p>将切片转为只读channel</p> <p>将切片转为只读channel</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToChannel[T any](array []T) <-chan T func ToChannel[T any](array []T) <-chan T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -222,33 +244,32 @@ import (
func main() { func main() {
ch := convertor.ToChannel([]int{1, 2, 3}) ch := convertor.ToChannel([]int{1, 2, 3})
result1 := <-ch
result2 := <-ch
result3 := <-ch
val1, _ := <-ch fmt.Println(result1)
fmt.Println(val1) //1 fmt.Println(result2)
fmt.Println(result3)
val2, _ := <-ch // Output:
fmt.Println(val2) //2 // 1
// 2
val3, _ := <-ch // 3
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
} }
``` ```
### <span id="ToFloat">ToFloat</span> ### <span id="ToFloat">ToFloat</span>
<p>将interface转成float64类型如果参数无法转换会返回0和error</p> <p>将interface转成float64类型如果参数无法转换会返回0和error</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToFloat(value any) (float64, error) func ToFloat(value any) (float64, error)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -259,29 +280,41 @@ import (
) )
func main() { func main() {
v, err := convertor.ToFloat("") result1, _ := convertor.ToFloat("")
if err != nil { result2, err := convertor.ToFloat("abc")
fmt.Println(err) //strconv.ParseFloat: parsing "": invalid syntax result3, _ := convertor.ToFloat("-1")
} result4, _ := convertor.ToFloat("-.11")
fmt.Println(v) //0 result5, _ := convertor.ToFloat("1.23e3")
result6, _ := convertor.ToFloat(true)
v, _ = convertor.ToFloat("-.11") fmt.Println(result1)
fmt.Println(v) //-0.11 fmt.Println(result2, err)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
// Output:
// 0
// 0 strconv.ParseFloat: parsing "": invalid syntax
// -1
// -0.11
// 1230
// 0
} }
``` ```
### <span id="ToInt">ToInt</span> ### <span id="ToInt">ToInt</span>
<p>将interface转成int64类型如果参数无法转换会返回0和error</p> <p>将interface转成int64类型如果参数无法转换会返回0和error</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToInt(value any) (int64, error) func ToInt(value any) (int64, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -292,29 +325,38 @@ import (
) )
func main() { func main() {
v, err := convertor.ToInt("") result1, _ := convertor.ToInt("123")
if err != nil { result2, _ := convertor.ToInt("-123")
fmt.Println(err) //strconv.ParseInt: parsing "": invalid syntax result3, _ := convertor.ToInt(float64(12.3))
} result4, err := convertor.ToInt("abc")
fmt.Println(v) //0 result5, _ := convertor.ToInt(true)
v, _ = convertor.ToFloat(1.12) fmt.Println(result1)
fmt.Println(v) //1 fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4, err)
fmt.Println(result5)
// Output:
// 123
// -123
// 12
// 0 strconv.ParseInt: parsing "": invalid syntax
// 0
} }
``` ```
### <span id="ToJson">ToJson</span> ### <span id="ToJson">ToJson</span>
<p>将interface转成json字符串如果参数无法转换会返回""和error</p> <p>将interface转成json字符串如果参数无法转换会返回""和error</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToJson(value any) (string, error) func ToJson(value any) (string, error)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -325,24 +367,31 @@ import (
) )
func main() { func main() {
var aMap = map[string]int{"a": 1, "b": 2, "c": 3} aMap := map[string]int{"a": 1, "b": 2, "c": 3}
jsonStr, _ := convertor.ToJson(aMap) result, err := ToJson(aMap)
fmt.Printf("%q", jsonStr) //"{\"a\":1,\"b\":2,\"c\":3}"
if err != nil {
fmt.Printf("%v", err)
}
fmt.Println(result)
// Output:
// {"a":1,"b":2,"c":3}
} }
``` ```
### <span id="ToMap">ToMap</span> ### <span id="ToMap">ToMap</span>
<p>将切片转为map</p> <p>将切片转为map</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -361,26 +410,29 @@ func main() {
{name: "Hello", code: 100}, {name: "Hello", code: 100},
{name: "Hi", code: 101}, {name: "Hi", code: 101},
} }
result := convertor.ToMap(messages, func(msg Message) (int, string) { result := convertor.ToMap(messages, func(msg Message) (int, string) {
return msg.code, msg.name return msg.code, msg.name
}) })
fmt.Println(result) //{100: "Hello", 101: "Hi"} fmt.Println(result)
// Output:
// map[100:Hello 101:Hi]
} }
``` ```
### <span id="ToPointer">ToPointer</span> ### <span id="ToPointer">ToPointer</span>
<p>返回传入值的指针</p> <p>返回传入值的指针</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToPointer[T any](value T) *T func ToPointer[T any](value T) *T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -392,22 +444,24 @@ import (
func main() { func main() {
result := convertor.ToPointer(123) result := convertor.ToPointer(123)
fmt.Println(*result) //123 fmt.Println(*result)
// Output:
// 123
} }
``` ```
### <span id="ToString">ToString</span> ### <span id="ToString">ToString</span>
<p>将值转换为字符串,对于数字、字符串、[]byte将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal</p> <p>将值转换为字符串,对于数字、字符串、[]byte将转换为字符串。 对于其他类型(切片、映射、数组、结构)将调用 json.Marshal</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func ToString(value any) string func ToString(value any) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -418,24 +472,44 @@ import (
) )
func main() { func main() {
fmt.Printf("%q", convertor.ToString(1)) //"1" result1 := convertor.ToString("")
fmt.Printf("%q", convertor.ToString(1.1)) //"1.1" result2 := convertor.ToString(nil)
fmt.Printf("%q", convertor.ToString([]int{1, 2, 3})) //"[1,2,3]" result3 := convertor.ToString(0)
result4 := convertor.ToString(1.23)
result5 := convertor.ToString(true)
result6 := convertor.ToString(false)
result7 := convertor.ToString([]int{1, 2, 3})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result6)
fmt.Println(result7)
// Output:
//
//
// 0
// 1.23
// true
// false
// [1,2,3]
} }
``` ```
### <span id="StructToMap">StructToMap</span> ### <span id="StructToMap">StructToMap</span>
<p>将struct转成map只会转换struct中可导出的字段。struct中导出字段需要设置json tag标记</p> <p>将struct转成map只会转换struct中可导出的字段。struct中导出字段需要设置json tag标记</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func StructToMap(value any) (map[string]any, error) func StructToMap(value any) (map[string]any, error)
``` ```
<b>列子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -456,22 +530,24 @@ func main() {
} }
pm, _ := convertor.StructToMap(p) pm, _ := convertor.StructToMap(p)
fmt.Printf("type: %T, value: %s", pm, pm) //type: map[string]interface {}, value: map[name:test] fmt.Println(pm)
// Output:
// map[name:test]
} }
``` ```
### <span id="MapToSlice">MapToSlice</span> ### <span id="MapToSlice">MapToSlice</span>
<p>map中key和value执行函数iteratee后转为切片</p> <p>map中key和value执行函数iteratee后转为切片</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T func MapToSlice[T any, K comparable, V any](aMap map[K]V, iteratee func(K, V) T) []T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -491,18 +567,17 @@ func main() {
} }
``` ```
### <span id="EncodeByte">EncodeByte</span> ### <span id="EncodeByte">EncodeByte</span>
<p>将data编码成字节切片</p> <p>将data编码成字节切片</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func EncodeByte(data any) ([]byte, error) func EncodeByte(data any) ([]byte, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -514,22 +589,24 @@ import (
func main() { func main() {
byteData, _ := convertor.EncodeByte("abc") byteData, _ := convertor.EncodeByte("abc")
fmt.Println(byteData) //[]byte{6, 12, 0, 3, 97, 98, 99} fmt.Println(byteData)
// Output:
// [6 12 0 3 97 98 99]
} }
``` ```
### <span id="DecodeByte">DecodeByte</span> ### <span id="DecodeByte">DecodeByte</span>
<p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p> <p>解码字节切片到目标对象,目标对象需要传入一个指针实例</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func DecodeByte(data []byte, target any) error func DecodeByte(data []byte, target any) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -542,7 +619,260 @@ import (
func main() { func main() {
var result string var result string
byteData := []byte{6, 12, 0, 3, 97, 98, 99} byteData := []byte{6, 12, 0, 3, 97, 98, 99}
convertor.DecodeByte(byteData, &result)
fmt.Println(result) //"abc" err := convertor.DecodeByte(byteData, &result)
if err != nil {
return
}
fmt.Println(result)
// Output:
// abc
}
```
### <span id="DeepClone">DeepClone</span>
<p>创建一个传入值的深拷贝, 无法克隆结构体的非导出字段。</p>
<b>函数签名:</b>
```go
func DeepClone[T any](src T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
type Struct struct {
Str string
Int int
Float float64
Bool bool
Nil interface{}
unexported string
}
cases := []interface{}{
true,
1,
0.1,
map[string]int{
"a": 1,
"b": 2,
},
&Struct{
Str: "test",
Int: 1,
Float: 0.1,
Bool: true,
Nil: nil,
// unexported: "can't be cloned",
},
}
for _, item := range cases {
cloned := convertor.DeepClone(item)
isPointerEqual := &cloned == &item
fmt.Println(cloned, isPointerEqual)
}
// Output:
// true false
// 1 false
// 0.1 false
// map[a:1 b:2] false
// &{test 1 0.1 true <nil> } false
}
```
### <span id="CopyProperties">CopyProperties</span>
<p>拷贝不同结构体之间的同名字段。使用json.Marshal序列化需要设置dst和src struct字段的json tag。</p>
<b>函数签名:</b>
```go
func CopyProperties[T, U any](dst T, src U) (err error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
type Disk struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type DiskVO struct {
Name string `json:"name"`
Total string `json:"total"`
Used string `json:"used"`
Percent float64 `json:"percent"`
}
type Indicator struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int `json:"cpu"`
Disk []Disk `json:"disk"`
Stop chan bool `json:"-"`
}
type IndicatorVO struct {
Id string `json:"id"`
Ip string `json:"ip"`
UpTime string `json:"upTime"`
LoadAvg string `json:"loadAvg"`
Cpu int64 `json:"cpu"`
Disk []DiskVO `json:"disk"`
}
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
}}
indicatorVO := IndicatorVO{}
err := convertor.CopyProperties(&indicatorVO, indicator)
if err != nil {
return
}
fmt.Println(indicatorVO.Id)
fmt.Println(indicatorVO.Ip)
fmt.Println(len(indicatorVO.Disk))
// Output:
// 001
// 127.0.0.1
// 3
}
```
### <span id="ToInterface">ToInterface</span>
<p>将反射值转换成对应的interface类型。</p>
<b>函数签名:</b>
```go
func ToInterface(v reflect.Value) (value interface{}, ok bool)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}
```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>utf8编码转GBK编码。</p>
<b>函数签名:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>GBK编码转utf8编码。</p>
<b>函数签名:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
} }
``` ```

View File

@@ -61,8 +61,6 @@ import (
## Documentation ## Documentation
### <span id="AesEcbEncrypt">AesEcbEncrypt</span> ### <span id="AesEcbEncrypt">AesEcbEncrypt</span>
<p>Encrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -83,16 +81,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesEcbDecrypt">AesEcbDecrypt</span> ### <span id="AesEcbDecrypt">AesEcbDecrypt</span>
<p>Decrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Decrypt data with key use AES ECB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -113,16 +114,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.AesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key)) decrypted := cryptor.AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCbcEncrypt">AesCbcEncrypt</span> ### <span id="AesCbcEncrypt">AesCbcEncrypt</span>
<p>Encrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -143,16 +147,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCbcDecrypt">AesCbcDecrypt</span> ### <span id="AesCbcDecrypt">AesCbcDecrypt</span>
<p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -174,16 +181,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key)) encrypted := cryptor.AesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key)) decrypted := cryptor.AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCtrCrypt">AesCtrCrypt</span> ### <span id="AesCtrCrypt">AesCtrCrypt</span>
<p>Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt or decrypt data with key use AES CTR algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -205,17 +215,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key)) encrypted := cryptor.AesCtrCrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key)) decrypted := cryptor.AesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCfbEncrypt">AesCfbEncrypt</span> ### <span id="AesCfbEncrypt">AesCfbEncrypt</span>
<p>Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Encrypt data with key use AES CFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -237,15 +249,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCfbDecrypt">AesCfbDecrypt</span> ### <span id="AesCfbDecrypt">AesCfbDecrypt</span>
<p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Decrypt data with key use AES CBC algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -267,16 +283,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.AesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key)) decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesOfbEncrypt">AesOfbEncrypt</span> ### <span id="AesOfbEncrypt">AesOfbEncrypt</span>
<p>Enecrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Enecrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -298,15 +317,18 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="AesCfbDecrypt">AesOfbDecrypt</span> ### <span id="AesCfbDecrypt">AesOfbDecrypt</span>
<p>Decrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p> <p>Decrypt data with key use AES OFB algorithm. Length of `key` param should be 16, 24 or 32.</p>
@@ -328,17 +350,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world encrypted := cryptor.AesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="Base64StdEncode">Base64StdEncode</span> ### <span id="Base64StdEncode">Base64StdEncode</span>
<p>Encode string with base64 encoding.</p> <p>Encode string with base64 encoding.</p>
@@ -359,13 +383,13 @@ import (
) )
func main() { func main() {
base64Str := cryptor.Base64StdEncode("hello world") base64Str := cryptor.Base64StdEncode("hello")
fmt.Println(base64Str) //aGVsbG8gd29ybGQ= fmt.Println(base64Str)
// Output:
// aGVsbG8=
} }
``` ```
### <span id="Base64StdDecode">Base64StdDecode</span> ### <span id="Base64StdDecode">Base64StdDecode</span>
<p>Decode a base64 encoded string.</p> <p>Decode a base64 encoded string.</p>
@@ -387,13 +411,14 @@ import (
) )
func main() { func main() {
str := cryptor.Base64StdDecode("aGVsbG8gd29ybGQ=") str := cryptor.Base64StdDecode("aGVsbG8=")
fmt.Println(str) //hello world fmt.Println(str)
// Output:
// hello
} }
``` ```
### <span id="DesEcbEncrypt">DesEcbEncrypt</span> ### <span id="DesEcbEncrypt">DesEcbEncrypt</span>
<p>Encrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p> <p>Encrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p>
@@ -415,16 +440,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesEcbDecrypt">DesEcbDecrypt</span> ### <span id="DesEcbDecrypt">DesEcbDecrypt</span>
<p>Decrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p> <p>Decrypt data with key use DES ECB algorithm. Length of `key` param should be 8.</p>
@@ -446,17 +474,20 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesEcbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key)) decrypted := cryptor.DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesCbcEncrypt">DesCbcEncrypt</span> ### <span id="DesCbcEncrypt">DesCbcEncrypt</span>
<p>Encrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p> <p>Encrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -478,16 +509,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
fmt.Println(string(encrypted)) encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesCbcDecrypt">DesCbcDecrypt</span> ### <span id="DesCbcDecrypt">DesCbcDecrypt</span>
<p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p> <p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -509,17 +543,18 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesCbcEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key)) decrypted := cryptor.DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesCtrCrypt">DesCtrCrypt</span> ### <span id="DesCtrCrypt">DesCtrCrypt</span>
<p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p> <p>Encrypt or decrypt data with key use DES CTR algorithm. Length of `key` param should be 8.</p>
@@ -541,17 +576,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key)) encrypted := cryptor.DesCtrCrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key)) decrypted := cryptor.DesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesCfbEncrypt">DesCfbEncrypt</span> ### <span id="DesCfbEncrypt">DesCfbEncrypt</span>
<p>Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.</p> <p>Encrypt data with key use DES CFB algorithm. Length of `key` param should be 8.</p>
@@ -573,15 +610,18 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
fmt.Println(string(encrypted)) encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesCfbDecrypt">DesCfbDecrypt</span> ### <span id="DesCfbDecrypt">DesCfbDecrypt</span>
<p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p> <p>Decrypt data with key use DES CBC algorithm. Length of `key` param should be 8.</p>
@@ -603,16 +643,18 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byt(key)
encrypted := cryptor.DesCfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key)) decrypted := cryptor.DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesOfbEncrypt">DesOfbEncrypt</span> ### <span id="DesOfbEncrypt">DesOfbEncrypt</span>
<p>Enecrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p> <p>Enecrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
@@ -634,15 +676,18 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
fmt.Println(string(encrypted)) decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="DesOfbDecrypt">DesOfbDecrypt</span> ### <span id="DesOfbDecrypt">DesOfbDecrypt</span>
<p>Decrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p> <p>Decrypt data with key use DES OFB algorithm. Length of `key` param should be 8.</p>
@@ -664,17 +709,19 @@ import (
) )
func main() { func main() {
data := "hello world" data := "hello"
key := "abcdefgh" key := "abcdefgh"
encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key)) encrypted := cryptor.DesOfbEncrypt([]byte(data), []byte(key))
decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key)) decrypted := cryptor.DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="HmacMd5">HmacMd5</span> ### <span id="HmacMd5">HmacMd5</span>
<p>Get the md5 hmac hash of string.</p> <p>Get the md5 hmac hash of string.</p>
@@ -696,13 +743,16 @@ import (
) )
func main() { func main() {
s := cryptor.HmacMd5("hello world", "12345")) str := "hello"
fmt.Println(s) //5f4c9faaff0a1ad3007d9ddc06abe36d key := "12345"
hms := cryptor.HmacMd5(str, key)
fmt.Println(hms)
// Output:
// e834306eab892d872525d4918a7a639a
} }
``` ```
### <span id="HmacSha1">HmacSha1</span> ### <span id="HmacSha1">HmacSha1</span>
<p>Get the sha1 hmac hash of string.</p> <p>Get the sha1 hmac hash of string.</p>
@@ -724,13 +774,16 @@ import (
) )
func main() { func main() {
s := cryptor.HmacSha1("hello world", "12345")) str := "hello"
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd key := "12345"
hms := cryptor.HmacSha1(str, key)
fmt.Println(hms)
// Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
} }
``` ```
### <span id="HmacSha256">HmacSha256</span> ### <span id="HmacSha256">HmacSha256</span>
<p>Get the sha256 hmac hash of string</p> <p>Get the sha256 hmac hash of string</p>
@@ -752,13 +805,17 @@ import (
) )
func main() { func main() {
s := cryptor.HmacSha256("hello world", "12345")) str := "hello"
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8 key := "12345"
hms := cryptor.HmacSha256(str, key)
fmt.Println(hms)
// Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
} }
``` ```
### <span id="HmacSha512">HmacSha512</span> ### <span id="HmacSha512">HmacSha512</span>
<p>Get the sha512 hmac hash of string.</p> <p>Get the sha512 hmac hash of string.</p>
@@ -780,14 +837,18 @@ import (
) )
func main() { func main() {
s := cryptor.HmacSha512("hello world", "12345")) str := "hello"
fmt.Println(s) key := "12345"
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
hms := cryptor.HmacSha512(str, key)
fmt.Println(hms)
// Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
} }
``` ```
### <span id="Md5String">Md5String</span> ### <span id="Md5String">Md5String</span>
<p>Get the md5 value of string.</p> <p>Get the md5 value of string.</p>
@@ -809,13 +870,16 @@ import (
) )
func main() { func main() {
s := cryptor.Md5String("hello")) str := "hello"
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
md5Str := cryptor.Md5String(str)
fmt.Println(md5Str)
// Output:
// 5d41402abc4b2a76b9719d911017c592
} }
``` ```
### <span id="Md5File">Md5File</span> ### <span id="Md5File">Md5File</span>
<p>Get the md5 value of file.</p> <p>Get the md5 value of file.</p>
@@ -842,8 +906,6 @@ func main() {
} }
``` ```
### <span id="Sha1">Sha1</span> ### <span id="Sha1">Sha1</span>
<p>Get the sha1 value of string.</p> <p>Get the sha1 value of string.</p>
@@ -865,13 +927,16 @@ import (
) )
func main() { func main() {
s := cryptor.Sha1("hello world")) str := "hello"
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
result := cryptor.Sha1(str)
fmt.Println(result)
// Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
} }
``` ```
### <span id="Sha256">Sha256</span> ### <span id="Sha256">Sha256</span>
<p>Get the sha256 value of string.</p> <p>Get the sha256 value of string.</p>
@@ -893,13 +958,16 @@ import (
) )
func main() { func main() {
s := cryptor.Sha256("hello world")) str := "hello"
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
result := cryptor.Sha256(str)
fmt.Println(result)
// Output:
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
} }
``` ```
### <span id="Sha512">Sha512</span> ### <span id="Sha512">Sha512</span>
<p>Get the sha512 value of string.</p> <p>Get the sha512 value of string.</p>
@@ -921,13 +989,16 @@ import (
) )
func main() { func main() {
s := cryptor.Sha512("hello world")) str := "hello"
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
result := cryptor.Sha512(str)
fmt.Println(result)
// Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
} }
``` ```
### <span id="GenerateRsaKey">GenerateRsaKey</span> ### <span id="GenerateRsaKey">GenerateRsaKey</span>
<p>Create the rsa public and private key file in current directory.</p> <p>Create the rsa public and private key file in current directory.</p>
@@ -956,8 +1027,6 @@ func main() {
} }
``` ```
### <span id="RsaEncrypt">RsaEncrypt</span> ### <span id="RsaEncrypt">RsaEncrypt</span>
<p>Encrypt data with public key file useing ras algorithm.</p> <p>Encrypt data with public key file useing ras algorithm.</p>
@@ -981,19 +1050,21 @@ import (
func main() { func main() {
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem") err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil { if err != nil {
fmt.Println(err) return
} }
data := []byte("hello world") 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)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```
### <span id="RsaDecrypt">RsaDecrypt</span> ### <span id="RsaDecrypt">RsaDecrypt</span>
<p>Decrypt data with private key file useing ras algorithm.</p> <p>Decrypt data with private key file useing ras algorithm.</p>
@@ -1017,14 +1088,17 @@ import (
func main() { func main() {
err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem") err := cryptor.GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil { if err != nil {
fmt.Println(err) return
} }
data := []byte("hello world") 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)) //hello world fmt.Println(string(decrypted))
// Output:
// hello
} }
``` ```

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,7 @@ import (
func NewHashMap() *HashMap func NewHashMap() *HashMap
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -72,7 +72,7 @@ func main() {
func NewHashMapWithCapacity(size, capacity uint64) *HashMap func NewHashMapWithCapacity(size, capacity uint64) *HashMap
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -98,7 +98,7 @@ func main() {
func (hm *HashMap) Get(key any) any func (hm *HashMap) Get(key any) any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -126,7 +126,7 @@ func main() {
func (hm *HashMap) Put(key any, value any) any func (hm *HashMap) Put(key any, value any) any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -155,7 +155,7 @@ func main() {
func (hm *HashMap) Delete(key any) func (hm *HashMap) Delete(key any)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -187,7 +187,7 @@ func main() {
func (hm *HashMap) Contains(key any) bool func (hm *HashMap) Contains(key any) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -217,7 +217,7 @@ func main() {
func (hm *HashMap) Iterate(iteratee func(key, value any)) func (hm *HashMap) Iterate(iteratee func(key, value any))
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -252,7 +252,7 @@ func main() {
func (hm *HashMap) Keys() []any func (hm *HashMap) Keys() []any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -284,7 +284,7 @@ func main() {
func (hm *HashMap) Values() []any func (hm *HashMap) Values() []any
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -48,7 +48,7 @@ type MaxHeap[T any] struct {
} }
func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T] func NewMaxHeap[T any](comparator lancetconstraints.Comparator) *MaxHeap[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -89,7 +89,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Push(value T) func (h *MaxHeap[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -136,7 +136,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Pop() (T, bool) func (h *MaxHeap[T]) Pop() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -184,7 +184,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Peek() (T, bool) func (h *MaxHeap[T]) Peek() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -232,7 +232,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Data() []T func (h *MaxHeap[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -277,7 +277,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) Size() int func (h *MaxHeap[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -323,7 +323,7 @@ func main() {
```go ```go
func (h *MaxHeap[T]) PrintStructure() func (h *MaxHeap[T]) PrintStructure()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -81,7 +81,7 @@ type SinglyLink[T any] struct {
} }
func NewSinglyLink[T any]() *SinglyLink[T] func NewSinglyLink[T any]() *SinglyLink[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -107,7 +107,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Values() []T func (link *SinglyLink[T]) Values() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -139,7 +139,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAt(index int, value T) func (link *SinglyLink[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -174,7 +174,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAtHead(value T) func (link *SinglyLink[T]) InsertAtHead(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -206,7 +206,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) InsertAtTail(value T) func (link *SinglyLink[T]) InsertAtTail(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -237,7 +237,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAt(index int) func (link *SinglyLink[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -271,7 +271,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAtHead() func (link *SinglyLink[T]) DeleteAtHead()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -306,7 +306,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteAtTail() func (link *SinglyLink[T]) DeleteAtTail()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -339,7 +339,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) DeleteValue(value T) func (link *SinglyLink[T]) DeleteValue(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -373,7 +373,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Reverse() func (link *SinglyLink[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -405,7 +405,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] func (link *SinglyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -437,7 +437,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Size() int func (link *SinglyLink[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -468,7 +468,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) IsEmpty() bool func (link *SinglyLink[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -500,7 +500,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Clear() func (link *SinglyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -533,7 +533,7 @@ func main() {
```go ```go
func (link *SinglyLink[T]) Clear() func (link *SinglyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -576,7 +576,7 @@ type DoublyLink[T any] struct {
} }
func NewDoublyLink[T any]() *DoublyLink[T] func NewDoublyLink[T any]() *DoublyLink[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -602,7 +602,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Values() []T func (link *DoublyLink[T]) Values() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -634,7 +634,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAt(index int, value T) func (link *DoublyLink[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -669,7 +669,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAtHead(value T) func (link *DoublyLink[T]) InsertAtHead(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -701,7 +701,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) InsertAtTail(value T) func (link *DoublyLink[T]) InsertAtTail(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -732,7 +732,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAt(index int) func (link *DoublyLink[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -766,7 +766,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAtHead() func (link *DoublyLink[T]) DeleteAtHead()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -801,7 +801,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) DeleteAtTail() func (link *DoublyLink[T]) DeleteAtTail()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -835,7 +835,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Reverse() func (link *DoublyLink[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -867,7 +867,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] func (link *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -899,7 +899,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Size() int func (link *DoublyLink[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -930,7 +930,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) IsEmpty() bool func (link *DoublyLink[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -962,7 +962,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Clear() func (link *DoublyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -995,7 +995,7 @@ func main() {
```go ```go
func (link *DoublyLink[T]) Clear() func (link *DoublyLink[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -47,6 +47,13 @@ import (
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList) - [SubList](#SubList)
- [DeleteIf](#DeleteIf) - [DeleteIf](#DeleteIf)
@@ -828,6 +835,233 @@ func main() {
### <span id="Difference">Difference</span>
<p>Return a list whose element in the original list, not in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) Difference(other *List[T]) *List[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3
}
```
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>Oppoiste operation of intersection function.</p>
<b>Signature:</b>
```go
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3, 4
}
```
### <span id="RetainAll">RetainAll</span>
<p>Retains only the elements in this list that are contained in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) RetainAll(list *List[T]) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
fmt.Println(list.Data()) //1, 2
fmt.Println(list1.Data()) //2, 3
fmt.Println(list2.Data()) //1, 2
}
```
### <span id="DeleteAll">DeleteAll</span>
<p>Removes from this list all of its elements that are contained in the given list.</p>
<b>Signature:</b>
```go
func (l *List[T]) DeleteAll(list *List[T]) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
fmt.Println(list.Data()) //2,3,4
fmt.Println(list1.Data()) //1,4
fmt.Println(list2.Data()) //3,4
}
```
### <span id="ForEach">ForEach</span>
<p>Performs the given action for each element of the list.</p>
<b>Signature:</b>
```go
func (l *List[T]) ForEach(consumer func(T))
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := make([]int, 0)
list.ForEach(func(i int) {
result = append(result, i)
})
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="Iterator">Iterator</span>
<p>Returns an iterator over the elements in this list in proper sequence.</p>
<b>Signature:</b>
```go
func (l *List[T]) Iterator() iterator.Iterator[T]
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
result := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
result = append(result, item)
}
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="ListToMap">ListToMap</span>
<p>Converts a list to a map based on iteratee function.</p>
<b>Signature:</b>
```go
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
fmt.Println(result) //map[int]bool{1: false, 2: true, 3: true, 4: true}
}
```
### <span id="SubList">SubList</span> ### <span id="SubList">SubList</span>
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p> <p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p>

View File

@@ -34,7 +34,6 @@ import (
- [PopLast](#PopLast) - [PopLast](#PopLast)
- [DeleteAt](#DeleteAt) - [DeleteAt](#DeleteAt)
- [InsertAt](#InsertAt) - [InsertAt](#InsertAt)
- [UpdateAt](#UpdateAt) - [UpdateAt](#UpdateAt)
- [Equal](#Equal) - [Equal](#Equal)
- [IsEmpty](#IsEmpty) - [IsEmpty](#IsEmpty)
@@ -48,6 +47,13 @@ import (
- [Unique](#Unique) - [Unique](#Unique)
- [Union](#Union) - [Union](#Union)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [Difference](#Difference)
- [SymmetricDifference](#SymmetricDifference)
- [RetainAll](#RetainAll)
- [DeleteAll](#DeleteAll)
- [ForEach](#ForEach)
- [Iterator](#Iterator)
- [ListToMap](#ListToMap)
- [SubList](#SubList) - [SubList](#SubList)
- [DeleteIf](#DeleteIf) - [DeleteIf](#DeleteIf)
@@ -66,7 +72,7 @@ type List[T any] struct {
} }
func NewList[T any](data []T) *List[T] func NewList[T any](data []T) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -92,7 +98,7 @@ func main() {
```go ```go
func (l *List[T]) Contain(value T) bool func (l *List[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -121,7 +127,7 @@ func main() {
```go ```go
func (l *List[T]) Data() []T func (l *List[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -150,7 +156,7 @@ func main() {
```go ```go
func (l *List[T]) ValueOf(index int) (*T, bool) func (l *List[T]) ValueOf(index int) (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -180,7 +186,7 @@ func main() {
```go ```go
func (l *List[T]) IndexOf(value T) int func (l *List[T]) IndexOf(value T) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -207,7 +213,7 @@ func main() {
```go ```go
func (l *List[T]) LastIndexOf(value T) int func (l *List[T]) LastIndexOf(value T) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -233,7 +239,7 @@ func main() {
```go ```go
func (l *List[T]) IndexOfFunc(f func(T) bool) int func (l *List[T]) IndexOfFunc(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -259,7 +265,7 @@ func main() {
```go ```go
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int func (l *List[T]) LastIndexOfFunc(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -287,7 +293,7 @@ func main() {
```go ```go
func (l *List[T]) Push(value T) func (l *List[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -316,7 +322,7 @@ func main() {
```go ```go
func (l *List[T]) PopFirst() (*T, bool) func (l *List[T]) PopFirst() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -348,7 +354,7 @@ func main() {
```go ```go
func (l *List[T]) PopLast() (*T, bool) func (l *List[T]) PopLast() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -379,7 +385,7 @@ func main() {
```go ```go
func (l *List[T]) DeleteAt(index int) func (l *List[T]) DeleteAt(index int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -417,7 +423,7 @@ func main() {
```go ```go
func (l *List[T]) InsertAt(index int, value T) func (l *List[T]) InsertAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -454,7 +460,7 @@ func main() {
```go ```go
func (l *List[T]) UpdateAt(index int, value T) func (l *List[T]) UpdateAt(index int, value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -487,7 +493,7 @@ func main() {
```go ```go
func (l *List[T]) Equal(other *List[T]) bool func (l *List[T]) Equal(other *List[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -517,7 +523,7 @@ func main() {
```go ```go
func (l *List[T]) IsEmpty() bool func (l *List[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -547,7 +553,7 @@ func main() {
```go ```go
func (l *List[T]) Clear() func (l *List[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -575,7 +581,7 @@ func main() {
```go ```go
func (l *List[T]) Clone() *List[T] func (l *List[T]) Clone() *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -604,7 +610,7 @@ func main() {
```go ```go
func (l *List[T]) Merge(other *List[T]) *List[T] func (l *List[T]) Merge(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -633,7 +639,7 @@ func main() {
```go ```go
func (l *List[T]) Size() int func (l *List[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -660,7 +666,7 @@ func main() {
```go ```go
func (l *List[T]) Cap() int func (l *List[T]) Cap() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -689,7 +695,7 @@ func main() {
```go ```go
func (l *List[T]) Swap(i, j int) func (l *List[T]) Swap(i, j int)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -718,7 +724,7 @@ func main() {
```go ```go
func (l *List[T]) Reverse() func (l *List[T]) Reverse()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -747,7 +753,7 @@ func main() {
```go ```go
func (l *List[T]) Unique() func (l *List[T]) Unique()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -776,7 +782,7 @@ func main() {
```go ```go
func (l *List[T]) Union(other *List[T]) *List[T] func (l *List[T]) Union(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -806,7 +812,7 @@ func main() {
```go ```go
func (l *List[T]) Intersection(other *List[T]) *List[T] func (l *List[T]) Intersection(other *List[T]) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -826,16 +832,244 @@ func main() {
``` ```
### <span id="Difference">Difference</span>
<p>差集运算。</p>
<b>函数签名:</b>
```go
func (l *List[T]) Difference(other *List[T]) *List[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3
}
```
### <span id="SymmetricDifference">SymmetricDifference</span>
<p>对称差集运算。</p>
<b>函数签名:</b>
```go
func (l *List[T]) SymmetricDifference(other *List[T]) *List[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list1 := NewList([]int{1, 2, 3})
list2 := NewList([]int{1, 2, 4})
list3 := list1.Intersection(list2)
fmt.Println(list3.Data()) //3, 4
}
```
### <span id="RetainAll">RetainAll</span>
<p>仅保留列表中包含在给定列表中的元素。</p>
<b>函数签名:</b>
```go
func (l *List[T]) RetainAll(list *List[T]) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
retain := NewList([]int{1, 2})
retain1 := NewList([]int{2, 3})
retain2 := NewList([]int{1, 2, 5})
list.RetainAll(retain)
list1.RetainAll(retain1)
list2.RetainAll(retain2)
fmt.Println(list.Data()) //1, 2
fmt.Println(list1.Data()) //2, 3
fmt.Println(list2.Data()) //1, 2
}
```
### <span id="DeleteAll">DeleteAll</span>
<p>从列表中删除给定列表中包含的所有元素。</p>
<b>函数签名:</b>
```go
func (l *List[T]) DeleteAll(list *List[T]) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
list1 := NewList([]int{1, 2, 3, 4})
list2 := NewList([]int{1, 2, 3, 4})
del := NewList([]int{1})
del1 := NewList([]int{2, 3})
del2 := NewList([]int{1, 2, 5})
list.DeleteAll(del)
list1.DeleteAll(del1)
list2.DeleteAll(del2)
fmt.Println(list.Data()) //2,3,4
fmt.Println(list1.Data()) //1,4
fmt.Println(list2.Data()) //3,4
}
```
### <span id="ForEach">ForEach</span>
<p>对列表的每个元素执行给定的操作。</p>
<b>函数签名:</b>
```go
func (l *List[T]) ForEach(consumer func(T))
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := make([]int, 0)
list.ForEach(func(i int) {
result = append(result, i)
})
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="Iterator">Iterator</span>
<p>按顺序返回列表中元素的迭代器。</p>
<b>函数签名:</b>
```go
func (l *List[T]) Iterator() iterator.Iterator[T]
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
result := make([]int, 0)
for iterator.HasNext() {
item, _ := iterator.Next()
result = append(result, item)
}
fmt.Println(result.Data()) //1,2,3,4
}
```
### <span id="ListToMap">ListToMap</span>
<p>基于iteratee函数将列表转换为映射map。</p>
<b>函数签名:</b>
```go
func ListToMap[T any, K comparable, V any](list *List[T], iteratee func(T) (K, V)) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
list "github.com/duke-git/lancet/v2/datastructure/list"
)
func main() {
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
fmt.Println(result) //map[int]bool{1: false, 2: true, 3: true, 4: true}
}
```
### <span id="SubList">SubList</span> ### <span id="SubList">SubList</span>
<p>SubList returns a sub list of the original list between the specified fromIndex, inclusive, and toIndex, exclusive.</p> <p>返回指定的fromIndex包含和toIndex不包含之间的原始列表的子列表。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func (l *List[T]) SubList(fromIndex, toIndex int) *List[T] func (l *List[T]) SubList(fromIndex, toIndex int) *List[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -863,7 +1097,7 @@ func main() {
```go ```go
func (l *List[T]) DeleteIf(f func(T) bool) int func (l *List[T]) DeleteIf(f func(T) bool) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -99,7 +99,7 @@ type ArrayQueue[T any] struct {
size int size int
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -125,7 +125,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Data() []T func (q *ArrayQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -152,7 +152,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Enqueue(item T) bool func (q *ArrayQueue[T]) Enqueue(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -183,7 +183,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Dequeue() (T, bool) func (q *ArrayQueue[T]) Dequeue() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -215,7 +215,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Front() T func (q *ArrayQueue[T]) Front() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -247,7 +247,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Back() T func (q *ArrayQueue[T]) Back() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -278,7 +278,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Size() int func (q *ArrayQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -308,7 +308,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) IsEmpty() bool func (q *ArrayQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -341,7 +341,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) IsFull() bool func (q *ArrayQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -373,7 +373,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Clear() func (q *ArrayQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -404,7 +404,7 @@ func main() {
```go ```go
func (q *ArrayQueue[T]) Contain(value T) bool func (q *ArrayQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -448,7 +448,7 @@ type QueueNode[T any] struct {
Next *QueueNode[T] Next *QueueNode[T]
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -474,7 +474,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Data() []T func (q *LinkedQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -501,7 +501,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Enqueue(value T) func (q *LinkedQueue[T]) Enqueue(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -532,7 +532,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Dequeue() (T, error) func (q *LinkedQueue[T]) Dequeue() (T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -564,7 +564,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Front() (*T, error) func (q *LinkedQueue[T]) Front() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -596,7 +596,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Back() (*T, error) func (q *LinkedQueue[T]) Back() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -627,7 +627,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Size() int func (q *LinkedQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -657,7 +657,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) IsEmpty() bool func (q *LinkedQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -690,7 +690,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Clear() func (q *LinkedQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -721,7 +721,7 @@ func main() {
```go ```go
func (q *LinkedQueue[T]) Contain(value T) bool func (q *LinkedQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -763,7 +763,7 @@ type CircularQueue[T any] struct {
capacity int capacity int
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -789,7 +789,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Data() []T func (q *CircularQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -816,7 +816,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Enqueue(value T) error func (q *CircularQueue[T]) Enqueue(value T) error
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -847,7 +847,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Dequeue() (*T, bool) func (q *CircularQueue[T]) Dequeue() (*T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -880,7 +880,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Front() T func (q *CircularQueue[T]) Front() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -912,7 +912,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Back() T func (q *CircularQueue[T]) Back() T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -943,7 +943,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Size() int func (q *CircularQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -973,7 +973,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) IsEmpty() bool func (q *CircularQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1006,7 +1006,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) IsFull() bool func (q *CircularQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1038,7 +1038,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Clear() func (q *CircularQueue[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1069,7 +1069,7 @@ func main() {
```go ```go
func (q *CircularQueue[T]) Contain(value T) bool func (q *CircularQueue[T]) Contain(value T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1108,7 +1108,7 @@ type PriorityQueue[T any] struct {
comparator lancetconstraints.Comparator comparator lancetconstraints.Comparator
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1134,7 +1134,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Data() []T func (q *PriorityQueue[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1161,7 +1161,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Enqueue(item T) bool func (q *PriorityQueue[T]) Enqueue(item T) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1207,7 +1207,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Dequeue() (T, bool) func (q *PriorityQueue[T]) Dequeue() (T, bool)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1254,7 +1254,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) IsEmpty() bool func (q *PriorityQueue[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1301,7 +1301,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) IsFull() bool func (q *PriorityQueue[T]) IsFull() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -1348,7 +1348,7 @@ func main() {
```go ```go
func (q *PriorityQueue[T]) Size() int func (q *PriorityQueue[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -1,4 +1,5 @@
# Set # Set
Set is a data container, like list, but elements of set is not duplicate. Set is a data container, like list, but elements of set is not duplicate.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Set is a data container, like list, but elements of set is not duplicate.
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go) - [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage ## Usage
```go ```go
import ( import (
set "github.com/duke-git/lancet/v2/datastructure/set" set "github.com/duke-git/lancet/v2/datastructure/set"
@@ -34,19 +35,19 @@ import (
- [Size](#Size) - [Size](#Size)
- [Equal](#Equal) - [Equal](#Equal)
- [Iterate](#Iterate) - [Iterate](#Iterate)
- [EachWithBreak](#EachWithBreak)
- [IsEmpty](#IsEmpty) - [IsEmpty](#IsEmpty)
- [Union](#Union) - [Union](#Union)
- [Intersection](#Intersection) - [Intersection](#Intersection)
- [SymmetricDifference](#SymmetricDifference) - [SymmetricDifference](#SymmetricDifference)
- [Minus](#Minus) - [Minus](#Minus)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="NewSet">NewSet</span> ### <span id="NewSet">NewSet</span>
<p>Create a set instance</p> <p>Create a set instance</p>
<b>Signature:</b> <b>Signature:</b>
@@ -55,6 +56,7 @@ import (
type Set[T comparable] map[T]bool type Set[T comparable] map[T]bool
func NewSet[T comparable](items ...T) Set[T] func NewSet[T comparable](items ...T) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -71,8 +73,8 @@ func main() {
} }
``` ```
### <span id="NewSetFromSlice">NewSetFromSlice</span> ### <span id="NewSetFromSlice">NewSetFromSlice</span>
<p>Create a set from slice</p> <p>Create a set from slice</p>
<b>Signature:</b> <b>Signature:</b>
@@ -80,6 +82,7 @@ func main() {
```go ```go
func NewSetFromSlice[T comparable](items []T) Set[T] func NewSetFromSlice[T comparable](items []T) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -96,9 +99,8 @@ func main() {
} }
``` ```
### <span id="Values">Values</span> ### <span id="Values">Values</span>
<p>Return slice of all set data</p> <p>Return slice of all set data</p>
<b>Signature:</b> <b>Signature:</b>
@@ -106,6 +108,7 @@ func main() {
```go ```go
func (s Set[T]) Values() []T func (s Set[T]) Values() []T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -122,10 +125,8 @@ func main() {
} }
``` ```
### <span id="Add">Add</span> ### <span id="Add">Add</span>
<p>Add items to set</p> <p>Add items to set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -133,6 +134,7 @@ func main() {
```go ```go
func (s Set[T]) Add(items ...T) func (s Set[T]) Add(items ...T)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -151,8 +153,8 @@ func main() {
} }
``` ```
### <span id="AddIfNotExist">AddIfNotExist</span> ### <span id="AddIfNotExist">AddIfNotExist</span>
<p>AddIfNotExist checks if item exists in the set, it adds the item to set and returns true if it does not exist in the set, or else it does nothing and returns false.</p> <p>AddIfNotExist checks if item exists in the set, it adds the item to set and returns true if it does not exist in the set, or else it does nothing and returns false.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -160,6 +162,7 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExist(item T) bool func (s Set[T]) AddIfNotExist(item T) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -183,8 +186,8 @@ func main() {
} }
``` ```
### <span id="AddIfNotExistBy">AddIfNotExistBy</span> ### <span id="AddIfNotExistBy">AddIfNotExistBy</span>
<p>AddIfNotExistBy checks if item exists in the set and pass the `checker` function it adds the item to set and returns true if it does not exists in the set and function `checker` returns true, or else it does nothing and returns false.</p> <p>AddIfNotExistBy checks if item exists in the set and pass the `checker` function it adds the item to set and returns true if it does not exists in the set and function `checker` returns true, or else it does nothing and returns false.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,6 +195,7 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -221,8 +225,8 @@ func main() {
} }
``` ```
### <span id="Delete">Delete</span> ### <span id="Delete">Delete</span>
<p>Delete item in set</p> <p>Delete item in set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -230,6 +234,7 @@ func main() {
```go ```go
func (s Set[T]) Delete(items ...T) func (s Set[T]) Delete(items ...T)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -249,9 +254,8 @@ func main() {
} }
``` ```
### <span id="Contain">Contain</span> ### <span id="Contain">Contain</span>
<p>Check if item is in set or not</p> <p>Check if item is in set or not</p>
<b>Signature:</b> <b>Signature:</b>
@@ -259,6 +263,7 @@ func main() {
```go ```go
func (s Set[T]) Contain(item T) bool func (s Set[T]) Contain(item T) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -278,10 +283,8 @@ func main() {
} }
``` ```
### <span id="ContainAll">ContainAll</span> ### <span id="ContainAll">ContainAll</span>
<p>Checks if set contains another set</p> <p>Checks if set contains another set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -289,6 +292,7 @@ func main() {
```go ```go
func (s Set[T]) ContainAll(other Set[T]) bool func (s Set[T]) ContainAll(other Set[T]) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -309,9 +313,8 @@ func main() {
} }
``` ```
### <span id="Size">Size</span> ### <span id="Size">Size</span>
<p>Get the number of elements in set</p> <p>Get the number of elements in set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -319,6 +322,7 @@ func main() {
```go ```go
func (s Set[T]) Size() int func (s Set[T]) Size() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -336,9 +340,8 @@ func main() {
} }
``` ```
### <span id="Clone">Clone</span> ### <span id="Clone">Clone</span>
<p>Make a copy of set</p> <p>Make a copy of set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -346,6 +349,7 @@ func main() {
```go ```go
func (s Set[T]) Clone() Set[T] func (s Set[T]) Clone() Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -365,10 +369,8 @@ func main() {
} }
``` ```
### <span id="Equal">Equal</span> ### <span id="Equal">Equal</span>
<p>Check if two sets has same elements or not</p> <p>Check if two sets has same elements or not</p>
<b>Signature:</b> <b>Signature:</b>
@@ -376,6 +378,7 @@ func main() {
```go ```go
func (s Set[T]) Equal(other Set[T]) bool func (s Set[T]) Equal(other Set[T]) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -396,9 +399,8 @@ func main() {
} }
``` ```
### <span id="Iterate">Iterate</span> ### <span id="Iterate">Iterate</span>
<p>Call function by every element of set</p> <p>Call function by every element of set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -406,6 +408,7 @@ func main() {
```go ```go
func (s Set[T]) Iterate(fn func(item T)) func (s Set[T]) Iterate(fn func(item T))
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -427,9 +430,45 @@ func main() {
} }
``` ```
### <span id="EachWithBreak">EachWithBreak</span>
<p>Iterates over elements of a set and invokes function for each element, when iteratee return false, will break the for each loop.</p>
<b>Signature:</b>
```go
func (s Set[T]) EachWithBreak(iteratee func(item T) bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
set "github.com/duke-git/lancet/v2/datastructure/set"
)
func main() {
s := set.NewSet(1, 2, 3, 4, 5)
var sum int
s.EachWithBreak(func(n int) bool {
if n > 3 {
return false
}
sum += n
return true
})
fmt.Println(sum) //6
}
```
### <span id="IsEmpty">IsEmpty</span> ### <span id="IsEmpty">IsEmpty</span>
<p>Check if the set is empty or not</p> <p>Check if the set is empty or not</p>
<b>Signature:</b> <b>Signature:</b>
@@ -437,6 +476,7 @@ func main() {
```go ```go
func (s Set[T]) IsEmpty() bool func (s Set[T]) IsEmpty() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -456,9 +496,8 @@ func main() {
} }
``` ```
### <span id="Union">Union</span> ### <span id="Union">Union</span>
<p>Create a new set contain all element of set s and other</p> <p>Create a new set contain all element of set s and other</p>
<b>Signature:</b> <b>Signature:</b>
@@ -466,6 +505,7 @@ func main() {
```go ```go
func (s Set[T]) Union(other Set[T]) Set[T] func (s Set[T]) Union(other Set[T]) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -485,9 +525,8 @@ func main() {
} }
``` ```
### <span id="Intersection">Intersection</span> ### <span id="Intersection">Intersection</span>
<p>Create a new set whose element both be contained in set s and other</p> <p>Create a new set whose element both be contained in set s and other</p>
<b>Signature:</b> <b>Signature:</b>
@@ -495,6 +534,7 @@ func main() {
```go ```go
func (s Set[T]) Intersection(other Set[T]) Set[T] func (s Set[T]) Intersection(other Set[T]) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -514,11 +554,8 @@ func main() {
} }
``` ```
### <span id="SymmetricDifference">SymmetricDifference</span> ### <span id="SymmetricDifference">SymmetricDifference</span>
<p>Create a new set whose element is in set1 or set2, but not in both set1 and set2</p> <p>Create a new set whose element is in set1 or set2, but not in both set1 and set2</p>
<b>Signature:</b> <b>Signature:</b>
@@ -526,6 +563,7 @@ func main() {
```go ```go
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -545,11 +583,8 @@ func main() {
} }
``` ```
### <span id="Minus">Minus</span> ### <span id="Minus">Minus</span>
<p>Create an set of whose element in origin set but not in compared set</p> <p>Create an set of whose element in origin set but not in compared set</p>
<b>Signature:</b> <b>Signature:</b>
@@ -557,6 +592,7 @@ func main() {
```go ```go
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -580,5 +616,35 @@ func main() {
} }
``` ```
### <span id="Pop">Pop</span>
<p>Delete the top element of set then return it, if set is empty, return nil-value of T and false.</p>
<b>Signature:</b>
```go
func (s Set[T]) Pop() (v T, ok bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
set "github.com/duke-git/lancet/v2/datastructure/set"
)
func main() {
s := set.NewSet[int]()
s.Add(1)
s.Add(2)
s.Add(3)
val, ok = s.Pop()
fmt.Println(val) // 3
fmt.Println(ok) // true
}
```

View File

@@ -1,4 +1,5 @@
# Set # Set
Set 集合数据结构类似列表。Set 中元素不重复。 Set 集合数据结构类似列表。Set 中元素不重复。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Set集合数据结构类似列表。Set中元素不重复。
- [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go) - [https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go](https://github.com/duke-git/lancet/blob/main/datastructure/set/set.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法 ## 用法
```go ```go
import ( import (
set "github.com/duke-git/lancet/v2/datastructure/set" set "github.com/duke-git/lancet/v2/datastructure/set"
@@ -40,13 +41,12 @@ import (
- [SymmetricDifference](#SymmetricDifference) - [SymmetricDifference](#SymmetricDifference)
- [Minus](#Minus) - [Minus](#Minus)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="NewSet">NewSet</span> ### <span id="NewSet">NewSet</span>
<p>返回Set结构体对象</p> <p>返回Set结构体对象</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -55,7 +55,8 @@ import (
type Set[T comparable] map[T]bool type Set[T comparable] map[T]bool
func NewSet[T comparable](items ...T) Set[T] func NewSet[T comparable](items ...T) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -71,9 +72,8 @@ func main() {
} }
``` ```
### <span id="NewSetFromSlice">NewSetFromSlice</span> ### <span id="NewSetFromSlice">NewSetFromSlice</span>
<p>基于切片创建集合</p> <p>基于切片创建集合</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -81,7 +81,8 @@ func main() {
```go ```go
func NewSetFromSlice[T comparable](items []T) Set[T] func NewSetFromSlice[T comparable](items []T) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -97,9 +98,8 @@ func main() {
} }
``` ```
### <span id="Values">Values</span> ### <span id="Values">Values</span>
<p>获取集合中所有元素的切片</p> <p>获取集合中所有元素的切片</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -107,7 +107,8 @@ func main() {
```go ```go
func (s Set[T]) Values() []T func (s Set[T]) Values() []T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -123,10 +124,8 @@ func main() {
} }
``` ```
### <span id="Add">Add</span> ### <span id="Add">Add</span>
<p>向集合中添加元素</p> <p>向集合中添加元素</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -134,7 +133,8 @@ func main() {
```go ```go
func (s Set[T]) Add(items ...T) func (s Set[T]) Add(items ...T)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -152,8 +152,8 @@ func main() {
} }
``` ```
### <span id="AddIfNotExist">AddIfNotExist</span> ### <span id="AddIfNotExist">AddIfNotExist</span>
<p>如果集合中不存在元素则添加该元素返回true, 如果集合中存在元素, 不做任何操作返回false</p> <p>如果集合中不存在元素则添加该元素返回true, 如果集合中存在元素, 不做任何操作返回false</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -161,7 +161,8 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExist(item T) bool func (s Set[T]) AddIfNotExist(item T) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -184,8 +185,8 @@ func main() {
} }
``` ```
### <span id="AddIfNotExistBy">AddIfNotExistBy</span> ### <span id="AddIfNotExistBy">AddIfNotExistBy</span>
<p>根据checker函数判断元素是否在集合中如果集合中不存在元素且checker返回true则添加该元素返回true, 否则不做任何操作返回false</p> <p>根据checker函数判断元素是否在集合中如果集合中不存在元素且checker返回true则添加该元素返回true, 否则不做任何操作返回false</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -193,7 +194,8 @@ func main() {
```go ```go
func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool func (s Set[T]) AddIfNotExistBy(item T, checker func(element T) bool) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -222,9 +224,8 @@ func main() {
} }
``` ```
### <span id="Delete">Delete</span> ### <span id="Delete">Delete</span>
<p>删除集合中元素</p> <p>删除集合中元素</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -232,7 +233,8 @@ func main() {
```go ```go
func (s Set[T]) Delete(items ...T) func (s Set[T]) Delete(items ...T)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -251,9 +253,8 @@ func main() {
} }
``` ```
### <span id="Contain">Contain</span> ### <span id="Contain">Contain</span>
<p>判断集合是否包含某个值</p> <p>判断集合是否包含某个值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -261,7 +262,8 @@ func main() {
```go ```go
func (s Set[T]) Contain(item T) bool func (s Set[T]) Contain(item T) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -280,10 +282,8 @@ func main() {
} }
``` ```
### <span id="ContainAll">ContainAll</span> ### <span id="ContainAll">ContainAll</span>
<p>判断集合是否包含另一个集合</p> <p>判断集合是否包含另一个集合</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -291,7 +291,8 @@ func main() {
```go ```go
func (s Set[T]) ContainAll(other Set[T]) bool func (s Set[T]) ContainAll(other Set[T]) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -311,9 +312,8 @@ func main() {
} }
``` ```
### <span id="Size">Size</span> ### <span id="Size">Size</span>
<p>获取集合中元素的个数</p> <p>获取集合中元素的个数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -321,7 +321,8 @@ func main() {
```go ```go
func (s Set[T]) Size() int func (s Set[T]) Size() int
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -338,9 +339,8 @@ func main() {
} }
``` ```
### <span id="Clone">Clone</span> ### <span id="Clone">Clone</span>
<p>克隆一个集合</p> <p>克隆一个集合</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -348,7 +348,8 @@ func main() {
```go ```go
func (s Set[T]) Clone() Set[T] func (s Set[T]) Clone() Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -367,10 +368,8 @@ func main() {
} }
``` ```
### <span id="Equal">Equal</span> ### <span id="Equal">Equal</span>
<p>比较两个集合是否相等,包含相同元素为相等</p> <p>比较两个集合是否相等,包含相同元素为相等</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -378,7 +377,8 @@ func main() {
```go ```go
func (s Set[T]) Equal(other Set[T]) bool func (s Set[T]) Equal(other Set[T]) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -398,9 +398,8 @@ func main() {
} }
``` ```
### <span id="Iterate">Iterate</span> ### <span id="Iterate">Iterate</span>
<p>迭代结合,在每个元素上调用函数</p> <p>迭代结合,在每个元素上调用函数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -408,7 +407,8 @@ func main() {
```go ```go
func (s Set[T]) Iterate(fn func(item T)) func (s Set[T]) Iterate(fn func(item T))
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -429,9 +429,45 @@ func main() {
} }
``` ```
### <span id="EachWithBreak">EachWithBreak</span>
<p>遍历集合的元素并为每个元素调用iteratee函数当iteratee函数返回false时终止遍历。</p>
<b>函数签名:</b>
```go
func (s Set[T]) EachWithBreak(iteratee func(item T) bool)
```
<b>示例:</b>
```go
package main
import (
"fmt"
set "github.com/duke-git/lancet/v2/datastructure/set"
)
func main() {
s := set.NewSet(1, 2, 3, 4, 5)
var sum int
s.EachWithBreak(func(n int) bool {
if n > 3 {
return false
}
sum += n
return true
})
fmt.Println(sum) //6
}
```
### <span id="IsEmpty">IsEmpty</span> ### <span id="IsEmpty">IsEmpty</span>
<p>判断集合是否为空</p> <p>判断集合是否为空</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -439,7 +475,8 @@ func main() {
```go ```go
func (s Set[T]) IsEmpty() bool func (s Set[T]) IsEmpty() bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -458,9 +495,8 @@ func main() {
} }
``` ```
### <span id="Union">Union</span> ### <span id="Union">Union</span>
<p>求两个集合的并集</p> <p>求两个集合的并集</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -468,7 +504,8 @@ func main() {
```go ```go
func (s Set[T]) Union(other Set[T]) Set[T] func (s Set[T]) Union(other Set[T]) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -487,9 +524,8 @@ func main() {
} }
``` ```
### <span id="Intersection">Intersection</span> ### <span id="Intersection">Intersection</span>
<p>求两个集合的交集</p> <p>求两个集合的交集</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -497,7 +533,8 @@ func main() {
```go ```go
func (s Set[T]) Intersection(other Set[T]) Set[T] func (s Set[T]) Intersection(other Set[T]) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -516,8 +553,8 @@ func main() {
} }
``` ```
### <span id="SymmetricDifference">SymmetricDifference</span> ### <span id="SymmetricDifference">SymmetricDifference</span>
<p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p> <p>返回一个集合,其中元素在第一个集合或第二个集合中,且不同时存在于两个集合中</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -525,7 +562,8 @@ func main() {
```go ```go
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] func (s Set[T]) SymmetricDifference(other Set[T]) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -544,11 +582,8 @@ func main() {
} }
``` ```
### <span id="Minus">Minus</span> ### <span id="Minus">Minus</span>
<p>创建一个集合,其元素在原始集中但不在比较集中</p> <p>创建一个集合,其元素在原始集中但不在比较集中</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -556,7 +591,8 @@ func main() {
```go ```go
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] func (s Set[T]) Minus(comparedSet Set[T]) Set[T]
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -579,5 +615,35 @@ func main() {
} }
``` ```
### <span id="Pop">Pop</span>
<p>删除并返回集合中的顶部元素</p>
<b>函数签名:</b>
```go
func (s Set[T]) Pop() (v T, ok bool)
```
<b>示例:</b>
```go
package main
import (
"fmt"
set "github.com/duke-git/lancet/v2/datastructure/set"
)
func main() {
s := set.NewSet[int]()
s.Add(1)
s.Add(2)
s.Add(3)
val, ok = s.Pop()
fmt.Println(val) // 3
fmt.Println(ok) // true
}
```

View File

@@ -64,7 +64,7 @@ type ArrayStack[T any] struct {
} }
func NewArrayStack[T any]() *ArrayStack[T] func NewArrayStack[T any]() *ArrayStack[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -91,7 +91,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Push(value T) func (s *ArrayStack[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -122,7 +122,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Pop() (*T, error) func (s *ArrayStack[T]) Pop() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -157,7 +157,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Peak() (*T, error) func (s *ArrayStack[T]) Peak() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -192,7 +192,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Data() []T func (s *ArrayStack[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -223,7 +223,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Size() int func (s *ArrayStack[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -254,7 +254,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) IsEmpty() bool func (s *ArrayStack[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -287,7 +287,7 @@ func main() {
```go ```go
func (s *ArrayStack[T]) Clear() func (s *ArrayStack[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -331,7 +331,7 @@ type LinkedStack[T any] struct {
} }
func NewLinkedStack[T any]() *LinkedStack[T] func NewLinkedStack[T any]() *LinkedStack[T]
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -358,7 +358,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Push(value T) func (s *LinkedStack[T]) Push(value T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -389,7 +389,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Pop() (*T, error) func (s *LinkedStack[T]) Pop() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -424,7 +424,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Peak() (*T, error) func (s *LinkedStack[T]) Peak() (*T, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -459,7 +459,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Data() []T func (s *LinkedStack[T]) Data() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -490,7 +490,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Size() int func (s *LinkedStack[T]) Size() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -521,7 +521,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) IsEmpty() bool func (s *LinkedStack[T]) IsEmpty() bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -554,7 +554,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Clear() func (s *LinkedStack[T]) Clear()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -588,7 +588,7 @@ func main() {
```go ```go
func (s *LinkedStack[T]) Print() func (s *LinkedStack[T]) Print()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

View File

@@ -62,7 +62,7 @@ type TreeNode[T any] struct {
Right *TreeNode[T] Right *TreeNode[T]
} }
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -103,7 +103,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Insert(data T) func (t *BSTree[T]) Insert(data T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -149,7 +149,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Delete(data T) func (t *BSTree[T]) Delete(data T)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -197,7 +197,7 @@ func main() {
```go ```go
func (t *BSTree[T]) PreOrderTraverse() []T func (t *BSTree[T]) PreOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -243,7 +243,7 @@ func main() {
```go ```go
func (t *BSTree[T]) InOrderTraverse() []T func (t *BSTree[T]) InOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -289,7 +289,7 @@ func main() {
```go ```go
func (t *BSTree[T]) PostOrderTraverse() []T func (t *BSTree[T]) PostOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -335,7 +335,7 @@ func main() {
```go ```go
func (t *BSTree[T]) LevelOrderTraverse() []T func (t *BSTree[T]) LevelOrderTraverse() []T
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -381,7 +381,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Depth() int func (t *BSTree[T]) Depth() int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -427,7 +427,7 @@ func main() {
```go ```go
func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool func (t *BSTree[T]) HasSubTree(subTree *BSTree[T]) bool
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -479,7 +479,7 @@ func main() {
```go ```go
func (t *BSTree[T]) Print() func (t *BSTree[T]) Print()
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
# Fileutil # Fileutil
Package fileutil implements some basic functions for file operations. Package fileutil implements some basic functions for file operations.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ Package fileutil implements some basic functions for file operations.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/fileutil" "github.com/duke-git/lancet/v2/fileutil"
@@ -19,10 +21,12 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [ClearFile](#ClearFile) - [ClearFile](#ClearFile)
- [CreateFile](#CreateFile) - [CreateFile](#CreateFile)
- [CreateDir](#CreateDir) - [CreateDir](#CreateDir)
- [CopyFile](#CopyFile) - [CopyFile](#CopyFile)
- [CurrentPath](#CurrentPath)
- [FileMode](#FileMode) - [FileMode](#FileMode)
- [MiMeType](#MiMeType) - [MiMeType](#MiMeType)
- [IsExist](#IsExist) - [IsExist](#IsExist)
@@ -33,16 +37,23 @@ import (
- [ReadFileToString](#ReadFileToString) - [ReadFileToString](#ReadFileToString)
- [ReadFileByLine](#ReadFileByLine) - [ReadFileByLine](#ReadFileByLine)
- [Zip](#Zip) - [Zip](#Zip)
- [ZipAppendEntry](#ZipAppendEntry)
- [UnZip](#UnZip) - [UnZip](#UnZip)
- [UnZip](#UnZip) - [IsZipFile](#IsZipFile)
- [FileSize](#FileSize)
- [MTime](#MTime)
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="ClearFile">ClearFile</span> ### <span id="ClearFile">ClearFile</span>
<p>Clear the file content, write empty string to the file.</p> <p>Clear the file content, write empty string to the file.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -50,6 +61,7 @@ import (
```go ```go
func ClearFile(path string) error func ClearFile(path string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -69,6 +81,7 @@ func main() {
``` ```
### <span id="CreateFile">CreateFile</span> ### <span id="CreateFile">CreateFile</span>
<p>Create file in path. return true if create succeed.</p> <p>Create file in path. return true if create succeed.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -76,6 +89,7 @@ func main() {
```go ```go
func CreateFile(path string) bool func CreateFile(path string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -92,9 +106,8 @@ func main() {
} }
``` ```
### <span id="CreateDir">CreateDir</span> ### <span id="CreateDir">CreateDir</span>
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p> <p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -102,6 +115,7 @@ func main() {
```go ```go
func CreateDir(absPath string) error func CreateDir(absPath string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -118,15 +132,16 @@ func main() {
} }
``` ```
### <span id="CopyFile">CopyFile</span> ### <span id="CopyFile">CopyFile</span>
<p>Copy src file to dest file. If dest file exist will overwrite it.</p> <p>Copy src file to dest file. If dest file exist will overwrite it.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func CopyFile(srcFilePath string, dstFilePath string) error func CopyFile(srcPath string, dstPath string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -145,9 +160,34 @@ func main() {
} }
``` ```
### <span id="CurrentPath">CurrentPath</span>
<p>return current absolute path.</p>
<b>Signature:</b>
```go
func CurrentPath() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
absPath := CurrentPath()
fmt.Println(absPath)
}
```
### <span id="FileMode">FileMode</span> ### <span id="FileMode">FileMode</span>
<p>Return file mode infomation.</p> <p>Return file mode infomation.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -155,6 +195,7 @@ func main() {
```go ```go
func FileMode(path string) (fs.FileMode, error) func FileMode(path string) (fs.FileMode, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -174,9 +215,8 @@ func main() {
} }
``` ```
### <span id="MiMeType">MiMeType</span> ### <span id="MiMeType">MiMeType</span>
<p>Get file mime type, 'file' param's type should be string or *os.File.</p> <p>Get file mime type, 'file' param's type should be string or *os.File.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -184,6 +224,7 @@ func main() {
```go ```go
func MiMeType(file any) string func MiMeType(file any) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -205,10 +246,8 @@ func main() {
} }
``` ```
### <span id="IsExist">IsExist</span> ### <span id="IsExist">IsExist</span>
<p>Checks if a file or directory exists.</p> <p>Checks if a file or directory exists.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -216,6 +255,7 @@ func main() {
```go ```go
func IsExist(path string) bool func IsExist(path string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -233,9 +273,8 @@ func main() {
} }
``` ```
### <span id="IsLink">IsLink</span> ### <span id="IsLink">IsLink</span>
<p>Checks if a file is symbol link or not.</p> <p>Checks if a file is symbol link or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -243,6 +282,7 @@ func main() {
```go ```go
func IsLink(path string) bool func IsLink(path string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -259,9 +299,8 @@ func main() {
} }
``` ```
### <span id="IsDir">IsDir</span> ### <span id="IsDir">IsDir</span>
<p>Checks if the path is directy or not.</p> <p>Checks if the path is directy or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -269,6 +308,7 @@ func main() {
```go ```go
func IsDir(path string) bool func IsDir(path string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -288,9 +328,8 @@ func main() {
} }
``` ```
### <span id="ListFileNames">ListFileNames</span> ### <span id="ListFileNames">ListFileNames</span>
<p>List all file names in given path.</p> <p>List all file names in given path.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -298,6 +337,7 @@ func main() {
```go ```go
func ListFileNames(path string) ([]string, error) func ListFileNames(path string) ([]string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -314,9 +354,8 @@ func main() {
} }
``` ```
### <span id="RemoveFile">RemoveFile</span> ### <span id="RemoveFile">RemoveFile</span>
<p>Remove the file of path.</p> <p>Remove the file of path.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -324,6 +363,7 @@ func main() {
```go ```go
func RemoveFile(path string) error func RemoveFile(path string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -342,8 +382,8 @@ func main() {
} }
``` ```
### <span id="ReadFileToString">ReadFileToString</span> ### <span id="ReadFileToString">ReadFileToString</span>
<p>Return string of file content.</p> <p>Return string of file content.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -351,6 +391,7 @@ func main() {
```go ```go
func ReadFileToString(path string) (string, error) func ReadFileToString(path string) (string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -374,9 +415,8 @@ func main() {
} }
``` ```
### <span id="ReadFileByLine">ReadFileByLine</span> ### <span id="ReadFileByLine">ReadFileByLine</span>
<p>Read file line by line, and return slice of lines</p> <p>Read file line by line, and return slice of lines</p>
<b>Signature:</b> <b>Signature:</b>
@@ -384,6 +424,7 @@ func main() {
```go ```go
func ReadFileByLine(path string)([]string, error) func ReadFileByLine(path string)([]string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -408,9 +449,8 @@ func main() {
} }
``` ```
### <span id="Zip">Zip</span> ### <span id="Zip">Zip</span>
<p>Create a zip file of fpath, fpath could be a file or a directory.</p> <p>Create a zip file of fpath, fpath could be a file or a directory.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -418,6 +458,7 @@ func main() {
```go ```go
func Zip(fpath string, destPath string) error func Zip(fpath string, destPath string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -436,10 +477,36 @@ func main() {
} }
``` ```
### <span id="ZipAppendEntry">ZipAppendEntry</span>
<p>Append a single file or directory by fpath to an existing zip file.</p>
<b>Signature:</b>
```go
func ZipAppendEntry(fpath string, destPath string) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
if err != nil {
fmt.Println(err)
}
}
```
### <span id="UnZip">UnZip</span> ### <span id="UnZip">UnZip</span>
<p>Unzip the file and save it to dest path.</p> <p>Unzip the file and save it to dest path.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -447,6 +514,7 @@ func main() {
```go ```go
func UnZip(zipFile string, destPath string) error func UnZip(zipFile string, destPath string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -465,7 +533,297 @@ func main() {
} }
``` ```
### <span id="IsZipFile">IsZipFile</span>
<p>Checks if file is zip file or not.</p>
<b>Signature:</b>
```go
func IsZipFile(filepath string) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
isZip := fileutil.IsZipFile("./zipfile.zip")
fmt.Println(isZip)
}
```
### <span id="FileSize">FileSize</span>
<p>Returns file size in bytes.</p>
<b>Signature:</b>
```go
func FileSize(path string) (int64, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
size, err := fileutil.FileSize("./testdata/test.txt")
fmt.Println(size)
fmt.Println(err)
// Output:
// 20
// <nil>
}
```
### <span id="MTime">MTime</span>
<p>Returns file modified time(unix timestamp).</p>
<b>Signature:</b>
```go
func MTime(filepath string) (int64, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
mtime, err := fileutil.MTime("./testdata/test.txt")
fmt.Println(mtime)
fmt.Println(err)
// Output:
// 1682391110
// <nil>
}
```
### <span id="Sha">Sha</span>
<p>returns file sha value, param `shaType` should be 1, 256 or 512.</p>
<b>Signature:</b>
```go
func Sha(filepath string, shaType ...int) (string, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
sha1, err := fileutil.Sha("./testdata/test.txt", 1)
sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
sha512, _ := fileutil.Sha("./testdata/test.txt", 512)
fmt.Println(sha1)
fmt.Println(sha256)
fmt.Println(sha512)
fmt.Println(err)
// Output:
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
// <nil>
}
```
### <span id="ReadCsvFile">ReadCsvFile</span>
<p>Reads file content into slice.</p>
<b>Signature:</b>
```go
func ReadCsvFile(filepath string) ([][]string, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
content, err := fileutil.ReadCsvFile("./testdata/test.csv")
fmt.Println(content)
fmt.Println(err)
// Output:
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
// <nil>
}
```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>Write content to target csv file.</p>
<b>Signature:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span>
<p>Writes bytes to target file.</p>
<b>Signature:</b>
```go
func WriteBytesToFile(filepath string, content []byte) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```
### <span id="WriteStringToFile">WriteStringToFile</span>
<p>Writes string to target file.</p>
<b>Signature:</b>
```go
func WriteStringToFile(filepath string, content string, append bool) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```

View File

@@ -1,4 +1,5 @@
# Fileutil # Fileutil
fileutil 包支持文件基本操作。 fileutil 包支持文件基本操作。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ fileutil包支持文件基本操作。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/fileutil" "github.com/duke-git/lancet/v2/fileutil"
@@ -19,10 +21,12 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [ClearFile](#ClearFile) - [ClearFile](#ClearFile)
- [CreateFile](#CreateFile) - [CreateFile](#CreateFile)
- [CreateDir](#CreateDir) - [CreateDir](#CreateDir)
- [CopyFile](#CopyFile) - [CopyFile](#CopyFile)
- [CurrentPath](#CurrentPath)
- [FileMode](#FileMode) - [FileMode](#FileMode)
- [MiMeType](#MiMeType) - [MiMeType](#MiMeType)
- [IsExist](#IsExist) - [IsExist](#IsExist)
@@ -33,15 +37,23 @@ import (
- [ReadFileToString](#ReadFileToString) - [ReadFileToString](#ReadFileToString)
- [ReadFileByLine](#ReadFileByLine) - [ReadFileByLine](#ReadFileByLine)
- [Zip](#Zip) - [Zip](#Zip)
- [ZipAppendEntry](#ZipAppendEntry)
- [UnZip](#UnZip) - [UnZip](#UnZip)
- [IsZipFile](#IsZipFile)
- [FileSize](#FileSize)
- [MTime](#MTime)
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="ClearFile">ClearFile</span> ### <span id="ClearFile">ClearFile</span>
<p>清空文件内容</p> <p>清空文件内容</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -49,7 +61,8 @@ import (
```go ```go
func ClearFile(path string) error func ClearFile(path string) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -68,6 +81,7 @@ func main() {
``` ```
### <span id="CreateFile">CreateFile</span> ### <span id="CreateFile">CreateFile</span>
<p>创建文件创建成功返回true, 否则返回false</p> <p>创建文件创建成功返回true, 否则返回false</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -75,7 +89,8 @@ func main() {
```go ```go
func CreateFile(path string) bool func CreateFile(path string) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -91,8 +106,8 @@ func main() {
} }
``` ```
### <span id="CreateDir">CreateDir</span> ### <span id="CreateDir">CreateDir</span>
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p> <p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -100,7 +115,8 @@ func main() {
```go ```go
func CreateDir(absPath string) error func CreateDir(absPath string) error
``` ```
<b>Example:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -116,17 +132,17 @@ func main() {
} }
``` ```
### <span id="CopyFile">CopyFile</span> ### <span id="CopyFile">CopyFile</span>
<p>拷贝文件,会覆盖原有的文件</p> <p>拷贝文件,会覆盖原有的文件</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func CopyFile(srcFilePath string, dstFilePath string) error func CopyFile(srcPath string, dstPath string) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -144,9 +160,34 @@ func main() {
} }
``` ```
### <span id="CurrentPath">CurrentPath</span>
<p>返回当前位置的绝对路径。</p>
<b>函数签名:</b>
```go
func CurrentPath() string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
absPath := CurrentPath()
fmt.Println(absPath)
}
```
### <span id="FileMode">FileMode</span> ### <span id="FileMode">FileMode</span>
<p>获取文件mode信息</p> <p>获取文件mode信息</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -154,7 +195,8 @@ func main() {
```go ```go
func FileMode(path string) (fs.FileMode, error) func FileMode(path string) (fs.FileMode, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -173,9 +215,8 @@ func main() {
} }
``` ```
### <span id="MiMeType">MiMeType</span> ### <span id="MiMeType">MiMeType</span>
<p>获取文件mime类型, 'file'参数的类型必须是string或者*os.File</p> <p>获取文件mime类型, 'file'参数的类型必须是string或者*os.File</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -183,7 +224,8 @@ func main() {
```go ```go
func MiMeType(file any) string func MiMeType(file any) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -204,10 +246,8 @@ func main() {
} }
``` ```
### <span id="IsExist">IsExist</span> ### <span id="IsExist">IsExist</span>
<p>判断文件或目录是否存在</p> <p>判断文件或目录是否存在</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -215,7 +255,8 @@ func main() {
```go ```go
func IsExist(path string) bool func IsExist(path string) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -232,9 +273,8 @@ func main() {
} }
``` ```
### <span id="IsLink">IsLink</span> ### <span id="IsLink">IsLink</span>
<p>判断文件是否是符号链接</p> <p>判断文件是否是符号链接</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -242,7 +282,8 @@ func main() {
```go ```go
func IsLink(path string) bool func IsLink(path string) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -258,9 +299,8 @@ func main() {
} }
``` ```
### <span id="IsDir">IsDir</span> ### <span id="IsDir">IsDir</span>
<p>判断参数是否是目录</p> <p>判断参数是否是目录</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -268,7 +308,8 @@ func main() {
```go ```go
func IsDir(path string) bool func IsDir(path string) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -287,9 +328,8 @@ func main() {
} }
``` ```
### <span id="ListFileNames">ListFileNames</span> ### <span id="ListFileNames">ListFileNames</span>
<p>返回目录下所有文件名</p> <p>返回目录下所有文件名</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -297,7 +337,8 @@ func main() {
```go ```go
func ListFileNames(path string) ([]string, error) func ListFileNames(path string) ([]string, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -313,9 +354,8 @@ func main() {
} }
``` ```
### <span id="RemoveFile">RemoveFile</span> ### <span id="RemoveFile">RemoveFile</span>
<p>删除文件</p> <p>删除文件</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -323,7 +363,8 @@ func main() {
```go ```go
func RemoveFile(path string) error func RemoveFile(path string) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -341,8 +382,8 @@ func main() {
} }
``` ```
### <span id="ReadFileToString">ReadFileToString</span> ### <span id="ReadFileToString">ReadFileToString</span>
<p>读取文件内容并返回字符串</p> <p>读取文件内容并返回字符串</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -350,7 +391,8 @@ func main() {
```go ```go
func ReadFileToString(path string) (string, error) func ReadFileToString(path string) (string, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -373,9 +415,8 @@ func main() {
} }
``` ```
### <span id="ReadFileByLine">ReadFileByLine</span> ### <span id="ReadFileByLine">ReadFileByLine</span>
<p>按行读取文件内容,返回字符串切片包含每一行</p> <p>按行读取文件内容,返回字符串切片包含每一行</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -383,7 +424,8 @@ func main() {
```go ```go
func ReadFileByLine(path string)([]string, error) func ReadFileByLine(path string)([]string, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -407,9 +449,8 @@ func main() {
} }
``` ```
### <span id="Zip">Zip</span> ### <span id="Zip">Zip</span>
<p>zip压缩文件, fpath参数可以是文件或目录</p> <p>zip压缩文件, fpath参数可以是文件或目录</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -417,7 +458,8 @@ func main() {
```go ```go
func Zip(fpath string, destPath string) error func Zip(fpath string, destPath string) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -435,18 +477,45 @@ func main() {
} }
``` ```
### <span id="ZipAppendEntry">ZipAppendEntry</span>
<p>通过将单个文件或目录追加到现有的zip文件</p>
<b>函数签名:</b>
```go
func ZipAppendEntry(fpath string, destPath string) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
if err != nil {
fmt.Println(err)
}
}
```
### <span id="UnZip">UnZip</span> ### <span id="UnZip">UnZip</span>
<p>zip解压缩文件并保存在目录中</p> <p>zip解压缩文件并保存在目录中</p>
<b>Signature:</b> <b>函数签名:</b>
```go ```go
func UnZip(zipFile string, destPath string) error func UnZip(zipFile string, destPath string) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -464,7 +533,297 @@ func main() {
} }
``` ```
### <span id="IsZipFile">IsZipFile</span>
<p>判断文件是否是zip压缩文件。</p>
<b>函数签名:</b>
```go
func IsZipFile(filepath string) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
isZip := fileutil.IsZipFile("./zipfile.zip")
fmt.Println(isZip)
}
```
### <span id="FileSize">FileSize</span>
<p>返回文件字节大小。</p>
<b>函数签名:</b>
```go
func FileSize(path string) (int64, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
size, err := fileutil.FileSize("./testdata/test.txt")
fmt.Println(size)
fmt.Println(err)
// Output:
// 20
// <nil>
}
```
### <span id="MTime">MTime</span>
<p>返回文件修改时间(unix timestamp).</p>
<b>函数签名:</b>
```go
func MTime(filepath string) (int64, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
mtime, err := fileutil.MTime("./testdata/test.txt")
fmt.Println(mtime)
fmt.Println(err)
// Output:
// 1682391110
// <nil>
}
```
### <span id="Sha">Sha</span>
<p>返回文件sha值参数`shaType` 应传值为: 1, 256512.</p>
<b>函数签名:</b>
```go
func Sha(filepath string, shaType ...int) (string, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
sha1, err := fileutil.Sha("./testdata/test.txt", 1)
sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
sha512, _ := fileutil.Sha("./testdata/test.txt", 512)
fmt.Println(sha1)
fmt.Println(sha256)
fmt.Println(sha512)
fmt.Println(err)
// Output:
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
// <nil>
}
```
### <span id="ReadCsvFile">ReadCsvFile</span>
<p>读取csv文件内容到切片</p>
<b>函数签名:</b>
```go
func ReadCsvFile(filepath string) ([][]string, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
content, err := fileutil.ReadCsvFile("./testdata/test.csv")
fmt.Println(content)
fmt.Println(err)
// Output:
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
// <nil>
}
```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>向csv文件写入内容。</p>
<b>函数签名:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span>
<p>将bytes写入文件。</p>
<b>函数签名:</b>
```go
func WriteBytesToFile(filepath string, content []byte) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```
### <span id="WriteStringToFile">WriteStringToFile</span>
<p>将字符串写入文件。</p>
<b>函数签名:</b>
```go
func WriteStringToFile(filepath string, content string, append bool) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```

View File

@@ -1,4 +1,5 @@
# Formatter # Formatter
formatter contains some functions for data formatting. formatter contains some functions for data formatting.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -6,10 +7,12 @@ formatter contains some functions for data formatting.
## Source: ## Source:
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go) - [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
- [https://github.com/duke-git/lancet/blob/main/formatter/byte.go](https://github.com/duke-git/lancet/blob/main/formatter/byte.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/formatter" "github.com/duke-git/lancet/v2/formatter"
@@ -19,15 +22,21 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Comma](#Comma) - [Comma](#Comma)
- [Pretty](#Pretty)
- [PrettyToWriter](#PrettyToWriter)
- [DecimalBytes](#DecimalBytes)
- [BinaryBytes](#BinaryBytes)
- [ParseDecimalBytes](#ParseDecimalBytes)
- [ParseBinaryBytes](#ParseBinaryBytes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Comma">Comma</span> ### <span id="Comma">Comma</span>
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p> <p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -35,6 +44,7 @@ import (
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -46,7 +56,255 @@ import (
) )
func main() { func main() {
fmt.Println(formatter.Comma("12345", "")) // "12,345" result1 := formatter.Comma("123", "")
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67" result2 := formatter.Comma("12345", "$")
result3 := formatter.Comma(1234567, "¥")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 123
// $12,345
// ¥1,234,567
}
```
### <span id="Pretty">Pretty</span>
<p>Pretty data to JSON string.</p>
<b>Signature:</b>
```go
func Pretty(v any) (string, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
result2, _ := formatter.Pretty(map[string]int{"a": 1})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [
// "a",
// "b",
// "c"
// ]
// {
// "a": 1
// }
}
```
### <span id="PrettyToWriter">PrettyToWriter</span>
<p>Pretty encode data to writer.</p>
<b>Signature:</b>
```go
func PrettyToWriter(v any, out io.Writer) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
type User struct {
Name string `json:"name"`
Aage uint `json:"age"`
}
user := User{Name: "King", Aage: 10000}
buf := &bytes.Buffer{}
err := formatter.PrettyToWriter(user, buf)
fmt.Println(buf)
fmt.Println(err)
// Output:
// {
// "name": "King",
// "age": 10000
// }
//
// <nil>
}
```
### <span id="DecimalBytes">DecimalBytes</span>
<p>Returns a human readable byte size under decimal standard (base 1000). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
<b>Signature:</b>
```go
func DecimalBytes(size float64, precision ...int) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1 := formatter.DecimalBytes(1000)
result2 := formatter.DecimalBytes(1024)
result3 := formatter.DecimalBytes(1234567)
result4 := formatter.DecimalBytes(1234567, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 1KB
// 1.024KB
// 1.2346MB
// 1.235MB
}
```
### <span id="BinaryBytes">BinaryBytes</span>
<p>Returns a human readable byte size under binary standard (base 1024). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
<b>Signature:</b>
```go
func BinaryBytes(size float64, precision ...int) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1 := formatter.BinaryBytes(1024)
result2 := formatter.BinaryBytes(1024 * 1024)
result3 := formatter.BinaryBytes(1234567)
result4 := formatter.BinaryBytes(1234567, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 1KiB
// 1MiB
// 1.1774MiB
// 1.18MiB
}
```
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
<p>Returns the human readable bytes size string into the amount it represents(base 1000).</p>
<b>Signature:</b>
```go
func ParseDecimalBytes(size string) (uint64, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.ParseDecimalBytes("12")
result2, _ := formatter.ParseDecimalBytes("12k")
result3, _ := formatter.ParseDecimalBytes("12 Kb")
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 12
// 12000
// 12000
// 12200
}
```
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
<p>Returns the human readable bytes size string into the amount it represents(base 1024).</p>
<b>Signature:</b>
```go
func ParseBinaryBytes(size string) (uint64, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.ParseBinaryBytes("12")
result2, _ := formatter.ParseBinaryBytes("12ki")
result3, _ := formatter.ParseBinaryBytes("12 KiB")
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 12
// 12288
// 12288
// 12492
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Formatter # Formatter
formatter 格式化器包含一些数据格式化处理方法。 formatter 格式化器包含一些数据格式化处理方法。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -6,10 +7,12 @@ formatter格式化器包含一些数据格式化处理方法。
## 源码: ## 源码:
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go) - [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
- [https://github.com/duke-git/lancet/blob/main/formatter/byte.go](https://github.com/duke-git/lancet/blob/main/formatter/byte.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/formatter" "github.com/duke-git/lancet/v2/formatter"
@@ -19,15 +22,21 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Comma](#Comma) - [Comma](#Comma)
- [Pretty](#Pretty)
- [PrettyToWriter](#PrettyToWriter)
- [DecimalBytes](#DecimalBytes)
- [BinaryBytes](#BinaryBytes)
- [ParseDecimalBytes](#ParseDecimalBytes)
- [ParseBinaryBytes](#ParseBinaryBytes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="Comma">Comma</span> ### <span id="Comma">Comma</span>
<p>用逗号每隔3位分割数字/字符串支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p> <p>用逗号每隔3位分割数字/字符串支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -35,7 +44,8 @@ import (
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -46,7 +56,255 @@ import (
) )
func main() { func main() {
fmt.Println(formatter.Comma("12345", "")) // "12,345" result1 := formatter.Comma("123", "")
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67" result2 := formatter.Comma("12345", "$")
result3 := formatter.Comma(1234567, "¥")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 123
// $12,345
// ¥1,234,567
}
```
### <span id="Pretty">Pretty</span>
<p>返回pretty JSON字符串.</p>
<b>函数签名:</b>
```go
func Pretty(v any) (string, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
result2, _ := formatter.Pretty(map[string]int{"a": 1})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [
// "a",
// "b",
// "c"
// ]
// {
// "a": 1
// }
}
```
### <span id="PrettyToWriter">PrettyToWriter</span>
<p>Pretty encode数据到writer。</p>
<b>函数签名:</b>
```go
func PrettyToWriter(v any, out io.Writer) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
type User struct {
Name string `json:"name"`
Aage uint `json:"age"`
}
user := User{Name: "King", Aage: 10000}
buf := &bytes.Buffer{}
err := formatter.PrettyToWriter(user, buf)
fmt.Println(buf)
fmt.Println(err)
// Output:
// {
// "name": "King",
// "age": 10000
// }
//
// <nil>
}
```
### <span id="DecimalBytes">DecimalBytes</span>
<p>返回十进制标准以1000为基数下的可读字节单位字符串。precision参数指定小数点后的位数默认为4。</p>
<b>函数签名:</b>
```go
func DecimalBytes(size float64, precision ...int) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1 := formatter.DecimalBytes(1000)
result2 := formatter.DecimalBytes(1024)
result3 := formatter.DecimalBytes(1234567)
result4 := formatter.DecimalBytes(1234567, 3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 1KB
// 1.024KB
// 1.2346MB
// 1.235MB
}
```
### <span id="BinaryBytes">BinaryBytes</span>
<p>返回binary标准以1024为基数下的可读字节单位字符串。precision参数指定小数点后的位数默认为4。</p>
<b>函数签名:</b>
```go
func BinaryBytes(size float64, precision ...int) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1 := formatter.BinaryBytes(1024)
result2 := formatter.BinaryBytes(1024 * 1024)
result3 := formatter.BinaryBytes(1234567)
result4 := formatter.BinaryBytes(1234567, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 1KiB
// 1MiB
// 1.1774MiB
// 1.18MiB
}
```
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
<p>将字节单位字符串转换成其所表示的字节数以1000为基数。</p>
<b>函数签名:</b>
```go
func ParseDecimalBytes(size string) (uint64, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.ParseDecimalBytes("12")
result2, _ := formatter.ParseDecimalBytes("12k")
result3, _ := formatter.ParseDecimalBytes("12 Kb")
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 12
// 12000
// 12000
// 12200
}
```
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
<p>将字节单位字符串转换成其所表示的字节数以1024为基数。</p>
<b>函数签名:</b>
```go
func ParseBinaryBytes(size string) (uint64, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/formatter"
)
func main() {
result1, _ := formatter.ParseBinaryBytes("12")
result2, _ := formatter.ParseBinaryBytes("12ki")
result3, _ := formatter.ParseBinaryBytes("12 KiB")
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 12
// 12288
// 12288
// 12492
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Function # Function
Package function can control the flow of function execution and support part of functional programming. Package function can control the flow of function execution and support part of functional programming.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ Package function can control the flow of function execution and support part of
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/function" "github.com/duke-git/lancet/v2/function"
@@ -20,12 +22,14 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [After](#After) - [After](#After)
- [Before](#Before) - [Before](#Before)
- [CurryFn](#CurryFn) - [CurryFn](#CurryFn)
- [Compose](#Compose) - [Compose](#Compose)
- [Debounced](#Debounced) - [Debounced](#Debounced)
- [Delay](#Delay) - [Delay](#Delay)
- [Schedule](#Schedule)
- [Pipeline](#Pipeline) - [Pipeline](#Pipeline)
- [Watcher](#Watcher) - [Watcher](#Watcher)
@@ -33,9 +37,8 @@ import (
## Documentation ## Documentation
### <span id="After">After</span> ### <span id="After">After</span>
<p>Creates a function that invokes given func once it's called n or more times.</p> <p>Creates a function that invokes given func once it's called n or more times.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -43,6 +46,7 @@ import (
```go ```go
func After(n int, fn any) func(args ...any) []reflect.Value func After(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -54,33 +58,18 @@ import (
) )
func main() { func main() {
arr := []string{"a", "b"} fn := function.After(2, func() {
f := function.After(len(arr), func(i int) int { fmt.Println("hello")
fmt.Println("last print")
return i
}) })
type cb func(args ...any) []reflect.Value fn()
print := func(i int, s string, fn cb) { fn()
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
}
fmt.Println("arr is", arr) // Output:
for i := 0; i < len(arr); i++ { // hello
print(i, arr[i], f)
}
//output:
// arr is [a b]
// arr[0] is a
// arr[1] is b
// last print
} }
``` ```
### <span id="Before">Before</span> ### <span id="Before">Before</span>
<p>creates a function that invokes func once it's called less than n times.</p> <p>creates a function that invokes func once it's called less than n times.</p>
@@ -90,6 +79,7 @@ func main() {
```go ```go
func Before(n int, fn any) func(args ...any) []reflect.Value func Before(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -102,29 +92,21 @@ import (
) )
func main() { func main() {
arr := []string{"a", "b", "c", "d", "e"} fn := function.Before(2, func() {
f := function.Before(3, func(i int) int { fmt.Println("hello")
return i
}) })
var res []int64 fn()
type cb func(args ...any) []reflect.Value fn()
appendStr := func(i int, s string, fn cb) { fn()
v := fn(i) fn()
res = append(res, v[0].Int())
}
for i := 0; i < len(arr); i++ { // Output:
appendStr(i, arr[i], f) // hello
} // hello
expected := []int64{0, 1, 2, 2, 2}
fmt.Println(res) // 0, 1, 2, 2, 2
} }
``` ```
### <span id="CurryFn">CurryFn</span> ### <span id="CurryFn">CurryFn</span>
<p>Make curry function.</p> <p>Make curry function.</p>
@@ -135,6 +117,7 @@ func main() {
type CurryFn[T any] func(...T) T type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T func (cf CurryFn[T]) New(val T) func(...T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -150,19 +133,20 @@ func main() {
return a + b return a + b
} }
var addCurry CurryFn[int] = func(values ...int) int { var addCurry function.CurryFn[int] = func(values ...int) int {
return add(values[0], values[1]) return add(values[0], values[1])
} }
add1 := addCurry.New(1) add1 := addCurry.New(1)
result := add1(2) result := add1(2)
fmt.Println(result) //3 fmt.Println(result)
// Output:
// 3
} }
``` ```
### <span id="Compose">Compose</span> ### <span id="Compose">Compose</span>
<p>Compose the function list from right to left, then return the composed function.</p> <p>Compose the function list from right to left, then return the composed function.</p>
@@ -172,6 +156,7 @@ func main() {
```go ```go
func Compose[T any](fnList ...func(...T) T) func(...T) T func Compose[T any](fnList ...func(...T) T) func(...T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -189,16 +174,17 @@ func main() {
toLower := func(strs ...string) string { toLower := func(strs ...string) string {
return strings.ToLower(strs[0]) return strings.ToLower(strs[0])
} }
transform := Compose(toUpper, toLower) transform := function.Compose(toUpper, toLower)
result := transform("aBCde") result := transform("aBCde")
fmt.Println(result) //ABCDE fmt.Println(result)
// Output:
// ABCDE
} }
``` ```
### <span id="Debounced">Debounced</span> ### <span id="Debounced">Debounced</span>
<p>Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.</p> <p>Creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.</p>
@@ -208,6 +194,7 @@ func main() {
```go ```go
func Debounced(fn func(), duration time.Duration) func() func Debounced(fn func(), duration time.Duration) func()
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -220,27 +207,34 @@ import (
func main() { func main() {
count := 0 count := 0
add := func() { add := func() {
count++ count++
} }
debouncedAdd := function.Debounced(add, 50*time.Microsecond) debouncedAdd := function.Debounced(add, 50*time.Microsecond)
function.debouncedAdd()
function.debouncedAdd() debouncedAdd()
function.debouncedAdd() debouncedAdd()
function.debouncedAdd() debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
fmt.Println(count) //1
function.debouncedAdd() fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
fmt.Println(count) //2
fmt.Println(count)
// Output:
// 1
// 2
} }
``` ```
### <span id="Delay">Delay</span> ### <span id="Delay">Delay</span>
<p>Invoke function after delayed time.</p> <p>Invoke function after delayed time.</p>
@@ -250,6 +244,7 @@ func main() {
```go ```go
func Delay(delay time.Duration, fn any, args ...any) func Delay(delay time.Duration, fn any, args ...any)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -262,14 +257,16 @@ import (
func main() { func main() {
var print = func(s string) { var print = func(s string) {
fmt.Println(count) //delay 2 seconds fmt.Println(s)
} }
function.Delay(2*time.Second, print, "delay 2 seconds")
function.Delay(2*time.Second, print, "hello")
// Output:
// hello
} }
``` ```
### <span id="Schedule">Schedule</span> ### <span id="Schedule">Schedule</span>
<p>Invoke function every duration time, until close the returned bool chan.</p> <p>Invoke function every duration time, until close the returned bool chan.</p>
@@ -279,6 +276,7 @@ func main() {
```go ```go
func Schedule(d time.Duration, fn any, args ...any) chan bool func Schedule(d time.Duration, fn any, args ...any) chan bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -290,20 +288,24 @@ import (
) )
func main() { func main() {
var res []string count := 0
appendStr := func(s string) {
res = append(res, s) increase := func() {
count++
} }
stop := function.Schedule(1*time.Second, appendStr, "*") stop := function.Schedule(2*time.Second, increase)
time.Sleep(5 * time.Second)
time.Sleep(2 * time.Second)
close(stop) close(stop)
fmt.Println(res) //[* * * * *] fmt.Println(count)
// Output:
// 2
} }
``` ```
### <span id="Pipeline">Pipeline</span> ### <span id="Pipeline">Pipeline</span>
<p>Pipeline takes a list of functions and returns a function whose param will be passed into <p>Pipeline takes a list of functions and returns a function whose param will be passed into
@@ -314,6 +316,7 @@ the functions one by one.</p>
```go ```go
func Pipeline[T any](funcs ...func(T) T) func(T) T func Pipeline[T any](funcs ...func(T) T) func(T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -335,13 +338,17 @@ func main() {
return x * x return x * x
} }
fn := Pipeline(addOne, double, square) fn := function.Pipeline(addOne, double, square)
fmt.Println(fn(2)) //36 result := fn(2)
fmt.Println(result)
// Output:
// 36
} }
``` ```
### <span id="Watcher">Watcher</span> ### <span id="Watcher">Watcher</span>
<p>Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.</p> <p>Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.</p>
@@ -360,6 +367,7 @@ func (w *Watcher) Stop() //stop the watcher
func (w *Watcher) Reset() //reset the watcher func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -396,6 +404,3 @@ func longRunningTask() {
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Function # Function
function 函数包控制函数执行流程,包含部分函数式编程。 function 函数包控制函数执行流程,包含部分函数式编程。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -11,6 +12,7 @@ function函数包控制函数执行流程包含部分函数式编程。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/function" "github.com/duke-git/lancet/v2/function"
@@ -20,12 +22,14 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [After](#After) - [After](#After)
- [Before](#Before) - [Before](#Before)
- [CurryFn](#CurryFn) - [CurryFn](#CurryFn)
- [Compose](#Compose) - [Compose](#Compose)
- [Debounced](#Debounced) - [Debounced](#Debounced)
- [Delay](#Delay) - [Delay](#Delay)
- [Schedule](#Schedule)
- [Pipeline](#Pipeline) - [Pipeline](#Pipeline)
- [Watcher](#Watcher) - [Watcher](#Watcher)
@@ -33,9 +37,8 @@ import (
## 文档 ## 文档
### <span id="After">After</span> ### <span id="After">After</span>
<p>创建一个函数当他被调用n或更多次之后将马上触发fn</p> <p>创建一个函数当他被调用n或更多次之后将马上触发fn</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -43,7 +46,8 @@ import (
```go ```go
func After(n int, fn any) func(args ...any) []reflect.Value func After(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -54,33 +58,18 @@ import (
) )
func main() { func main() {
arr := []string{"a", "b"} fn := function.After(2, func() {
f := function.After(len(arr), func(i int) int { fmt.Println("hello")
fmt.Println("last print")
return i
}) })
type cb func(args ...any) []reflect.Value fn()
print := func(i int, s string, fn cb) { fn()
fmt.Printf("arr[%d] is %s \n", i, s)
fn(i)
}
fmt.Println("arr is", arr) // Output:
for i := 0; i < len(arr); i++ { // hello
print(i, arr[i], f)
}
//output:
// arr is [a b]
// arr[0] is a
// arr[1] is b
// last print
} }
``` ```
### <span id="Before">Before</span> ### <span id="Before">Before</span>
<p>创建一个函数调用次数不超过n次之后再调用这个函数将返回一次最后调用fn的结果</p> <p>创建一个函数调用次数不超过n次之后再调用这个函数将返回一次最后调用fn的结果</p>
@@ -90,7 +79,8 @@ func main() {
```go ```go
func Before(n int, fn any) func(args ...any) []reflect.Value func Before(n int, fn any) func(args ...any) []reflect.Value
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -102,28 +92,21 @@ import (
) )
func main() { func main() {
arr := []string{"a", "b", "c", "d", "e"} fn := function.Before(2, func() {
f := function.Before(3, func(i int) int { fmt.Println("hello")
return i
}) })
var res []int64 fn()
type cb func(args ...any) []reflect.Value fn()
appendStr := func(i int, s string, fn cb) { fn()
v := fn(i) fn()
res = append(res, v[0].Int())
}
for i := 0; i < len(arr); i++ { // Output:
appendStr(i, arr[i], f) // hello
} // hello
fmt.Println(res) // 0, 1, 2, 2, 2
} }
``` ```
### <span id="CurryFn">CurryFn</span> ### <span id="CurryFn">CurryFn</span>
<p>创建柯里化函数</p> <p>创建柯里化函数</p>
@@ -134,7 +117,8 @@ func main() {
type CurryFn[T any] func(...T) T type CurryFn[T any] func(...T) T
func (cf CurryFn[T]) New(val T) func(...T) T func (cf CurryFn[T]) New(val T) func(...T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -149,19 +133,20 @@ func main() {
return a + b return a + b
} }
var addCurry CurryFn[int] = func(values ...int) int { var addCurry function.CurryFn[int] = func(values ...int) int {
return add(values[0], values[1]) return add(values[0], values[1])
} }
add1 := addCurry.New(1) add1 := addCurry.New(1)
result := add1(2) result := add1(2)
fmt.Println(result) //3 fmt.Println(result)
// Output:
// 3
} }
``` ```
### <span id="Compose">Compose</span> ### <span id="Compose">Compose</span>
<p>从右至左组合函数列表fnList返回组合后的函数</p> <p>从右至左组合函数列表fnList返回组合后的函数</p>
@@ -171,7 +156,8 @@ func main() {
```go ```go
func Compose[T any](fnList ...func(...T) T) func(...T) T func Compose[T any](fnList ...func(...T) T) func(...T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -188,16 +174,17 @@ func main() {
toLower := func(strs ...string) string { toLower := func(strs ...string) string {
return strings.ToLower(strs[0]) return strings.ToLower(strs[0])
} }
transform := Compose(toUpper, toLower) transform := function.Compose(toUpper, toLower)
result := transform("aBCde") result := transform("aBCde")
fmt.Println(result) //ABCDE fmt.Println(result)
// Output:
// ABCDE
} }
``` ```
### <span id="Debounced">Debounced</span> ### <span id="Debounced">Debounced</span>
<p>创建一个debounced函数该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。</p> <p>创建一个debounced函数该函数延迟调用fn直到自上次调用debounced函数后等待持续时间过去。</p>
@@ -207,7 +194,8 @@ func main() {
```go ```go
func Debounced(fn func(), duration time.Duration) func() func Debounced(fn func(), duration time.Duration) func()
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -219,27 +207,34 @@ import (
func main() { func main() {
count := 0 count := 0
add := func() { add := func() {
count++ count++
} }
debouncedAdd := function.Debounced(add, 50*time.Microsecond) debouncedAdd := function.Debounced(add, 50*time.Microsecond)
function.debouncedAdd()
function.debouncedAdd() debouncedAdd()
function.debouncedAdd() debouncedAdd()
function.debouncedAdd() debouncedAdd()
debouncedAdd()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
fmt.Println(count) //1
function.debouncedAdd() fmt.Println(count)
debouncedAdd()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
fmt.Println(count) //2
fmt.Println(count)
// Output:
// 1
// 2
} }
``` ```
### <span id="Delay">Delay</span> ### <span id="Delay">Delay</span>
<p>延迟delay时间后调用函数</p> <p>延迟delay时间后调用函数</p>
@@ -249,7 +244,8 @@ func main() {
```go ```go
func Delay(delay time.Duration, fn any, args ...any) func Delay(delay time.Duration, fn any, args ...any)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -261,14 +257,16 @@ import (
func main() { func main() {
var print = func(s string) { var print = func(s string) {
fmt.Println(count) //test delay fmt.Println(s)
} }
function.Delay(2*time.Second, print, "test delay")
function.Delay(2*time.Second, print, "hello")
// Output:
// hello
} }
``` ```
### <span id="Schedule">Schedule</span> ### <span id="Schedule">Schedule</span>
<p>每次持续时间调用函数,直到关闭返回的 bool chan</p> <p>每次持续时间调用函数,直到关闭返回的 bool chan</p>
@@ -278,7 +276,8 @@ func main() {
```go ```go
func Schedule(d time.Duration, fn any, args ...any) chan bool func Schedule(d time.Duration, fn any, args ...any) chan bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -289,21 +288,24 @@ import (
) )
func main() { func main() {
var res []string count := 0
appendStr := func(s string) {
res = append(res, s) increase := func() {
count++
} }
stop := function.Schedule(1*time.Second, appendStr, "*") stop := function.Schedule(2*time.Second, increase)
time.Sleep(5 * time.Second)
time.Sleep(2 * time.Second)
close(stop) close(stop)
fmt.Println(res) //[* * * * *] fmt.Println(count)
// Output:
// 2
} }
``` ```
### <span id="Pipeline">Pipeline</span> ### <span id="Pipeline">Pipeline</span>
<p>执行函数pipeline.</p> <p>执行函数pipeline.</p>
@@ -313,7 +315,8 @@ func main() {
```go ```go
func Pipeline[T any](funcs ...func(T) T) func(T) T func Pipeline[T any](funcs ...func(T) T) func(T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -334,14 +337,17 @@ func main() {
return x * x return x * x
} }
f := Pipeline(addOne, double, square) fn := function.Pipeline(addOne, double, square)
fmt.Println(fn(2)) //36 result := fn(2)
fmt.Println(result)
// Output:
// 36
} }
``` ```
### <span id="Watcher">Watcher</span> ### <span id="Watcher">Watcher</span>
<p>Watcher用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。</p> <p>Watcher用于记录代码执行时间。可以启动/停止/重置手表定时器。获取函数执行的时间。</p>
@@ -360,7 +366,8 @@ func (w *Watcher) Stop() //stop the watcher
func (w *Watcher) Reset() //reset the watcher func (w *Watcher) Reset() //reset the watcher
func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution func (w *Watcher) GetElapsedTime() time.Duration //get the elapsed time of function execution
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -397,6 +404,3 @@ func longRunningTask() {
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Maputil # Maputil
Package maputil includes some functions to manipulate map. Package maputil includes some functions to manipulate map.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package maputil includes some functions to manipulate map.
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go) - [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Example: ## Example:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/maputil" "github.com/duke-git/lancet/v2/maputil"
@@ -20,13 +21,27 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [MapTo](#MapTo)
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [Filter](#Filter) - [Filter](#Filter)
- [FilterByKeys](#FilterByKeys)
- [FilterByValues](#FilterByValues)
- [OmitBy](#OmitBy)
- [OmitByKeys](#OmitByKeys)
- [OmitByValues](#OmitByValues)
- [Intersect](#Intersect) - [Intersect](#Intersect)
- [Keys](#Keys) - [Keys](#Keys)
- [Values](#Values)
- [KeysBy](#KeysBy)
- [ValuesBy](#ValuesBy)
- [MapKeys](#MapKeys)
- [MapValues](#MapValues)
- [Entries](#Entries)
- [FromEntries](#FromEntries)
- [Transform](#Transform)
- [Merge](#Merge) - [Merge](#Merge)
- [Minus](#Minus) - [Minus](#Minus)
- [Values](#Values)
- [IsDisjoint](#IsDisjoint) - [IsDisjoint](#IsDisjoint)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -34,8 +49,65 @@ import (
## Documentation ## Documentation
### <span id="MapTo">MapTo</span>
<p>Rry to map any interface to struct or base type.</p>
<b>Signature:</b>
```go
func MapTo(src any, dst any) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
type (
Person struct {
Name string `json:"name"`
Age int `json:"age"`
Phone string `json:"phone"`
Addr Address `json:"address"`
}
Address struct {
Street string `json:"street"`
Number int `json:"number"`
}
)
personInfo := map[string]interface{}{
"name": "Nothin",
"age": 28,
"phone": "123456789",
"address": map[string]interface{}{
"street": "test",
"number": 1,
},
}
var p Person
err := MapTo(personInfo, &p)
fmt.Println(err)
fmt.Println(p)
// Output:
// <nil>
// {Nothin 28 123456789 {test 1}}
}
```
### <span id="ForEach">ForEach</span> ### <span id="ForEach">ForEach</span>
<p>Executes iteratee funcation for every key and value pair in map.</p> <p>Executes iteratee funcation for every key and value pair in map.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -43,6 +115,7 @@ import (
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -66,14 +139,16 @@ func main() {
maputil.ForEach(m, func(_ string, value int) { maputil.ForEach(m, func(_ string, value int) {
sum += value sum += value
}) })
fmt.Println(sum) // 10
fmt.Println(sum)
// Output:
// 10
} }
``` ```
### <span id="Filter">Filter</span> ### <span id="Filter">Filter</span>
<p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p> <p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -81,6 +156,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -106,15 +182,211 @@ func main() {
maputil.Filter(m, func(_ string, value int) { maputil.Filter(m, func(_ string, value int) {
sum += value sum += value
}) })
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,} result := maputil.Filter(m, isEven)
fmt.Println(result)
// Output:
// map[b:2 d:4]
} }
``` ```
### <span id="FilterByKeys">FilterByKeys</span>
<p>Iterates over map, return a new map whose keys are all given keys.</p>
<b>Signature:</b>
```go
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.FilterByKeys(m, []string{"a", "b"})
fmt.Println(result)
// Output:
// map[a:1 b:2]
}
```
### <span id="FilterByValues">FilterByValues</span>
<p>Iterates over map, return a new map whose values are all given values.</p>
<b>Signature:</b>
```go
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.FilterByValues(m, []int{3, 4})
fmt.Println(result)
// Output:
// map[c:3 d:4]
}
```
### <span id="OmitBy">OmitBy</span>
<p>OmitBy is the opposite of Filter, removes all the map elements for which the predicate function returns true.</p>
<b>Signature:</b>
```go
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
result := maputil.OmitBy(m, isEven)
fmt.Println(result)
// Output:
// map[a:1 c:3 e:5]
}
```
### <span id="OmitByKeys">OmitByKeys</span>
<p>The opposite of FilterByKeys, extracts all the map elements which keys are not omitted.</p>
<b>Signature:</b>
```go
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.OmitByKeys(m, []string{"a", "b"})
fmt.Println(result)
// Output:
// map[c:3 d:4 e:5]
}
```
### <span id="OmitByValues">OmitByValues</span>
<p>The opposite of FilterByValues. remov all elements whose value are in the give slice.</p>
<b>Signature:</b>
```go
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.OmitByValues(m, []int{4, 5})
fmt.Println(result)
// Output:
// map[a:1 b:2 c:3]
}
```
### <span id="Intersect">Intersect</span> ### <span id="Intersect">Intersect</span>
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p> <p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -122,6 +394,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -152,18 +425,23 @@ func main() {
"e": 9, "e": 9,
} }
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3} result1 := maputil.Intersect(m1)
result2 := maputil.Intersect(m1, m2)
result3 := maputil.Intersect(m1, m2, m3)
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2} fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1} // Output:
// map[a:1 b:2 c:3]
// map[a:1 b:2]
// map[a:1]
} }
``` ```
### <span id="Keys">Keys</span> ### <span id="Keys">Keys</span>
<p>Returns a slice of the map's keys.</p> <p>Returns a slice of the map's keys.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -171,6 +449,7 @@ func main() {
```go ```go
func Keys[K comparable, V any](m map[K]V) []K func Keys[K comparable, V any](m map[K]V) []K
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -178,6 +457,7 @@ package main
import ( import (
"fmt" "fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil" "github.com/duke-git/lancet/v2/maputil"
) )
@@ -192,14 +472,16 @@ func main() {
keys := maputil.Keys(m) keys := maputil.Keys(m)
sort.Ints(keys) sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
fmt.Println(keys)
// Output:
// [1 2 3 4 5]
} }
``` ```
### <span id="Merge">Merge</span> ### <span id="Merge">Merge</span>
<p>Merge maps, next key will overwrite previous key.</p> <p>Merge maps, next key will overwrite previous key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -207,6 +489,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -226,14 +509,18 @@ func main() {
1: "1", 1: "1",
3: "2", 3: "2",
} }
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
result := maputil.Merge(m1, m2)
fmt.Println(result)
// Output:
// map[1:c 2:b 3:d]
} }
``` ```
### <span id="Minus">Minus</span> ### <span id="Minus">Minus</span>
<p>Creates an map of whose key in mapA but not in mapB.</p> <p>Creates an map of whose key in mapA but not in mapB.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -241,6 +528,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -264,13 +552,17 @@ func main() {
"d": 33, "d": 33,
} }
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3} result := maputil.Minus(m1, m2)
fmt.Println(result)
// Output:
// map[c:3]
} }
``` ```
### <span id="Values">Values</span> ### <span id="Values">Values</span>
<p>Returns a slice of the map's values.</p> <p>Returns a slice of the map's values.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -278,6 +570,7 @@ func main() {
```go ```go
func Values[K comparable, V any](m map[K]V) []V func Values[K comparable, V any](m map[K]V) []V
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -285,6 +578,7 @@ package main
import ( import (
"fmt" "fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil" "github.com/duke-git/lancet/v2/maputil"
) )
@@ -300,18 +594,240 @@ func main() {
values := maputil.Values(m) values := maputil.Values(m)
sort.Strings(values) sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"} fmt.Println(values)
// Output:
// [a a b c d]
} }
``` ```
### <span id="IsDisjoint">IsDisjoint</span> ### <span id="KeysBy">KeysBy</span>
<p>Checks two maps are disjoint if they have no keys in common</p>
<p>Creates a slice whose element is the result of function mapper invoked by every map's key.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
``` ```
<b>Example:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
}
keys := maputil.KeysBy(m, func(n int) int {
return n + 1
})
sort.Ints(keys)
fmt.Println(keys)
// Output:
// [2 3 4]
}
```
### <span id="ValuesBy">ValuesBy</span>
<p>Creates a slice whose element is the result of function mapper invoked by every map's value.</p>
<b>Signature:</b>
```go
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
values := maputil.ValuesBy(m, func(v string) string {
switch v {
case "a":
return "a-1"
case "b":
return "b-2"
case "c":
return "c-3"
default:
return ""
}
})
sort.Strings(values)
fmt.Println(values)
// Output:
// [a-1 b-2 c-3]
}
```
### <span id="MapKeys">MapKeys</span>
<p>Transforms a map to other type map by manipulating it's keys.</p>
<b>Signature:</b>
```go
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
```
<b>Example:</b>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
result := maputil.MapKeys(m, func(k int, _ string) string {
return strconv.Itoa(k)
})
fmt.Println(result)
// Output:
// map[1:a 2:b 3:c]
}
```
### <span id="MapValues">MapValues</span>
<p>Transforms a map to other type map by manipulating it's values.</p>
<b>Signature:</b>
```go
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
result := maputil.MapValues(m, func(k int, v string) string {
return v + strconv.Itoa(k)
})
fmt.Println(result)
// Output:
// map[1:a1 2:b2 3:c3]
}
```
### <span id="Entry">Entry</span>
<p>Transforms a map into array of key/value pairs.</p>
<b>Signature:</b>
```go
type Entry[K comparable, V any] struct {
Key K
Value V
}
func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
```
<b>Example:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
result := maputil.Entries(m)
sort.Slice(result, func(i, j int) bool {
return result[i].Value < result[j].Value
})
fmt.Println(result)
// Output:
// [{a 1} {b 2} {c 3}]
}
```
### <span id="FromEntries">FromEntries</span>
<p>Creates a map based on a slice of key/value pairs.</p>
<b>Signature:</b>
```go
type Entry[K comparable, V any] struct {
Key K
Value V
}
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -323,30 +839,101 @@ import (
) )
func main() { func main() {
m1 := map[int]string{ result := maputil.FromEntries([]Entry[string, int]{
1: "a", {Key: "a", Value: 1},
2: "a", {Key: "b", Value: 2},
3: "b", {Key: "c", Value: 3},
4: "c", })
5: "d",
}
m2 := map[int]string{ fmt.Println(result)
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
m3 := map[int]string{ // Output:
6: "a", // map[a:1 b:2 c:3]
} }
```
ok := maputil.IsDisjoint(m2, m1)
fmt.Println(ok) // false ### <span id="Transform">Transform</span>
ok = maputil.IsDisjoint(m2, m3) <p>Transform a map to another type map.</p>
fmt.Println(ok) // true
<b>Signature:</b>
```go
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>Example:</b>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
result := Transform(m, func(k string, v int) (string, string) {
return k, strconv.Itoa(v)
})
fmt.Println(result)
// Output:
// map[a:1 b:2 c:3]
}
```
### <span id="IsDisjoint">IsDisjoint</span>
<p>Checks two maps are disjoint if they have no keys in common</p>
<b>Signature:</b>
```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"d": 22,
}
m3 := map[string]int{
"a": 22,
}
result1 := maputil.IsDisjoint(m1, m2)
result2 := maputil.IsDisjoint(m1, m3)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Maputil # Maputil
maputil 包包括一些操作 map 的函数。 maputil 包包括一些操作 map 的函数。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ maputil包包括一些操作map的函数。
- [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go) - [https://github.com/duke-git/lancet/blob/main/maputil/map.go](https://github.com/duke-git/lancet/blob/main/maputil/map.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/maputil" "github.com/duke-git/lancet/v2/maputil"
@@ -20,22 +21,92 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录: ## 目录:
- [MapTo](#MapTo)
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [Filter](#Filter) - [Filter](#Filter)
- [FilterByKeys](#FilterByKeys)
- [FilterByValues](#FilterByValues)
- [OmitBy](#OmitBy)
- [OmitByKeys](#OmitByKeys)
- [OmitByValues](#OmitByValues)
- [Intersect](#Intersect) - [Intersect](#Intersect)
- [Keys](#Keys) - [Keys](#Keys)
- [Values](#Values)
- [KeysBy](#KeysBy)
- [ValuesBy](#ValuesBy)
- [MapKeys](#MapKeys)
- [MapValues](#MapValues)
- [Entries](#Entries)
- [FromEntries](#FromEntries)
- [Transform](#Transform)
- [Merge](#Merge) - [Merge](#Merge)
- [Minus](#Minus) - [Minus](#Minus)
- [Values](#Values)
- [IsDisjoint](#IsDisjoint) - [IsDisjoint](#IsDisjoint)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## API 文档: ## API 文档:
### <span id="MapTo">MapTo</span>
<p>快速将map或者其他类型映射到结构体或者指定类型。</p>
<b>函数签名:</b>
```go
func MapTo(src any, dst any) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
type (
Person struct {
Name string `json:"name"`
Age int `json:"age"`
Phone string `json:"phone"`
Addr Address `json:"address"`
}
Address struct {
Street string `json:"street"`
Number int `json:"number"`
}
)
personInfo := map[string]interface{}{
"name": "Nothin",
"age": 28,
"phone": "123456789",
"address": map[string]interface{}{
"street": "test",
"number": 1,
},
}
var p Person
err := MapTo(personInfo, &p)
fmt.Println(err)
fmt.Println(p)
// Output:
// <nil>
// {Nothin 28 123456789 {test 1}}
}
```
### <span id="ForEach">ForEach</span> ### <span id="ForEach">ForEach</span>
<p>对map中的每对key和value执行iteratee函数</p> <p>对map中的每对key和value执行iteratee函数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -43,7 +114,8 @@ import (
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -66,22 +138,25 @@ func main() {
maputil.ForEach(m, func(_ string, value int) { maputil.ForEach(m, func(_ string, value int) {
sum += value sum += value
}) })
fmt.Println(sum) // 10
fmt.Println(sum)
// Output:
// 10
} }
``` ```
### <span id="Filter">Filter</span> ### <span id="Filter">Filter</span>
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -106,15 +181,211 @@ func main() {
maputil.Filter(m, func(_ string, value int) { maputil.Filter(m, func(_ string, value int) {
sum += value sum += value
}) })
res := maputil.Filter(m, isEven)
fmt.Println(res) // map[string]int{"b": 2, "d": 4,} result := Filter(m, isEven)
fmt.Println(result)
// Output:
// map[b:2 d:4]
} }
``` ```
### <span id="FilterByKeys">FilterByKeys</span>
<p>迭代map, 返回一个新map其key都是给定的key值。</p>
<b>函数签名:</b>
```go
func FilterByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.FilterByKeys(m, []string{"a", "b"})
fmt.Println(result)
// Output:
// map[a:1 b:2]
}
```
### <span id="FilterByValues">FilterByValues</span>
<p>迭代map, 返回一个新map其value都是给定的value值。</p>
<b>函数签名:</b>
```go
func FilterByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.FilterByValues(m, []int{3, 4})
fmt.Println(result)
// Output:
// map[c:3 d:4]
}
```
### <span id="OmitBy">OmitBy</span>
<p>Filter的反向操作, 迭代map中的每对key和value, 删除符合predicate函数的key, value, 返回新map。</p>
<b>函数签名:</b>
```go
func OmitBy[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
isEven := func(_ string, value int) bool {
return value%2 == 0
}
result := maputil.OmitBy(m, isEven)
fmt.Println(result)
// Output:
// map[a:1 c:3 e:5]
}
```
### <span id="OmitByKeys">OmitByKeys</span>
<p>FilterByKeys的反向操作, 迭代map, 返回一个新map其key不包括给定的key值。</p>
<b>函数签名:</b>
```go
func OmitByKeys[K comparable, V any](m map[K]V, keys []K) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.OmitByKeys(m, []string{"a", "b"})
fmt.Println(result)
// Output:
// map[c:3 d:4 e:5]
}
```
### <span id="OmitByValues">OmitByValues</span>
<p>FilterByValues的反向操作, 迭代map, 返回一个新map其value不包括给定的value值。</p>
<b>函数签名:</b>
```go
func OmitByValues[K comparable, V comparable](m map[K]V, values []V) map[K]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
result := maputil.OmitByValues(m, []int{4, 5})
fmt.Println(result)
// Output:
// map[a:1 b:2 c:3]
}
```
### <span id="Intersect">Intersect</span> ### <span id="Intersect">Intersect</span>
<p>多个map的交集操作</p> <p>多个map的交集操作</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -122,7 +393,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -152,18 +424,23 @@ func main() {
"e": 9, "e": 9,
} }
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3} result1 := maputil.Intersect(m1)
result2 := maputil.Intersect(m1, m2)
result3 := maputil.Intersect(m1, m2, m3)
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2} fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1} // Output:
// map[a:1 b:2 c:3]
// map[a:1 b:2]
// map[a:1]
} }
``` ```
### <span id="Keys">Keys</span> ### <span id="Keys">Keys</span>
<p>返回map中所有key的切片</p> <p>返回map中所有key的切片</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -171,7 +448,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -192,14 +470,16 @@ func main() {
keys := maputil.Keys(m) keys := maputil.Keys(m)
sort.Ints(keys) sort.Ints(keys)
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
fmt.Println(keys)
// Output:
// [1 2 3 4 5]
} }
``` ```
### <span id="Merge">Merge</span> ### <span id="Merge">Merge</span>
<p>合并多个maps, 相同的key会被后来的key覆盖</p> <p>合并多个maps, 相同的key会被后来的key覆盖</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -207,7 +487,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -226,13 +507,18 @@ func main() {
1: "1", 1: "1",
3: "2", 3: "2",
} }
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
result := maputil.Merge(m1, m2)
fmt.Println(result)
// Output:
// map[1:c 2:b 3:d]
} }
``` ```
### <span id="Minus">Minus</span> ### <span id="Minus">Minus</span>
<p>返回一个map其中的key存在于mapA不存在于mapB.</p> <p>返回一个map其中的key存在于mapA不存在于mapB.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -240,7 +526,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -263,13 +550,17 @@ func main() {
"d": 33, "d": 33,
} }
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3} result := maputil.Minus(m1, m2)
fmt.Println(result)
// Output:
// map[c:3]
} }
``` ```
### <span id="Values">Values</span> ### <span id="Values">Values</span>
<p>返回map中所有value的切片</p> <p>返回map中所有value的切片</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -277,7 +568,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -299,20 +591,239 @@ func main() {
values := maputil.Values(m) values := maputil.Values(m)
sort.Strings(values) sort.Strings(values)
fmt.Println(values) // []string{"a", "a", "b", "c", "d"} // Output:
// [a a b c d]
} }
``` ```
### <span id="KeysBy">KeysBy</span>
### <span id="IsDisjoint">IsDisjoint</span> <p>创建一个切片其元素是每个map的key调用mapper函数的结果。</p>
<p>验证两个map是否具有不同的key</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool func KeysBy[K comparable, V any, T any](m map[K]V, mapper func(item K) T) []T
``` ```
<b>例子:</b>
<b>示例:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "a",
3: "b",
}
keys := maputil.KeysBy(m, func(n int) int {
return n + 1
})
sort.Ints(keys)
fmt.Println(keys)
// Output:
// [2 3 4]
}
```
### <span id="ValuesBy">ValuesBy</span>
<p>创建一个切片其元素是每个map的value调用mapper函数的结果。</p>
<b>函数签名:</b>
```go
func ValuesBy[K comparable, V any, T any](m map[K]V, mapper func(item V) T) []T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
values := maputil.ValuesBy(m, func(v string) string {
switch v {
case "a":
return "a-1"
case "b":
return "b-2"
case "c":
return "c-3"
default:
return ""
}
})
sort.Strings(values)
fmt.Println(values)
// Output:
// [a-1 b-2 c-3]
}
```
### <span id="MapKeys">MapKeys</span>
<p>操作map的每个key然后转为新的map。</p>
<b>函数签名:</b>
```go
func MapKeys[K comparable, V any, T comparable](m map[K]V, iteratee func(key K, value V) T) map[T]V
```
<b>示例:</b>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
result := maputil.MapKeys(m, func(k int, _ string) string {
return strconv.Itoa(k)
})
fmt.Println(result)
// Output:
// map[1:a 2:b 3:c]
}
```
### <span id="MapValues">MapValues</span>
<p>操作map的每个value然后转为新的map。</p>
<b>函数签名:</b>
```go
func MapValues[K comparable, V any, T any](m map[K]V, iteratee func(key K, value V) T) map[K]T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[int]string{
1: "a",
2: "b",
3: "c",
}
result := maputil.MapValues(m, func(k int, v string) string {
return v + strconv.Itoa(k)
})
fmt.Println(result)
// Output:
// map[1:a1 2:b2 3:c3]
}
```
### <span id="Entry">Entry</span>
<p>将map转换为键/值对切片。</p>
<b>函数签名:</b>
```go
type Entry[K comparable, V any] struct {
Key K
Value V
}
func Entries[K comparable, V any](m map[K]V) []Entry[K, V]
```
<b>示例:</b>
```go
package main
import (
"fmt"
"sort"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
result := maputil.Entries(m)
sort.Slice(result, func(i, j int) bool {
return result[i].Value < result[j].Value
})
fmt.Println(result)
// Output:
// [{a 1} {b 2} {c 3}]
}
```
### <span id="FromEntries">FromEntries</span>
<p>基于键/值对的切片创建map。</p>
<b>函数签名:</b>
```go
type Entry[K comparable, V any] struct {
Key K
Value V
}
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V
```
<b>示例:</b>
```go ```go
package main package main
@@ -323,30 +834,101 @@ import (
) )
func main() { func main() {
m1 := map[int]string{ result := maputil.FromEntries([]Entry[string, int]{
1: "a", {Key: "a", Value: 1},
2: "a", {Key: "b", Value: 2},
3: "b", {Key: "c", Value: 3},
4: "c", })
5: "d",
}
m2 := map[int]string{ fmt.Println(result)
1: "a",
2: "a",
3: "b",
4: "c",
5: "d",
}
m3 := map[int]string{ // Output:
6: "a", // map[a:1 b:2 c:3]
} }
```
ok := maputil.IsDisjoint(m2, m1)
fmt.Println(ok) // false ### <span id="Transform">Transform</span>
ok = maputil.IsDisjoint(m2, m3) <p>将map转换为其他类型的map。</p>
fmt.Println(ok) // true
<b>函数签名:</b>
```go
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>
```go
package main
import (
"fmt"
"strconv"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
result := Transform(m, func(k string, v int) (string, string) {
return k, strconv.Itoa(v)
})
fmt.Println(result)
// Output:
// map[a:1 b:2 c:3]
}
```
### <span id="IsDisjoint">IsDisjoint</span>
<p>验证两个map是否具有不同的key</p>
<b>函数签名:</b>
```go
func IsDisjoint[K comparable, V any](mapA, mapB map[K]V) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/maputil"
)
func main() {
m1 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
m2 := map[string]int{
"d": 22,
}
m3 := map[string]int{
"a": 22,
}
result1 := maputil.IsDisjoint(m1, m2)
result2 := maputil.IsDisjoint(m1, m3)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Mathutil # Mathutil
Package mathutil implements some functions for math calculation. Package mathutil implements some functions for math calculation.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package mathutil implements some functions for math calculation.
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go) - [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Example: ## Example:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/mathutil" "github.com/duke-git/lancet/v2/mathutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Average](#Average) - [Average](#Average)
- [Exponent](#Exponent) - [Exponent](#Exponent)
- [Fibonacci](#Fibonacci) - [Fibonacci](#Fibonacci)
@@ -32,14 +34,25 @@ import (
- [RoundToFloat](#RoundToFloat) - [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString) - [RoundToString](#RoundToString)
- [TruncRound](#TruncRound) - [TruncRound](#TruncRound)
- [Range](#Range)
- [RangeWithStep](#RangeWithStep)
- [AngleToRadian](#AngleToRadian)
- [RadianToAngle](#RadianToAngle)
- [PointDistance](#PointDistance)
- [IsPrime](#IsPrime)
- [GCD](#GCD)
- [LCM](#LCM)
- [Cos](#Cos)
- [Sin](#Sin)
- [Log](#Log)
- [Sum](#Sum)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Average">Average</span> ### <span id="Average">Average</span>
<p>Return average value of numbers. Maybe call RoundToFloat to round result.</p> <p>Return average value of numbers. Maybe call RoundToFloat to round result.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -47,6 +60,7 @@ import (
```go ```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -58,16 +72,22 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Average(0, 0)) //0 result1 := mathutil.Average(1, 2)
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998 avg := mathutil.Average(1.2, 1.4)
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3 result2 := mathutil.RoundToFloat(avg, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.3
} }
``` ```
### <span id="Exponent">Exponent</span> ### <span id="Exponent">Exponent</span>
<p>Calculate x to the nth power.</p> <p>Calculate x to the nth power.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -75,6 +95,7 @@ func main() {
```go ```go
func Exponent(x, n int64) int64 func Exponent(x, n int64) int64
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -86,15 +107,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1 result1 := mathutil.Exponent(10, 0)
fmt.Println(mathutil.Exponent(10, 1)) //10 result2 := mathutil.Exponent(10, 1)
fmt.Println(mathutil.Exponent(10, 2)) //100 result3 := mathutil.Exponent(10, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 10
// 100
} }
``` ```
### <span id="Fibonacci">Fibonacci</span> ### <span id="Fibonacci">Fibonacci</span>
<p>Calculate the nth number of fibonacci sequence.</p> <p>Calculate the nth number of fibonacci sequence.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -102,6 +131,7 @@ func main() {
```go ```go
func Fibonacci(first, second, n int) int func Fibonacci(first, second, n int) int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -113,17 +143,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1 result1 := mathutil.Fibonacci(1, 1, 1)
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1 result2 := mathutil.Fibonacci(1, 1, 2)
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2 result3 := mathutil.Fibonacci(1, 1, 5)
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 1
// 5
} }
``` ```
### <span id="Factorial">Factorial</span> ### <span id="Factorial">Factorial</span>
<p>Calculate the factorial of x.</p> <p>Calculate the factorial of x.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -131,6 +167,7 @@ func main() {
```go ```go
func Factorial(x uint) uint func Factorial(x uint) uint
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -142,16 +179,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Factorial(0)) //1 result1 := mathutil.Factorial(1)
fmt.Println(mathutil.Factorial(1)) //1 result2 := mathutil.Factorial(2)
fmt.Println(mathutil.Factorial(2)) //2 result3 := mathutil.Factorial(3)
fmt.Println(mathutil.Factorial(3)) //6
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 6
} }
``` ```
### <span id="Max">Max</span> ### <span id="Max">Max</span>
<p>Return max value of numbers.</p> <p>Return max value of numbers.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -159,6 +203,7 @@ func main() {
```go ```go
func Max[T constraints.Integer | constraints.Float](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -170,16 +215,20 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Max(0, 0)) //0 result1 := mathutil.Max(1, 2, 3)
fmt.Println(mathutil.Max(1, 2, 3)) //3 result2 := mathutil.Max(1.2, 1.4, 1.1, 1.4)
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.4
} }
``` ```
### <span id="MaxBy">MaxBy</span> ### <span id="MaxBy">MaxBy</span>
<p>Return the maximum value of a slice using the given comparator function.</p> <p>Return the maximum value of a slice using the given comparator function.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -187,6 +236,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -198,26 +248,31 @@ import (
) )
func main() { func main() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool { result1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool { result2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool { result3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abc
// abd
//
} }
``` ```
### <span id="Min">Min</span> ### <span id="Min">Min</span>
<p>Return the minimum value of numbers.</p> <p>Return the minimum value of numbers.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -225,6 +280,7 @@ func main() {
```go ```go
func Min[T constraints.Integer | constraints.Float](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -236,15 +292,20 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Min(0, 0)) //0 result1 := mathutil.Min(1, 2, 3)
fmt.Println(mathutil.Min(1, 2, 3)) //1 result2 := mathutil.Min(1.2, 1.4, 1.1, 1.4)
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.1
} }
``` ```
### <span id="MinBy">MinBy</span> ### <span id="MinBy">MinBy</span>
<p>Return the minimum value of a slice using the given comparator function.</p> <p>Return the minimum value of a slice using the given comparator function.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -252,6 +313,7 @@ func main() {
```go ```go
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>Example:</b> <b>Example:</b>
```go ```go
@@ -263,27 +325,31 @@ import (
) )
func main() { func main() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool { result1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool { result2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool { result3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// a
// ab
//
} }
``` ```
### <span id="Percent">Percent</span> ### <span id="Percent">Percent</span>
<p>calculate the percentage of val to total, retain n decimal places.</p> <p>calculate the percentage of val to total, retain n decimal places.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -291,6 +357,7 @@ func main() {
```go ```go
func Percent(val, total float64, n int) float64 func Percent(val, total float64, n int) float64
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -302,14 +369,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //0.5 result1 := mathutil.Percent(1, 2, 2)
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //0.33 result2 := mathutil.Percent(0.1, 0.3, 2)
result3 := mathutil.Percent(-30305, 408420, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 50
// 33.33
// -7.42
} }
``` ```
### <span id="RoundToFloat">RoundToFloat</span> ### <span id="RoundToFloat">RoundToFloat</span>
<p>Round float up to n decimal places.</p> <p>Round float up to n decimal places.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -317,6 +393,7 @@ func main() {
```go ```go
func RoundToFloat(x float64, n int) float64 func RoundToFloat(x float64, n int) float64
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -328,18 +405,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0 result1 := mathutil.RoundToFloat(0.124, 2)
fmt.Println(mathutil.RoundToFloat(0, 1)) //0 result2 := mathutil.RoundToFloat(0.125, 2)
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12 result3 := mathutil.RoundToFloat(0.125, 3)
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
} }
``` ```
### <span id="RoundToString">RoundToString</span> ### <span id="RoundToString">RoundToString</span>
<p>Round float up to n decimal places. will return string.</p> <p>Round float up to n decimal places. will return string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -347,6 +429,7 @@ func main() {
```go ```go
func RoundToString(x float64, n int) string func RoundToString(x float64, n int) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -358,17 +441,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0" result1 := mathutil.RoundToString(0.124, 2)
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0: result2 := mathutil.RoundToString(0.125, 2)
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12" result3 := mathutil.RoundToString(0.125, 3)
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125" fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
} }
``` ```
### <span id="TruncRound">TruncRound</span> ### <span id="TruncRound">TruncRound</span>
<p>Round float off n decimal places.</p> <p>Round float off n decimal places.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -376,6 +465,7 @@ func main() {
```go ```go
func TruncRound(x float64, n int) float64 func TruncRound(x float64, n int) float64
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -387,13 +477,469 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0 result1 := mathutil.TruncRound(0.124, 2)
fmt.Println(mathutil.TruncRound(0, 1)) //0 result2 := mathutil.TruncRound(0.125, 2)
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12 result3 := mathutil.TruncRound(0.125, 3)
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.12
// 0.125
}
```
### <span id="Range">Range</span>
<p>Creates a slice of numbers from start with specified count, element step is 1.</p>
<b>Signature:</b>
```go
func Range[T constraints.Integer | constraints.Float](start T, count int) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Range(1, 4)
result2 := mathutil.Range(1, -4)
result3 := mathutil.Range(-4, 4)
result4 := mathutil.Range(1.0, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// [1 2 3 4]
// [1 2 3 4]
// [-4 -3 -2 -1]
// [1 2 3 4]
}
```
### <span id="RangeWithStep">RangeWithStep</span>
<p>Creates a slice of numbers from start to end with specified step.</p>
<b>Signature:</b>
```go
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.RangeWithStep(1, 4, 1)
result2 := mathutil.RangeWithStep(1, -1, 0)
result3 := mathutil.RangeWithStep(-4, 1, 2)
result4 := mathutil.RangeWithStep(1.0, 4.0, 1.1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// [1 2 3]
// []
// [-4 -2 0]
// [1 2.1 3.2]
}
```
### <span id="AngleToRadian">AngleToRadian</span>
<p>Converts angle value to radian value.</p>
<b>Signature:</b>
```go
func AngleToRadian(angle float64) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.AngleToRadian(45)
result2 := mathutil.AngleToRadian(90)
result3 := mathutil.AngleToRadian(180)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.7853981633974483
// 1.5707963267948966
// 3.141592653589793
}
```
### <span id="RadianToAngle">RadianToAngle</span>
<p>Converts radian value to angle value.</p>
<b>Signature:</b>
```go
func RadianToAngle(radian float64) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.RadianToAngle(math.Pi)
result2 := mathutil.RadianToAngle(math.Pi / 2)
result3 := mathutil.RadianToAngle(math.Pi / 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 180
// 90
// 45
}
```
### <span id="PointDistance">PointDistance</span>
<p>Caculates two points distance.</p>
<b>Signature:</b>
```go
func PointDistance(x1, y1, x2, y2 float64) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.PointDistance(1, 1, 4, 5)
fmt.Println(result1)
// Output:
// 5
}
```
### <span id="IsPrime">IsPrime</span>
<p>Checks if number is prime number.</p>
<b>Signature:</b>
```go
func IsPrime(n int) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.IsPrime(-1)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// false
// true
}
```
### <span id="GCD">GCD</span>
<p>Return greatest common divisor (GCD) of integers.</p>
<b>Signature:</b>
```go
func GCD[T constraints.Integer](integers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.GCD(1, 1)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// 1
// -1
// -1
// 3
}
```
### <span id="LCM">LCM</span>
<p>Return Least Common Multiple (LCM) of integers.</p>
<b>Signature:</b>
```go
func LCM[T constraints.Integer](integers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.LCM(1, 1)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 18
} }
``` ```
### <span id="Cos">Cos</span>
<p>Returns the cosine of the radian argument.</p>
<b>Signature:</b>
```go
func Cos(radian float64, precision ...int) float64
```
<b>Example:</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>Returns the sine of the radian argument.</p>
<b>Signature:</b>
```go
func Sin(radian float64, precision ...int) float64
```
<b>Example:</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>Returns the logarithm of base n.</p>
<b>Signature:</b>
```go
func Log(n, base float64) float64
```
<b>Example:</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>Returns sum of passed numbers.</p>
<b>Signature:</b>
```go
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sum(1, 2)
result2 := mathutil.Sum(0.1, float64(1))
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.1
}
```

View File

@@ -1,4 +1,5 @@
# Mathutil # Mathutil
mathutil 包实现了一些数学计算的函数. mathutil 包实现了一些数学计算的函数.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ mathutil包实现了一些数学计算的函数.
- [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go) - [https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/main/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/mathutil" "github.com/duke-git/lancet/v2/mathutil"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Average](#Average) - [Average](#Average)
- [Exponent](#Exponent) - [Exponent](#Exponent)
- [Fibonacci](#Fibonacci) - [Fibonacci](#Fibonacci)
@@ -32,13 +34,25 @@ import (
- [RoundToFloat](#RoundToFloat) - [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString) - [RoundToString](#RoundToString)
- [TruncRound](#TruncRound) - [TruncRound](#TruncRound)
- [Range](#Range)
- [RangeWithStep](#RangeWithStep)
- [AngleToRadian](#AngleToRadian)
- [RadianToAngle](#RadianToAngle)
- [PointDistance](#PointDistance)
- [IsPrime](#IsPrime)
- [GCD](#GCD)
- [LCM](#LCM)
- [Cos](#Cos)
- [Sin](#Sin)
- [Log](#Log)
- [Sum](#Sum)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="Average">Average</span> ### <span id="Average">Average</span>
<p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p> <p>计算平均数. 可能需要对结果调用RoundToFloat方法四舍五入</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -46,7 +60,8 @@ import (
```go ```go
func Average[T constraints.Integer | constraints.Float](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -57,15 +72,22 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Average(0, 0)) //0 result1 := mathutil.Average(1, 2)
fmt.Println(mathutil.Average(1, 1)) //1
avg := mathutil.Average(1.2, 1.4) //1.2999999998 avg := mathutil.Average(1.2, 1.4)
roundAvg := mmathutil.RoundToFloat(avg, 1) // 1.3 result2 := mathutil.RoundToFloat(avg, 1)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.3
} }
``` ```
### <span id="Exponent">Exponent</span> ### <span id="Exponent">Exponent</span>
<p>指数计算x的n次方</p> <p>指数计算x的n次方</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -73,7 +95,8 @@ func main() {
```go ```go
func Exponent(x, n int64) int64 func Exponent(x, n int64) int64
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -84,15 +107,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1 result1 := mathutil.Exponent(10, 0)
fmt.Println(mathutil.Exponent(10, 1)) //10 result2 := mathutil.Exponent(10, 1)
fmt.Println(mathutil.Exponent(10, 2)) //100 result3 := mathutil.Exponent(10, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 10
// 100
} }
``` ```
### <span id="Fibonacci">Fibonacci</span> ### <span id="Fibonacci">Fibonacci</span>
<p>计算斐波那契数列的第n个数</p> <p>计算斐波那契数列的第n个数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -100,7 +131,8 @@ func main() {
```go ```go
func Fibonacci(first, second, n int) int func Fibonacci(first, second, n int) int
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -111,17 +143,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1 result1 := mathutil.Fibonacci(1, 1, 1)
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1 result2 := mathutil.Fibonacci(1, 1, 2)
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2 result3 := mathutil.Fibonacci(1, 1, 5)
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 1
// 5
} }
``` ```
### <span id="Factorial">Factorial</span> ### <span id="Factorial">Factorial</span>
<p>计算阶乘</p> <p>计算阶乘</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -129,7 +167,8 @@ func main() {
```go ```go
func Factorial(x uint) uint func Factorial(x uint) uint
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -140,15 +179,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Factorial(0)) //1 result1 := mathutil.Factorial(1)
fmt.Println(mathutil.Factorial(1)) //1 result2 := mathutil.Factorial(2)
fmt.Println(mathutil.Factorial(2)) //2 result3 := mathutil.Factorial(3)
fmt.Println(mathutil.Factorial(3)) //6
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 6
} }
``` ```
### <span id="Max">Max</span> ### <span id="Max">Max</span>
<p>返回参数中的最大数</p> <p>返回参数中的最大数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -156,7 +203,8 @@ func main() {
```go ```go
func Max[T constraints.Integer | constraints.Float](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -167,15 +215,20 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Max(0, 0)) //0 result1 := mathutil.Max(1, 2, 3)
fmt.Println(mathutil.Max(1, 2, 3)) //3 result2 := mathutil.Max(1.2, 1.4, 1.1, 1.4)
fmt.Println(mathutil.Max(1.2, 1.4, 1.1, 1.4)) //1.4
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.4
} }
``` ```
### <span id="MaxBy">MaxBy</span> ### <span id="MaxBy">MaxBy</span>
<p>使用给定的比较器函数返回切片的最大值</p> <p>使用给定的比较器函数返回切片的最大值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -183,7 +236,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -194,27 +248,31 @@ import (
) )
func main() { func main() {
res1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool { result1 := mathutil.MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res1) //abc
res2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool { result2 := mathutil.MaxBy([]string{"abd", "abc", "ab"}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res2) //abd
res3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool { result3 := mathutil.MaxBy([]string{}, func(v1, v2 string) bool {
return len(v1) > len(v2) return len(v1) > len(v2)
}) })
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abc
// abd
//
} }
``` ```
### <span id="Min">Min</span> ### <span id="Min">Min</span>
<p>返回参数中的最小数</p> <p>返回参数中的最小数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -222,7 +280,8 @@ func main() {
```go ```go
func Min[T constraints.Integer | constraints.Float](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -233,15 +292,20 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Min(0, 0)) //0 result1 := mathutil.Min(1, 2, 3)
fmt.Println(mathutil.Min(1, 2, 3)) //1 result2 := mathutil.Min(1.2, 1.4, 1.1, 1.4)
fmt.Println(mathutil.Min(1.2, 1.4, 1.1, 1.4)) //1.1
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 1
// 1.1
} }
``` ```
### <span id="MinBy">MinBy</span> ### <span id="MinBy">MinBy</span>
<p>使用给定的比较器函数返回切片的最小值</p> <p>使用给定的比较器函数返回切片的最小值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -249,7 +313,8 @@ func main() {
```go ```go
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>示例:</b>
```go ```go
package main package main
@@ -260,27 +325,31 @@ import (
) )
func main() { func main() {
res1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool { result1 := mathutil.MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res1) //a
res2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool { result2 := mathutil.MinBy([]string{"ab", "ac", "abc"}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res2) //ab
res3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool { result3 := mathutil.MinBy([]string{}, func(v1, v2 string) bool {
return len(v1) < len(v2) return len(v1) < len(v2)
}) })
fmt.Println(res3) //“”
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// a
// ab
//
} }
``` ```
### <span id="Percent">Percent</span> ### <span id="Percent">Percent</span>
<p>计算百分比保留n位小数</p> <p>计算百分比保留n位小数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -288,7 +357,8 @@ func main() {
```go ```go
func Percent(val, total float64, n int) float64 func Percent(val, total float64, n int) float64
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -299,14 +369,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //0.5 result1 := mathutil.Percent(1, 2, 2)
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //0.33 result2 := mathutil.Percent(0.1, 0.3, 2)
result3 := mathutil.Percent(-30305, 408420, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 50
// 33.33
// -7.42
} }
``` ```
### <span id="RoundToFloat">RoundToFloat</span> ### <span id="RoundToFloat">RoundToFloat</span>
<p>四舍五入保留n位小数</p> <p>四舍五入保留n位小数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -314,7 +393,8 @@ func main() {
```go ```go
func RoundToFloat(x float64, n int) float64 func RoundToFloat(x float64, n int) float64
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -325,18 +405,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0 result1 := mathutil.RoundToFloat(0.124, 2)
fmt.Println(mathutil.RoundToFloat(0, 1)) //0 result2 := mathutil.RoundToFloat(0.125, 2)
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12 result3 := mathutil.RoundToFloat(0.125, 3)
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
} }
``` ```
### <span id="RoundToString">RoundToString</span> ### <span id="RoundToString">RoundToString</span>
<p>四舍五入保留n位小数返回字符串</p> <p>四舍五入保留n位小数返回字符串</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -344,7 +429,8 @@ func main() {
```go ```go
func RoundToString(x float64, n int) string func RoundToString(x float64, n int) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -355,17 +441,23 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0" result1 := mathutil.RoundToString(0.124, 2)
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0: result2 := mathutil.RoundToString(0.125, 2)
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12" result3 := mathutil.RoundToString(0.125, 3)
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125" fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.13
// 0.125
} }
``` ```
### <span id="TruncRound">TruncRound</span> ### <span id="TruncRound">TruncRound</span>
<p>截短n位小数不进行四舍五入</p> <p>截短n位小数不进行四舍五入</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -373,7 +465,8 @@ func main() {
```go ```go
func TruncRound(x float64, n int) float64 func TruncRound(x float64, n int) float64
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -384,13 +477,467 @@ import (
) )
func main() { func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0 result1 := mathutil.TruncRound(0.124, 2)
fmt.Println(mathutil.TruncRound(0, 1)) //0 result2 := mathutil.TruncRound(0.125, 2)
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12 result3 := mathutil.TruncRound(0.125, 3)
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125 fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.12
// 0.12
// 0.125
} }
``` ```
### <span id="Range">Range</span>
<p>根据指定的起始值和数量,创建一个数字切片。</p>
<b>函数签名:</b>
```go
func Range[T constraints.Integer | constraints.Float](start T, count int) []T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Range(1, 4)
result2 := mathutil.Range(1, -4)
result3 := mathutil.Range(-4, 4)
result4 := mathutil.Range(1.0, 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// [1 2 3 4]
// [1 2 3 4]
// [-4 -3 -2 -1]
// [1 2 3 4]
}
```
### <span id="RangeWithStep">RangeWithStep</span>
<p>根据指定的起始值,结束值,步长,创建一个数字切片。</p>
<b>函数签名:</b>
```go
func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T) []T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.RangeWithStep(1, 4, 1)
result2 := mathutil.RangeWithStep(1, -1, 0)
result3 := mathutil.RangeWithStep(-4, 1, 2)
result4 := mathutil.RangeWithStep(1.0, 4.0, 1.1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// [1 2 3]
// []
// [-4 -2 0]
// [1 2.1 3.2]
}
```
### <span id="AngleToRadian">AngleToRadian</span>
<p>将角度值转为弧度值</p>
<b>函数签名:</b>
```go
func AngleToRadian(angle float64) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.AngleToRadian(45)
result2 := mathutil.AngleToRadian(90)
result3 := mathutil.AngleToRadian(180)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 0.7853981633974483
// 1.5707963267948966
// 3.141592653589793
}
```
### <span id="RadianToAngle">RadianToAngle</span>
<p>将弧度值转为角度值</p>
<b>函数签名:</b>
```go
func RadianToAngle(radian float64) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.RadianToAngle(math.Pi)
result2 := mathutil.RadianToAngle(math.Pi / 2)
result3 := mathutil.RadianToAngle(math.Pi / 4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 180
// 90
// 45
}
```
### <span id="PointDistance">PointDistance</span>
<p>计算两个坐标点的距离</p>
<b>函数签名:</b>
```go
func PointDistance(x1, y1, x2, y2 float64) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.PointDistance(1, 1, 4, 5)
fmt.Println(result1)
// Output:
// 5
}
```
### <span id="IsPrime">IsPrime</span>
<p>判断质数。</p>
<b>函数签名:</b>
```go
func IsPrime(n int) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.IsPrime(-1)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// false
// true
}
```
### <span id="GCD">GCD</span>
<p>计算最大公约数。</p>
<b>函数签名:</b>
```go
func GCD[T constraints.Integer](integers ...T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.GCD(1, 1)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// 1
// -1
// -1
// 3
}
```
### <span id="LCM">LCM</span>
<p>计算最小公倍数。</p>
<b>函数签名:</b>
```go
func LCM[T constraints.Integer](integers ...T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.LCM(1, 1)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 18
}
```
### <span id="Cos">Cos</span>
<p>计算弧度的余弦值</p>
<b>函数签名:</b>
```go
func Cos(radian float64, precision ...int) float64
```
<b>示例:</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>示例:</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>示例:</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>示例:</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
}
```

View File

@@ -1,4 +1,5 @@
# Netutil # Netutil
Package netutil contains functions to get net information and send http request. Package netutil contains functions to get net information and send http request.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,13 +8,12 @@ Package netutil contains functions to get net information and send http request.
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go) - [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/netutil" "github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [ConvertMapToQueryString](#ConvertMapToQueryString) - [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl) - [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp) - [GetInternalIp](#GetInternalIp)
@@ -43,13 +44,17 @@ import (
- [HttpPut<sup>Deprecated</sup>](#HttpPut) - [HttpPut<sup>Deprecated</sup>](#HttpPut)
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch) - [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
- [ParseHttpResponse](#ParseHttpResponse) - [ParseHttpResponse](#ParseHttpResponse)
- [DownloadFile](#DownloadFile)
- [UploadFile](#UploadFile)
- [IsPingConnected](#IsPingConnected)
- [IsTelnetConnected](#IsTelnetConnected)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span> ### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>Convert map to url query string.</p> <p>Convert map to url query string.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -57,6 +62,7 @@ import (
```go ```go
func ConvertMapToQueryString(param map[string]any) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -75,13 +81,13 @@ func main() {
} }
qs := netutil.ConvertMapToQueryString(m) qs := netutil.ConvertMapToQueryString(m)
fmt.Println(qs) //a=1&b=2&c=3 // Output:
// a=1&b=2&c=3
} }
``` ```
### <span id="EncodeUrl">EncodeUrl</span> ### <span id="EncodeUrl">EncodeUrl</span>
<p>Encode url query string values.</p> <p>Encode url query string values.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -89,6 +95,7 @@ func main() {
```go ```go
func EncodeUrl(urlStr string) (string, error) func EncodeUrl(urlStr string) (string, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -102,16 +109,20 @@ import (
func main() { func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]" urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr) encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
fmt.Println(encodedUrl)
// Output:
// http://www.lancet.com?a=1&b=%5B2%5D
} }
``` ```
### <span id="GetInternalIp">GetInternalIp</span> ### <span id="GetInternalIp">GetInternalIp</span>
<p>Get internal ip information.</p> <p>Get internal ip information.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -119,6 +130,7 @@ func main() {
```go ```go
func GetInternalIp() string func GetInternalIp() string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -134,13 +146,15 @@ func main() {
internalIp := netutil.GetInternalIp() internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp) ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9 fmt.Println(ip)
// Output:
// 192.168.1.9
} }
``` ```
### <span id="GetIps">GetIps</span> ### <span id="GetIps">GetIps</span>
<p>Get all ipv4 list.</p> <p>Get all ipv4 list.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -148,6 +162,7 @@ func main() {
```go ```go
func GetIps() []string func GetIps() []string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -161,13 +176,15 @@ import (
func main() { func main() {
ips := netutil.GetIps() ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9] fmt.Println(ips)
// Output:
// [192.168.1.9]
} }
``` ```
### <span id="GetMacAddrs">GetMacAddrs</span> ### <span id="GetMacAddrs">GetMacAddrs</span>
<p>Get all mac addresses list.</p> <p>Get all mac addresses list.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -175,6 +192,7 @@ func main() {
```go ```go
func GetMacAddrs() []string { func GetMacAddrs() []string {
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -187,14 +205,16 @@ import (
) )
func main() { func main() {
addrs := netutil.GetMacAddrs() macAddrs := netutil.GetMacAddrs()
fmt.Println(addrs) fmt.Println(macAddrs)
// Output:
// [18:31:bf:09:d1:56 76:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f]
} }
``` ```
### <span id="GetPublicIpInfo">GetPublicIpInfo</span> ### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
<p>Get public ip information.</p> <p>Get public ip information.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -216,6 +236,7 @@ type PublicIpInfo struct {
Ip string `json:"query"` Ip string `json:"query"`
} }
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -236,9 +257,8 @@ func main() {
} }
``` ```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span> ### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>Get http request public ip.</p> <p>Get http request public ip.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -246,6 +266,7 @@ func main() {
```go ```go
func GetRequestPublicIp(req *http.Request) string func GetRequestPublicIp(req *http.Request) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -259,29 +280,23 @@ import (
func main() { func main() {
ip := "36.112.24.10" ip := "36.112.24.10"
request1 := http.Request{ request := http.Request{
Method: "GET", Method: "GET",
Header: http.Header{ Header: http.Header{
"X-Forwarded-For": {ip}, "X-Forwarded-For": {ip},
}, },
} }
publicIp1 := netutil.GetRequestPublicIp(&request1) publicIp := netutil.GetRequestPublicIp(&request)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{ fmt.Println(publicIp)
Method: "GET",
Header: http.Header{ // Output:
"X-Real-Ip": {ip}, // 36.112.24.10
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
} }
``` ```
### <span id="IsPublicIP">IsPublicIP</span> ### <span id="IsPublicIP">IsPublicIP</span>
<p>Checks if an ip is public or not.</p> <p>Checks if an ip is public or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -289,6 +304,7 @@ func main() {
```go ```go
func IsPublicIP(IP net.IP) bool func IsPublicIP(IP net.IP) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -301,18 +317,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("192.168.0.1") ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsPublicIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsPublicIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsPublicIP(ip1)) //false fmt.Println(ip1)
fmt.Println(netutil.IsPublicIP(ip2)) //true fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
} }
``` ```
### <span id="IsInternalIP">IsInternalIP</span> ### <span id="IsInternalIP">IsInternalIP</span>
<p>Checks if an ip is intranet or not.</p> <p>Checks if an ip is intranet or not.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -320,6 +341,7 @@ func main() {
```go ```go
func IsInternalIP(IP net.IP) bool func IsInternalIP(IP net.IP) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -332,16 +354,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("127.0.0.1") ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsInternalIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsInternalIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsInternalIP(ip1)) //true fmt.Println(ip1)
fmt.Println(netutil.IsInternalIP(ip2)) //false fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
} }
``` ```
### <span id="HttpRequest">HttpRequest</span> ### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest is a struct used to abstract HTTP request entity.</p> <p>HttpRequest is a struct used to abstract HTTP request entity.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -356,6 +385,7 @@ type HttpRequest struct {
Body []byte Body []byte
} }
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -384,8 +414,8 @@ func main() {
} }
``` ```
### <span id="HttpClient">HttpClient</span> ### <span id="HttpClient">HttpClient</span>
<p>HttpClient is a struct used to send HTTP request. It can be instanced with some configurations or none config.</p> <p>HttpClient is a struct used to send HTTP request. It can be instanced with some configurations or none config.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -412,6 +442,7 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -433,9 +464,8 @@ func main() {
} }
``` ```
### <span id="SendRequest">SendRequest</span> ### <span id="SendRequest">SendRequest</span>
<p>Use HttpClient to send HTTP request.</p> <p>Use HttpClient to send HTTP request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -443,6 +473,7 @@ func main() {
```go ```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -464,7 +495,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -475,15 +506,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="DecodeResponse">DecodeResponse</span> ### <span id="DecodeResponse">DecodeResponse</span>
<p>Decode http response into target object.</p> <p>Decode http response into target object.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -491,6 +527,7 @@ func main() {
```go ```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -512,7 +549,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -523,14 +560,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="StructToUrlValues">StructToUrlValues</span> ### <span id="StructToUrlValues">StructToUrlValues</span>
<p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p> <p>Convert struct to url values, only convert the field which is exported and has `json` tag.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -538,6 +581,7 @@ func main() {
```go ```go
func StructToUrlValues(targetStruct any) url.Values func StructToUrlValues(targetStruct any) url.Values
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -552,22 +596,33 @@ func main() {
type TodoQuery struct { type TodoQuery struct {
Id int `json:"id"` Id int `json:"id"`
UserId int `json:"userId"` UserId int `json:"userId"`
Name string `json:"name,omitempty"`
Status string
} }
todoQuery := TodoQuery{ item := TodoQuery{
Id: 1, Id: 1,
UserId: 2, UserId: 123,
Name: "test",
Status: "completed",
} }
todoValues := netutil.StructToUrlValues(todoQuery) queryValues := netutil.StructToUrlValues(item)
fmt.Println(todoValues.Get("id")) //1 fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("userId")) //2 fmt.Println(todoValues.Get("userId"))
fmt.Println(todoValues.Get("name"))
fmt.Println(todoValues.Get("status"))
// Output:
// 1
// 123
// test
//
} }
``` ```
### <span id="HttpGet">HttpGet</span>
<p>Send http get request. (Deprecated: use SendRequest for replacement)</p>
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>Send http get request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -578,6 +633,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpGet(url string, params ...any) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -606,10 +662,9 @@ func main() {
} }
``` ```
### <span id="HttpPost">HttpPost</span>
<p>Send http post request.(Deprecated: use SendRequest for replacement)</p>
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>Send http post request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -620,6 +675,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPost(url string, params ...any) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -636,16 +692,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)
} }
@@ -655,10 +709,9 @@ func main() {
} }
``` ```
### <span id="HttpPut">HttpPut</span>
<p>Send http put request. (Deprecated: use SendRequest for replacement)</p>
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>Send http put request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -669,6 +722,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPut(url string, params ...any) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -705,10 +759,9 @@ func main() {
} }
``` ```
### <span id="HttpDelete">HttpDelete</span>
<p>Send http delete request. (Deprecated: use SendRequest for replacement)</p>
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>Send http delete request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -719,6 +772,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpDelete(url string, params ...any) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -744,10 +798,9 @@ func main() {
} }
``` ```
### <span id="HttpPatch">HttpPatch</span>
<p>Send http patch request. (Deprecated: use SendRequest for replacement)</p>
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>Send http patch request.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -758,6 +811,7 @@ func main() {
// params[3] is http client which type should be http.Client. // params[3] is http client which type should be http.Client.
func HttpPatch(url string, params ...any) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -794,9 +848,8 @@ func main() {
} }
``` ```
### <span id="ParseHttpResponse">ParseHttpResponse</span> ### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>Decode http response to specified interface.</p> <p>Decode http response to specified interface.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -804,6 +857,7 @@ func main() {
```go ```go
func ParseHttpResponse(resp *http.Response, obj any) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -845,3 +899,123 @@ func main() {
} }
``` ```
### <span id="DownloadFile">DownloadFile</span>
<p>Download the file exist in url to a local file.</p>
<b>Signature:</b>
```go
func DownloadFile(filepath string, url string) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
err := netutil.DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
fmt.Println(err)
}
```
### <span id="UploadFile">UploadFile</span>
<p>Upload the file to a server.</p>
<b>Signature:</b>
```go
func UploadFile(filepath string, server string) (bool, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
ok, err := netutil.UploadFile("./a.jpg", "http://www.xxx.com/bucket/test")
fmt.Println(ok)
fmt.Println(err)
}
```
### <span id="IsPingConnected">IsPingConnected</span>
<p>checks if can ping the specified host or not.</p>
<b>Signature:</b>
```go
func IsPingConnected(host string) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
result1 := netutil.IsPingConnected("www.baidu.com")
result2 := netutil.IsPingConnected("www.!@#&&&.com")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="IsTelnetConnected">IsTelnetConnected</span>
<p>Checks if can telnet the specified host or not.</p>
<b>Signature:</b>
```go
func IsTelnetConnected(host string, port string) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
result1 := netutil.IsTelnetConnected("www.baidu.com", "80")
result2 := netutil.IsTelnetConnected("www.baidu.com", "123")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```

View File

@@ -1,4 +1,5 @@
# Netutil # Netutil
netutil 网络包支持获取 ip 地址,发送 http 请求。 netutil 网络包支持获取 ip 地址,发送 http 请求。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,13 +8,12 @@ netutil网络包支持获取ip地址发送http请求。
- [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go) - [https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http_client.go](https://github.com/duke-git/lancet/blob/main/netutil/http_client.go)
- [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go) - [https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/netutil" "github.com/duke-git/lancet/v2/netutil"
@@ -23,6 +23,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [ConvertMapToQueryString](#ConvertMapToQueryString) - [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl) - [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp) - [GetInternalIp](#GetInternalIp)
@@ -43,13 +44,17 @@ import (
- [HttpPut<sup>Deprecated</sup>](#HttpPut) - [HttpPut<sup>Deprecated</sup>](#HttpPut)
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch) - [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
- [ParseHttpResponse](#ParseHttpResponse) - [ParseHttpResponse](#ParseHttpResponse)
- [DownloadFile](#DownloadFile)
- [UploadFile](#UploadFile)
- [IsPingConnected](#IsPingConnected)
- [IsTelnetConnected](#IsTelnetConnected)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span> ### <span id="ConvertMapToQueryString">ConvertMapToQueryString</span>
<p>将map转换成http查询字符串.</p> <p>将map转换成http查询字符串.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -57,7 +62,8 @@ import (
```go ```go
func ConvertMapToQueryString(param map[string]any) string func ConvertMapToQueryString(param map[string]any) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -75,13 +81,15 @@ func main() {
} }
qs := netutil.ConvertMapToQueryString(m) qs := netutil.ConvertMapToQueryString(m)
fmt.Println(qs) //a=1&b=2&c=3 fmt.Println(qs)
// Output:
// a=1&b=2&c=3
} }
``` ```
### <span id="EncodeUrl">EncodeUrl</span> ### <span id="EncodeUrl">EncodeUrl</span>
<p>编码url query string的值</p> <p>编码url query string的值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -89,7 +97,8 @@ func main() {
```go ```go
func EncodeUrl(urlStr string) (string, error) func EncodeUrl(urlStr string) (string, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -102,17 +111,20 @@ import (
func main() { func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]" urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr) encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
fmt.Println(encodedUrl)
// Output:
// http://www.lancet.com?a=1&b=%5B2%5D
} }
``` ```
### <span id="GetInternalIp">GetInternalIp</span> ### <span id="GetInternalIp">GetInternalIp</span>
<p>获取内部ip</p> <p>获取内部ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -120,7 +132,8 @@ func main() {
```go ```go
func GetInternalIp() string func GetInternalIp() string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -135,12 +148,15 @@ func main() {
internalIp := netutil.GetInternalIp() internalIp := netutil.GetInternalIp()
ip := net.ParseIP(internalIp) ip := net.ParseIP(internalIp)
fmt.Println(ip) //192.168.1.9 fmt.Println(ip)
// Output:
// 192.168.1.9
} }
``` ```
### <span id="GetIps">GetIps</span> ### <span id="GetIps">GetIps</span>
<p>获取ipv4地址列表</p> <p>获取ipv4地址列表</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -148,7 +164,8 @@ func main() {
```go ```go
func GetIps() []string func GetIps() []string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -161,13 +178,15 @@ import (
func main() { func main() {
ips := netutil.GetIps() ips := netutil.GetIps()
fmt.Println(ips) //[192.168.1.9] fmt.Println(ips)
// Output:
// [192.168.1.9]
} }
``` ```
### <span id="GetMacAddrs">GetMacAddrs</span> ### <span id="GetMacAddrs">GetMacAddrs</span>
<p>获取mac地址列</p> <p>获取mac地址列</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -175,7 +194,8 @@ func main() {
```go ```go
func GetMacAddrs() []string { func GetMacAddrs() []string {
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -187,14 +207,16 @@ import (
) )
func main() { func main() {
addrs := netutil.GetMacAddrs() macAddrs := netutil.GetMacAddrs()
fmt.Println(addrs) fmt.Println(macAddrs)
// Output:
// [18:31:bf:09:d1:56 76:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f 74:ee:2a:e6:2e:0f]
} }
``` ```
### <span id="GetPublicIpInfo">GetPublicIpInfo</span> ### <span id="GetPublicIpInfo">GetPublicIpInfo</span>
<p>获取公网ip信息</p> <p>获取公网ip信息</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -216,7 +238,8 @@ type PublicIpInfo struct {
Ip string `json:"query"` Ip string `json:"query"`
} }
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -236,9 +259,8 @@ func main() {
} }
``` ```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span> ### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>获取http请求ip</p> <p>获取http请求ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -246,7 +268,8 @@ func main() {
```go ```go
func GetRequestPublicIp(req *http.Request) string func GetRequestPublicIp(req *http.Request) string
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -259,30 +282,23 @@ import (
func main() { func main() {
ip := "36.112.24.10" ip := "36.112.24.10"
request1 := http.Request{ request := http.Request{
Method: "GET", Method: "GET",
Header: http.Header{ Header: http.Header{
"X-Forwarded-For": {ip}, "X-Forwarded-For": {ip},
}, },
} }
publicIp1 := netutil.GetRequestPublicIp(&request1) publicIp := netutil.GetRequestPublicIp(&request)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{ fmt.Println(publicIp)
Method: "GET",
Header: http.Header{ // Output:
"X-Real-Ip": {ip}, // 36.112.24.10
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
} }
``` ```
### <span id="IsPublicIP">IsPublicIP</span> ### <span id="IsPublicIP">IsPublicIP</span>
<p>判断ip是否是公共ip</p> <p>判断ip是否是公共ip</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -290,7 +306,8 @@ func main() {
```go ```go
func IsPublicIP(IP net.IP) bool func IsPublicIP(IP net.IP) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -302,17 +319,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("192.168.0.1") ip1 := netutil.IsPublicIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsPublicIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsPublicIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsPublicIP(ip1)) //false fmt.Println(ip1)
fmt.Println(netutil.IsPublicIP(ip2)) //true fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
} }
``` ```
### <span id="IsInternalIP">IsInternalIP</span> ### <span id="IsInternalIP">IsInternalIP</span>
<p>判断ip是否是局域网ip.</p> <p>判断ip是否是局域网ip.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -320,7 +343,8 @@ func main() {
```go ```go
func IsInternalIP(IP net.IP) bool func IsInternalIP(IP net.IP) bool
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -332,16 +356,23 @@ import (
) )
func main() { func main() {
ip1 := net.ParseIP("127.0.0.1") ip1 := netutil.IsInternalIP(net.ParseIP("127.0.0.1"))
ip2 := net.ParseIP("36.112.24.10") ip2 := netutil.IsInternalIP(net.ParseIP("192.168.0.1"))
ip3 := netutil.IsInternalIP(net.ParseIP("36.112.24.10"))
fmt.Println(netutil.IsInternalIP(ip1)) //true fmt.Println(ip1)
fmt.Println(netutil.IsInternalIP(ip2)) //false fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
} }
``` ```
### <span id="HttpRequest">HttpRequest</span> ### <span id="HttpRequest">HttpRequest</span>
<p>HttpRequest用于抽象HTTP请求实体的结构</p> <p>HttpRequest用于抽象HTTP请求实体的结构</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -356,7 +387,8 @@ type HttpRequest struct {
Body []byte Body []byte
} }
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -384,8 +416,8 @@ func main() {
} }
``` ```
### <span id="HttpClient">HttpClient</span> ### <span id="HttpClient">HttpClient</span>
<p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p> <p>HttpClient是用于发送HTTP请求的结构体。它可以用一些配置参数或无配置实例化.</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -412,7 +444,8 @@ func NewHttpClient() *HttpClient
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -433,9 +466,8 @@ func main() {
} }
``` ```
### <span id="SendRequest">SendRequest</span> ### <span id="SendRequest">SendRequest</span>
<p>HttpClient发送http请求</p> <p>HttpClient发送http请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -443,7 +475,8 @@ func main() {
```go ```go
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -464,7 +497,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -475,15 +508,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="DecodeResponse">DecodeResponse</span> ### <span id="DecodeResponse">DecodeResponse</span>
<p>解析http响应体到目标结构体</p> <p>解析http响应体到目标结构体</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -491,7 +529,8 @@ func main() {
```go ```go
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -512,7 +551,7 @@ func main() {
httpClient := netutil.NewHttpClient() httpClient := netutil.NewHttpClient()
resp, err := httpClient.SendRequest(request) resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 { if err != nil || resp.StatusCode != 200 {
log.Fatal(err) return
} }
type Todo struct { type Todo struct {
@@ -523,14 +562,20 @@ func main() {
} }
var todo Todo var todo Todo
httpClient.DecodeResponse(resp, &todo) err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id) //1 fmt.Println(todo.Id)
// Output:
// 1
} }
``` ```
### <span id="StructToUrlValues">StructToUrlValues</span> ### <span id="StructToUrlValues">StructToUrlValues</span>
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p> <p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -538,7 +583,8 @@ func main() {
```go ```go
func StructToUrlValues(targetStruct any) url.Values func StructToUrlValues(targetStruct any) url.Values
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -552,22 +598,33 @@ func main() {
type TodoQuery struct { type TodoQuery struct {
Id int `json:"id"` Id int `json:"id"`
UserId int `json:"userId"` UserId int `json:"userId"`
Name string `json:"name,omitempty"`
Status string
} }
todoQuery := TodoQuery{ item := TodoQuery{
Id: 1, Id: 1,
UserId: 2, UserId: 123,
Name: "test",
Status: "completed",
} }
todoValues := netutil.StructToUrlValues(todoQuery) queryValues := netutil.StructToUrlValues(item)
fmt.Println(todoValues.Get("id")) //1 fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("userId")) //2 fmt.Println(todoValues.Get("userId"))
fmt.Println(todoValues.Get("name"))
fmt.Println(todoValues.Get("status"))
// Output:
// 1
// 123
// test
//
} }
``` ```
### <span id="HttpGet">HttpGet</span>
<p>发送http get请求。(已废弃:使用SendRequest)</p>
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
<p>发送http get请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -578,7 +635,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpGet(url string, params ...any) (*http.Response, error) func HttpGet(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -606,10 +664,9 @@ func main() {
} }
``` ```
### <span id="HttpPost">HttpPost</span>
<p>发送http post请求。(已废弃:使用SendRequest)</p>
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
<p>发送http post请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -620,7 +677,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPost(url string, params ...any) (*http.Response, error) func HttpPost(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -636,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)
} }
@@ -655,10 +711,9 @@ func main() {
} }
``` ```
### <span id="HttpPut">HttpPut</span>
<p>发送http put请求。(已废弃:使用SendRequest)</p>
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
<p>发送http put请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -669,7 +724,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPut(url string, params ...any) (*http.Response, error) func HttpPut(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -705,10 +761,9 @@ func main() {
} }
``` ```
### <span id="HttpDelete">HttpDelete</span>
<p>发送http delete请求。(已废弃:使用SendRequest)</p>
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
<p>发送http delete请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -719,7 +774,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpDelete(url string, params ...any) (*http.Response, error) func HttpDelete(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -744,10 +800,9 @@ func main() {
} }
``` ```
### <span id="HttpPatch">HttpPatch</span>
<p>发送http patch请求。(已废弃:使用SendRequest)</p>
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
<p>发送http patch请求</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -758,7 +813,8 @@ func main() {
// params[3] http client类型必须是http.Client // params[3] http client类型必须是http.Client
func HttpPatch(url string, params ...any) (*http.Response, error) func HttpPatch(url string, params ...any) (*http.Response, error)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -794,9 +850,8 @@ func main() {
} }
``` ```
### <span id="ParseHttpResponse">ParseHttpResponse</span> ### <span id="ParseHttpResponse">ParseHttpResponse</span>
<p>将http请求响应解码成特定struct值</p> <p>将http请求响应解码成特定struct值</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -804,7 +859,8 @@ func main() {
```go ```go
func ParseHttpResponse(resp *http.Response, obj any) error func ParseHttpResponse(resp *http.Response, obj any) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -845,3 +901,123 @@ func main() {
} }
``` ```
### <span id="DownloadFile">DownloadFile</span>
<p>从指定的server地址下载文件。</p>
<b>函数签名:</b>
```go
func DownloadFile(filepath string, url string) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
err := netutil.DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
fmt.Println(err)
}
```
### <span id="UploadFile">UploadFile</span>
<p>将文件上传指定的server地址。</p>
<b>函数签名:</b>
```go
func UploadFile(filepath string, server string) (bool, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
ok, err := netutil.UploadFile("./a.jpg", "http://www.xxx.com/bucket/test")
fmt.Println(ok)
fmt.Println(err)
}
```
### <span id="IsPingConnected">IsPingConnected</span>
<p>检查能否ping通主机。</p>
<b>函数签名:</b>
```go
func IsPingConnected(host string) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
result1 := netutil.IsPingConnected("www.baidu.com")
result2 := netutil.IsPingConnected("www.!@#&&&.com")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="IsTelnetConnected">IsTelnetConnected</span>
<p>检查能否telnet到主机。</p>
<b>函数签名:</b>
```go
func IsTelnetConnected(host string, port string) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
result1 := netutil.IsTelnetConnected("www.baidu.com", "80")
result2 := netutil.IsTelnetConnected("www.baidu.com", "123")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral) - [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter) - [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4) - [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -245,3 +246,30 @@ func main() {
fmt.Println(uuid) fmt.Println(uuid)
} }
``` ```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>Generate a slice of random int of length n that do not repeat.</p>
<b>Signature:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
result := RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral) - [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter) - [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4) - [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -45,7 +46,7 @@ import (
func RandBytes(length int) []byte func RandBytes(length int) []byte
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -71,7 +72,7 @@ func main() {
func RandInt(min, max int) int func RandInt(min, max int) int
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -97,7 +98,7 @@ func main() {
func RandString(length int) string func RandString(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -123,7 +124,7 @@ func main() {
func RandUpper(length int) string func RandUpper(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -149,7 +150,7 @@ func main() {
func RandLower(length int) string func RandLower(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -175,7 +176,7 @@ func main() {
func RandNumeral(length int) string func RandNumeral(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -201,7 +202,7 @@ func main() {
func RandNumeralOrLetter(length int) string func RandNumeralOrLetter(length int) string
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -227,7 +228,7 @@ func main() {
func UUIdV4() (string, error) func UUIdV4() (string, error)
``` ```
<b>例:</b> <b>例:</b>
```go ```go
package main package main
@@ -245,3 +246,29 @@ 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>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
result := RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -1,4 +1,5 @@
# Retry # Retry
Package retry is for executing a function repeatedly until it was successful or canceled by the context. Package retry is for executing a function repeatedly until it was successful or canceled by the context.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package retry is for executing a function repeatedly until it was successful or
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [Context](#Context) - [Context](#Context)
- [Retry](#Retry) - [Retry](#Retry)
- [RetryFunc](#RetryFunc) - [RetryFunc](#RetryFunc)
@@ -30,8 +32,8 @@ import (
## Documentation ## Documentation
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>Set retry context config, can cancel the retry with context.</p> <p>Set retry context config, can cancel the retry with context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -39,6 +41,7 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -52,7 +55,8 @@ import (
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number > 3 { if number > 3 {
@@ -61,21 +65,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, duration := retry.RetryDuration(time.Microsecond*50)
retry.RetryDuration(time.Microsecond*50),
retry.Retry(increaseNumber,
duration,
retry.Context(ctx), retry.Context(ctx),
) )
if err != nil { fmt.Println(number)
fmt.Println(err) //retry is cancelled
} // Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>Function that retry executes.</p> <p>Function that retry executes.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -83,6 +88,7 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -96,9 +102,8 @@ import (
) )
func main() { func main() {
var number int number := 0
var increaseNumber retry.RetryFunc = func() error {
increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
@@ -106,18 +111,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>Set times of retry. Default times is 5.</p> <p>Set times of retry. Default times is 5.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -125,6 +134,7 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -138,7 +148,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
@@ -150,14 +160,16 @@ func main() {
err := retry.Retry(increaseNumber, retry.RetryTimes(2)) err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil { if err != nil {
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1 fmt.Println(err)
} }
// Output:
// function main.main.func1 run failed after 2 times retry
} }
``` ```
### <span id="RetryDuration">RetryDuration</span> ### <span id="RetryDuration">RetryDuration</span>
<p>Set duration of retries. Default duration is 3 second.</p> <p>Set duration of retries. Default duration is 3 second.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -165,6 +177,7 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -178,7 +191,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -187,17 +200,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p> <p>Executes the retryFunc repeatedly until it was successful or canceled by the context.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -205,6 +223,7 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -218,7 +237,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -227,11 +246,16 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```

View File

@@ -1,4 +1,5 @@
# Retry # Retry
retry 重试执行函数直到函数运行成功或被 context cancel。 retry 重试执行函数直到函数运行成功或被 context cancel。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ retry重试执行函数直到函数运行成功或被context cancel。
- [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go) - [https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
@@ -20,20 +21,19 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [Context](#Context) - [Context](#Context)
- [Retry](#Retry) - [Retry](#Retry)
- [RetryFunc](#RetryFunc) - [RetryFunc](#RetryFunc)
- [RetryDuration](#RetryDuration) - [RetryDuration](#RetryDuration)
- [RetryTimes](#RetryTimes) - [RetryTimes](#RetryTimes)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Document 文档 ## Document 文档
### <span id="Context">Context</span> ### <span id="Context">Context</span>
<p>设置重试context参数</p> <p>设置重试context参数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -41,7 +41,8 @@ import (
```go ```go
func Context(ctx context.Context) func Context(ctx context.Context)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
@@ -54,7 +55,8 @@ import (
func main() { func main() {
ctx, cancel := context.WithCancel(context.TODO()) ctx, cancel := context.WithCancel(context.TODO())
var number int
number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number > 3 { if number > 3 {
@@ -63,21 +65,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, duration := retry.RetryDuration(time.Microsecond*50)
retry.RetryDuration(time.Microsecond*50),
retry.Retry(increaseNumber,
duration,
retry.Context(ctx), retry.Context(ctx),
) )
if err != nil { fmt.Println(number)
fmt.Println(err) //retry is cancelled
} // Output:
// 4
} }
``` ```
### <span id="RetryFunc">RetryFunc</span> ### <span id="RetryFunc">RetryFunc</span>
<p>被重试执行的函数</p> <p>被重试执行的函数</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -85,7 +88,8 @@ func main() {
```go ```go
type RetryFunc func() error type RetryFunc func() error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -98,8 +102,8 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { var increaseNumber retry.RetryFunc = func() error {
number++ number++
if number == 3 { if number == 3 {
return nil return nil
@@ -107,18 +111,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="RetryTimes">RetryTimes</span> ### <span id="RetryTimes">RetryTimes</span>
<p>设置重试次数默认5</p> <p>设置重试次数默认5</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -126,7 +134,8 @@ func main() {
```go ```go
func RetryTimes(n uint) func RetryTimes(n uint)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -139,7 +148,8 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -150,14 +160,16 @@ func main() {
err := retry.Retry(increaseNumber, retry.RetryTimes(2)) err := retry.Retry(increaseNumber, retry.RetryTimes(2))
if err != nil { if err != nil {
log.Fatal(err) //2022/02/01 18:42:25 function main.main.func1 run failed after 2 times retry exit status 1 fmt.Println(err)
} }
// Output:
// function main.main.func1 run failed after 2 times retry
} }
``` ```
### <span id="RetryDuration">RetryDuration</span> ### <span id="RetryDuration">RetryDuration</span>
<p>设置重试间隔时间默认3秒</p> <p>设置重试间隔时间默认3秒</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -165,7 +177,8 @@ func main() {
```go ```go
func RetryDuration(d time.Duration) func RetryDuration(d time.Duration)
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -178,7 +191,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -187,17 +200,22 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```
### <span id="Retry">Retry</span> ### <span id="Retry">Retry</span>
<p>重试执行函数retryFunc直到函数运行成功或被context停止</p> <p>重试执行函数retryFunc直到函数运行成功或被context停止</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -205,7 +223,8 @@ func main() {
```go ```go
func Retry(retryFunc RetryFunc, opts ...Option) error func Retry(retryFunc RetryFunc, opts ...Option) error
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -218,7 +237,7 @@ import (
) )
func main() { func main() {
var number int number := 0
increaseNumber := func() error { increaseNumber := func() error {
number++ number++
if number == 3 { if number == 3 {
@@ -227,11 +246,16 @@ func main() {
return errors.New("error occurs") return errors.New("error occurs")
} }
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50)) duration := retry.RetryDuration(time.Microsecond*50)
err := retry.Retry(increaseNumber, duration)
if err != nil { if err != nil {
log.Fatal(err) return
} }
fmt.Println(number) //3 fmt.Println(number)
// Output:
// 3
} }
``` ```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

940
docs/stream.md Normal file
View File

@@ -0,0 +1,940 @@
# Stream
Package stream implements a sequence of elements supporting sequential and operations. This package is an experiment to explore if stream in go can work as the way java does. it's feature is very limited.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/stream"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Of](#Of)
- [FromSlice](#FromSlice)
- [FromChannel](#FromChannel)
- [FromRange](#FromRange)
- [Generate](#Generate)
- [Concat](#Concat)
- [Distinct](#Distinct)
- [Filter](#Filter)
- [Map](#Map)
- [Peek](#Peek)
- [Skip](#Skip)
- [Limit](#Limit)
- [Reverse](#Reverse)
- [Range](#Range)
- [Sorted](#Sorted)
- [ForEach](#ForEach)
- [Reduce](#Reduce)
- [FindFirst](#FindFirst)
- [FindLast](#FindLast)
- [Max](#Max)
- [Min](#Min)
- [AllMatch](#AllMatch)
- [AnyMatch](#AnyMatch)
- [NoneMatch](#NoneMatch)
- [Count](#Count)
- [ToSlice](#ToSlice)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Of">Of</span>
<p>Creates a stream whose elements are the specified values.</p>
<b>Signature:</b>
```go
func Of[T any](elems ...T) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.Of(1, 2, 3)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromSlice">FromSlice</span>
<p>Creates a stream from slice.</p>
<b>Signature:</b>
```go
func FromSlice[T any](source []T) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.FromSlice([]int{1, 2, 3})
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromChannel">FromChannel</span>
<p>Creates a stream from channel.</p>
<b>Signature:</b>
```go
func FromChannel[T any](source <-chan T) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
ch := make(chan int)
go func() {
for i := 1; i < 4; i++ {
ch <- i
}
close(ch)
}()
s := stream.FromChannel(ch)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromRange">FromRange</span>
<p>Creates a number stream from start to end. both start and end are included. [start, end]</p>
<b>Signature:</b>
```go
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.FromRange(1, 5, 1)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3 4 5]
}
```
### <span id="Generate">Generate</span>
<p>Creates a stream where each element is generated by the provided generater function.</p>
<b>Signature:</b>
```go
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
n := 0
max := 4
generator := func() func() (int, bool) {
return func() (int, bool) {
n++
return n, n < max
}
}
s := stream.Generate(generator)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="Concat">Concat</span>
<p>Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.</p>
<b>Signature:</b>
```go
func Concat[T any](a, b stream[T]) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s1 := stream.FromSlice([]int{1, 2, 3})
s2 := stream.FromSlice([]int{4, 5, 6})
s := Concat(s1, s2)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="Distinct">Distinct</span>
<p>Creates returns a stream that removes the duplicated items. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Distinct() stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
distinct := original.Distinct()
data1 := original.ToSlice()
data2 := distinct.ToSlice()
fmt.Println(data1)
fmt.Println(data2)
// Output:
// [1 2 2 3 3 3]
// [1 2 3]
}
```
### <span id="Filter">Filter</span>
<p>Returns a stream consisting of the elements of this stream that match the given predicate. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
isEven := func(n int) bool {
return n%2 == 0
}
even := original.Filter(isEven)
fmt.Println(even.ToSlice())
// Output:
// [2 4]
}
```
### <span id="Map">Map</span>
<p>Returns a stream consisting of the elements of this stream that apply the given function to elements of stream. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Map(mapper func(item T) T) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
addOne := func(n int) int {
return n + 1
}
increament := original.Map(addOne)
fmt.Println(increament.ToSlice())
// Output:
// [2 3 4]
}
```
### <span id="Peek">Peek</span>
<p>Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Peek(consumer func(item T)) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
data := []string{}
peekStream := original.Peek(func(n int) {
data = append(data, fmt.Sprint("value", n))
})
fmt.Println(original.ToSlice())
fmt.Println(peekStream.ToSlice())
fmt.Println(data)
// Output:
// [1 2 3]
// [1 2 3]
// [value1 value2 value3]
}
```
### <span id="Skip">Skip</span>
<p>Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Skip(n int) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4})
s1 := original.Skip(-1)
s2 := original.Skip(0)
s3 := original.Skip(1)
s4 := original.Skip(5)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// [1 2 3 4]
// [1 2 3 4]
// [2 3 4]
// []
}
```
### <span id="Limit">Limit</span>
<p>Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Limit(maxSize int) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4})
s1 := original.Limit(-1)
s2 := original.Limit(0)
s3 := original.Limit(1)
s4 := original.Limit(5)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// []
// []
// [1]
// [1 2 3 4]
}
```
### <span id="Reverse">Reverse</span>
<p>Returns a stream whose elements are reverse order of given stream. <b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Reverse() stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
reverse := original.Reverse()
fmt.Println(reverse.ToSlice())
// Output:
// [3 2 1]
}
```
### <span id="Range">Range</span>
<p>Returns a stream whose elements are in the range from start(included) to end(excluded) original stream.<b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Range(start, end int) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
s1 := original.Range(0, 0)
s2 := original.Range(0, 1)
s3 := original.Range(0, 3)
s4 := original.Range(1, 2)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// []
// [1]
// [1 2 3]
// [2]
}
```
### <span id="Sorted">Sorted</span>
<p>Returns a stream consisting of the elements of this stream, sorted according to the provided less function.<b>Support chainable operation</b></p>
<b>Signature:</b>
```go
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
sorted := original.Sorted(func(a, b int) bool { return a < b })
fmt.Println(original.ToSlice())
fmt.Println(sorted.ToSlice())
// Output:
// [4 2 1 3]
// [1 2 3 4]
}
```
### <span id="ForEach">ForEach</span>
<p>Performs an action for each element of this stream.</p>
<b>Signature:</b>
```go
func (s stream[T]) ForEach(action func(item T))
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result := 0
original.ForEach(func(item int) {
result += item
})
fmt.Println(result)
// Output:
// 6
}
```
### <span id="Reduce">Reduce</span>
<p>Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.</p>
<b>Signature:</b>
```go
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result := original.Reduce(0, func(a, b int) int {
return a + b
})
fmt.Println(result)
// Output:
// 6
}
```
### <span id="FindFirst">FindFirst</span>
<p>Returns the first element of this stream and true, or zero value and false if the stream is empty.</p>
<b>Signature:</b>
```go
func (s stream[T]) FindFirst() (T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result, ok := original.FindFirst()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="FindLast">FindLast</span>
<p>Returns the last element of this stream and true, or zero value and false if the stream is empty.</p>
<b>Signature:</b>
```go
func (s stream[T]) FindLast() (T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="Max">Max</span>
<p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p>
<b>Signature:</b>
```go
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
max, ok := original.Max(func(a, b int) bool { return a > b })
fmt.Println(max)
fmt.Println(ok)
// Output:
// 4
// true
}
```
### <span id="Min">Min</span>
<p>Returns the minimum element of this stream according to the provided less function. less fuction: a < b</p>
<b>Signature:</b>
```go
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
min, ok := original.Min(func(a, b int) bool { return a < b })
fmt.Println(min)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="AllMatch">AllMatch</span>
<p>Returns whether all elements of this stream match the provided predicate.</p>
<b>Signature:</b>
```go
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.AllMatch(func(item int) bool {
return item > 0
})
result2 := original.AllMatch(func(item int) bool {
return item > 1
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="AnyMatch">AnyMatch</span>
<p>Returns whether any elements of this stream match the provided predicate.</p>
<b>Signature:</b>
```go
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.AnyMatch(func(item int) bool {
return item > 1
})
result2 := original.AnyMatch(func(item int) bool {
return item > 3
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="NoneMatch">NoneMatch</span>
<p>Returns whether no elements of this stream match the provided predicate.</p>
<b>Signature:</b>
```go
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.NoneMatch(func(item int) bool {
return item > 3
})
result2 := original.NoneMatch(func(item int) bool {
return item > 1
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="Count">Count</span>
<p>Returns the count of elements in the stream.</p>
<b>Signature:</b>
```go
func (s stream[T]) Count() int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s1 := stream.FromSlice([]int{1, 2, 3})
s2 := stream.FromSlice([]int{})
fmt.Println(s1.Count())
fmt.Println(s2.Count())
// Output:
// 3
// 0
}
```
### <span id="ToSlice">ToSlice</span>
<p>Returns the elements in the stream.</p>
<b>Signature:</b>
```go
func (s stream[T]) ToSlice() []T
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.Of(1, 2, 3)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```

940
docs/stream_zh-CN.md Normal file
View File

@@ -0,0 +1,940 @@
# Stream
Stream 流,该包仅验证简单 stream 实现,功能有限。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/stream"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Of](#Of)
- [FromSlice](#FromSlice)
- [FromChannel](#FromChannel)
- [FromRange](#FromRange)
- [Generate](#Generate)
- [Concat](#Concat)
- [Distinct](#Distinct)
- [Filter](#Filter)
- [Map](#Map)
- [Peek](#Peek)
- [Skip](#Skip)
- [Limit](#Limit)
- [Reverse](#Reverse)
- [Range](#Range)
- [Sorted](#Sorted)
- [ForEach](#ForEach)
- [Reduce](#Reduce)
- [FindFirst](#FindFirst)
- [FindLast](#FindLast)
- [Max](#Max)
- [Min](#Min)
- [AllMatch](#AllMatch)
- [AnyMatch](#AnyMatch)
- [NoneMatch](#NoneMatch)
- [Count](#Count)
- [ToSlice](#ToSlice)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Of">Of</span>
<p>创建元素为指定值的stream。</p>
<b>函数签名:</b>
```go
func Of[T any](elems ...T) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.Of(1, 2, 3)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromSlice">FromSlice</span>
<p>从切片创建stream。</p>
<b>函数签名:</b>
```go
func FromSlice[T any](source []T) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.FromSlice([]int{1, 2, 3})
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromChannel">FromChannel</span>
<p>从通道创建stream。</p>
<b>函数签名:</b>
```go
func FromChannel[T any](source <-chan T) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
ch := make(chan int)
go func() {
for i := 1; i < 4; i++ {
ch <- i
}
close(ch)
}()
s := stream.FromChannel(ch)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="FromRange">FromRange</span>
<p>指定一个范围创建stream, 范围两端点值都包括在内。</p>
<b>函数签名:</b>
```go
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.FromRange(1, 5, 1)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3 4 5]
}
```
### <span id="Generate">Generate</span>
<p>创建一个stream其中每个元素都由提供的生成器函数生成</p>
<b>函数签名:</b>
```go
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
n := 0
max := 4
generator := func() func() (int, bool) {
return func() (int, bool) {
n++
return n, n < max
}
}
s := stream.Generate(generator)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```
### <span id="Concat">Concat</span>
<p>创建一个延迟连接stream其元素是第一个stream的所有元素后跟第二个stream的全部元素。</p>
<b>函数签名:</b>
```go
func Concat[T any](a, b stream[T]) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s1 := stream.FromSlice([]int{1, 2, 3})
s2 := stream.FromSlice([]int{4, 5, 6})
s := Concat(s1, s2)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3 4 5 6]
}
```
### <span id="Distinct">Distinct</span>
<p>创建并返回一个stream用于删除重复的项。 <b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Distinct() stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
distinct := original.Distinct()
data1 := original.ToSlice()
data2 := distinct.ToSlice()
fmt.Println(data1)
fmt.Println(data2)
// Output:
// [1 2 2 3 3 3]
// [1 2 3]
}
```
### <span id="Filter">Filter</span>
<p>返回一个通过判定函数的stream <b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
isEven := func(n int) bool {
return n%2 == 0
}
even := original.Filter(isEven)
fmt.Println(even.ToSlice())
// Output:
// [2 4]
}
```
### <span id="Map">Map</span>
<p>返回一个stream该stream由将给定函数应用于源stream元素的元素组成。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Map(mapper func(item T) T) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
addOne := func(n int) int {
return n + 1
}
increament := original.Map(addOne)
fmt.Println(increament.ToSlice())
// Output:
// [2 3 4]
}
```
### <span id="Peek">Peek</span>
<p>返回一个由源stream的元素组成的stream并在从生成的stream中消耗元素时对每个元素执行所提供的操作。 <b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Peek(consumer func(item T)) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
data := []string{}
peekStream := original.Peek(func(n int) {
data = append(data, fmt.Sprint("value", n))
})
fmt.Println(original.ToSlice())
fmt.Println(peekStream.ToSlice())
fmt.Println(data)
// Output:
// [1 2 3]
// [1 2 3]
// [value1 value2 value3]
}
```
### <span id="Skip">Skip</span>
<p>在丢弃stream的前n个元素后返回由源stream的其余元素组成的stream。如果此stream包含的元素少于n个则将返回一个空stream。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Skip(n int) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4})
s1 := original.Skip(-1)
s2 := original.Skip(0)
s3 := original.Skip(1)
s4 := original.Skip(5)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// [1 2 3 4]
// [1 2 3 4]
// [2 3 4]
// []
}
```
### <span id="Limit">Limit</span>
<p>返回由源stream的元素组成的stream该stream被截断为长度不超过maxSize。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Limit(maxSize int) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3, 4})
s1 := original.Limit(-1)
s2 := original.Limit(0)
s3 := original.Limit(1)
s4 := original.Limit(5)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// []
// []
// [1]
// [1 2 3 4]
}
```
### <span id="Reverse">Reverse</span>
<p>返回元素与源stream的顺序相反的stream。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Reverse() stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
reverse := original.Reverse()
fmt.Println(reverse.ToSlice())
// Output:
// [3 2 1]
}
```
### <span id="Range">Range</span>
<p>返回一个stream该stream的元素在从源stream的开始包含到结束排除的范围内。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Range(start, end int) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
s1 := original.Range(0, 0)
s2 := original.Range(0, 1)
s3 := original.Range(0, 3)
s4 := original.Range(1, 2)
fmt.Println(s1.ToSlice())
fmt.Println(s2.ToSlice())
fmt.Println(s3.ToSlice())
fmt.Println(s4.ToSlice())
// Output:
// []
// [1]
// [1 2 3]
// [2]
}
```
### <span id="Sorted">Sorted</span>
<p>返回一个stream该stream由源stream的元素组成并根据提供的less函数进行排序。<b>支持链式操作</b></p>
<b>函数签名:</b>
```go
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
sorted := original.Sorted(func(a, b int) bool { return a < b })
fmt.Println(original.ToSlice())
fmt.Println(sorted.ToSlice())
// Output:
// [4 2 1 3]
// [1 2 3 4]
}
```
### <span id="ForEach">ForEach</span>
<p>对stream的每个元素执行一个操作。</p>
<b>函数签名:</b>
```go
func (s stream[T]) ForEach(action func(item T))
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result := 0
original.ForEach(func(item int) {
result += item
})
fmt.Println(result)
// Output:
// 6
}
```
### <span id="Reduce">Reduce</span>
<p>使用关联累加函数对stream的元素执行reduce操作并reduce操作结果如果有。</p>
<b>函数签名:</b>
```go
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result := original.Reduce(0, func(a, b int) int {
return a + b
})
fmt.Println(result)
// Output:
// 6
}
```
### <span id="FindFirst">FindFirst</span>
<p>返回此stream的第一个元素和true如果stream为空则返回零值和false。</p>
<b>函数签名:</b>
```go
func (s stream[T]) FindFirst() (T, bool)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result, ok := original.FindFirst()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="FindLast">FindLast</span>
<p>返回此stream最后一个元素和true如果stream为空则返回零值和false。</p>
<b>函数签名:</b>
```go
func (s stream[T]) FindLast() (T, bool)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="Max">Max</span>
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>
<b>函数签名:</b>
```go
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
max, ok := original.Max(func(a, b int) bool { return a > b })
fmt.Println(max)
fmt.Println(ok)
// Output:
// 4
// true
}
```
### <span id="Min">Min</span>
<p>根据提供的less函数返回stream的最小元素。less函数: a < b</p>
<b>函数签名:</b>
```go
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{4, 2, 1, 3})
min, ok := original.Min(func(a, b int) bool { return a < b })
fmt.Println(min)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="AllMatch">AllMatch</span>
<p>判断stream的所有元素是否全部匹配指定判定函数。</p>
<b>函数签名:</b>
```go
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.AllMatch(func(item int) bool {
return item > 0
})
result2 := original.AllMatch(func(item int) bool {
return item > 1
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="AnyMatch">AnyMatch</span>
<p>判断stream是否包含匹配指定判定函数的元素。</p>
<b>函数签名:</b>
```go
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.AnyMatch(func(item int) bool {
return item > 1
})
result2 := original.AnyMatch(func(item int) bool {
return item > 3
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="NoneMatch">NoneMatch</span>
<p>判断stream的元素是否全部不匹配指定的判定函数。</p>
<b>函数签名:</b>
```go
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := stream.FromSlice([]int{1, 2, 3})
result1 := original.NoneMatch(func(item int) bool {
return item > 3
})
result2 := original.NoneMatch(func(item int) bool {
return item > 1
})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="Count">Count</span>
<p>返回stream中元素的数量。</p>
<b>函数签名:</b>
```go
func (s stream[T]) Count() int
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s1 := stream.FromSlice([]int{1, 2, 3})
s2 := stream.FromSlice([]int{})
fmt.Println(s1.Count())
fmt.Println(s2.Count())
// Output:
// 3
// 0
}
```
### <span id="ToSlice">ToSlice</span>
<p>返回stream中的元素切片。</p>
<b>函数签名:</b>
```go
func (s stream[T]) ToSlice() []T
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
s := stream.Of(1, 2, 3)
data := s.ToSlice()
fmt.Println(data)
// Output:
// [1 2 3]
}
```

354
docs/structs/field.md Normal file
View File

@@ -0,0 +1,354 @@
# Field
Field is abstract struct field for provide several high level functions
<div STYLE="page-break-after: always;"></div>
## Source:
- [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>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/structs"
)
```
<div STYLE="page-break-after: always;"></div>
## Index:
- [Tag](#Tag)
- [Name](#Name)
- [Value](#Value)
- [Kind](#Kind)
- [IsEmbedded](#IsEmbedded)
- [IsExported](#IsExported)
- [IsZero](#IsZero)
- [IsSlice](#IsSlice)
> NoteSince `Field` inherits from `Struct`, it also has all the methods of 'Struct', as follows:
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#ToMap)
- [Fields](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#Fields)
- [Field](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#Field)
- [IsStruct](https://github.com/duke-git/lancet/blob/main/docs/structs/struct.md#IsStruct)
<div STYLE="page-break-after: always;"></div>
## Documentation:
### <span id="Tag">Tag</span>
<p>Get a `Tag` of the `Field`, `Tag` is a abstract struct field tag</p>
<b>Signature:</b>
```go
func (f *Field) Tag() *Tag
```
<b>Example:</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>Get the `Field` underlying value</p>
<b>Signature:</b>
```go
func (f *Field) Value() any
```
<b>Example:</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>Check if the field is an embedded field</p>
<b>Signature:</b>
```go
func (f *Field) IsEmbedded() bool
```
<b>Example:</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>Check if the field is exported</p>
<b>Signature:</b>
```go
func (f *Field) IsExported() bool
```
<b>Example:</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>Check if the field is zero value</p>
<b>Signature:</b>
```go
func (f *Field) IsZero() bool
```
<b>Example:</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>Get the field name</p>
<b>Signature:</b>
```go
func (f *Field) Name() string
```
<b>Example:</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>Get the field's kind</p>
<b>Signature:</b>
```go
func (f *Field) Kind() reflect.Kind
```
<b>Example:</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>Check if the field is a slice</p>
<b>Signature:</b>
```go
func (f *Field) IsSlice() bool
```
<b>Example:</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
}
```

353
docs/structs/field_zh-CN.md Normal file
View File

@@ -0,0 +1,353 @@
# Field
Field 包封装了一个抽象的`Field`结构体,提供了操作`struct`属性的相关函数
<div STYLE="page-break-after: always;"></div>
## 源码:
- [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>
## 目录:
- [Tag](#Tag)
- [Name](#Name)
- [Value](#Value)
- [Kind](#Kind)
- [IsEmbedded](#IsEmbedded)
- [IsExported](#IsExported)
- [IsZero](#IsZero)
- [IsSlice](#IsSlice)
> 注意:由于`Field`继承于`Struct`,所以同样拥有`Struct`所有方法,如下:
- [ToMap](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#ToMap)
- [Fields](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#Fields)
- [Field](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#Field)
- [IsStruct](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#IsStruct)
<div STYLE="page-break-after: always;"></div>
## API 文档:
### <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
}
```

214
docs/structs/struct.md Normal file
View File

@@ -0,0 +1,214 @@
# Structs
Struct is abstract struct for provide several high level functions
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/structs/struct.go](https://github.com/duke-git/lancet/blob/main/structs/struct.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/structs"
)
```
<div STYLE="page-break-after: always;"></div>
## Index:
- [New](#New)
- [ToMap](#ToMap)
- [Fields](#Fields)
- [Field](#Field)
- [IsStruct](#IsStruct)
<div STYLE="page-break-after: always;"></div>
## Documentation:
### <span id="New">New</span>
<p>The constructor function of the `Struct` </p>
<b>Signature:</b>
```go
func New(value any, tagName ...string) *Struct
```
<b>Example:</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>convert a valid struct to a map</p>
<b>Signature:</b>
```go
func (s *Struct) ToMap() (map[string]any, error)
```
> In addition, provided a convenient static function ToMap
```go
func ToMap(v any) (map[string]any, error)
```
<b>Example:</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"}
// use constructor function
s1 := structs.New(p1)
m1, _ := s1.ToMap()
fmt.Println(m1)
// use static function
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
}
```
### <span id="Fields">Fields</span>
<p>Get all fields of a given struct, that the fields are abstract struct field</p>
<b>Signature:</b>
```go
func (s *Struct) Fields() []*Field
```
<b>Example:</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>Get an abstract field of a struct by given field name </p>
<b>Signature:</b>
```go
func (s *Struct) Field(name string) *Field
```
<b>Example:</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>Check if the struct is valid</p>
<b>Signature:</b>
```go
func (s *Struct) IsStruct() bool
```
<b>Example:</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
}
```

View File

@@ -0,0 +1,213 @@
# 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)
<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)
<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
}
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
# System # System
Package system contains some functions about os, runtime, shell command. Package system contains some functions about os, runtime, shell command.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ Package system contains some functions about os, runtime, shell command.
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [IsWindows](#IsWindows) - [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsLinux](#IsLinux)
- [IsMac](#IsMac) - [IsMac](#IsMac)
@@ -30,13 +32,12 @@ import (
- [ExecCommand](#ExecCommand) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits) - [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>Check if current os is windows.</p> <p>Check if current os is windows.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,6 +45,7 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -58,10 +60,8 @@ func main() {
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>Check if current os is linux.</p> <p>Check if current os is linux.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,6 +69,7 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -83,9 +84,8 @@ func main() {
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>Check if current os is macos.</p> <p>Check if current os is macos.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,6 +93,7 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -107,9 +108,8 @@ func main() {
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>Gets the value of the environment variable named by the key.</p> <p>Gets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,6 +117,7 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -126,14 +127,19 @@ import (
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>Sets the value of the environment variable named by the key.</p> <p>Sets the value of the environment variable named by the key.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,6 +147,7 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -150,15 +157,19 @@ import (
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err) fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>Remove a single environment variable.</p> <p>Remove a single environment variable.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,6 +177,7 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -175,16 +187,27 @@ import (
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} err2 := system.RemoveOsEnv("foo")
result2 := GetOsEnv("foo")
fmt.Println(err1)
fmt.Println(err2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// <nil>
// <nil>
// abc
//
} }
``` ```
### <span id="CompareOsEnv">CompareOsEnv</span> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>Get env named by the key and compare it with comparedEnv.</p> <p>Get env named by the key and compare it with comparedEnv.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,6 +215,7 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -201,23 +225,33 @@ import (
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">ExecCommand</span>
### <span id="ExecCommand">CompareOsEnv</span>
<p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p> <p>Execute shell command, return the stdout and stderr string of command, and error if error occur. param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1. In linux, use /bin/bash -c to execute command, In windows, use powershell.exe to execute command.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) type (
Option func(*exec.Cmd)
)
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -248,10 +282,8 @@ func main() {
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p> <p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
<b>Signature:</b> <b>Signature:</b>
@@ -259,6 +291,7 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -269,9 +302,6 @@ import (
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```

View File

@@ -1,4 +1,5 @@
# System # System
system 包含 os, runtime, shell command 相关函数。 system 包含 os, runtime, shell command 相关函数。
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -7,10 +8,10 @@ system包含os, runtime, shell command相关函数。
- [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go) - [https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/system" "github.com/duke-git/lancet/v2/system"
@@ -20,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [IsWindows](#IsWindows) - [IsWindows](#IsWindows)
- [IsLinux](#IsLinux) - [IsLinux](#IsLinux)
- [IsMac](#IsMac) - [IsMac](#IsMac)
@@ -30,13 +32,12 @@ import (
- [ExecCommand](#ExecCommand) - [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits) - [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation 文档 ## Documentation 文档
### <span id="IsWindows">IsWindows</span> ### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p> <p>检查当前操作系统是否是windows</p>
<b>Signature:</b> <b>Signature:</b>
@@ -44,6 +45,7 @@ import (
```go ```go
func IsWindows() bool func IsWindows() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -58,10 +60,8 @@ func main() {
} }
``` ```
### <span id="IsLinux">IsLinux</span> ### <span id="IsLinux">IsLinux</span>
<p>检查当前操作系统是否是linux</p> <p>检查当前操作系统是否是linux</p>
<b>Signature:</b> <b>Signature:</b>
@@ -69,6 +69,7 @@ func main() {
```go ```go
func IsLinux() bool func IsLinux() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -83,9 +84,8 @@ func main() {
} }
``` ```
### <span id="IsMac">IsMac</span> ### <span id="IsMac">IsMac</span>
<p>检查当前操作系统是否是macos</p> <p>检查当前操作系统是否是macos</p>
<b>Signature:</b> <b>Signature:</b>
@@ -93,6 +93,7 @@ func main() {
```go ```go
func IsMac() bool func IsMac() bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -107,9 +108,8 @@ func main() {
} }
``` ```
### <span id="GetOsEnv">GetOsEnv</span> ### <span id="GetOsEnv">GetOsEnv</span>
<p>获取key命名的环境变量的值</p> <p>获取key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -117,6 +117,7 @@ func main() {
```go ```go
func GetOsEnv(key string) string func GetOsEnv(key string) string
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -126,14 +127,19 @@ import (
) )
func main() { func main() {
fooEnv := system.GetOsEnv("foo") err := system.SetOsEnv("foo", "abc")
fmt.Println(fooEnv) result := system.GetOsEnv("foo")
fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="SetOsEnv">SetOsEnv</span> ### <span id="SetOsEnv">SetOsEnv</span>
<p>设置由key命名的环境变量的值</p> <p>设置由key命名的环境变量的值</p>
<b>Signature:</b> <b>Signature:</b>
@@ -141,6 +147,7 @@ func main() {
```go ```go
func SetOsEnv(key, value string) error func SetOsEnv(key, value string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -150,15 +157,19 @@ import (
) )
func main() { func main() {
err := system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
result := system.GetOsEnv("foo")
fmt.Println(err) fmt.Println(err)
fmt.Println(result)
// Output:
// <nil>
// abc
} }
``` ```
### <span id="RemoveOsEnv">RemoveOsEnv</span> ### <span id="RemoveOsEnv">RemoveOsEnv</span>
<p>删除单个环境变量</p> <p>删除单个环境变量</p>
<b>Signature:</b> <b>Signature:</b>
@@ -166,6 +177,7 @@ func main() {
```go ```go
func RemoveOsEnv(key string) error func RemoveOsEnv(key string) error
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -175,16 +187,27 @@ import (
) )
func main() { func main() {
err := system.RemoveOsEnv("foo") err1 := system.SetOsEnv("foo", "abc")
if err != nil { result1 := GetOsEnv("foo")
fmt.Println(err)
} err2 := system.RemoveOsEnv("foo")
result2 := GetOsEnv("foo")
fmt.Println(err1)
fmt.Println(err2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// <nil>
// <nil>
// abc
//
} }
``` ```
### <span id="CompareOsEnv">CompareOsEnv</span> ### <span id="CompareOsEnv">CompareOsEnv</span>
<p>获取key命名的环境变量值并与compareEnv进行比较</p> <p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b> <b>Signature:</b>
@@ -192,6 +215,7 @@ func main() {
```go ```go
func CompareOsEnv(key, comparedEnv string) bool func CompareOsEnv(key, comparedEnv string) bool
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -201,23 +225,33 @@ import (
) )
func main() { func main() {
system.SetOsEnv("foo", "foo_value") err := system.SetOsEnv("foo", "abc")
res := system.CompareOsEnv("foo", "foo_value") if err != nil {
fmt.Println(res) //true return
}
result := system.CompareOsEnv("foo", "abc")
fmt.Println(result)
// Output:
// true
} }
``` ```
### <span id="ExecCommand">ExecCommand</span> ### <span id="ExecCommand">ExecCommand</span>
<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>Signature:</b>
```go ```go
func ExecCommand(command string) (stdout, stderr string, err error) type (
Option func(*exec.Cmd)
)
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -248,10 +282,8 @@ func main() {
} }
``` ```
### <span id="GetOsBits">GetOsBits</span> ### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数返回32或64</p> <p>获取当前操作系统位数返回32或64</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -259,7 +291,8 @@ func main() {
```go ```go
func GetOsBits() int func GetOsBits() int
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
import ( import (
@@ -269,13 +302,6 @@ import (
func main() { func main() {
osBit := system.GetOsBits() osBit := system.GetOsBits()
fmt.Println(osBit) fmt.Println(osBit) // 32 or 64
} }
``` ```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
# Xerror # Xerror
Package xerror implements helpers for errors. Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ Package xerror implements helpers for errors.
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Usage: ## Usage:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,22 +21,43 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Index ## Index
- [New](#New)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
- [XError_Wrap](#XError_Wrap)
- [XError_Unwrap](#XError_Unwrap)
- [XError_With](#XError_With)
- [XError_Is](#XError_Is)
- [XError_Id](#XError_Id)
- [XError_Values](#XError_Values)
- [XError_StackTrace](#XError_StackTrace)
- [XError_Info](#XError_Info)
- [XError_Error](#XError_Error)
- [TryUnwrap](#TryUnwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## Documentation ## Documentation
### <span id="New">New</span>
<p>Creates a new XError pointer instance with message.</p>
### <span id="Unwrap">Unwrap</span>
<p>Unwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Unwrap[T any](val T, err error) T type XError struct {
id string
message string
stack *stack
cause error
values map[string]any
}
func New(format string, args ...any) *XError
``` ```
<b>Example:</b> <b>Example:</b>
```go ```go
@@ -46,7 +69,407 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) err := xerror.New("error")
fmt.Println(err.Error())
// Output:
// error
}
```
### <span id="Wrap">Wrap</span>
<p>Creates a new XError pointer instance based on error object, and add message.</p>
<b>Signature:</b>
```go
func Wrap(cause error, message ...any) *XError
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("wrong password")
wrapErr := xerror.Wrap(err, "error")
fmt.Println(wrapErr.Error())
// Output:
// error: wrong password
}
```
### <span id="Unwrap">Unwrap</span>
<p>Returns unwrapped XError from err by errors.As. If no XError, returns nil.</p>
<b>Signature:</b>
```go
func Unwrap(err error) *XError
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/pkg/errors"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").With("level", "high")
wrapErr := errors.Wrap(err1, "oops")
err := xerror.Unwrap(wrapErr)
values := err.Values()
fmt.Println(values["level"])
// Output:
// high
}
```
### <span id="XError_Wrap">XError_Wrap</span>
<p>Creates a new XError and copy message and id to new one.</p>
<b>Signature:</b>
```go
func (e *XError) Wrap(cause error) *XError
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("wrong password")
wrapErr := xerror.Wrap(err, "error")
fmt.Println(wrapErr.Error())
// Output:
// error: wrong password
}
```
### <span id="XError_Unwrap">XError_Unwrap</span>
<p>Compatible with github.com/pkg/errors.</p>
<b>Signature:</b>
```go
func (e *XError) Unwrap() error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").With("level", "high")
err2 := err1.Wrap(errors.New("invalid username"))
err := err2.Unwrap()
fmt.Println(err.Error())
// Output:
// invalid username
}
```
### <span id="XError_With">XError_With</span>
<p>Adds key and value related to the XError object.</p>
<b>Signature:</b>
```go
func (e *XError) With(key string, value any) *XError
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error").With("level", "high")
errLevel := err.Values()["level"]
fmt.Println(errLevel)
// Output:
// high
}
```
### <span id="XError_Id">XError_Id</span>
<p>Sets XError object id to check equality in XError.Is.</p>
<b>Signature:</b>
```go
func (e *XError) Id(id string) *XError
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").Id("e001")
err2 := xerror.New("error").Id("e001")
err3 := xerror.New("error").Id("e003")
equal := err1.Is(err2)
notEqual := err1.Is(err3)
fmt.Println(equal)
fmt.Println(notEqual)
// Output:
// true
// false
}
```
### <span id="XError_Is">XError_Is</span>
<p>Checks if target error is XError and Error.id of two errors are matched.</p>
<b>Signature:</b>
```go
func (e *XError) Is(target error) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").Id("e001")
err2 := xerror.New("error").Id("e001")
err3 := xerror.New("error").Id("e003")
equal := err1.Is(err2)
notEqual := err1.Is(err3)
fmt.Println(equal)
fmt.Println(notEqual)
// Output:
// true
// false
}
```
### <span id="XError_Values">XError_Values</span>
<p>Returns map of key and value that is set by With. All wrapped xerror.XError key and values will be merged. Key and values of wrapped error is overwritten by upper xerror.XError.</p>
<b>Signature:</b>
```go
func (e *XError) Values() map[string]any
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error").With("level", "high")
errLevel := err.Values()["level"]
fmt.Println(errLevel)
// Output:
// high
}
```
### <span id="XError_StackTrace">XError_StackTrace</span>
<p>Returns stack trace which is compatible with pkg/errors.</p>
<b>Signature:</b>
```go
func (e *XError) StackTrace() StackTrace
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error")
stacks := err.Stacks()
fmt.Println(stacks[0].Func)
fmt.Println(stacks[0].Line)
containFile := strings.Contains(stacks[0].File, "xxx.go")
fmt.Println(containFile)
}
```
### <span id="XError_Info">XError_Info</span>
<p>Returns information of xerror, which can be printed.</p>
<b>Signature:</b>
```go
func (e *XError) Info() *errInfo
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
cause := errors.New("error")
err := xerror.Wrap(cause, "invalid username").Id("e001").With("level", "high")
errInfo := err.Info()
fmt.Println(errInfo.Id)
fmt.Println(errInfo.Cause)
fmt.Println(errInfo.Values["level"])
fmt.Println(errInfo.Message)
// Output:
// e001
// error
// high
// invalid username
}
```
### <span id="XError_Error">XError_Error</span>
<p>Error implements standard error interface.</p>
<b>Signature:</b>
```go
func (e *XError) Error() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error")
fmt.Println(err.Error())
// Output:
// error
}
```
### <span id="TryUnwrap">TryUnwrap</span>
<p>TryUnwrap if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.</p>
<b>Signature:</b>
```go
func TryUnwrap[T any](val T, err error) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
result1 := xerror.TryUnwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
@@ -56,7 +479,7 @@ func main() {
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.TryUnwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42

View File

@@ -1,4 +1,5 @@
# Xerror # Xerror
xerror 错误处理逻辑封装 xerror 错误处理逻辑封装
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -10,6 +11,7 @@ xerror错误处理逻辑封装
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 用法: ## 用法:
```go ```go
import ( import (
"github.com/duke-git/lancet/v2/xerror" "github.com/duke-git/lancet/v2/xerror"
@@ -19,23 +21,44 @@ import (
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 目录 ## 目录
- [New](#New)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
- [XError_Wrap](#XError_Wrap)
- [XError_Unwrap](#XError_Unwrap)
- [XError_With](#XError_With)
- [XError_Is](#XError_Is)
- [XError_Id](#XError_Id)
- [XError_Values](#XError_Values)
- [XError_StackTrace](#XError_StackTrace)
- [XError_Info](#XError_Info)
- [XError_Error](#XError_Error)
- [TryUnwrap](#TryUnwrap)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
## 文档 ## 文档
### <span id="New">New</span>
<p>创建XError对象实例。</p>
### <span id="Unwrap">Unwrap</span>
<p>检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。</p>
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Unwrap[T any](val T, err error) T type XError struct {
id string
message string
stack *stack
cause error
values map[string]any
}
func New(format string, args ...any) *XError
``` ```
<b>例子:</b>
<b>示例:</b>
```go ```go
package main package main
@@ -46,7 +69,408 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42")) err := xerror.New("error")
fmt.Println(err.Error())
// Output:
// error
}
```
### <span id="Wrap">Wrap</span>
<p>根据error对象创建XError对象实例可添加message。</p>
<b>函数签名:</b>
```go
func Wrap(cause error, message ...any) *XError
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("wrong password")
wrapErr := xerror.Wrap(err, "error")
fmt.Println(wrapErr.Error())
// Output:
// error: wrong password
}
```
### <span id="Unwrap">Unwrap</span>
<p>从error对象中解构出XError。</p>
<b>函数签名:</b>
```go
func Unwrap(err error) *XError
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/pkg/errors"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").With("level", "high")
wrapErr := errors.Wrap(err1, "oops")
err := xerror.Unwrap(wrapErr)
values := err.Values()
fmt.Println(values["level"])
// Output:
// high
}
```
### <span id="XError_Wrap">XError_Wrap</span>
<p>创建新的XError对象并将消息和id复制到新的对象中。</p>
<b>函数签名:</b>
```go
func (e *XError) Wrap(cause error) *XError
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("wrong password")
wrapErr := xerror.Wrap(err, "error")
fmt.Println(wrapErr.Error())
// Output:
// error: wrong password
}
```
### <span id="XError_Unwrap">XError_Unwrap</span>
<p>解构XEerror为error对象。适配github.com/pkg/errors。</p>
<b>函数签名:</b>
```go
func (e *XError) Unwrap() error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").With("level", "high")
err2 := err1.Wrap(errors.New("invalid username"))
err := err2.Unwrap()
fmt.Println(err.Error())
// Output:
// invalid username
}
```
### <span id="XError_With">XError_With</span>
<p>添加与XError对象的键和值。</p>
<b>函数签名:</b>
```go
func (e *XError) With(key string, value any) *XError
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error").With("level", "high")
errLevel := err.Values()["level"]
fmt.Println(errLevel)
// Output:
// high
}
```
### <span id="XError_Id">XError_Id</span>
<p>设置XError对象的id。</p>
<b>函数签名:</b>
```go
func (e *XError) Id(id string) *XError
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").Id("e001")
err2 := xerror.New("error").Id("e001")
err3 := xerror.New("error").Id("e003")
equal := err1.Is(err2)
notEqual := err1.Is(err3)
fmt.Println(equal)
fmt.Println(notEqual)
// Output:
// true
// false
}
```
### <span id="XError_Is">XError_Is</span>
<p>检查目标error是否为XError两个错误中的error.id是否匹配。</p>
<b>函数签名:</b>
```go
func (e *XError) Is(target error) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err1 := xerror.New("error").Id("e001")
err2 := xerror.New("error").Id("e001")
err3 := xerror.New("error").Id("e003")
equal := err1.Is(err2)
notEqual := err1.Is(err3)
fmt.Println(equal)
fmt.Println(notEqual)
// Output:
// true
// false
}
```
### <span id="XError_Values">XError_Values</span>
<p>返回由With设置的键和值的映射。将合并所有XError键和值。</p>
<b>函数签名:</b>
```go
func (e *XError) Values() map[string]any
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error").With("level", "high")
errLevel := err.Values()["level"]
fmt.Println(errLevel)
// Output:
// high
}
```
### <span id="XError_StackTrace">XError_StackTrace</span>
<p>返回与pkg/error兼容的堆栈信息。</p>
<b>函数签名:</b>
```go
func (e *XError) StackTrace() StackTrace
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error")
stacks := err.Stacks()
fmt.Println(stacks[0].Func)
fmt.Println(stacks[0].Line)
containFile := strings.Contains(stacks[0].File, "xxx.go")
fmt.Println(containFile)
}
```
### <span id="XError_Info">XError_Info</span>
<p>返回可打印的XError对象信息。</p>
<b>函数签名:</b>
```go
func (e *XError) Info() *errInfo
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
cause := errors.New("error")
err := xerror.Wrap(cause, "invalid username").Id("e001").With("level", "high")
errInfo := err.Info()
fmt.Println(errInfo.Id)
fmt.Println(errInfo.Cause)
fmt.Println(errInfo.Values["level"])
fmt.Println(errInfo.Message)
// Output:
// e001
// error
// high
// invalid username
}
```
### <span id="XError_Error">XError_Error</span>
<p>实现标准库的error接口。</p>
<b>函数签名:</b>
```go
func (e *XError) Error() string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
err := xerror.New("error")
fmt.Println(err.Error())
// Output:
// error
}
```
### <span id="TryUnwrap">TryUnwrap</span>
<p>检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则TryUnwrap使用err发生panic。</p>
<b>函数签名:</b>
```go
func TryUnwrap[T any](val T, err error) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
result1 := xerror.TryUnwrap(strconv.Atoi("42"))
fmt.Println(result1) fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
@@ -56,7 +480,7 @@ func main() {
fmt.Println(result2) fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.TryUnwrap(strconv.Atoi("4o2"))
// Output: // Output:
// 42 // 42

View File

@@ -7,6 +7,11 @@ package fileutil
import ( import (
"archive/zip" "archive/zip"
"bufio" "bufio"
"bytes"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/csv"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@@ -15,6 +20,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
) )
@@ -67,14 +73,14 @@ func RemoveFile(path string) error {
// CopyFile copy src file to dest file. // CopyFile copy src file to dest file.
// Play: https://go.dev/play/p/Jg9AMJMLrJi // Play: https://go.dev/play/p/Jg9AMJMLrJi
func CopyFile(srcFilePath string, dstFilePath string) error { func CopyFile(srcPath string, dstPath string) error {
srcFile, err := os.Open(srcFilePath) srcFile, err := os.Open(srcPath)
if err != nil { if err != nil {
return err return err
} }
defer srcFile.Close() defer srcFile.Close()
distFile, err := os.Create(dstFilePath) distFile, err := os.Create(dstPath)
if err != nil { if err != nil {
return err return err
} }
@@ -173,6 +179,23 @@ func ListFileNames(path string) ([]string, error) {
return result, nil return result, nil
} }
// IsZipFile checks if file is zip or not.
// Play: https://go.dev/play/p/9M0g2j_uF_e
func IsZipFile(filepath string) bool {
f, err := os.Open(filepath)
if err != nil {
return false
}
defer f.Close()
buf := make([]byte, 4)
if n, err := f.Read(buf); err != nil || n < 4 {
return false
}
return bytes.Equal(buf, []byte("PK\x03\x04"))
}
// Zip create zip file, fpath could be a single file or a directory. // Zip create zip file, fpath could be a single file or a directory.
// Play: https://go.dev/play/p/j-3sWBp8ik_P // Play: https://go.dev/play/p/j-3sWBp8ik_P
func Zip(fpath string, destPath string) error { func Zip(fpath string, destPath string) error {
@@ -185,7 +208,11 @@ func Zip(fpath string, destPath string) error {
archive := zip.NewWriter(zipFile) archive := zip.NewWriter(zipFile)
defer archive.Close() defer archive.Close()
err = filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error { return addFileToArchive(fpath, archive)
}
func addFileToArchive(fpath string, archive *zip.Writer) error {
err := filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
@@ -201,34 +228,24 @@ func Zip(fpath string, destPath string) error {
header.Name += "/" header.Name += "/"
} else { } else {
header.Method = zip.Deflate header.Method = zip.Deflate
}
writer, err := archive.CreateHeader(header) writer, err := archive.CreateHeader(header)
if err != nil { if err != nil {
return err return err
} }
if !info.IsDir() {
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
return err return err
} }
defer file.Close() defer file.Close()
_, err = io.Copy(writer, file) if _, err := io.Copy(writer, file); err != nil {
if err != nil {
return err return err
} }
} }
return nil return nil
}) })
if err != nil {
return err return err
} }
return nil
}
// UnZip unzip the file and save it to destPath. // UnZip unzip the file and save it to destPath.
// Play: https://go.dev/play/p/g0w34kS7B8m // Play: https://go.dev/play/p/g0w34kS7B8m
func UnZip(zipFile string, destPath string) error { func UnZip(zipFile string, destPath string) error {
@@ -275,9 +292,68 @@ func UnZip(zipFile string, destPath string) error {
} }
} }
} }
return nil return nil
} }
// ZipAppendEntry append a single file or directory by fpath to an existing zip file.
// Play: https://go.dev/play/p/cxvaT8TRNQp
func ZipAppendEntry(fpath string, destPath string) error {
tempFile, err := os.CreateTemp("", "temp.zip")
if err != nil {
return err
}
defer os.Remove(tempFile.Name())
zipReader, err := zip.OpenReader(destPath)
if err != nil {
return err
}
archive := zip.NewWriter(tempFile)
for _, zipItem := range zipReader.File {
zipItemReader, err := zipItem.Open()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(zipItem.FileInfo())
if err != nil {
return err
}
header.Name = zipItem.Name
targetItem, err := archive.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(targetItem, zipItemReader)
if err != nil {
return err
}
}
err = addFileToArchive(fpath, archive)
if err != nil {
return err
}
err = zipReader.Close()
if err != nil {
return err
}
err = archive.Close()
if err != nil {
return err
}
err = tempFile.Close()
if err != nil {
return err
}
return CopyFile(tempFile.Name(), destPath)
}
func safeFilepathJoin(path1, path2 string) (string, error) { func safeFilepathJoin(path1, path2 string) (string, error) {
relPath, err := filepath.Rel(".", path2) relPath, err := filepath.Rel(".", path2)
if err != nil || strings.HasPrefix(relPath, "..") { if err != nil || strings.HasPrefix(relPath, "..") {
@@ -345,3 +421,141 @@ func MiMeType(file any) string {
} }
return mediatype return mediatype
} }
// CurrentPath return current absolute path.
// Play: https://go.dev/play/p/s74a9iBGcSw
func CurrentPath() string {
var absPath string
_, filename, _, ok := runtime.Caller(1)
if ok {
absPath = path.Dir(filename)
}
return absPath
}
// FileSize returns file size in bytes.
// Play: https://go.dev/play/p/H9Z05uD-Jjc
func FileSize(path string) (int64, error) {
f, err := os.Stat(path)
if err != nil {
return 0, err
}
return f.Size(), nil
}
// MTime returns file modified time.
// Play: https://go.dev/play/p/s_Tl7lZoAaY
func MTime(filepath string) (int64, error) {
f, err := os.Stat(filepath)
if err != nil {
return 0, err
}
return f.ModTime().Unix(), nil
}
// Sha returns file sha value, param `shaType` should be 1, 256 or 512.
// Play: https://go.dev/play/p/VfEEcO2MJYf
func Sha(filepath string, shaType ...int) (string, error) {
file, err := os.Open(filepath)
if err != nil {
return "", err
}
defer file.Close()
h := sha1.New()
if len(shaType) > 0 {
if shaType[0] == 1 {
h = sha1.New()
} else if shaType[0] == 256 {
h = sha256.New()
} else if shaType[0] == 512 {
h = sha512.New()
} else {
return "", errors.New("param `shaType` should be 1, 256 or 512.")
}
}
_, err = io.Copy(h, file)
if err != nil {
return "", err
}
sha := fmt.Sprintf("%x", h.Sum(nil))
return sha, nil
}
// ReadCsvFile read file content into slice.
// Play: https://go.dev/play/p/OExTkhGEd3_u
func ReadCsvFile(filepath string) ([][]string, error) {
f, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer f.Close()
csvReader := csv.NewReader(f)
records, err := csvReader.ReadAll()
if err != nil {
return nil, err
}
return records, nil
}
// WriteCsvFile write content to target csv file.
// Play: todo
func WriteCsvFile(filepath string, records [][]string, append bool) error {
flag := os.O_RDWR | os.O_CREATE
if append {
flag = flag | os.O_APPEND
}
f, err := os.OpenFile(filepath, flag, 0644)
if err != nil {
return err
}
defer f.Close()
writer := csv.NewWriter(f)
writer.Comma = ','
return writer.WriteAll(records)
}
// WriteStringToFile write string to target file.
// Play: https://go.dev/play/p/GhLS6d8lH_g
func WriteStringToFile(filepath string, content string, append bool) error {
flag := os.O_RDWR | os.O_CREATE
if append {
flag = flag | os.O_APPEND
}
f, err := os.OpenFile(filepath, flag, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(content)
return err
}
// WriteBytesToFile write bytes to target file.
// Play: https://go.dev/play/p/s7QlDxMj3P8
func WriteBytesToFile(filepath string, content []byte) error {
f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(content)
return err
}

View File

@@ -175,11 +175,11 @@ func ExampleReadFileByLine() {
} }
func ExampleListFileNames() { func ExampleListFileNames() {
fileList, _ := ListFileNames("../formatter/") fileList, _ := ListFileNames("../internal")
fmt.Println(fileList) fmt.Println(fileList)
// Output: // Output:
// [formatter.go formatter_example_test.go formatter_test.go] // [assert.go assert_test.go error_join.go]
} }
func ExampleZip() { func ExampleZip() {
@@ -223,3 +223,159 @@ func ExampleUnZip() {
// Output: // Output:
// application/octet-stream // application/octet-stream
} }
func ExampleZipAppendEntry() {
zipFile := "./test.zip"
CopyFile("./testdata/file.go.zip", zipFile)
ZipAppendEntry("./testdata", zipFile)
unZipPath := "./unzip"
UnZip(zipFile, unZipPath)
fmt.Println(IsExist("./unzip/file.go"))
fmt.Println(IsExist("./unzip/testdata/file.go.zip"))
fmt.Println(IsExist("./unzip/testdata/test.txt"))
os.Remove(zipFile)
os.RemoveAll(unZipPath)
// Output:
// true
// true
// true
}
func ExampleIsZipFile() {
result1 := IsZipFile("./file.go")
result2 := IsZipFile("./testdata/file.go.zip")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// false
// true
}
func ExampleFileSize() {
size, err := FileSize("./testdata/test.txt")
fmt.Println(size)
fmt.Println(err)
// Output:
// 20
// <nil>
}
// func ExampleMTime() {
// mtime, err := MTime("./testdata/test.txt")
// fmt.Println(mtime) // 1682478195 (unix timestamp)
// fmt.Println(err)
// // Output:
// // 1682478195
// // <nil>
// }
func ExampleSha() {
sha1, err := Sha("./testdata/test.txt", 1)
sha256, _ := Sha("./testdata/test.txt", 256)
sha512, _ := Sha("./testdata/test.txt", 512)
fmt.Println(sha1)
fmt.Println(sha256)
fmt.Println(sha512)
fmt.Println(err)
// Output:
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
// <nil>
}
func ExampleReadCsvFile() {
content, err := ReadCsvFile("./testdata/demo.csv")
fmt.Println(content)
fmt.Println(err)
// Output:
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
// <nil>
}
func ExampleWriteCsvFile() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
func ExampleWriteStringToFile() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
func ExampleWriteBytesToFile() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}

View File

@@ -107,7 +107,7 @@ func TestReadFileToString(t *testing.T) {
_, err := f.WriteString("hello world") _, err := f.WriteString("hello world")
if err != nil { if err != nil {
t.Log(err) t.Error(err)
} }
content, _ := ReadFileToString(path) content, _ := ReadFileToString(path)
@@ -127,7 +127,7 @@ func TestClearFile(t *testing.T) {
_, err := f.WriteString("hello world") _, err := f.WriteString("hello world")
if err != nil { if err != nil {
t.Log(err) t.Error(err)
} }
err = ClearFile(path) err = ClearFile(path)
@@ -151,7 +151,7 @@ func TestReadFileByLine(t *testing.T) {
_, err := f.WriteString("hello\nworld") _, err := f.WriteString("hello\nworld")
if err != nil { if err != nil {
t.Log(err) t.Error(err)
} }
expected := []string{"hello", "world"} expected := []string{"hello", "world"}
@@ -191,6 +191,44 @@ func TestZipAndUnZip(t *testing.T) {
os.RemoveAll(unZipPath) os.RemoveAll(unZipPath)
} }
func TestZipAppendEntry(t *testing.T) {
assert := internal.NewAssert(t, "TestZipAppendEntry")
zipFile := "./text.zip"
err := CopyFile("./testdata/file.go.zip", zipFile)
assert.IsNil(err)
srcFile := "./text.txt"
CreateFile(srcFile)
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, os.ModePerm)
_, err = file.WriteString("hello\nworld")
if err != nil {
t.Fail()
}
file.Close()
err = ZipAppendEntry(srcFile, zipFile)
assert.IsNil(err)
err = ZipAppendEntry("./testdata", zipFile)
assert.IsNil(err)
unZipPath := "./unzip"
err = UnZip(zipFile, unZipPath)
assert.IsNil(err)
assert.Equal(true, IsExist("./unzip/text.txt"))
assert.Equal(true, IsExist("./unzip/file.go"))
assert.Equal(true, IsExist("./unzip/testdata/file.go.zip"))
assert.Equal(true, IsExist("./unzip/testdata/test.txt"))
os.Remove(srcFile)
os.Remove(zipFile)
os.RemoveAll(unZipPath)
}
func TestFileMode(t *testing.T) { func TestFileMode(t *testing.T) {
assert := internal.NewAssert(t, "TestFileMode") assert := internal.NewAssert(t, "TestFileMode")
@@ -198,9 +236,9 @@ func TestFileMode(t *testing.T) {
CreateFile(srcFile) CreateFile(srcFile)
mode, err := FileMode(srcFile) mode, err := FileMode(srcFile)
assert.IsNil(err)
t.Log(mode) assert.IsNotNil(mode)
assert.IsNil(err)
os.Remove(srcFile) os.Remove(srcFile)
} }
@@ -235,9 +273,152 @@ func TestMiMeType(t *testing.T) {
func TestListFileNames(t *testing.T) { func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames") assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("../formatter/") filesInPath, err := ListFileNames("../internal")
assert.IsNil(err) assert.IsNil(err)
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"} expected := []string{"assert.go", "assert_test.go", "error_join.go"}
assert.Equal(expected, filesInPath) assert.Equal(expected, filesInPath)
} }
func TestCurrentPath(t *testing.T) {
absPath := CurrentPath()
t.Log(absPath)
}
func TestIsZipFile(t *testing.T) {
assert := internal.NewAssert(t, "TestIsZipFile")
assert.Equal(false, IsZipFile("./file.go"))
assert.Equal(true, IsZipFile("./testdata/file.go.zip"))
}
func TestFileSize(t *testing.T) {
assert := internal.NewAssert(t, "TestFileSize")
size, err := FileSize("./testdata/test.txt")
assert.IsNil(err)
assert.Equal(int64(20), size)
}
func TestMTime(t *testing.T) {
assert := internal.NewAssert(t, "TestMTime")
mtime, err := MTime("./testdata/test.txt")
t.Log("TestMTime", mtime)
assert.IsNil(err)
// assert.Equal(int64(1682478195), mtime)
}
func TestSha(t *testing.T) {
assert := internal.NewAssert(t, "TestSha")
sha1, err := Sha("./testdata/test.txt", 1)
sha256, err := Sha("./testdata/test.txt", 256)
sha512, err := Sha("./testdata/test.txt", 512)
assert.IsNil(err)
assert.Equal("dda3cf10c5a6ff6c6659a497bf7261b287af2bc7", sha1)
assert.Equal("aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35", sha256)
assert.Equal("d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870", sha512)
}
func TestReadCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestReadCsvFile")
content, err := ReadCsvFile("./testdata/demo.csv")
assert.IsNil(err)
assert.Equal(3, len(content))
assert.Equal(3, len(content[0]))
assert.Equal("Bob", content[0][0])
}
func TestWriteCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteCsvFile")
csvFilePath := "./testdata/test1.csv"
content := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile(csvFilePath, content, false)
assert.IsNil(err)
readContent, err := ReadCsvFile(csvFilePath)
assert.IsNil(err)
assert.Equal(2, len(readContent))
assert.Equal(3, len(readContent[0]))
assert.Equal("Lili", content[0][0])
// RemoveFile(csvFilePath)
}
func TestWriteStringToFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteStringToFile")
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
t.Fail()
}
defer file.Close()
err = WriteStringToFile(filepath, "hello", false)
if err != nil {
t.Fail()
}
content1, err := ReadFileToString(filepath)
if err != nil {
t.Fail()
}
err = WriteStringToFile(filepath, " world", true)
if err != nil {
t.Fail()
}
content2, err := os.ReadFile(filepath)
if err != nil {
t.Fail()
}
assert.Equal("hello", content1)
assert.Equal("hello world", string(content2))
os.Remove(filepath)
}
func TestWriteBytesToFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteBytesToFile")
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
t.Fail()
}
defer file.Close()
err = WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
t.Fail()
}
content, err := os.ReadFile(filepath)
if err != nil {
t.Fail()
}
assert.Equal("hello", string(content))
os.Remove(filepath)
}

3
fileutil/testdata/demo.csv vendored Normal file
View File

@@ -0,0 +1,3 @@
Bob, 12, male
Duke, 14, male
Lucy, 16, female
1 Bob 12 male
2 Duke 14 male
3 Lucy 16 female

BIN
fileutil/testdata/file.go.zip vendored Normal file

Binary file not shown.

1
fileutil/testdata/test.txt vendored Normal file
View File

@@ -0,0 +1 @@
this is a test file.

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