mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-23 13:52:26 +08:00
Compare commits
10 Commits
v2.3.1
...
ca373b00a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca373b00a7 | ||
|
|
a220220f09 | ||
|
|
aeef0418a4 | ||
|
|
9b7d8d7abf | ||
|
|
4d21e81263 | ||
|
|
ce2397422e | ||
|
|
4b3a62b36a | ||
|
|
e054680d20 | ||
|
|
5381842eec | ||
|
|
6e0498514c |
@@ -901,10 +901,15 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>HasKey</big>** : checks if map has key or not.
|
- **<big>HasKey</big>** : checks if map has key or not.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#HasKey)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#HasKey)]
|
||||||
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
||||||
|
- **<big>MapToStruct</big>** : converts map to struct.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#MapToStruct)]
|
||||||
|
[[play](https://go.dev/play/p/7wYyVfX38Dp)]
|
||||||
- **<big>ToSortedSlicesDefault</big>** : converts a map to two slices sorted by key: one for the keys and another for the values.
|
- **<big>ToSortedSlicesDefault</big>** : converts a map to two slices sorted by key: one for the keys and another for the values.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesDefault)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesDefault)]
|
||||||
|
[[play](https://go.dev/play/p/43gEM2po-qy)]
|
||||||
- **<big>ToSortedSlicesWithComparator</big>** : converts a map to two slices sorted by key and using a custom comparison function: one for the keys and another for the values.
|
- **<big>ToSortedSlicesWithComparator</big>** : converts a map to two slices sorted by key and using a custom comparison function: one for the keys and another for the values.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
||||||
|
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
|
||||||
- **<big>NewConcurrentMap</big>** : creates a ConcurrentMap with specific shard count.
|
- **<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)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#NewConcurrentMap)]
|
||||||
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
||||||
@@ -1440,9 +1445,10 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Break)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Break)]
|
||||||
- **<big>RightPadding</big>** : adds padding to the right end of a slice.
|
- **<big>RightPadding</big>** : adds padding to the right end of a slice.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#RightPadding)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#RightPadding)]
|
||||||
|
[[play](https://go.dev/play/p/0_2rlLEMBXL)]
|
||||||
- **<big>LeftPadding</big>** : adds padding to the left begin of a slice.
|
- **<big>LeftPadding</big>** : adds padding to the left begin of a slice.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#LeftPadding)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#LeftPadding)]
|
||||||
|
[[play](https://go.dev/play/p/jlQVoelLl2k)]
|
||||||
|
|
||||||
|
|
||||||
<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. <a href="#index">index</a></h3>
|
<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. <a href="#index">index</a></h3>
|
||||||
|
|||||||
@@ -903,10 +903,15 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
- **<big>HasKey</big>** : 检查 map 是否包含某个 key。
|
- **<big>HasKey</big>** : 检查 map 是否包含某个 key。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#HasKey)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#HasKey)]
|
||||||
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
[[play](https://go.dev/play/p/isZZHOsDhFc)]
|
||||||
|
- **<big>MapToStruct</big>** : 将map转成struct。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#MapToStruct)]
|
||||||
|
[[play](https://go.dev/play/p/7wYyVfX38Dp)]
|
||||||
- **<big>ToSortedSlicesDefault</big>** : 将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。
|
- **<big>ToSortedSlicesDefault</big>** : 将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesDefault)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesDefault)]
|
||||||
|
[[play](https://go.dev/play/p/43gEM2po-qy)]
|
||||||
- **<big>ToSortedSlicesWithComparator</big>** : 将map的key和value转化成两个使用比较器函数根据key的值自定义排序规则的切片,value切片中元素的位置与key对应。
|
- **<big>ToSortedSlicesWithComparator</big>** : 将map的key和value转化成两个使用比较器函数根据key的值自定义排序规则的切片,value切片中元素的位置与key对应。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#ToSortedSlicesWithComparator)]
|
||||||
|
[[play](https://go.dev/play/p/0nlPo6YLdt3)]
|
||||||
- **<big>NewConcurrentMap</big>** : ConcurrentMap 协程安全的 map 结构。
|
- **<big>NewConcurrentMap</big>** : ConcurrentMap 协程安全的 map 结构。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewConcurrentMap)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/maputil.md#NewConcurrentMap)]
|
||||||
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
[[play](https://go.dev/play/p/3PenTPETJT0)]
|
||||||
@@ -1439,8 +1444,11 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Break)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Break)]
|
||||||
- **<big>RightPadding</big>** : 在切片的右部添加元素。
|
- **<big>RightPadding</big>** : 在切片的右部添加元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#RightPadding)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#RightPadding)]
|
||||||
|
[[play](https://go.dev/play/p/0_2rlLEMBXL)]
|
||||||
- **<big>LeftPadding</big>** : 在切片的左部添加元素。
|
- **<big>LeftPadding</big>** : 在切片的左部添加元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#LeftPadding)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#LeftPadding)]
|
||||||
|
[[play](https://go.dev/play/p/jlQVoelLl2k)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const slugify = (str: string): string =>
|
|||||||
export const commonConfig = defineConfig({
|
export const commonConfig = defineConfig({
|
||||||
title: 'Lancet',
|
title: 'Lancet',
|
||||||
appearance: true,
|
appearance: true,
|
||||||
|
ignoreDeadLinks: true,
|
||||||
|
|
||||||
markdown: {
|
markdown: {
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import (
|
|||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
- [IsDisjoint](#IsDisjoint)
|
- [IsDisjoint](#IsDisjoint)
|
||||||
- [HasKey](#HasKey)
|
- [HasKey](#HasKey)
|
||||||
|
- [MapToStruct](#MapToStruct)
|
||||||
- [ToSortedSlicesDefault](#ToSortedSlicesDefault)
|
- [ToSortedSlicesDefault](#ToSortedSlicesDefault)
|
||||||
- [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator)
|
- [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator)
|
||||||
- [NewConcurrentMap](#NewConcurrentMap)
|
- [NewConcurrentMap](#NewConcurrentMap)
|
||||||
@@ -54,6 +55,8 @@ import (
|
|||||||
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
|
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
|
||||||
- [ConcurrentMap_Has](#ConcurrentMap_Has)
|
- [ConcurrentMap_Has](#ConcurrentMap_Has)
|
||||||
- [ConcurrentMap_Range](#ConcurrentMap_Range)
|
- [ConcurrentMap_Range](#ConcurrentMap_Range)
|
||||||
|
- [GetOrSet](#GetOrSet)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -948,14 +951,6 @@ func main() {
|
|||||||
|
|
||||||
<p>检查map是否包含某个key。用于代替以下样板代码:</p>
|
<p>检查map是否包含某个key。用于代替以下样板代码:</p>
|
||||||
|
|
||||||
```go
|
|
||||||
_, haskey := amap["baz"];
|
|
||||||
|
|
||||||
if haskey {
|
|
||||||
fmt.Println("map has key baz")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -990,6 +985,49 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="MapToStruct">MapToStruct</span>
|
||||||
|
|
||||||
|
<p>将map转成struct。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapToStruct(m map[string]any, structObj any) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/7wYyVfX38Dp)</span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
personReqMap := map[string]any{
|
||||||
|
"name": "Nothin",
|
||||||
|
"max_age": 35,
|
||||||
|
"page": 1,
|
||||||
|
"pageSize": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
type PersonReq struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MaxAge int `json:"max_age"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
PageSize int `json:"pageSize"`
|
||||||
|
}
|
||||||
|
var personReq PersonReq
|
||||||
|
_ = maputil.MapToStruct(personReqMap, &personReq)
|
||||||
|
fmt.Println(personReq)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {Nothin 35 1 10}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ToSortedSlicesDefault">ToSortedSlicesDefault</span>
|
### <span id="ToSortedSlicesDefault">ToSortedSlicesDefault</span>
|
||||||
|
|
||||||
<p>将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。</p>
|
<p>将map的key和value转化成两个根据key的值从小到大排序的切片,value切片中元素的位置与key对应。</p>
|
||||||
@@ -1000,7 +1038,7 @@ func main() {
|
|||||||
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V)
|
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]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/43gEM2po-qy)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1012,19 +1050,19 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m := map[int]string{
|
m := map[int]string{
|
||||||
1: "a",
|
1: "a",
|
||||||
3: "c",
|
3: "c",
|
||||||
2: "b",
|
2: "b",
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, values := ToSortedSlicesDefault(m)
|
keys, values := ToSortedSlicesDefault(m)
|
||||||
|
|
||||||
fmt.Println(keys)
|
fmt.Println(keys)
|
||||||
fmt.Println(values)
|
fmt.Println(values)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [1 2 3]
|
// [1 2 3]
|
||||||
// [a b c]
|
// [a b c]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1038,7 +1076,7 @@ func main() {
|
|||||||
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V)
|
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;">[运行](todo)</span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0nlPo6YLdt3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1050,35 +1088,35 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m1 := map[time.Time]string{
|
m1 := map[time.Time]string{
|
||||||
time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today",
|
time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today",
|
||||||
time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday",
|
time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday",
|
||||||
time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow",
|
time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow",
|
||||||
}
|
}
|
||||||
|
|
||||||
keys1, values1 := ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool {
|
keys1, values1 := maputil.ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool {
|
||||||
return a.Before(b)
|
return a.Before(b)
|
||||||
})
|
})
|
||||||
|
|
||||||
m2 := map[int]string{
|
m2 := map[int]string{
|
||||||
1: "a",
|
1: "a",
|
||||||
3: "c",
|
3: "c",
|
||||||
2: "b",
|
2: "b",
|
||||||
}
|
}
|
||||||
keys2, values2 := ToSortedSlicesWithComparator(m2, func(a, b int) bool {
|
keys2, values2 := maputil.ToSortedSlicesWithComparator(m2, func(a, b int) bool {
|
||||||
return a > b
|
return a > b
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(keys2)
|
fmt.Println(keys2)
|
||||||
fmt.Println(values2)
|
fmt.Println(values2)
|
||||||
|
|
||||||
fmt.Println(keys1)
|
fmt.Println(keys1)
|
||||||
fmt.Println(values1)
|
fmt.Println(values1)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC]
|
// [3 2 1]
|
||||||
// [yesterday today tomorrow]
|
// [c b a]
|
||||||
// [3 2 1]
|
// [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC]
|
||||||
// [c b a]
|
// [yesterday today tomorrow]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1144,15 +1182,15 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||||
fmt.Println(val, ok)
|
fmt.Println(val, ok)
|
||||||
wg2.Done()
|
wg2.Done()
|
||||||
}(j)
|
}(j)
|
||||||
}
|
}
|
||||||
wg2.Wait()
|
wg2.Wait()
|
||||||
|
|
||||||
// output: (order may change)
|
// output: (order may change)
|
||||||
// 1 true
|
// 1 true
|
||||||
@@ -1198,15 +1236,15 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||||
fmt.Println(val, ok)
|
fmt.Println(val, ok)
|
||||||
wg2.Done()
|
wg2.Done()
|
||||||
}(j)
|
}(j)
|
||||||
}
|
}
|
||||||
wg2.Wait()
|
wg2.Wait()
|
||||||
|
|
||||||
// output: (order may change)
|
// output: (order may change)
|
||||||
// 1 true
|
// 1 true
|
||||||
@@ -1296,7 +1334,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
cm.Delete(fmt.Sprintf("%d", n))
|
cm.Delete(fmt.Sprintf("%d", n))
|
||||||
@@ -1342,7 +1380,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
|
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
|
||||||
@@ -1392,7 +1430,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
|
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
@@ -1447,3 +1485,41 @@ func main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="GetOrSet">GetOrSet</span>
|
||||||
|
|
||||||
|
<p>返回给定键的值,如果不存在则设置该值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GetOrSet[K comparable, V any](m map[K]V, key K, value V) V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:<span style="float:right;display:inline-block;"></span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
}
|
||||||
|
|
||||||
|
result1 := maputil.GetOrSet(m, 1, "1")
|
||||||
|
result2 := maputil.GetOrSet(m, 2, "b")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a
|
||||||
|
// b
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -322,12 +322,12 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Concat">Concat</span>
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
<p>合并多个slices到slice中</p>
|
<p>创建一个新的切片,将传入的切片拼接起来返回。</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Concat[T any](slice []T, slices ...[]T) []T
|
func Concat[T any](slices ...[]T) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
||||||
@@ -1542,7 +1542,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
### <span id="Merge">Merge(废弃:使用Concat)</span>
|
||||||
|
|
||||||
<p>合并多个切片(不会消除重复元素).</p>
|
<p>合并多个切片(不会消除重复元素).</p>
|
||||||
|
|
||||||
@@ -2615,7 +2615,7 @@ func main() {
|
|||||||
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/yLYcBTyeQIz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -2648,7 +2648,7 @@ func main() {
|
|||||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/0_2rlLEMBXL)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -2675,7 +2675,7 @@ func main() {
|
|||||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/jlQVoelLl2k)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import (
|
|||||||
- [Minus](#Minus)
|
- [Minus](#Minus)
|
||||||
- [IsDisjoint](#IsDisjoint)
|
- [IsDisjoint](#IsDisjoint)
|
||||||
- [HasKey](#HasKey)
|
- [HasKey](#HasKey)
|
||||||
|
- [MapToStruct](#MapToStruct)
|
||||||
- [ToSortedSlicesDefault](#ToSortedSlicesDefault)
|
- [ToSortedSlicesDefault](#ToSortedSlicesDefault)
|
||||||
- [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator)
|
- [ToSortedSlicesWithComparator](#ToSortedSlicesWithComparator)
|
||||||
- [NewConcurrentMap](#NewConcurrentMap)
|
- [NewConcurrentMap](#NewConcurrentMap)
|
||||||
@@ -54,6 +55,7 @@ import (
|
|||||||
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
|
- [ConcurrentMap_GetAndDelete](#ConcurrentMap_GetAndDelete)
|
||||||
- [ConcurrentMap_Has](#ConcurrentMap_Has)
|
- [ConcurrentMap_Has](#ConcurrentMap_Has)
|
||||||
- [ConcurrentMap_Range](#ConcurrentMap_Range)
|
- [ConcurrentMap_Range](#ConcurrentMap_Range)
|
||||||
|
- [GetOrSet](#GetOrSet)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -994,6 +996,49 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="MapToStruct">MapToStruct</span>
|
||||||
|
|
||||||
|
<p>Converts map to struct</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapToStruct(m map[string]any, structObj any) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/7wYyVfX38Dp)</span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
personReqMap := map[string]any{
|
||||||
|
"name": "Nothin",
|
||||||
|
"max_age": 35,
|
||||||
|
"page": 1,
|
||||||
|
"pageSize": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
type PersonReq struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MaxAge int `json:"max_age"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
PageSize int `json:"pageSize"`
|
||||||
|
}
|
||||||
|
var personReq PersonReq
|
||||||
|
_ = maputil.MapToStruct(personReqMap, &personReq)
|
||||||
|
fmt.Println(personReq)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {Nothin 35 1 10}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ToSortedSlicesDefault">ToSortedSlicesDefault</span>
|
### <span id="ToSortedSlicesDefault">ToSortedSlicesDefault</span>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -1005,7 +1050,7 @@ Translate the key and value of the map into two slices that are sorted in ascend
|
|||||||
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V)
|
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]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/43gEM2po-qy)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1017,19 +1062,19 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m := map[int]string{
|
m := map[int]string{
|
||||||
1: "a",
|
1: "a",
|
||||||
3: "c",
|
3: "c",
|
||||||
2: "b",
|
2: "b",
|
||||||
}
|
}
|
||||||
|
|
||||||
keys, values := ToSortedSlicesDefault(m)
|
keys, values := maputil.ToSortedSlicesDefault(m)
|
||||||
|
|
||||||
fmt.Println(keys)
|
fmt.Println(keys)
|
||||||
fmt.Println(values)
|
fmt.Println(values)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [1 2 3]
|
// [1 2 3]
|
||||||
// [a b c]
|
// [a b c]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1045,7 +1090,7 @@ Translate the key and value of the map into two slices that are sorted according
|
|||||||
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V)
|
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]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/0nlPo6YLdt3)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1057,35 +1102,35 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
m1 := map[time.Time]string{
|
m1 := map[time.Time]string{
|
||||||
time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today",
|
time.Date(2024, 3, 31, 0, 0, 0, 0, time.UTC): "today",
|
||||||
time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday",
|
time.Date(2024, 3, 30, 0, 0, 0, 0, time.UTC): "yesterday",
|
||||||
time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow",
|
time.Date(2024, 4, 1, 0, 0, 0, 0, time.UTC): "tomorrow",
|
||||||
}
|
}
|
||||||
|
|
||||||
keys1, values1 := ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool {
|
keys1, values1 := maputil.ToSortedSlicesWithComparator(m1, func(a, b time.Time) bool {
|
||||||
return a.Before(b)
|
return a.Before(b)
|
||||||
})
|
})
|
||||||
|
|
||||||
m2 := map[int]string{
|
m2 := map[int]string{
|
||||||
1: "a",
|
1: "a",
|
||||||
3: "c",
|
3: "c",
|
||||||
2: "b",
|
2: "b",
|
||||||
}
|
}
|
||||||
keys2, values2 := ToSortedSlicesWithComparator(m2, func(a, b int) bool {
|
keys2, values2 := maputil.ToSortedSlicesWithComparator(m2, func(a, b int) bool {
|
||||||
return a > b
|
return a > b
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(keys2)
|
fmt.Println(keys2)
|
||||||
fmt.Println(values2)
|
fmt.Println(values2)
|
||||||
|
|
||||||
fmt.Println(keys1)
|
fmt.Println(keys1)
|
||||||
fmt.Println(values1)
|
fmt.Println(values1)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC]
|
|
||||||
// [yesterday today tomorrow]
|
|
||||||
// [3 2 1]
|
// [3 2 1]
|
||||||
// [c b a]
|
// [c b a]
|
||||||
|
// [2024-03-30 00:00:00 +0000 UTC 2024-03-31 00:00:00 +0000 UTC 2024-04-01 00:00:00 +0000 UTC]
|
||||||
|
// [yesterday today tomorrow]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1152,15 +1197,15 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||||
fmt.Println(val, ok)
|
fmt.Println(val, ok)
|
||||||
wg2.Done()
|
wg2.Done()
|
||||||
}(j)
|
}(j)
|
||||||
}
|
}
|
||||||
wg2.Wait()
|
wg2.Wait()
|
||||||
|
|
||||||
// output: (order may change)
|
// output: (order may change)
|
||||||
// 1 true
|
// 1 true
|
||||||
@@ -1207,15 +1252,15 @@ func main() {
|
|||||||
|
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
val, ok := cm.Get(fmt.Sprintf("%d", n))
|
||||||
fmt.Println(val, ok)
|
fmt.Println(val, ok)
|
||||||
wg2.Done()
|
wg2.Done()
|
||||||
}(j)
|
}(j)
|
||||||
}
|
}
|
||||||
wg2.Wait()
|
wg2.Wait()
|
||||||
|
|
||||||
// output: (order may change)
|
// output: (order may change)
|
||||||
// 1 true
|
// 1 true
|
||||||
@@ -1305,7 +1350,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
cm.Delete(fmt.Sprintf("%d", n))
|
cm.Delete(fmt.Sprintf("%d", n))
|
||||||
@@ -1352,7 +1397,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
|
val, ok := cm.GetAndDelete(fmt.Sprintf("%d", n))
|
||||||
@@ -1404,7 +1449,7 @@ func main() {
|
|||||||
wg1.Wait()
|
wg1.Wait()
|
||||||
|
|
||||||
var wg2 sync.WaitGroup
|
var wg2 sync.WaitGroup
|
||||||
wg2.Add(5)
|
wg2.Add(5)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
go func(n int) {
|
go func(n int) {
|
||||||
ok := cm.Has(fmt.Sprintf("%d", n))
|
ok := cm.Has(fmt.Sprintf("%d", n))
|
||||||
@@ -1457,3 +1502,40 @@ func main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="GetOrSet">GetOrSet</span>
|
||||||
|
|
||||||
|
<p>Returns value of the given key or set the given value value if not present.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GetOrSet[K comparable, V any](m map[K]V, key K, value V) V
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:<span style="float:right;display:inline-block;"></span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
}
|
||||||
|
|
||||||
|
result1 := maputil.GetOrSet(m, 1, "1")
|
||||||
|
result2 := maputil.GetOrSet(m, 2, "b")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a
|
||||||
|
// b
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -321,12 +321,12 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Concat">Concat</span>
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
<p>Creates a new slice concatenating slice with any additional slices.</p>
|
<p>Concat creates a new slice concatenating slice with any additional slices.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Concat[T any](slice []T, slices ...[]T) []T
|
func Concat[T any](slices ...[]T) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/gPt-q7zr5mk)</span></b>
|
||||||
@@ -1540,7 +1540,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="Merge">Merge</span>
|
### <span id="Merge">Merge(deprecated: use Concat)</span>
|
||||||
|
|
||||||
<p>Merge all given slices into one slice.</p>
|
<p>Merge all given slices into one slice.</p>
|
||||||
|
|
||||||
@@ -2612,7 +2612,7 @@ func main() {
|
|||||||
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
func Break[T any](values []T, predicate func(T) bool) ([]T, []T)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/yLYcBTyeQIz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -2645,7 +2645,7 @@ func main() {
|
|||||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/0_2rlLEMBXL)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -2655,7 +2655,7 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
nums := []int{1, 2, 3, 4, 5}
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
padded := RightPadding(nums, 0, 3)
|
padded := slice.RightPadding(nums, 0, 3)
|
||||||
fmt.Println(padded)
|
fmt.Println(padded)
|
||||||
// Output:
|
// Output:
|
||||||
// [1 2 3 4 5 0 0 0]
|
// [1 2 3 4 5 0 0 0]
|
||||||
@@ -2672,7 +2672,7 @@ func main() {
|
|||||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/jlQVoelLl2k)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -2682,7 +2682,7 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
nums := []int{1, 2, 3, 4, 5}
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
padded := LeftPadding(nums, 0, 3)
|
padded := slice.LeftPadding(nums, 0, 3)
|
||||||
fmt.Println(padded)
|
fmt.Println(padded)
|
||||||
// Output:
|
// Output:
|
||||||
// [0 0 0 1 2 3 4 5]
|
// [0 0 0 1 2 3 4 5]
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ features:
|
|||||||
details: Well structure, test for every exported function.
|
details: Well structure, test for every exported function.
|
||||||
---
|
---
|
||||||
|
|
||||||
<p style="position:relative; top: -316px;left: 560px;">
|
<p style="position:relative; inline-block;top: -330px;left: 30%">
|
||||||
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||||
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ features:
|
|||||||
details: 结构良好,测试每个导出的函数。
|
details: 结构良好,测试每个导出的函数。
|
||||||
---
|
---
|
||||||
|
|
||||||
<p style="position:relative;display: inline-block;top: -316px;left: 32%">
|
<p style="position:relative;display: inline-block;top: -330px;left: 30%">
|
||||||
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
<img style="display: inline-block;margin-right:10px;" src="https://img.shields.io/github/stars/duke-git/lancet?style=social" alt="">
|
||||||
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
<img style="display: inline-block" src="https://img.shields.io/github/forks/duke-git/lancet?style=social" alt="">
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
1171
docs/package-lock.json
generated
1171
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,6 @@
|
|||||||
"docs:preview": "vitepress preview"
|
"docs:preview": "vitepress preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vitepress": "^1.0.0-rc.4"
|
"vitepress": "^1.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,58 +119,43 @@ func CreateDir(absPath string) error {
|
|||||||
// if dstPath exists, it will return an error.
|
// if dstPath exists, it will return an error.
|
||||||
// Play: https://go.dev/play/p/YAyFTA_UuPb
|
// Play: https://go.dev/play/p/YAyFTA_UuPb
|
||||||
func CopyDir(srcPath string, dstPath string) error {
|
func CopyDir(srcPath string, dstPath string) error {
|
||||||
if !IsDir(srcPath) {
|
srcInfo, err := os.Stat(srcPath)
|
||||||
return errors.New("source path is not a directory")
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
srcPath, err = filepath.Abs(srcPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to get source directory info: %w", err)
|
||||||
}
|
|
||||||
if IsExist(dstPath) {
|
|
||||||
return errors.New("destination path already exists")
|
|
||||||
}
|
|
||||||
dstPath, err = filepath.Abs(dstPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get srcPath's file info
|
if !srcInfo.IsDir() {
|
||||||
srcFileInfo, err := os.Stat(srcPath)
|
return fmt.Errorf("source path is not a directory: %s", srcPath)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create dstPath with srcPath's mode
|
err = os.MkdirAll(dstPath, 0755)
|
||||||
err = os.MkdirAll(dstPath, srcFileInfo.Mode())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to create destination directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = filepath.Walk(srcPath, func(path string, info os.FileInfo, err error) error {
|
entries, err := os.ReadDir(srcPath)
|
||||||
if srcPath == path {
|
if err != nil {
|
||||||
return nil
|
return fmt.Errorf("failed to read source directory: %w", err)
|
||||||
}
|
}
|
||||||
curDstPath := filepath.Join(dstPath, filepath.Base(path))
|
|
||||||
if info.IsDir() {
|
for _, entry := range entries {
|
||||||
err = CopyDir(path, curDstPath)
|
srcDir := filepath.Join(srcPath, entry.Name())
|
||||||
|
dstDir := filepath.Join(dstPath, entry.Name())
|
||||||
|
|
||||||
|
if entry.IsDir() {
|
||||||
|
err := CopyDir(srcDir, dstDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = CopyFile(path, curDstPath)
|
err := CopyFile(srcDir, dstDir)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = os.Chmod(curDstPath, info.Mode())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
}
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDir checks if the path is directory or not.
|
// IsDir checks if the path is directory or not.
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ func HasKey[K comparable, V any](m map[K]V, key K) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MapToStruct converts map to struct
|
// MapToStruct converts map to struct
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/7wYyVfX38Dp
|
||||||
func MapToStruct(m map[string]any, structObj any) error {
|
func MapToStruct(m map[string]any, structObj any) error {
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
err := setStructField(structObj, k, v)
|
err := setStructField(structObj, k, v)
|
||||||
@@ -389,6 +389,7 @@ func getFieldNameByJsonTag(structObj any, jsonTag string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToSortedSlicesDefault converts a map to two slices sorted by key: one for the keys and another for the values.
|
// ToSortedSlicesDefault converts a map to two slices sorted by key: one for the keys and another for the values.
|
||||||
|
// Play: https://go.dev/play/p/43gEM2po-qy
|
||||||
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) {
|
func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) {
|
||||||
keys := make([]K, 0, len(m))
|
keys := make([]K, 0, len(m))
|
||||||
|
|
||||||
@@ -413,6 +414,7 @@ func ToSortedSlicesDefault[K constraints.Ordered, V any](m map[K]V) ([]K, []V) {
|
|||||||
|
|
||||||
// ToSortedSlicesWithComparator converts a map to two slices sorted by key and using a custom comparison function:
|
// ToSortedSlicesWithComparator converts a map to two slices sorted by key and using a custom comparison function:
|
||||||
// one for the keys and another for the values.
|
// one for the keys and another for the values.
|
||||||
|
// Play: https://go.dev/play/p/0nlPo6YLdt3
|
||||||
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) {
|
func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator func(a, b K) bool) ([]K, []V) {
|
||||||
keys := make([]K, 0, len(m))
|
keys := make([]K, 0, len(m))
|
||||||
|
|
||||||
@@ -434,3 +436,15 @@ func ToSortedSlicesWithComparator[K comparable, V any](m map[K]V, comparator fun
|
|||||||
|
|
||||||
return keys, sortedValues
|
return keys, sortedValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOrSet returns value of the given key or set the given value value if not present.
|
||||||
|
// Play: todo
|
||||||
|
func GetOrSet[K comparable, V any](m map[K]V, key K, value V) V {
|
||||||
|
if v, ok := m[key]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
m[key] = value
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|||||||
@@ -524,3 +524,19 @@ func ExampleToSortedSlicesWithComparator() {
|
|||||||
// [3 2 1]
|
// [3 2 1]
|
||||||
// [c b a]
|
// [c b a]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleGetOrSet() {
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
}
|
||||||
|
|
||||||
|
result1 := GetOrSet(m, 1, "1")
|
||||||
|
result2 := GetOrSet(m, 2, "b")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// a
|
||||||
|
// b
|
||||||
|
}
|
||||||
|
|||||||
@@ -691,3 +691,19 @@ func TestToSortedSlicesWithComparator(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetOrSet(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestGetOrSet")
|
||||||
|
|
||||||
|
m := map[int]string{
|
||||||
|
1: "a",
|
||||||
|
}
|
||||||
|
|
||||||
|
result1 := GetOrSet(m, 1, "1")
|
||||||
|
result2 := GetOrSet(m, 2, "b")
|
||||||
|
|
||||||
|
assert.Equal("a", result1)
|
||||||
|
assert.Equal("b", result2)
|
||||||
|
}
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ type HttpRequest struct {
|
|||||||
|
|
||||||
// HttpClientConfig contains some configurations for http client
|
// HttpClientConfig contains some configurations for http client
|
||||||
type HttpClientConfig struct {
|
type HttpClientConfig struct {
|
||||||
|
Timeout time.Duration
|
||||||
SSLEnabled bool
|
SSLEnabled bool
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
Compressed bool
|
Compressed bool
|
||||||
@@ -113,9 +114,10 @@ type HttpClientConfig struct {
|
|||||||
|
|
||||||
// defaultHttpClientConfig defalut client config.
|
// defaultHttpClientConfig defalut client config.
|
||||||
var defaultHttpClientConfig = &HttpClientConfig{
|
var defaultHttpClientConfig = &HttpClientConfig{
|
||||||
|
Timeout: 50 * time.Second,
|
||||||
Compressed: false,
|
Compressed: false,
|
||||||
HandshakeTimeout: 20 * time.Second,
|
HandshakeTimeout: 10 * time.Second,
|
||||||
ResponseTimeout: 40 * time.Second,
|
ResponseTimeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HttpClient is used for sending http request.
|
// HttpClient is used for sending http request.
|
||||||
@@ -131,6 +133,7 @@ type HttpClient struct {
|
|||||||
func NewHttpClient() *HttpClient {
|
func NewHttpClient() *HttpClient {
|
||||||
client := &HttpClient{
|
client := &HttpClient{
|
||||||
Client: &http.Client{
|
Client: &http.Client{
|
||||||
|
Timeout: defaultHttpClientConfig.Timeout,
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
||||||
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
||||||
|
|||||||
@@ -109,18 +109,18 @@ func Compact[T comparable](slice []T) []T {
|
|||||||
|
|
||||||
// Concat creates a new slice concatenating slice with any additional slices.
|
// Concat creates a new slice concatenating slice with any additional slices.
|
||||||
// Play: https://go.dev/play/p/gPt-q7zr5mk
|
// Play: https://go.dev/play/p/gPt-q7zr5mk
|
||||||
func Concat[T any](slice []T, slices ...[]T) []T {
|
func Concat[T any](slices ...[]T) []T {
|
||||||
totalLen := len(slice)
|
totalLen := 0
|
||||||
|
|
||||||
for _, v := range slices {
|
for _, v := range slices {
|
||||||
totalLen += len(v)
|
totalLen += len(v)
|
||||||
|
if totalLen < 0 {
|
||||||
|
panic("len out of range")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]T, 0, totalLen)
|
result := make([]T, 0, totalLen)
|
||||||
|
|
||||||
result = append(result, slice...)
|
for _, v := range slices {
|
||||||
for _, s := range slices {
|
result = append(result, v...)
|
||||||
result = append(result, s...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -833,20 +833,11 @@ func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated: Please use Concat() function instead.
|
||||||
// Merge all given slices into one slice.
|
// Merge all given slices into one slice.
|
||||||
// Play: https://go.dev/play/p/lbjFp784r9N
|
// Play: https://go.dev/play/p/lbjFp784r9N
|
||||||
func Merge[T any](slices ...[]T) []T {
|
func Merge[T any](slices ...[]T) []T {
|
||||||
totalLen := 0
|
return Concat(slices...)
|
||||||
for _, v := range slices {
|
|
||||||
totalLen += len(v)
|
|
||||||
}
|
|
||||||
result := make([]T, 0, totalLen)
|
|
||||||
|
|
||||||
for _, v := range slices {
|
|
||||||
result = append(result, v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection creates a slice of unique elements that included by all slices.
|
// Intersection creates a slice of unique elements that included by all slices.
|
||||||
@@ -1254,7 +1245,7 @@ func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Breaks a list into two parts at the point where the predicate for the first time is true.
|
// Breaks a list into two parts at the point where the predicate for the first time is true.
|
||||||
// Play: Todo
|
// Play: https://go.dev/play/p/yLYcBTyeQIz
|
||||||
func Break[T any](values []T, predicate func(T) bool) ([]T, []T) {
|
func Break[T any](values []T, predicate func(T) bool) ([]T, []T) {
|
||||||
a := make([]T, 0)
|
a := make([]T, 0)
|
||||||
b := make([]T, 0)
|
b := make([]T, 0)
|
||||||
@@ -1289,7 +1280,7 @@ func Random[T any](slice []T) (val T, idx int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RightPadding adds padding to the right end of a slice.
|
// RightPadding adds padding to the right end of a slice.
|
||||||
// Play: Todo
|
// Play: https://go.dev/play/p/0_2rlLEMBXL
|
||||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||||
if paddingLength == 0 {
|
if paddingLength == 0 {
|
||||||
return slice
|
return slice
|
||||||
@@ -1301,7 +1292,7 @@ func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LeftPadding adds padding to the left begin of a slice.
|
// LeftPadding adds padding to the left begin of a slice.
|
||||||
// Play: Todo
|
// Play: https://go.dev/play/p/jlQVoelLl2k
|
||||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||||
if paddingLength == 0 {
|
if paddingLength == 0 {
|
||||||
return slice
|
return slice
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ func IsIpV4(ipstr string) bool {
|
|||||||
if ip == nil {
|
if ip == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return strings.Contains(ipstr, ".")
|
return ip.To4() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIpV6 check if the string is a ipv6 address.
|
// IsIpV6 check if the string is a ipv6 address.
|
||||||
@@ -224,7 +224,7 @@ func IsIpV6(ipstr string) bool {
|
|||||||
if ip == nil {
|
if ip == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return strings.Contains(ipstr, ":")
|
return ip.To4() == nil && len(ip) == net.IPv6len
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPort check if the string is a valid net port.
|
// IsPort check if the string is a valid net port.
|
||||||
|
|||||||
Reference in New Issue
Block a user