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

Compare commits

...

7 Commits

Author SHA1 Message Date
BoWen Qiu
a254ebdc8e fix(algorithm): fix bug of lrucache in issue #251 (#254) 2024-10-16 09:55:38 +08:00
dudaodong
0bc11001a4 fix: add rsa public and private key example file 2024-10-12 15:16:39 +08:00
dudaodong
85d98ad915 Merge branch 'rc' into v2 2024-10-12 14:06:15 +08:00
77
cb08613ac3 fix(orderedmap): fix set bug (#252)
set : when the key is present, the value of the data map should be set,
not the value of the list

Co-authored-by: congziqi <congziqi@lixiang.com>
2024-10-12 14:05:13 +08:00
dudaodong
bad1b05224 doc: add doc for RsaSign and RsaVerifySign 2024-10-11 15:38:42 +08:00
dudaodong
527328739a feat: add RsaSign and RsaVerifySign 2024-10-10 15:40:32 +08:00
dudaodong
213e2b4ead doc: add play ground demo 2024-10-09 16:56:56 +08:00
37 changed files with 813 additions and 315 deletions

2
.gitignore vendored
View File

@@ -8,7 +8,7 @@ fileutil/*.link
fileutil/unzip/*
fileutil/tempdir/*
slice/testdata/*
cryptor/*.pem
# cryptor/*.pem
test
docs/node_modules
docs/.vitepress/cache

104
README.md
View File

@@ -364,10 +364,10 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
- **<big>AesGcmEncrypt</big>** : encrypt byte slice data with key use AES GCM algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#AesGcmEncrypt)]
[[play](todo)]
[[play](https://go.dev/play/p/rUt0-DmsPCs)]
- **<big>AesGcmDecrypt</big>** : decrypt byte slice data with key use AES GCM algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#AesGcmDecrypt)]
[[play](todo)]
[[play](https://go.dev/play/p/rUt0-DmsPCs)]
- **<big>Base64StdEncode</big>** : encode string with base64 encoding.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#Base64StdEncode)]
[[play](https://go.dev/play/p/VOaUyQUreoK)]
@@ -611,13 +611,13 @@ import "github.com/duke-git/lancet/v2/datetime"
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
- **<big>TrackFuncTime</big>** : tracks function execution time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#TrackFuncTime)]
[[play](todo)]
[[play](https://go.dev/play/p/QBSEdfXHPTp)]
- **<big>DaysBetween</big>** : returns the number of days between two times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#DaysBetween)]
[[play](todo)]
[[play](https://go.dev/play/p/qD6qGb3TbOy)]
- **<big>GenerateDatetimesBetween</big>** : returns a slice of strings between two times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/datetime.md#GenerateDatetimesBetween)]
[[play](todo)]
[[play](https://go.dev/play/p/6kHBpAxD9ZC)]
<h3 id="datastructure"> 8. Datastructure package contains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -813,10 +813,10 @@ import "github.com/duke-git/lancet/v2/function"
[[play](https://go.dev/play/p/absuEGB_GN7)]
- **<big>Debounce</big>** : creates a debounced version of the provided function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Debounce)]
[[play](todo)]
[[play](https://go.dev/play/p/-dGFrYn_1Zi)]
- **<big>Throttle</big>** : creates a throttled version of the provided function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Throttle)]
[[play](todo)]
[[play](https://go.dev/play/p/HpoMov-tJSN)]
- **<big>Schedule</big>** : invoke function every duration time, util close the returned bool channel.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/function.md#Schedule)]
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
@@ -937,58 +937,58 @@ import "github.com/duke-git/lancet/v2/maputil"
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
- **<big>NewOrderedMap</big>** : creates a new OrderedMap.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewOrderedMap)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Set</big>** : sets the given key-value pair for ordered map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Set)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Get</big>** : returns the value for the given key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Get)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Delete</big>** : deletes the key-value pair for the given key.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Delete)]
[[play](todo)]
[[play](ttps://go.dev/play/p/5bIi4yaZ3K-)]
- **<big>OrderedMap_Clear</big>** : clears the ordered map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Clear)]
[[play](todo)]
[[play](https://go.dev/play/p/8LwoJyEfuFr)]
- **<big>OrderedMap_Front</big>** : returns the first key-value pair.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Front)]
[[play](todo)]
[[play](https://go.dev/play/p/ty57XSimpoe)]
- **<big>OrderedMap_Back</big>** : returns the last key-value pair.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Back)]
[[play](todo)]
[[play](https://go.dev/play/p/rQMjp1yQmpa)]
- **<big>OrderedMap_Range</big>** : calls the given function for each key-value pair.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Range)]
[[play](todo)]
[[play](https://go.dev/play/p/U-KpORhc7LZ)]
- **<big>OrderedMap_Keys</big>** : returns the keys in order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Keys)]
[[play](todo)]
[[play](https://go.dev/play/p/Vv_y9ExKclA)]
- **<big>OrderedMap_Values</big>** : returns the values in order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Values)]
[[play](todo)]
[[play](https://go.dev/play/p/TWj5n1-PUfx)]
- **<big>OrderedMap_Elements</big>** : returns the key-value pairs in order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Elements)]
[[play](todo)]
[[play](https://go.dev/play/p/4BHG4kKz6bB)]
- **<big>OrderedMap_Len</big>** : returns the number of key-value pairs.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Len)]
[[play](todo)]
[[play](https://go.dev/play/p/cLe6z2VX5N-)]
- **<big>OrderedMap_Contains</big>** : returns true if the given key exists.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Contains)]
[[play](todo)]
[[play](https://go.dev/play/p/QuwqqnzwDNX)]
- **<big>OrderedMap_Iter</big>** : returns a channel that yields key-value pairs in order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_Iter)]
[[play](todo)]
[[play](https://go.dev/play/p/tlq2tdvicPt)]
- **<big>OrderedMap_ReverseIter</big>** : returns a channel that yields key-value pairs in reverse order.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_ReverseIter)]
[[play](todo)]
[[play](https://go.dev/play/p/8Q0ssg6hZzO)]
- **<big>OrderedMap_SortByKey</big>** : sorts the map by key given less function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_SortByKey)]
[[play](todo)]
[[play](https://go.dev/play/p/N7hjD_alZPq)]
- **<big>OrderedMap_MarshalJSON</big>** : implements the json.Marshaler interface.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_MarshalJSON)]
[[play](todo)]
[[play](https://go.dev/play/p/C-wAwydIAC7)]
- **<big>OrderedMap_UnmarshalJSON</big>** : implements the json.Unmarshaler interface.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#OrderedMap_UnmarshalJSON)]
[[play](todo)]
[[play](https://go.dev/play/p/t_pkwerIRVx)]
- **<big>NewConcurrentMap</big>** : creates a ConcurrentMap with specific shard count.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewConcurrentMap)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
@@ -1015,10 +1015,10 @@ import "github.com/duke-git/lancet/v2/maputil"
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
- **<big>SortByKey</big>** : sorts the map by its keys and returns a new map with sorted keys.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#SortByKey)]
[[play](todo)]
[[play](https://go.dev/play/p/PVdmBSnm6P_W)]
- **<big>GetOrDefault</big>** : returns the value of the given key or a default value if the key is not present.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#GetOrDefault)]
[[play](todo)]
[[play](https://go.dev/play/p/99QjSYSBdiM)]
<h3 id="mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1264,22 +1264,22 @@ import "github.com/duke-git/lancet/v2/random"
[[play](https://go.dev/play/p/I3yndUQ-rhh)]
- **<big>RandStringSlice</big>** : generate a slice of random string of length strLen based on charset.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandStringSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/2_-PiDv3tGn)]
- **<big>RandBool</big>** : generate a random boolean value (true or false).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandBool)]
[[play](todo)]
[[play](https://go.dev/play/p/to6BLc26wBv)]
- **<big>RandBoolSlice</big>** : generate a random boolean slice of specified length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandBoolSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/o-VSjPjnILI)]
- **<big>RandIntSlice</big>** : generate a slice of random int. Number range in [min, max)
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandIntSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/GATTQ5xTEG8)]
- **<big>RandFromGivenSlice</big>** : generate a random element from given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFromGivenSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/UrkWueF6yYo)]
- **<big>RandSliceFromGivenSlice</big>** : generate a random slice of length num from given slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandSliceFromGivenSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/68UikN9d6VT)]
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1424,7 +1424,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/qScs39f3D9W)]
- **<big>ForEachConcurrent</big>** : applies the iteratee function to each item in the slice concurrently.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ForEachConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/kT4XW7DKVoV)]
- **<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/en/api/packages/slice.md#GroupBy)]
[[play](https://go.dev/play/p/QVkPxzPR0iA)]
@@ -1454,7 +1454,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/biaTefqPquw)]
- **<big>MapConcurrent</big>** : applies the iteratee function to each item in the slice by concrrent.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#MapConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/H1ehfPkPen0)]
- **<big>Merge</big>** : merge all given slices into one slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Merge)]
[[play](https://go.dev/play/p/lbjFp784r9N)]
@@ -1472,7 +1472,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/qT9dZC03A1K)]
- **<big>ReduceConcurrent</big>** : reduces the slice to a single value by applying the reducer function to each item in the slice concurrently.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#ReduceConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/Tjwe6OtaG07)]
- **<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/en/api/packages/slice.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
@@ -1526,16 +1526,16 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
- **<big>UniqueBy</big>** : remove duplicate elements from the input slice based on the values returned by the iteratee function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueBy)]
[[play](https://go.dev/play/p/UR323iZLDpv)]
[[play](https://go.dev/play/p/GY7JE4yikrl)]
- **<big>UniqueByComparator</big>** : remove duplicate elements from the input slice using the provided comparator function.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByComparator)]
[[play](todo)]
[[play](https://go.dev/play/p/rwSacr-ZHsR)]
- **<big>UniqueByField</big>** : remove duplicate elements in struct slice by struct field.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByField)]
[[play](https://go.dev/play/p/6cifcZSPIGu)]
- **<big>UniqueByConcurrent</big>** : remove duplicate elements from the slice by concurrent.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#UniqueByConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/wXZ7LcYRMGL)]
- **<big>Union</big>** : creates a slice of unique elements, in order, from all given slices.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Union)]
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
@@ -1573,7 +1573,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/jlQVoelLl2k)]
- **<big>Frequency</big>** : counts the frequency of each element in the slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Frequency)]
[[play](todo)]
[[play](https://go.dev/play/p/CW3UVNdUZOq)]
<h3 id="stream"> 19. 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. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1610,7 +1610,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[play](https://go.dev/play/p/MFlSANo-buc)]
- **<big>FilterConcurrent</big>** : Applies the provided filter function `predicate` to each element of the input slice concurrently.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/stream.md#FilterConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/t_pkwerIRVx)]
- **<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/en/api/packages/stream.md#Map)]
[[play](https://go.dev/play/p/OtNQUImdYko)]
@@ -1830,19 +1830,23 @@ import "github.com/duke-git/lancet/v2/strutil"
[[play](https://go.dev/play/p/glNdQEA9HUi)]
- **<big>Concat</big>** : concatenates strings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Concat)]
[[play](todo)]
[[play](https://go.dev/play/p/gD52SZHr4Kp)]
- **<big>Ellipsis</big>** : truncates a string to a specified length and appends an ellipsis.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Ellipsis)]
[[play](todo)]
[[play](https://go.dev/play/p/i1vbdQiQVRR)]
- **<big>Shuffle</big>** : shuffle the order of characters of given string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Shuffle)]
[[play](todo)]
[[play](https://go.dev/play/p/iStFwBwyGY7)]
- **<big>Rotate</big>** : rotates the string by the specified number of characters.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#Rotate)]
[[play](todo)]
[[play](https://go.dev/play/p/Kf03iOeT5bd)]
- **<big>TemplateReplace</big>** : replaces the placeholders in the template string with the corresponding values in the data map.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#TemplateReplace)]
[[play](todo)]
[[play](https://go.dev/play/p/cXSuFvyZqv9)]
- **<big>RegexMatchAllGroups</big>** : matches all subgroups in a string using a regular expression and returns the result.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#RegexMatchAllGroups)]
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
<h3 id="system"> 22. System package contain some functions about os, runtime, shell command. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
@@ -1881,16 +1885,16 @@ import "github.com/duke-git/lancet/v2/system"
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
- **<big>StartProcess</big>** : start a new process with the specified name and arguments.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StartProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/5GVol6ryS_X)]
- **<big>StopProcess</big>** : stop a process by pid.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StopProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/jJZhRYGGcmD)]
- **<big>KillProcess</big>** : kill a new process with the specified name and arguments.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#KillProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/XKmvV-ExBWa)]
- **<big>GetProcessInfo</big>** : retrieves detailed process information by pid.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetProcessInfo)]
[[play](todo)]
[[play](https://go.dev/play/p/NQDVywEYYx7)]
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>

View File

@@ -365,10 +365,10 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[play](https://go.dev/play/p/VtHxtkUj-3F)]
- **<big>AesGcmEncrypt</big>** : 使用 AES GCM 算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesGcmEncrypt)]
[[play](todo)]
[[play](https://go.dev/play/p/rUt0-DmsPCs)]
- **<big>AesGcmDecrypt</big>** : 使用 AES GCM 算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#AesGcmDecrypt)]
[[play](todo)]
[[play](https://go.dev/play/p/rUt0-DmsPCs)]
- **<big>Base64StdEncode</big>** : 将字符串 base64 编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#Base64StdEncode)]
[[play](https://go.dev/play/p/VOaUyQUreoK)]
@@ -614,13 +614,13 @@ import "github.com/duke-git/lancet/v2/datetime"
[[play](https://go.dev/play/p/A9Oq_COrcCF)]
- **<big>TrackFuncTime</big>** : 测试函数执行时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#TrackFuncTime)]
[[play](todo)]
[[play](https://go.dev/play/p/QBSEdfXHPTp)]
- **<big>DaysBetween</big>** : 返回两个日期之间的天数差。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#DaysBetween)]
[[play](todo)]
[[play](https://go.dev/play/p/qD6qGb3TbOy)]
- **<big>GenerateDatetimesBetween</big>** : 生成从start到end的所有日期时间的字符串列表。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#GenerateDatetimesBetween)]
[[play](todo)]
[[play](https://go.dev/play/p/6kHBpAxD9ZC)]
<h3 id="datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -814,10 +814,10 @@ import "github.com/duke-git/lancet/v2/function"
[[play](https://go.dev/play/p/absuEGB_GN7)]
- **<big>Debounce</big>** : 创建一个函数的去抖动版本。该去抖动函数仅在上次调用后的指定延迟时间过去之后才会调用原始函数。支持取消去抖动。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Debounce)]
[[play](todo)]
[[play](https://go.dev/play/p/-dGFrYn_1Zi)]
- **<big>Throttle</big>** : 创建一个函数的节流版本。返回的函数保证在每个时间间隔内最多只会被调用一次。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Throttle)]
[[play](todo)]
[[play](https://go.dev/play/p/HpoMov-tJSN)]
- **<big>Schedule</big>** : 每次持续时间调用函数,直到关闭返回的 channel。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/function.md#Schedule)]
[[play](https://go.dev/play/p/hbON-Xeyn5N)]
@@ -939,58 +939,58 @@ import "github.com/duke-git/lancet/v2/maputil"
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
- **<big>NewOrderedMap</big>** : 创建有序映射。有序映射是键值对的集合,其中键是唯一的,并且保留键插入的顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewOrderedMap)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Set</big>** : 设置给定的键值对。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Set)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Get</big>** : 返回给定键的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Get)]
[[play](todo)]
[[play](https://go.dev/play/p/Y4ZJ_oOc1FU)]
- **<big>OrderedMap_Delete</big>** : 删除给定键的键值对。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Delete)]
[[play](todo)]
[[play](ttps://go.dev/play/p/5bIi4yaZ3K-)]
- **<big>OrderedMap_Clear</big>** : 清空map数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Clear)]
[[play](todo)]
[[play](https://go.dev/play/p/8LwoJyEfuFr)]
- **<big>OrderedMap_Front</big>** : 返回第一个键值对。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Front)]
[[play](todo)]
[[play](https://go.dev/play/p/ty57XSimpoe)]
- **<big>OrderedMap_Back</big>** : 返回最后一个键值对。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Back)]
[[play](todo)]
[[play](https://go.dev/play/p/rQMjp1yQmpa)]
- **<big>OrderedMap_Range</big>** : 为每个键值对调用给定的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Range)]
[[play](todo)]
[[play](https://go.dev/play/p/U-KpORhc7LZ)]
- **<big>OrderedMap_Keys</big>** : 按顺序返回键的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Keys)]
[[play](todo)]
[[play](https://go.dev/play/p/Vv_y9ExKclA)]
- **<big>OrderedMap_Values</big>** : 按顺序返回值的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Values)]
[[play](todo)]
[[play](https://go.dev/play/p/TWj5n1-PUfx)]
- **<big>OrderedMap_Elements</big>** : 按顺序返回键值对。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Elements)]
[[play](todo)]
[[play](https://go.dev/play/p/4BHG4kKz6bB)]
- **<big>OrderedMap_Len</big>** : 返回键值对的数量。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Len)]
[[play](todo)]
[[play](https://go.dev/play/p/cLe6z2VX5N-)]
- **<big>OrderedMap_Contains</big>** : 如果给定的键存在则返回true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Contains)]
[[play](todo)]
[[play](https://go.dev/play/p/QuwqqnzwDNX)]
- **<big>OrderedMap_Iter</big>** : 返回按顺序产生键值对的通道。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_Iter)]
[[play](todo)]
[[play](https://go.dev/play/p/tlq2tdvicPt)]
- **<big>OrderedMap_ReverseIter</big>** : 返回以相反顺序产生键值对的通道。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_ReverseIter)]
[[play](todo)]
[[play](https://go.dev/play/p/8Q0ssg6hZzO)]
- **<big>OrderedMap_SortByKey</big>** : 使用传入的比较函数排序map key。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_SortByKey)]
[[play](todo)]
[[play](https://go.dev/play/p/N7hjD_alZPq)]
- **<big>OrderedMap_MarshalJSON</big>** : 实现json.Marshaler接口。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_MarshalJSON)]
[[play](todo)]
[[play](https://go.dev/play/p/C-wAwydIAC7)]
- **<big>OrderedMap_UnmarshalJSON</big>** : 实现json.Unmarshaler接口。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#OrderedMap_UnmarshalJSON)]
[[play](todo)]
[[play](https://go.dev/play/p/8C3MvJ3-mut)]
- **<big>NewConcurrentMap</big>** : ConcurrentMap 协程安全的 map 结构。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewConcurrentMap)]
[[play](https://go.dev/play/p/3PenTPETJT0)]
@@ -1017,10 +1017,10 @@ import "github.com/duke-git/lancet/v2/maputil"
[[play](https://go.dev/play/p/iqcy7P8P0Pr)]
- **<big>SortByKey</big>** : 对传入的map根据key进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#SortByKey)]
[[play](todo)]
[[play](https://go.dev/play/p/PVdmBSnm6P_W)]
- **<big>GetOrDefault</big>** : 返回给定键的值,如果键不存在,则返回默认值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#GetOrDefault)]
[[play](todo)]
[[play](https://go.dev/play/p/99QjSYSBdiM)]
<h3 id="mathutil"> 13. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1265,22 +1265,22 @@ import "github.com/duke-git/lancet/v2/random"
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
- **<big>RandStringSlice</big>** : 生成随机字符串slice。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandStringSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/2_-PiDv3tGn)]
- **<big>RandBool</big>** : 生成随机bool值(true or false)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBool)]
[[play](todo)]
[[play](https://go.dev/play/p/to6BLc26wBv)]
- **<big>RandBoolSlice</big>** : 生成特定长度的随机bool slice。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandBoolSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/o-VSjPjnILI)]
- **<big>RandIntSlice</big>** : 生成一个特定长度的随机int切片数值范围[min, max)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandIntSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/GATTQ5xTEG8)]
- **<big>RandFromGivenSlice</big>** : 从给定切片中随机生成元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFromGivenSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/UrkWueF6yYo)]
- **<big>RandSliceFromGivenSlice</big>** : 从给定切片中生成长度为 num 的随机切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSliceFromGivenSlice)]
[[play](todo)]
[[play](https://go.dev/play/p/68UikN9d6VT)]
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1420,7 +1420,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/DrPaa4YsHRF)]
- **<big>ForEachConcurrent</big>** : 对slice并发执行foreach操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ForEachConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/kT4XW7DKVoV)]
- **<big>ForEachWithBreak</big>** : 遍历切片的元素并为每个元素调用 iteratee 函数,当 iteratee 函数返回 false 时,终止遍历。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ForEachWithBreak)]
[[play](https://go.dev/play/p/qScs39f3D9W)]
@@ -1453,7 +1453,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/biaTefqPquw)]
- **<big>MapConcurrent</big>** : 对slice并发执行map操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#MapConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/H1ehfPkPen0)]
- **<big>Merge</big>** : 合并多个切片(不会消除重复元素)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Merge)]
[[play](https://go.dev/play/p/lbjFp784r9N)]
@@ -1471,7 +1471,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/qT9dZC03A1K)]
- **<big>ReduceConcurrent</big>** : 对切片元素执行并发reduce操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#ReduceConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/Tjwe6OtaG07)]
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Replace)]
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
@@ -1525,16 +1525,16 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/AXw0R3ZTE6a)]
- **<big>UniqueBy</big>** : 根据迭代函数返回的值,从输入切片中移除重复元素。此函数保持元素的顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueBy)]
[[play](https://go.dev/play/p/UR323iZLDpv)]
[[play](https://go.dev/play/p/GY7JE4yikrl)]
- **<big>UniqueByComparator</big>** : 使用提供的比较器函数从输入切片中移除重复元素。此函数保持元素的顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByComparator)]
[[play](todo)]
[[play](https://go.dev/play/p/rwSacr-ZHsR)]
- **<big>UniqueByField</big>** : 根据struct字段对struct切片去重复。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByField)]
[[play](https://go.dev/play/p/6cifcZSPIGu)]
- **<big>UniqueByConcurrent</big>** : 并发的从输入切片中移除重复元素,结果保持元素的顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#UniqueByConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/wXZ7LcYRMGL)]
- **<big>Union</big>** : 合并多个切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Union)]
[[play](https://go.dev/play/p/hfXV1iRIZOf)]
@@ -1571,7 +1571,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[play](https://go.dev/play/p/jlQVoelLl2k)]
- **<big>Frequency</big>** : 计算切片中每个元素出现的频率。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Frequency)]
[[play](todo)]
[[play](https://go.dev/play/p/CW3UVNdUZOq)]
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1608,7 +1608,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[play](https://go.dev/play/p/MFlSANo-buc)]
- **<big>FilterConcurrent</big>** : 对slice并发执行filter操作。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#FilterConcurrent)]
[[play](todo)]
[[play](https://go.dev/play/p/t_pkwerIRVx)]
- **<big>Map</big>** : 返回一个 stream该 stream 由将给定函数应用于源 stream 元素的元素组成。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/stream.md#Map)]
[[play](https://go.dev/play/p/OtNQUImdYko)]
@@ -1832,19 +1832,22 @@ import "github.com/duke-git/lancet/v2/strutil"
[[play](https://go.dev/play/p/glNdQEA9HUi)]
- **<big>Concat</big>** : 拼接字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Concat)]
[[play](todo)]
[[play](https://go.dev/play/p/gD52SZHr4Kp)]
- **<big>Ellipsis</big>** : 将字符串截断到指定长度,并在末尾添加省略号。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Ellipsis)]
[[play](todo)]
[[play](https://go.dev/play/p/i1vbdQiQVRR)]
- **<big>Shuffle</big>** : 打乱给定字符串中的字符顺序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Shuffle)]
[[play](todo)]
[[play](https://go.dev/play/p/iStFwBwyGY7)]
- **<big>Rotate</big>** : 按指定的字符数旋转字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#Rotate)]
[[play](todo)]
[[play](https://go.dev/play/p/Kf03iOeT5bd)]
- **<big>TemplateReplace</big>** : 将模板字符串中的占位符替换为map中的相应值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#TemplateReplace)]
[[play](todo)]
[[play](https://go.dev/play/p/cXSuFvyZqv9)]
- **<big>RegexMatchAllGroups</big>** : 使用正则表达式匹配字符串中的所有子组并返回结果。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#RegexMatchAllGroups)]
[[play](https://go.dev/play/p/JZiu0RXpgN-)]
<h3 id="system"> 22. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
@@ -1883,16 +1886,16 @@ import "github.com/duke-git/lancet/v2/system"
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
- **<big>StartProcess</big>** :创建进程。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StartProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/5GVol6ryS_X)]
- **<big>StopProcess</big>** : 停止进程。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StopProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/jJZhRYGGcmD)]
- **<big>KillProcess</big>** : 杀掉进程。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#KillProcess)]
[[play](todo)]
[[play](https://go.dev/play/p/XKmvV-ExBWa)]
- **<big>GetProcessInfo</big>** : 根据进程id获取进程信息。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)]
[[play](todo)]
[[play](https://go.dev/play/p/NQDVywEYYx7)]

View File

@@ -44,7 +44,7 @@ func (l *LRUCache[K, V]) Get(key K) (V, bool) {
node, ok := l.cache[key]
if ok {
l.moveToHead(node)
l.moveToTail(node)
return node.value, true
}
@@ -66,7 +66,7 @@ func (l *LRUCache[K, V]) Put(key K, value V) {
}
} else {
node.value = value
l.moveToHead(node)
l.moveToTail(node)
}
l.length = len(l.cache)
}
@@ -79,7 +79,7 @@ func (l *LRUCache[K, V]) Delete(key K) bool {
delete(l.cache, key)
return true
}
l.length = len(l.cache)
return false
}
@@ -112,7 +112,7 @@ func (l *LRUCache[K, V]) deleteNode(node *lruNode[K, V]) K {
return node.key
}
func (l *LRUCache[K, V]) moveToHead(node *lruNode[K, V]) {
func (l *LRUCache[K, V]) moveToTail(node *lruNode[K, V]) {
if l.tail == node {
return
}

View File

@@ -8,16 +8,20 @@ package cryptor
import (
"bytes"
"crypto"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"errors"
"io"
"os"
"strings"
)
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
@@ -245,7 +249,7 @@ func AesOfbDecrypt(data, key []byte) []byte {
}
// AesGcmEncrypt encrypt data with key use AES GCM algorithm
// Play: todo
// Play: https://go.dev/play/p/rUt0-DmsPCs
func AesGcmEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
@@ -268,7 +272,7 @@ func AesGcmEncrypt(data, key []byte) []byte {
}
// AesGcmDecrypt decrypt data with key use AES GCM algorithm
// Play: todo
// Play: https://go.dev/play/p/rUt0-DmsPCs
func AesGcmDecrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
@@ -591,6 +595,7 @@ func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
if err != nil {
panic(err)
}
return cipherText
}
@@ -624,6 +629,7 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
if err != nil {
panic(err)
}
return plainText
}
@@ -655,3 +661,150 @@ func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte
return decryptedBytes, nil
}
// RsaSign signs the data with RSA.
// Play: todo
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error) {
privateKey, err := loadRasPrivateKey(privateKeyFileName)
if err != nil {
return nil, err
}
hashed, err := hashData(hash, data)
if err != nil {
return nil, err
}
return rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed)
}
// RsaVerifySign verifies the signature of the data with RSA.
// Play: todo
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error {
publicKey, err := loadRsaPublicKey(pubKeyFileName)
if err != nil {
return err
}
hashed, err := hashData(hash, data)
if err != nil {
return err
}
return rsa.VerifyPKCS1v15(publicKey, hash, hashed, signature)
}
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRsaPublicKey(filename string) (*rsa.PublicKey, error) {
pubKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(pubKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the public key")
}
var pubKey *rsa.PublicKey
blockType := strings.ToUpper(block.Type)
if blockType == "RSA PUBLIC KEY" {
pubKey, err = x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
// todo: here should be a bug, should return nil, err
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
}
} else if blockType == "PUBLIC KEY" {
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return pubKey, nil
}
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRasPrivateKey(filename string) (*rsa.PrivateKey, error) {
priKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(priKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the private key")
}
var privateKey *rsa.PrivateKey
blockType := strings.ToUpper(block.Type)
// PKCS#1 format
if blockType == "RSA PRIVATE KEY" {
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
} else if blockType == "PRIVATE KEY" { // PKCS#8 format
priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
privateKey, ok = priKey.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return privateKey, nil
}
// hashData returns the hash value of the data, using the specified hash function
func hashData(hash crypto.Hash, data []byte) ([]byte, error) {
if !hash.Available() {
return nil, errors.New("unsupported hash algorithm")
}
var hashed []byte
switch hash {
case crypto.SHA224:
h := sha256.Sum224(data)
hashed = h[:]
case crypto.SHA256:
h := sha256.Sum256(data)
hashed = h[:]
case crypto.SHA384:
h := sha512.Sum384(data)
hashed = h[:]
case crypto.SHA512:
h := sha512.Sum512(data)
hashed = h[:]
default:
return nil, errors.New("unsupported hash algorithm")
}
return hashed, nil
}

View File

@@ -1,6 +1,7 @@
package cryptor
import (
"crypto"
"fmt"
)
@@ -284,7 +285,7 @@ func ExampleDesOfbDecrypt() {
func ExampleGenerateRsaKey() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
if err != nil {
return
}
@@ -297,14 +298,14 @@ func ExampleGenerateRsaKey() {
func ExampleRsaEncrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
encrypted := RsaEncrypt(data, "rsa_public_example.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private_example.pem")
fmt.Println(string(decrypted))
@@ -314,14 +315,14 @@ func ExampleRsaEncrypt() {
func ExampleRsaDecrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
err := GenerateRsaKey(4096, "rsa_private_example.pem", "rsa_public_example.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
encrypted := RsaEncrypt(data, "rsa_public_example.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private_example.pem")
fmt.Println(string(decrypted))
@@ -536,3 +537,49 @@ func ExampleRsaEncryptOAEP() {
// Output:
// hello world
}
func ExampleRsaSign() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private_example.pem"
publicKey := "./rsa_public_example.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
fmt.Println("ok")
// Output:
// ok
}
func ExampleRsaVerifySign() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private_example.pem"
publicKey := "./rsa_public_example.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
fmt.Println("ok")
// Output:
// ok
}

View File

@@ -1,6 +1,7 @@
package cryptor
import (
"crypto"
"testing"
"github.com/duke-git/lancet/v2/internal"
@@ -139,13 +140,13 @@ func TestDesOfbEncrypt(t *testing.T) {
func TestRsaEncrypt(t *testing.T) {
t.Parallel()
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
err := GenerateRsaKey(4096, "./rsa_private_example.pem", "./rsa_public_example.pem")
if err != nil {
t.FailNow()
}
data := []byte("hello world")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
encrypted := RsaEncrypt(data, "./rsa_public_example.pem")
decrypted := RsaDecrypt(encrypted, "./rsa_private_example.pem")
assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted))
@@ -170,7 +171,6 @@ func TestRsaEncryptOAEP(t *testing.T) {
}
func TestAesGcmEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
@@ -182,3 +182,53 @@ func TestAesGcmEncrypt(t *testing.T) {
assert := internal.NewAssert(t, "TestAesGcmEncrypt")
assert.Equal(data, string(decrypted))
}
func TestRsaSignAndVerify(t *testing.T) {
t.Parallel()
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
t.Run("RSA Sign and Verify", func(t *testing.T) {
privateKey := "./rsa_private_example.pem"
publicKey := "./rsa_public_example.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
t.Fatalf("RsaSign failed: %v", err)
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
t.Fatalf("RsaVerifySign failed: %v", err)
}
})
t.Run("RSA Sign and Verify Invalid Signature", func(t *testing.T) {
publicKey := "./rsa_public_example.pem"
invalidSig := []byte("InvalidSignature")
err := RsaVerifySign(hash, data, invalidSig, publicKey)
if err == nil {
t.Fatalf("RsaVerifySign failed: %v", err)
}
})
t.Run("RSA Sign and Verify With Different Hash", func(t *testing.T) {
publicKey := "./rsa_public_example.pem"
privateKey := "./rsa_private_example.pem"
hashSign := crypto.SHA256
hashVerify := crypto.SHA512
signature, err := RsaSign(hashSign, data, privateKey)
if err != nil {
t.Fatalf("RsaSign failed: %v", err)
}
err = RsaVerifySign(hashVerify, data, signature, publicKey)
if err == nil {
t.Fatalf("RsaVerifySign failed: %v", err)
}
})
}

View File

@@ -0,0 +1,51 @@
-----BEGIN rsa private key-----
MIIJJwIBAAKCAgEAs+rfCwwvBb9JplwDAaNtpEPCm1DoS8PkqzwSSxfA7JHSMYdY
UMq92vbSqEKomNgyksaGIiqDHop+9pHjYI1Aftd6mbZJwRtQxo+5eYGh88FzPqem
mNubZk7SxGq0MEz1XmZ9viQyp3GxAJjeSdAG9GRdstNcczSy9Ij9YGJ8ehLhL/pn
g4ZsLUtwDbYsilJDx28qDX/jJ/nbopaHWk2XTSu8KK3zXBjppTU4uKKicOswaJ6k
fk9J6ItkQ15uS+z2eHsxpa8K++gIt2swJkiERlqUzwiC75w92JH1nQPXqEqaaEx0
izdHUmFF33cgGb6gw5tJePzOmYs8KLJcOhfJQcqjW4MjCfnaw4tB/cpi3zYKzDoC
7mzwitrkBO1MG11luzR1m9uMfWczL2hK2zMHI51vayC1d1T0gc56vS/SAdicl5Oq
cD6oc6Dmym3rguF/pauTIOrvGtipeYk/Mbb4qj2CI33QFTZc3G55yHVB6vDWIpMS
WF60HHHqv7Ens4MIPIev0WS893vsNscg4Ph3QxXDNjOc3kEK17TnDGXmL7C+Ykfq
9brm32IrOMZ4KR3NJ+aO83yLewPoQAy8QCC32b1O3c1nAgSY9sIwJV8ikAdNDBhL
nkXFrYE2ZFl/Kl5HXd0LCz/BQu3Ey0RsZfXIpD7KUcdNq3QRloTATntE9U0CAwEA
AQKCAgBebqKPC+AKZjJj7NtvGrZLh303RCoIylLVRXxciaUrBgaLFHzYOvGXYgGD
aylOv/sbarOwbxvPBeZJyJzNapY1fSfOUg04G/wzm/A/xDia1iiE9D3O8UUJV8ns
ag0VZO9MkwLgr+MeW+AJbjMODu/3ik5bs/BMT5a2HsjOtCKdeBdVtVprgDx7MaMo
rzuFhlQo80HhQAScUNpk5hk43ozRZmkl+NdIuZK4scyJrGMSXX9VCh9QZJFoSvFf
IstFcqSS7CZMzik3urwIeWwWS+2Rd62vVMpUtW8IouOFfCTPIgkVQTvSbjszE/c2
qTHiEVoUEQdpR1ew45G50pPxsdZhnoKY7SskyvmMNQmG0fIIM/wozAU2NQhJ13PC
duUPTEr2tPhuiHH7Rbjh0J7dEDQEacW+TKyzOaY88CDS5dpe1TBFuRlO7HjfK1r6
Jc6xiR00Waylp5ct8aOgO4q5VAwL9PzRgDrUZhfQmLPaLkxybEuJ6Jo5qIloPXmD
Yyso1t43VH+IqmgU+eNNlq8d5sphzBXj+glSLtT+B2kP27Raz2VetZi70gKf6TPC
QdoeUduzph+VSeJgfRa9slBOrTz3p2YNqZggBM51VA9jITCa8B3kiazgA4ggXMRq
z4+++ae38rCQx8TVeMt6pqQ1aA8eFrKI8GoqEe+Co9og/yYZgQKCAQEA2vwKpje2
5VzaqOFl7aktz8eAkn3YuzfacKSESdXvv7ardBQIRaAAHZ8eMW1dfcVBi7BiE6Ti
SCmll/NT91udR4i0bvjinDBZJCgqo6AiiIKp53yUNuyAWFI08rVDXn1BXaete9UL
hBo8BCwQfV4VxyzYJVwl6Px/RrAB44Cu89ZHwB/6i+Wss97QmEgnOrqcsyZO6Qew
WitvxBuksz4oPGbJqV58tVPC+I4KKALplp76Tt1N1rm6yF+JMu59g/d1+yqua8A5
ON9bRPU2aA1Pb0Ya8+MqigbeGGpaqkJF2OMBcar2MbVVbNq5eUu7Zh4XqqGvDIN4
nL7eXHL+axeIsQKCAQEA0lRPCK3tB8rxivJ+NIIgsP7lIMUG+LecZa5z7BZITamP
yghkSnCyR1wD7RPHCVUUYXtW9/7inGck3KhXzPERBdbLTYtI6gVYkbdGX2bnIQRE
GThyYqyxcoBdfwOXVuixOIAMYQBY1K/MyEgSH4XgM5q/OhN6FCutnBnifR9rTrUO
4bzIM3e5CCSuuwY8/n9lPyzOpJwkxsXT8K6nS0Q1kZqbFT4YSAQhVzRHkYU/cFy2
AtbCOuflek7d7gv4bGi2e/KkKyVOZJYP3i7eOwh6+xAe8f+QDkOzWGNunfe0ggIQ
78jnSENZRU8zExLDgXowIcfrF2iNVrGTFaz4PBBdXQKCAQAut0gaT5Zv9dAb6QHS
op3ITroqBjjfL7ok/6PNEJu13WVUPRXKrKh5qUFKsBcaxqMGBtnVcP5pAKF3+gv2
oA+8e/hqGCRXx6Sspvj5sSbM0nsmjBgeY3O548ex42N82+G+9g93dGqhgus8xJ27
8P9aX0G5LqBTxNHuJYwxmXk5QYRLA0dy4stmD+mWIwZja/4T5d89rUs84TlVr8QC
DQeOYyswO50FHdphJgQapwxn+oBRpLp/TV4AcwkU2XXjWj5MF73f9MEAVf3lhx5V
Mkm45k7HqrWffnmQ4dd3rO2zqDHdqugckJ+pujuJGdPfpBnOZ/GtDLsFTV6ogEuw
UvPxAoIBAE6/RAvy2nD1ebPVEI1mPwkllfHL8s1CKWskgsBco1t4ZZ51v97jDMyM
1ed4ZSfIU+YfgLM/GecG8xUubhkMFJyEDAAPaxA7SircXJuxck25RCnRKXpqP9Gn
39mDJbFjU57cykWzFI8k9t3xpd9ph0Sq5ne+/RD6PXjZdCP2lH2Wamj3/ljOtVco
LMdXEZUTa3vYsdGNqHNHdA+DxJz4f7nxEalFY1/rM/RrXXRNWDAgdgDgGT5mvlMp
ngvXLX6hQdlsQizpPc2JJY3BLHEbvrerFHr0fSHqFQa9y5eXO10FmwO7y2QR2yWI
/o1glBQxBD5RlGJiQbC4sWIHLbWHRv0CggEAXfJYZ+HfUHAsP/QTOgHmlZETcb/s
giZ/b2JUsvcyc+i7Rt6XLZr6ScHhV+bL1iaxy6QNUeSMOCPPhlsPfsjlW13MIBpg
Ux/lOgpb3UC6vEf+uJTRygiTwji65sitFdKW7vt1PBgBHnZ9ZmC2EShx0+E4QV0S
MDwptdewcKHYg5y4r86uER5XhZIJ1F+M0tKMVpzqGFQeCegRY6+S11Vdw5G28iOS
4+r+xCRSPD4TVUJpxxnNERlzqjbS27C2AvkHs/J6tChhYndmrT/oLXd68ki2cphg
ryKTB6TGP/iW6xODGxPefJYyxr4dTNOJeqdXTAgG9Sze5BH4/ku/ouzqZQ==
-----END rsa private key-----

View File

@@ -0,0 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs+rfCwwvBb9JplwDAaNt
pEPCm1DoS8PkqzwSSxfA7JHSMYdYUMq92vbSqEKomNgyksaGIiqDHop+9pHjYI1A
ftd6mbZJwRtQxo+5eYGh88FzPqemmNubZk7SxGq0MEz1XmZ9viQyp3GxAJjeSdAG
9GRdstNcczSy9Ij9YGJ8ehLhL/png4ZsLUtwDbYsilJDx28qDX/jJ/nbopaHWk2X
TSu8KK3zXBjppTU4uKKicOswaJ6kfk9J6ItkQ15uS+z2eHsxpa8K++gIt2swJkiE
RlqUzwiC75w92JH1nQPXqEqaaEx0izdHUmFF33cgGb6gw5tJePzOmYs8KLJcOhfJ
QcqjW4MjCfnaw4tB/cpi3zYKzDoC7mzwitrkBO1MG11luzR1m9uMfWczL2hK2zMH
I51vayC1d1T0gc56vS/SAdicl5OqcD6oc6Dmym3rguF/pauTIOrvGtipeYk/Mbb4
qj2CI33QFTZc3G55yHVB6vDWIpMSWF60HHHqv7Ens4MIPIev0WS893vsNscg4Ph3
QxXDNjOc3kEK17TnDGXmL7C+Ykfq9brm32IrOMZ4KR3NJ+aO83yLewPoQAy8QCC3
2b1O3c1nAgSY9sIwJV8ikAdNDBhLnkXFrYE2ZFl/Kl5HXd0LCz/BQu3Ey0RsZfXI
pD7KUcdNq3QRloTATntE9U0CAwEAAQ==
-----END rsa public key-----

View File

@@ -385,7 +385,7 @@ func TimestampNano(timezone ...string) int64 {
// TrackFuncTime track the time of function execution.
// call it at top of the func like `defer TrackFuncTime(time.Now())()`
// Play: todo
// Play: https://go.dev/play/p/QBSEdfXHPTp
func TrackFuncTime(pre time.Time) func() {
callerName := getCallerName()
return func() {
@@ -413,7 +413,7 @@ func getCallerName() string {
}
// DaysBetween returns the number of days between two times.
// Play: todo
// Play: https://go.dev/play/p/qD6qGb3TbOy
func DaysBetween(start, end time.Time) int {
duration := end.Sub(start)
days := int(duration.Hours() / 24)
@@ -424,7 +424,7 @@ func DaysBetween(start, end time.Time) int {
// GenerateDatetimesBetween returns a slice of strings between two times.
// layout: the format of the datetime string
// interval: the interval between two datetimes
// Play: todo
// Play: https://go.dev/play/p/6kHBpAxD9ZC
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error) {
var result []string

View File

@@ -70,6 +70,9 @@ import (
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
- [RsaEncryptOAEP](#RsaEncryptOAEP)
- [RsaDecryptOAEP](#RsaDecryptOAEP)
- [RsaSign](#RsaSign)
- [RsaVerifySign](#RsaVerifySign)
<div STYLE="page-break-after: always;"></div>
@@ -391,7 +394,7 @@ func main() {
func AesGcmEncrypt(data, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rUt0-DmsPCs)</span></b>
```go
package main
@@ -425,7 +428,7 @@ func main() {
func AesGcmDecrypt(data, key []byte) []byte
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rUt0-DmsPCs)</span></b>
```go
package main
@@ -1607,3 +1610,81 @@ func main() {
// hello world
}
```
### <span id="RsaSign">RsaSign</span>
<p>应用RSA算法签名数据。</p>
<b>函数签名:</b>
```go
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private.pem"
publicKey := "./rsa_public.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
}
```
### <span id="RsaVerifySign">RsaVerifySign</span>
<p>验证数据的签名是否符合RSA算法。</p>
<b>函数签名:</b>
```go
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private.pem"
publicKey := "./rsa_public.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
}
```

View File

@@ -1479,7 +1479,7 @@ func main() {
func TrackFuncTime(pre time.Time) func()
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/QBSEdfXHPTp)</span></b>
```go
package main
@@ -1511,7 +1511,7 @@ func main() {
func DaysBetween(start, end time.Time) int
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/qD6qGb3TbOy)</span></b>
```go
package main
@@ -1544,7 +1544,7 @@ func main() {
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/6kHBpAxD9ZC)</span></b>
```go
package main

View File

@@ -205,7 +205,7 @@ func main() {
func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func())
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/-dGFrYn_1Zi)</span></b>
```go
package main
@@ -753,7 +753,7 @@ func main() {
func Throttle(fn func(), interval time.Duration) func()
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/HpoMov-tJSN)</span></b>
```go
package main

View File

@@ -1191,7 +1191,7 @@ func main() {
func (om *OrderedMap[K, V]) Set(key K, value V)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Y4ZJ_oOc1FU)</span></b>
```go
package main
@@ -1230,7 +1230,7 @@ func main() {
func (om *OrderedMap[K, V]) Get(key K) (V, bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Y4ZJ_oOc1FU)</span></b>
```go
package main
@@ -1270,7 +1270,7 @@ func main() {
func (om *OrderedMap[K, V]) Delete(key K)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/5bIi4yaZ3K-)</span></b>
```go
package main
@@ -1306,7 +1306,7 @@ func main() {
func (om *OrderedMap[K, V]) Clear()
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8LwoJyEfuFr)</span></b>
```go
package main
@@ -1345,7 +1345,7 @@ func (om *OrderedMap[K, V]) Front() (struct {
}, bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/ty57XSimpoe)</span></b>
```go
package main
@@ -1385,7 +1385,7 @@ func (om *OrderedMap[K, V]) Back() (struct {
}, bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rQMjp1yQmpa)</span></b>
```go
package main
@@ -1402,12 +1402,12 @@ func main() {
om.Set("b", 2)
om.Set("c", 3)
frontElement, ok := om.Front()
fmt.Println(frontElement)
backElement, ok := om.Back()
fmt.Println(backElement)
fmt.Println(ok)
// Output:
// {a 1}
// {c 3}
// true
}
```
@@ -1422,7 +1422,7 @@ func main() {
func (om *OrderedMap[K, V]) Range(iteratee func(key K, value V) bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/U-KpORhc7LZ)</span></b>
```go
package main
@@ -1461,7 +1461,7 @@ func main() {
func (om *OrderedMap[K, V]) Keys() []K
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Vv_y9ExKclA)</span></b>
```go
package main
@@ -1497,7 +1497,7 @@ func main() {
func (om *OrderedMap[K, V]) Values() []V
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/TWj5n1-PUfx)</span></b>
```go
package main
@@ -1533,7 +1533,7 @@ func main() {
func (om *OrderedMap[K, V]) Elements() []struct
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/4BHG4kKz6bB)</span></b>
```go
package main
@@ -1569,7 +1569,7 @@ func main() {
func (om *OrderedMap[K, V]) Len() int
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cLe6z2VX5N-)</span></b>
```go
package main
@@ -1605,7 +1605,7 @@ func main() {
func (om *OrderedMap[K, V]) Contains(key K) bool
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/QuwqqnzwDNX)</span></b>
```go
package main
@@ -1647,7 +1647,7 @@ func (om *OrderedMap[K, V]) Iter() <-chan struct {
}
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/tlq2tdvicPt)</span></b>
```go
package main
@@ -1688,7 +1688,7 @@ func (om *OrderedMap[K, V]) ReverseIter() <-chan struct {
}
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8Q0ssg6hZzO)</span></b>
```go
package main
@@ -1726,7 +1726,7 @@ func main() {
func (om *OrderedMap[K, V]) SortByKey(less func(a, b K) bool)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/N7hjD_alZPq)</span></b>
```go
package main
@@ -1737,7 +1737,7 @@ import (
)
func main() {
om := maputil.NewOrderedMap[string, int]()
om := maputil.NewOrderedMap[int, string]()
om.Set(3, "c")
om.Set(1, "a")
@@ -1765,7 +1765,7 @@ func main() {
func (om *OrderedMap[K, V]) MarshalJSON() ([]byte, error)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/C-wAwydIAC7)</span></b>
```go
package main
@@ -1776,7 +1776,7 @@ import (
)
func main() {
om := maputil.NewOrderedMap[string, int]()
om := maputil.NewOrderedMap[int, string]()
om.Set(3, "c")
om.Set(1, "a")
@@ -1802,7 +1802,7 @@ func main() {
func (om *OrderedMap[K, V]) UnmarshalJSON(data []byte) error
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/8C3MvJ3-mut)</span></b>
```go
package main
@@ -1822,6 +1822,7 @@ func main() {
fmt.Println(om.Elements())
// Output:
// [{a 1} {b 2} {c 3}]
}
```
@@ -2239,7 +2240,7 @@ func main() {
func SortByKey[K constraints.Ordered, V any](m map[K]V) (sortedKeysMap map[K]V)
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/PVdmBSnm6P_W)</span></b>
```go
package main
@@ -2257,7 +2258,9 @@ func main() {
2: "b",
}
result := maputil.SortByKey(m)
result := maputil.SortByKey(m, func(a, b int) bool {
return a < b
})
fmt.Println(result)
@@ -2276,7 +2279,7 @@ func main() {
func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/99QjSYSBdiM)</span></b>
```go
package main

View File

@@ -134,7 +134,7 @@ func main() {
func RandFromGivenSlice[T any](slice []T) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UrkWueF6yYo)</span></b>
```go
package main
@@ -161,7 +161,7 @@ func main() {
func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/68UikN9d6VT)</span></b>
```go
package main
@@ -172,9 +172,11 @@ import (
)
func main() {
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon","mango", "nectarine", "orange"}
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
fmt.Println(chosen3goods)
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon","mango", "nectarine", "orange"}
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
fmt.Println(chosen3goods)
}
```
@@ -347,7 +349,7 @@ func main() {
func RandIntSlice(length, min, max int) []int
```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GATTQ5xTEG8)</span></b>
```go
package main
@@ -451,7 +453,7 @@ func main() {
func RandStringSlice(charset string, sliceLen, strLen int) []string
```
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/2_-PiDv3tGn)</span></b>
```go
package main
@@ -480,7 +482,7 @@ func main() {
func RandBool() bool
```
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/to6BLc26wBv)</span></b>
```go
package main
@@ -506,7 +508,7 @@ func main() {
func RandBoolSlice(length int) []bool
```
<b>实例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>实例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/o-VSjPjnILI)</span></b>
```go
package main

View File

@@ -915,7 +915,7 @@ func main() {
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/t_pkwerIRVx)</span></b>
```go
import (
@@ -1192,7 +1192,7 @@ func main() {
func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numThreads int)
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/kT4XW7DKVoV)</span></b>
```go
import (
@@ -1570,7 +1570,7 @@ func main() {
func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U, numThreads int) []U
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/H1ehfPkPen0)</span></b>
```go
import (
@@ -1771,7 +1771,7 @@ func main() {
func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item T, agg T) T, numThreads int) T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Tjwe6OtaG07)</span></b>
```go
import (
@@ -2449,7 +2449,7 @@ func main() {
func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T
```
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/UR323iZLDpv)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/GY7JE4yikrl)</span></b>
```go
import (
@@ -2480,7 +2480,7 @@ func main() {
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T
```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/rwSacr-ZHsR)</span></b>
```go
import (
@@ -2516,7 +2516,7 @@ func main() {
func UniqueByConcurrent[T comparable](slice []T, comparator func(item T, other T) bool, numThreads int) []T
```
<b>示例:</b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/wXZ7LcYRMGL)</span></b>
```go
import (
@@ -2967,7 +2967,7 @@ func main() {
func Frequency[T comparable](slice []T) map[T]int
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/CW3UVNdUZOq)</span></b>
```go
import (

View File

@@ -1547,7 +1547,7 @@ func main() {
func Concat(length int, str ...string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gD52SZHr4Kp)</span></b>
```go
import (
@@ -1556,10 +1556,10 @@ import (
)
func main() {
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
result2 := strutil.Concat(11, "Go", " ", "Language")
result3 := strutil.Concat(0, "An apple a ", "day", "keeps the", " doctor away")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
@@ -1581,7 +1581,7 @@ func main() {
func Ellipsis(str string, length int) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/i1vbdQiQVRR)</span></b>
```go
import (
@@ -1615,7 +1615,7 @@ func main() {
func Shuffle(str string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/iStFwBwyGY7)</span></b>
```go
import (
@@ -1639,7 +1639,7 @@ func main() {
func Rotate(str string, shift int) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Kf03iOeT5bd)</span></b>
```go
import (
@@ -1648,9 +1648,9 @@ import (
)
func main() {
result1 := Rotate("Hello", 0)
result2 := Rotate("Hello", 1)
result3 := Rotate("Hello", 2)
result1 := strutil.Rotate("Hello", 0)
result2 := strutil.Rotate("Hello", 1)
result3 := strutil.Rotate("Hello", 2)
fmt.Println(result1)
fmt.Println(result2)
@@ -1673,7 +1673,7 @@ func main() {
func TemplateReplace(template string, data map[string]string) string
```
<b>示例:<span style="float:right;display:inline-block;">[运行]()</span></b>
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/cXSuFvyZqv9)</span></b>
```go
import (
@@ -1707,7 +1707,7 @@ func main() {
func RegexMatchAllGroups(pattern, str string) [][]string
```
<b>示例:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/JZiu0RXpgN-)</span></b>
```go
import (

View File

@@ -324,7 +324,7 @@ func main() {
func StartProcess(command string, args ...string) (int, error)
```
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/5GVol6ryS_X)</span></b>
```go
import (
@@ -352,7 +352,7 @@ func main() {
func StopProcess(pid int) error
```
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/jJZhRYGGcmD)</span></b>
```go
import (
@@ -386,7 +386,7 @@ func main() {
func KillProcess(pid int) error
```
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/XKmvV-ExBWa)</span></b>
```go
import (
@@ -420,7 +420,7 @@ func main() {
func GetProcessInfo(pid int) (*ProcessInfo, error)
```
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
<b>示例:<span style="float:right;display:inline-block">[运行](https://go.dev/play/p/NQDVywEYYx7)</span></b>
```go
import (

View File

@@ -70,6 +70,8 @@ import (
- [GenerateRsaKeyPair](#GenerateRsaKeyPair)
- [RsaEncryptOAEP](#RsaEncryptOAEP)
- [RsaDecryptOAEP](#RsaDecryptOAEP)
- [RsaSign](#RsaSign)
- [RsaVerifySign](#RsaVerifySign)
<div STYLE="page-break-after: always;"></div>
@@ -391,7 +393,7 @@ func main() {
func AesGcmEncrypt(data, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run]()</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/rUt0-DmsPCs)</span></b>
```go
package main
@@ -425,7 +427,7 @@ func main() {
func AesGcmDecrypt(data, key []byte) []byte
```
<b>Example:<span style="float:right;display:inline-block;">[Run]()</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/rUt0-DmsPCs)</span></b>
```go
package main
@@ -1061,13 +1063,13 @@ import (
func main() {
str := "hello"
key := "12345"
key := "12345"
hms := cryptor.HmacSha512WithBase64(str, key)
fmt.Println(hms)
hms := cryptor.HmacSha512WithBase64(str, key)
fmt.Println(hms)
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
// Output:
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
}
```
@@ -1124,10 +1126,10 @@ import (
func main() {
md5Str := cryptor.Md5StringWithBase64("hello")
fmt.Println(md5Str)
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
@@ -1153,10 +1155,10 @@ import (
func main() {
md5Str := cryptor.Md5Byte([]byte{'a'})
fmt.Println(md5Str)
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
```
@@ -1182,10 +1184,10 @@ import (
func main() {
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
fmt.Println(md5Str)
fmt.Println(md5Str)
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
// Output:
// XUFAKrxLKna5cZ2REBfFkg==
}
```
@@ -1268,10 +1270,10 @@ import (
func main() {
result := cryptor.Sha1WithBase64("hello")
fmt.Println(result)
fmt.Println(result)
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
// Output:
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
}
```
@@ -1328,10 +1330,10 @@ import (
func main() {
result := cryptor.Sha256WithBase64("hello")
fmt.Println(result)
fmt.Println(result)
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
// Output:
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
}
```
@@ -1388,10 +1390,10 @@ import (
func main() {
result := cryptor.Sha512WithBase64("hello")
fmt.Println(result)
fmt.Println(result)
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
// Output:
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
}
```
@@ -1607,3 +1609,81 @@ func main() {
// hello world
}
```
### <span id="RsaSign">RsaSign</span>
<p>Signs the data with RSA algorithm.</p>
<b>Signature:</b>
```go
func RsaSign(hash crypto.Hash, data []byte, privateKeyFileName string) ([]byte, error)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private.pem"
publicKey := "./rsa_public.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
}
```
### <span id="RsaVerifySign">RsaVerifySign</span>
<p>Verifies the signature of the data with RSA algorithm.</p>
<b>Signature:</b>
```go
func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName string) error
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
data := []byte("This is a test data for RSA signing")
hash := crypto.SHA256
privateKey := "./rsa_private.pem"
publicKey := "./rsa_public.pem"
signature, err := RsaSign(hash, data, privateKey)
if err != nil {
return
}
err = RsaVerifySign(hash, data, signature, publicKey)
if err != nil {
return
}
}
```

View File

@@ -1480,7 +1480,7 @@ func main() {
func TrackFuncTime(pre time.Time) func()
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/QBSEdfXHPTp)</span></b>
```go
package main
@@ -1512,7 +1512,7 @@ func main() {
func DaysBetween(start, end time.Time) int
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/qD6qGb3TbOy)</span></b>
```go
package main
@@ -1545,7 +1545,7 @@ func main() {
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/6kHBpAxD9ZC)</span></b>
```go
package main

View File

@@ -204,7 +204,7 @@ func main() {
func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func())
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/-dGFrYn_1Zi)</span></b>
```go
package main
@@ -752,7 +752,7 @@ func main() {
func Throttle(fn func(), interval time.Duration) func()
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/HpoMov-tJSN)</span></b>
```go
package main

View File

@@ -1167,7 +1167,7 @@ func main() {
func NewOrderedMap[K comparable, V any]() *OrderedMap[K, V]
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/99QjSYSBdiM)</span></b>
```go
package main
@@ -1206,7 +1206,7 @@ func main() {
func (om *OrderedMap[K, V]) Set(key K, value V)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Y4ZJ_oOc1FU)</span></b>
```go
package main
@@ -1245,7 +1245,7 @@ func main() {
func (om *OrderedMap[K, V]) Get(key K) (V, bool)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Y4ZJ_oOc1FU)</span></b>
```go
package main
@@ -1285,7 +1285,7 @@ func main() {
func (om *OrderedMap[K, V]) Delete(key K)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/5bIi4yaZ3K-)</span></b>
```go
package main
@@ -1321,7 +1321,7 @@ func main() {
func (om *OrderedMap[K, V]) Clear()
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/8LwoJyEfuFr)</span></b>
```go
package main
@@ -1360,7 +1360,7 @@ func (om *OrderedMap[K, V]) Front() (struct {
}, bool)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/ty57XSimpoe)</span></b>
```go
package main
@@ -1400,7 +1400,7 @@ func (om *OrderedMap[K, V]) Back() (struct {
}, bool)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/rQMjp1yQmpa)</span></b>
```go
package main
@@ -1417,12 +1417,12 @@ func main() {
om.Set("b", 2)
om.Set("c", 3)
frontElement, ok := om.Front()
fmt.Println(frontElement)
backElement, ok := om.Back()
fmt.Println(backElement)
fmt.Println(ok)
// Output:
// {a 1}
// {c 3}
// true
}
```
@@ -1437,7 +1437,7 @@ func main() {
func (om *OrderedMap[K, V]) Range(iteratee func(key K, value V) bool)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/U-KpORhc7LZ)</span></b>
```go
package main
@@ -1476,7 +1476,7 @@ func main() {
func (om *OrderedMap[K, V]) Keys() []K
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Vv_y9ExKclA)</span></b>
```go
package main
@@ -1512,7 +1512,7 @@ func main() {
func (om *OrderedMap[K, V]) Values() []V
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/TWj5n1-PUfx)</span></b>
```go
package main
@@ -1548,7 +1548,7 @@ func main() {
func (om *OrderedMap[K, V]) Elements() []struct
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/4BHG4kKz6bB)</span></b>
```go
package main
@@ -1584,7 +1584,7 @@ func main() {
func (om *OrderedMap[K, V]) Len() int
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/cLe6z2VX5N-)</span></b>
```go
package main
@@ -1620,7 +1620,7 @@ func main() {
func (om *OrderedMap[K, V]) Contains(key K) bool
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/QuwqqnzwDNX)</span></b>
```go
package main
@@ -1662,7 +1662,7 @@ func (om *OrderedMap[K, V]) Iter() <-chan struct {
}
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/tlq2tdvicPt)</span></b>
```go
package main
@@ -1703,7 +1703,7 @@ func (om *OrderedMap[K, V]) ReverseIter() <-chan struct {
}
```
<b>Example:<span style="float:right;display:inline-block;">[Run]()</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/8Q0ssg6hZzO)</span></b>
```go
package main
@@ -1741,7 +1741,7 @@ func main() {
func (om *OrderedMap[K, V]) SortByKey(less func(a, b K) bool)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/N7hjD_alZPq)</span></b>
```go
package main
@@ -1752,7 +1752,7 @@ import (
)
func main() {
om := maputil.NewOrderedMap[string, int]()
om := maputil.NewOrderedMap[int, string]()
om.Set(3, "c")
om.Set(1, "a")
@@ -1780,7 +1780,7 @@ func main() {
func (om *OrderedMap[K, V]) MarshalJSON() ([]byte, error)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/C-wAwydIAC7)</span></b>
```go
package main
@@ -1791,7 +1791,7 @@ import (
)
func main() {
om := maputil.NewOrderedMap[string, int]()
om := maputil.NewOrderedMap[int, string]()
om.Set(3, "c")
om.Set(1, "a")
@@ -1817,7 +1817,7 @@ func main() {
func (om *OrderedMap[K, V]) UnmarshalJSON(data []byte) error
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/8C3MvJ3-mut)</span></b>
```go
package main
@@ -1837,6 +1837,7 @@ func main() {
fmt.Println(om.Elements())
// Output:
// [{a 1} {b 2} {c 3}]
}
```
@@ -2256,7 +2257,7 @@ func main() {
func SortByKey[K constraints.Ordered, V any](m map[K]V) (sortedKeysMap map[K]V)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/PVdmBSnm6P_W)</span></b>
```go
package main
@@ -2274,7 +2275,9 @@ func main() {
2: "b",
}
result := maputil.SortByKey(m)
result := maputil.SortByKey(m, func(a, b int) bool {
return a < b
})
fmt.Println(result)
@@ -2293,7 +2296,7 @@ func main() {
func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V
```
<b>Example:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/99QjSYSBdiM)</span></b>
```go
package main

View File

@@ -133,7 +133,7 @@ func main() {
func RandFromGivenSlice[T any](slice []T) T
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/UrkWueF6yYo)</span></b>
```go
package main
@@ -160,7 +160,7 @@ func main() {
func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/68UikN9d6VT)</span></b>
```go
package main
@@ -171,8 +171,10 @@ import (
)
func main() {
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange"}
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
goods := []string{"apple", "banana", "cherry", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange"}
chosen3goods := random.RandSliceFromGivenSlice(goods, 3, false)
fmt.Println(chosen3goods)
}
```
@@ -346,7 +348,7 @@ func main() {
func RandIntSlice(length, min, max int) []int
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GATTQ5xTEG8)</span></b>
```go
package main
@@ -452,7 +454,7 @@ func main() {
func RandStringSlice(charset string, sliceLen, strLen int) []string
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/2_-PiDv3tGn)</span></b>
```go
package main
@@ -481,7 +483,7 @@ func main() {
func RandBool() bool
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/to6BLc26wBv)</span></b>
```go
package main
@@ -507,7 +509,7 @@ func main() {
func RandBoolSlice(length int) []bool
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/o-VSjPjnILI)</span></b>
```go
package main

View File

@@ -913,7 +913,7 @@ func main() {
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/t_pkwerIRVx)</span></b>
```go
import (
@@ -1190,7 +1190,7 @@ func main() {
func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numThreads int)
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/kT4XW7DKVoV)</span></b>
```go
import (
@@ -1567,7 +1567,7 @@ func main() {
func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U, numThreads int) []U
```
<b>Example:</b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/H1ehfPkPen0)</span></b>
```go
import (
@@ -1766,7 +1766,7 @@ func main() {
func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item T, agg T) T, numThreads int) T
```
<b>Example:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/Tjwe6OtaG07)</span></b>
```go
import (
@@ -2445,7 +2445,7 @@ func main() {
func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T
```
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/UR323iZLDpv)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/GY7JE4yikrl)</span></b>
```go
import (
@@ -2476,7 +2476,7 @@ func main() {
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T
```
<b>Example:</b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/rwSacr-ZHsR)</span></b>
```go
import (
@@ -2512,7 +2512,7 @@ func main() {
func UniqueByConcurrent[T comparable](slice []T, comparator func(item T, other T) bool, numThreads int) []T
```
<b>Example:</b>
<b>Example:<span style="float:right;display:inline-block;">[Runs](https://go.dev/play/p/wXZ7LcYRMGL)</span></b>
```go
import (
@@ -2962,7 +2962,7 @@ func main() {
func Frequency[T comparable](slice []T) map[T]int
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/CW3UVNdUZOq)</span></b>
```go
import (

View File

@@ -1549,7 +1549,7 @@ func main() {
func Concat(length int, str ...string) string
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/gD52SZHr4Kp)</span></b>
```go
import (
@@ -1561,6 +1561,7 @@ func main() {
result1 := strutil.Concat(12, "Hello", " ", "World", "!")
result2 := strutil.Concat(11, "Go", " ", "Language")
result3 := strutil.Concat(0, "An apple a ", "day", "keeps the", " doctor away")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
@@ -1582,7 +1583,7 @@ func main() {
func Ellipsis(str string, length int) string
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/i1vbdQiQVRR)</span></b>
```go
import (
@@ -1616,7 +1617,7 @@ func main() {
func Shuffle(str string) string
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/iStFwBwyGY7)</span></b>
```go
import (
@@ -1640,7 +1641,7 @@ func main() {
func Rotate(str string, shift int) string
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/Kf03iOeT5bd)</span></b>
```go
import (
@@ -1673,7 +1674,7 @@ func main() {
func TemplateReplace(template string, data map[string]string string
```
<b>example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/cXSuFvyZqv9)</span></b>
```go
import (
@@ -1707,7 +1708,7 @@ func main() {
func RegexMatchAllGroups(pattern, str string) [][]string
```
<b>example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
<b>example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/JZiu0RXpgN-)</span></b>
```go
import (

View File

@@ -325,7 +325,7 @@ func main() {
func StartProcess(command string, args ...string) (int, error)
```
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/5GVol6ryS_X)</span></b>
```go
import (
@@ -353,7 +353,7 @@ func main() {
func StopProcess(pid int) error
```
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/jJZhRYGGcmD)</span></b>
```go
import (
@@ -387,7 +387,7 @@ func main() {
func KillProcess(pid int) error
```
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/XKmvV-ExBWa)</span></b>
```go
import (
@@ -421,7 +421,7 @@ func main() {
func GetProcessInfo(pid int) (*ProcessInfo, error)
```
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
<b>Example:<span style="float:right;display:inline-block">[Run](https://go.dev/play/p/NQDVywEYYx7)</span></b>
```go
import (

View File

@@ -10,7 +10,7 @@ outline: deep
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.1. </b>
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.4. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x

View File

@@ -10,7 +10,7 @@ outline: deep
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.1。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.4。</b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x

View File

@@ -93,7 +93,7 @@ func Debounced(fn func(), delay time.Duration) func() {
}
// Debounce creates a debounced version of the provided function.
// Play: todo
// Play: https://go.dev/play/p/-dGFrYn_1Zi
func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func()) {
var (
timer *time.Timer
@@ -127,7 +127,7 @@ func Debounce(fn func(), delay time.Duration) (debouncedFn func(), cancelFn func
// Throttle creates a throttled version of the provided function.
// The returned function guarantees that it will only be invoked at most once per interval.
// Play: todo
// Play: https://go.dev/play/p/HpoMov-tJSN
func Throttle(fn func(), interval time.Duration) func() {
var (
timer *time.Timer

View File

@@ -455,7 +455,7 @@ func GetOrSet[K comparable, V any](m map[K]V, key K, value V) V {
}
// SortByKey sorts the map by its keys and returns a new map with sorted keys.
// Play: todo
// Play: https://go.dev/play/p/PVdmBSnm6P_W
func SortByKey[K constraints.Ordered, V any](m map[K]V, less func(a, b K) bool) (sortedKeysMap map[K]V) {
keys := make([]K, 0, len(m))
for k := range m {
@@ -659,7 +659,7 @@ func convertMap(src reflect.Value, dst reflect.Value) error {
}
// GetOrDefault returns the value of the given key or a default value if the key is not present.
// Play: todo
// Play: https://go.dev/play/p/99QjSYSBdiM
func GetOrDefault[K comparable, V any](m map[K]V, key K, defaultValue V) V {
if v, ok := m[key]; ok {
return v

View File

@@ -29,13 +29,13 @@ func NewOrderedMap[K comparable, V any]() *OrderedMap[K, V] {
}
// Sets the given key-value pair.
// Play: todo
// Play: https://go.dev/play/p/Y4ZJ_oOc1FU
func (om *OrderedMap[K, V]) Set(key K, value V) {
om.mu.Lock()
defer om.mu.Unlock()
if elem, ok := om.index[key]; ok {
elem.Value = value
om.data[key] = value
om.order.MoveToBack(elem)
return
@@ -48,7 +48,7 @@ func (om *OrderedMap[K, V]) Set(key K, value V) {
}
// Get returns the value for the given key.
// Play: todo
// Play: https://go.dev/play/p/Y4ZJ_oOc1FU
func (om *OrderedMap[K, V]) Get(key K) (V, bool) {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -59,7 +59,7 @@ func (om *OrderedMap[K, V]) Get(key K) (V, bool) {
}
// Delete deletes the given key.
// Play: todo
// Play: https://go.dev/play/p/5bIi4yaZ3K-
func (om *OrderedMap[K, V]) Delete(key K) {
om.mu.Lock()
defer om.mu.Unlock()
@@ -72,7 +72,7 @@ func (om *OrderedMap[K, V]) Delete(key K) {
}
// Clear clears the map.
// Play: todo
// Play: https://go.dev/play/p/8LwoJyEfuFr
func (om *OrderedMap[K, V]) Clear() {
om.mu.Lock()
defer om.mu.Unlock()
@@ -83,7 +83,7 @@ func (om *OrderedMap[K, V]) Clear() {
}
// Front returns the first key-value pair.
// Play: todo
// Play: https://go.dev/play/p/ty57XSimpoe
func (om *OrderedMap[K, V]) Front() (struct {
Key K
Value V
@@ -111,7 +111,7 @@ func (om *OrderedMap[K, V]) Front() (struct {
}
// Back returns the last key-value pair.
// Play: todo
// Play: https://go.dev/play/p/rQMjp1yQmpa
func (om *OrderedMap[K, V]) Back() (struct {
Key K
Value V
@@ -139,7 +139,7 @@ func (om *OrderedMap[K, V]) Back() (struct {
}
// Range calls the given function for each key-value pair.
// Play: todo
// Play: https://go.dev/play/p/U-KpORhc7LZ
func (om *OrderedMap[K, V]) Range(iteratee func(key K, value V) bool) {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -155,7 +155,7 @@ func (om *OrderedMap[K, V]) Range(iteratee func(key K, value V) bool) {
}
// Keys returns the keys in order.
// Play: todo
// Play: https://go.dev/play/p/Vv_y9ExKclA
func (om *OrderedMap[K, V]) Keys() []K {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -170,7 +170,7 @@ func (om *OrderedMap[K, V]) Keys() []K {
}
// Values returns the values in order.
// Play: todo
// Play: https://go.dev/play/p/TWj5n1-PUfx
func (om *OrderedMap[K, V]) Values() []V {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -186,7 +186,7 @@ func (om *OrderedMap[K, V]) Values() []V {
}
// Len returns the number of key-value pairs.
// Play: todo
// Play: https://go.dev/play/p/cLe6z2VX5N-
func (om *OrderedMap[K, V]) Len() int {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -195,7 +195,7 @@ func (om *OrderedMap[K, V]) Len() int {
}
// Contains returns true if the given key exists.
// Play: todo
// Play: https://go.dev/play/p/QuwqqnzwDNX
func (om *OrderedMap[K, V]) Contains(key K) bool {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -206,7 +206,7 @@ func (om *OrderedMap[K, V]) Contains(key K) bool {
}
// Elements returns the key-value pairs in order.
// Play: todo
// Play: https://go.dev/play/p/4BHG4kKz6bB
func (om *OrderedMap[K, V]) Elements() []struct {
Key K
Value V
@@ -232,7 +232,7 @@ func (om *OrderedMap[K, V]) Elements() []struct {
}
// Iter returns a channel that yields key-value pairs in order.
// Play: todo
// Play: https://go.dev/play/p/tlq2tdvicPt
func (om *OrderedMap[K, V]) Iter() <-chan struct {
Key K
Value V
@@ -262,7 +262,7 @@ func (om *OrderedMap[K, V]) Iter() <-chan struct {
}
// ReverseIter returns a channel that yields key-value pairs in reverse order.
// Play: todo
// Play: https://go.dev/play/p/8Q0ssg6hZzO
func (om *OrderedMap[K, V]) ReverseIter() <-chan struct {
Key K
Value V
@@ -292,7 +292,7 @@ func (om *OrderedMap[K, V]) ReverseIter() <-chan struct {
}
// SortByValue sorts the map by key given less function.
// Play: todo
// Play: https://go.dev/play/p/N7hjD_alZPq
func (om *OrderedMap[K, V]) SortByKey(less func(a, b K) bool) {
om.mu.Lock()
defer om.mu.Unlock()
@@ -315,7 +315,7 @@ func (om *OrderedMap[K, V]) SortByKey(less func(a, b K) bool) {
}
// MarshalJSON implements the json.Marshaler interface.
// Play: todo
// Play: https://go.dev/play/p/C-wAwydIAC7
func (om *OrderedMap[K, V]) MarshalJSON() ([]byte, error) {
om.mu.RLock()
defer om.mu.RUnlock()
@@ -334,7 +334,7 @@ func (om *OrderedMap[K, V]) MarshalJSON() ([]byte, error) {
}
// UnmarshalJSON implements the json.Unmarshaler interface.
// Play: todo
// Play: https://go.dev/play/p/8C3MvJ3-mut
func (om *OrderedMap[K, V]) UnmarshalJSON(data []byte) error {
om.mu.Lock()
defer om.mu.Unlock()

View File

@@ -19,6 +19,10 @@ func TestOrderedMap_Set_Get(t *testing.T) {
assert.Equal(1, val)
assert.Equal(true, ok)
om.Set("a", 2)
val, _ = om.Get("a")
assert.Equal(2, val)
val, ok = om.Get("d")
assert.Equal(false, ok)
assert.Equal(0, val)

View File

@@ -33,13 +33,13 @@ func init() {
}
// RandBool generates a random boolean value (true or false).
// Play: todo
// Play: https://go.dev/play/p/to6BLc26wBv
func RandBool() bool {
return rand.Intn(2) == 1
}
// RandBoolSlice generates a random boolean slice of specified length.
// Play: todo
// Play: https://go.dev/play/p/o-VSjPjnILI
func RandBoolSlice(length int) []bool {
if length <= 0 {
return []bool{}
@@ -73,7 +73,7 @@ func RandInt(min, max int) int {
// RandIntSlice generates a slice of random integers.
// The generated integers are between min and max (exclusive).
// Play: todo
// Play: https://go.dev/play/p/GATTQ5xTEG8
func RandIntSlice(length, min, max int) []int {
if length <= 0 || min > max {
return []int{}
@@ -170,7 +170,7 @@ func RandString(length int) string {
// RandString generate a slice of random string of length strLen based on charset.
// chartset should be one of the following: random.Numeral, random.LowwerLetters, random.UpperLetters
// random.Letters, random.SymbolChars, random.AllChars. or a combination of them.
// Play: todo
// Play: https://go.dev/play/p/2_-PiDv3tGn
func RandStringSlice(charset string, sliceLen, strLen int) []string {
if sliceLen <= 0 || strLen <= 0 {
return []string{}
@@ -186,7 +186,7 @@ func RandStringSlice(charset string, sliceLen, strLen int) []string {
}
// RandFromGivenSlice generate a random element from given slice.
// Play: todo
// Play: https://go.dev/play/p/UrkWueF6yYo
func RandFromGivenSlice[T any](slice []T) T {
if len(slice) == 0 {
var zero T
@@ -198,7 +198,7 @@ func RandFromGivenSlice[T any](slice []T) T {
// RandSliceFromGivenSlice generate a random slice of length num from given slice.
// - If repeatable is true, the generated slice may contain duplicate elements.
//
// Play: todo
// Play: https://go.dev/play/p/68UikN9d6VT
func RandSliceFromGivenSlice[T any](slice []T, num int, repeatable bool) []T {
if num <= 0 || len(slice) == 0 {
return slice

View File

@@ -789,7 +789,7 @@ func Unique[T comparable](slice []T) []T {
// UniqueBy removes duplicate elements from the input slice based on the values returned by the iteratee function.
// The function maintains the order of the elements.
// Play: todo
// Play: https://go.dev/play/p/GY7JE4yikrl
func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T {
result := make([]T, 0, len(slice))
seen := make(map[U]struct{}, len(slice))
@@ -810,7 +810,7 @@ func UniqueBy[T any, U comparable](slice []T, iteratee func(item T) U) []T {
// UniqueByComparator removes duplicate elements from the input slice using the provided comparator function.
// The function maintains the order of the elements.
// Play: todo
// Play: https://go.dev/play/p/rwSacr-ZHsR
func UniqueByComparator[T comparable](slice []T, comparator func(item T, other T) bool) []T {
result := make([]T, 0, len(slice))
seen := make([]T, 0, len(slice))
@@ -1388,7 +1388,7 @@ func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
}
// Frequency counts the frequency of each element in the slice.
// Play: todo
// Play: https://go.dev/play/p/CW3UVNdUZOq
func Frequency[T comparable](slice []T) map[T]int {
result := make(map[T]int)

View File

@@ -9,7 +9,7 @@ import (
)
// ForEachConcurrent applies the iteratee function to each item in the slice concurrently.
// Play: todo
// Play: https://go.dev/play/p/kT4XW7DKVoV
func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numThreads int) {
sliceLen := len(slice)
if sliceLen == 0 {
@@ -50,7 +50,7 @@ func ForEachConcurrent[T any](slice []T, iteratee func(index int, item T), numTh
}
// MapConcurrent applies the iteratee function to each item in the slice concurrently.
// Play: todo
// Play: https://go.dev/play/p/H1ehfPkPen0
func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U, numThreads int) []U {
result := make([]U, len(slice))
var wg sync.WaitGroup
@@ -77,7 +77,7 @@ func MapConcurrent[T any, U any](slice []T, iteratee func(index int, item T) U,
}
// ReduceConcurrent reduces the slice to a single value by applying the reducer function to each item in the slice concurrently.
// Play: todo
// Play: https://go.dev/play/p/Tjwe6OtaG07
func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item T, agg T) T, numThreads int) T {
if numThreads <= 0 {
numThreads = 1
@@ -121,7 +121,7 @@ func ReduceConcurrent[T any](slice []T, initial T, reducer func(index int, item
}
// FilterConcurrent applies the provided filter function `predicate` to each element of the input slice concurrently.
// Play: todo
// Play: https://go.dev/play/p/t_pkwerIRVx
func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool, numThreads int) []T {
result := make([]T, 0)
var wg sync.WaitGroup
@@ -154,7 +154,7 @@ func FilterConcurrent[T any](slice []T, predicate func(index int, item T) bool,
// The numThreads parameter specifies the number of threads to use
// If numThreads is less than or equal to 0, it will be set to 1
// The comparator function should return true if the two elements are equal
// Play: todo
// Play: https://go.dev/play/p/wXZ7LcYRMGL
func UniqueByConcurrent[T comparable](slice []T, comparator func(item T, other T) bool, numThreads int) []T {
if numThreads <= 0 {
numThreads = 1

View File

@@ -627,7 +627,7 @@ func HammingDistance(a, b string) (int, error) {
// - `length` is the expected length of the concatenated string.
// - if you are unsure about the length of the string to be concatenated, please pass 0 or a negative number.
//
// Play: todo
// Play: https://go.dev/play/p/gD52SZHr4Kp
func Concat(length int, str ...string) string {
if len(str) == 0 {
return ""
@@ -647,7 +647,7 @@ func Concat(length int, str ...string) string {
}
// Ellipsis truncates a string to a specified length and appends an ellipsis.
// Play: todo
// Play: https://go.dev/play/p/i1vbdQiQVRR
func Ellipsis(str string, length int) string {
str = strings.TrimSpace(str)
@@ -665,7 +665,7 @@ func Ellipsis(str string, length int) string {
}
// Shuffle the order of characters of given string.
// Play: todo
// Play: https://go.dev/play/p/iStFwBwyGY7
func Shuffle(str string) string {
runes := []rune(str)
@@ -678,7 +678,7 @@ func Shuffle(str string) string {
}
// Rotate rotates the string by the specified number of characters.
// Play: todo
// Play: https://go.dev/play/p/Kf03iOeT5bd
func Rotate(str string, shift int) string {
if shift == 0 {
return str
@@ -709,7 +709,7 @@ func Rotate(str string, shift int) string {
// The placeholders are enclosed in curly braces, e.g. {key}.
// for example, the template string is "Hello, {name}!", and the data map is {"name": "world"},
// the result will be "Hello, world!".
// Play: todo
// Play: https://go.dev/play/p/cXSuFvyZqv9
func TemplateReplace(template string, data map[string]string) string {
re := regexp.MustCompile(`\{(\w+)\}`)
@@ -729,7 +729,7 @@ func TemplateReplace(template string, data map[string]string) string {
}
// RegexMatchAllGroups Matches all subgroups in a string using a regular expression and returns the result.
// Play: todo
// Play: https://go.dev/play/p/JZiu0RXpgN-
func RegexMatchAllGroups(pattern, str string) [][]string {
re := regexp.MustCompile(pattern)
matches := re.FindAllStringSubmatch(str, -1)

View File

@@ -137,7 +137,7 @@ func GetOsBits() int {
}
// StartProcess start a new process with the specified name and arguments.
// Play: todo
// Play: https://go.dev/play/p/5GVol6ryS_X
func StartProcess(command string, args ...string) (int, error) {
cmd := exec.Command(command, args...)
@@ -149,7 +149,7 @@ func StartProcess(command string, args ...string) (int, error) {
}
// StopProcess stop a process by pid.
// Play: todo
// Play: https://go.dev/play/p/jJZhRYGGcmD
func StopProcess(pid int) error {
process, err := os.FindProcess(pid)
if err != nil {
@@ -160,7 +160,7 @@ func StopProcess(pid int) error {
}
// KillProcess kill a process by pid.
// Play: todo
// Play: https://go.dev/play/p/XKmvV-ExBWa
func KillProcess(pid int) error {
process, err := os.FindProcess(pid)
if err != nil {
@@ -186,7 +186,7 @@ type ProcessInfo struct {
}
// GetProcessInfo retrieves detailed process information by pid.
// Play: todo
// Play: https://go.dev/play/p/NQDVywEYYx7
func GetProcessInfo(pid int) (*ProcessInfo, error) {
var cmd *exec.Cmd