diff --git a/.github/images/pod.png b/.github/images/pod.png
new file mode 100644
index 0000000..30a16c7
Binary files /dev/null and b/.github/images/pod.png differ
diff --git a/.github/images/yc-cpu.png b/.github/images/yc-cpu.png
new file mode 100644
index 0000000..65a32e1
Binary files /dev/null and b/.github/images/yc-cpu.png differ
diff --git a/.github/images/yc-event.png b/.github/images/yc-event.png
new file mode 100644
index 0000000..ddfa322
Binary files /dev/null and b/.github/images/yc-event.png differ
diff --git a/.github/images/yc-memory.png b/.github/images/yc-memory.png
new file mode 100644
index 0000000..bf73cfa
Binary files /dev/null and b/.github/images/yc-memory.png differ
diff --git a/.github/images/yc1.png b/.github/images/yc1.png
new file mode 100644
index 0000000..30a6f35
Binary files /dev/null and b/.github/images/yc1.png differ
diff --git a/.github/images/yc2.png b/.github/images/yc2.png
new file mode 100644
index 0000000..aac82d9
Binary files /dev/null and b/.github/images/yc2.png differ
diff --git a/README.md b/README.md
index 6befa61..7d63835 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,53 @@
# Minotaur
+Minotaur 是一个用于服务端开发的支持库,其中采用了大量泛型设计,主要被用于游戏服务器开发,但由于拥有大量通用的功能,也常被用于 WEB 开发。
+***
+
[](https://pkg.go.dev/github.com/kercylan98/minotaur)
-
-
+
-Minotaur 是一个基于 Golang 1.20 编写的服务端开发支持库,其中采用了大量泛型设计,主要被用于游戏服务器开发,但由于拥有大量通用的功能,也常被用于 WEB 开发。
+
+
+
+
+
+
+
+
+> - 这是支持快速搭建多功能游戏服务器及 HTTP 服务器的 `Golang` 服务端框架;
+> - 网络传输基于 [`gorilla/websocket`](https://github.com/gorilla/websocket)、[`gin-gonic/gin`](https://github.com/gin-gonic/gin)、[`grpc/grpc-go`](https://github.com/grpc/grpc-go)、[`panjf2000/gnet`](https://github.com/panjf2000/gnet)、[`xtaci/kcp-go`](https://github.com/xtaci/kcp-go) 构建;
+> - 该项目的目标是提供一个简单、高效、可扩展的游戏服务器框架,让开发者可以专注于游戏逻辑的开发,而不用花费大量时间在网络传输、配置导表、日志、监控等基础功能的开发上;
+
+***
+在 Minotaur 中不包括任何跨服实现,但支持基于多级路由器快速实现跨服功能。推荐使用 [`NATS.io`](https://nats.io/) 作为跨服消息中间件。
+ - 目前已实践的弹幕游戏项目以 `NATS.io` 作为消息队列,实现了跨服、埋点日志收集等功能,部署在 `Kubernetes` 集群中;
+ - 该项目客户端与服务端采用 `WebSocket` 进行通讯,服务端暴露 `HTTP` 接口接收互动数据消息回调,通过负载均衡器进入 `Kubernetes` 集群中的 `Minotaur` 服务,最终通过 `NATS.io` 消息队列转发至对应所在的 `Pod` 中进行处理;
+
+
+关于 Pod 配置参数及非极限压测数据
+
+> 本次压测 `Pod` 扩容数量为 1,但由于压测连接是最开始就建立好的,所以该扩容的 `Pod` 并没有接受到压力。
+> 理论上来说该 `Pod` 也应该接受 `HTTP` 回调压力,实测过程中,这个扩容的 `Pod` 没有接受到任何压力
+
+**Pod 配置参数**
+
+
+
+**压测结果**
+
+
+
+
+**监控数据**
+
+
+
+
+
+
+
+***
## 特色内容
```mermaid
diff --git a/server/README.md b/server/README.md
index bb0d216..25df78f 100644
--- a/server/README.md
+++ b/server/README.md
@@ -47,6 +47,8 @@ server 提供了包含多种网络类型的服务器实现
|[WithWebsocketMessageType](#WithWebsocketMessageType)|设置仅支持特定类型的Websocket消息
|[WithPProf](#WithPProf)|通过性能分析工具PProf创建服务器
|[New](#New)|根据特定网络类型创建一个服务器
+|[LoadData](#LoadData)|加载绑定的服务器数据
+|[BindData](#BindData)|绑定数据到特定服务器
|[BindService](#BindService)|绑定服务到特定 Server,被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法
@@ -515,6 +517,16 @@ func TestNew(t *testing.T) {
+***
+#### func LoadData\[T any\](srv *Server, name string, data any) T
+
+> 加载绑定的服务器数据
+
+***
+#### func BindData(srv *Server, name string, data any)
+
+> 绑定数据到特定服务器
+
***
#### func BindService(srv *Server, services ...Service)
@@ -1340,6 +1352,7 @@ type Server struct {
systemSignal chan os.Signal
closeChannel chan struct{}
multipleRuntimeErrorChan chan error
+ data map[string]any
messageCounter atomic.Int64
addr string
network Network
@@ -1347,6 +1360,18 @@ type Server struct {
services []func()
}
```
+
+
+#### func (*Server) LoadData(name string, data any) any
+> 加载绑定的服务器数据
+
+***
+
+
+#### func (*Server) BindData(name string, data any)
+> 绑定数据到特定服务器
+
+***
#### func (*Server) Run(addr string) (err error)
diff --git a/utils/collection/README.md b/utils/collection/README.md
index 4c5f566..64f38b0 100644
--- a/utils/collection/README.md
+++ b/utils/collection/README.md
@@ -22,6 +22,10 @@ collection 定义了各种对于集合操作有用的各种函数
|[CloneMapN](#CloneMapN)|通过创建一个新 map 并将 m 的元素复制到新 map 的方式来克隆 map 为 n 个 map
|[CloneSlices](#CloneSlices)|对 slices 中的每一项元素进行克隆,最终返回一个新的二维切片
|[CloneMaps](#CloneMaps)|对 maps 中的每一项元素进行克隆,最终返回一个新的 map 切片
+|[EqualSlice](#EqualSlice)|检查两个切片是否相等,当 handler 返回 true 时,表示 slice1 中的某个元素和 slice2 中的某个元素相匹配
+|[EqualComparableSlice](#EqualComparableSlice)|检查两个切片的值是否相同
+|[EqualMap](#EqualMap)|检查两个 map 是否相等,当 handler 返回 true 时,表示 map1 中的某个元素和 map2 中的某个元素相匹配
+|[EqualComparableMap](#EqualComparableMap)|检查两个 map 的值是否相同
|[InSlice](#InSlice)|检查 v 是否被包含在 slice 中,当 handler 返回 true 时,表示 v 和 slice 中的某个元素相匹配
|[InComparableSlice](#InComparableSlice)|检查 v 是否被包含在 slice 中
|[AllInSlice](#AllInSlice)|检查 values 中的所有元素是否均被包含在 slice 中,当 handler 返回 true 时,表示 values 中的某个元素和 slice 中的某个元素相匹配
@@ -50,6 +54,9 @@ collection 定义了各种对于集合操作有用的各种函数
|[AnyValueInMaps](#AnyValueInMaps)|检查 maps 中的任意一个元素是否包含 value 中的任意一个元素,当 handler 返回 true 时,表示 value 中的某个元素和 maps 中的某个元素相匹配
|[KeyInAllMaps](#KeyInAllMaps)|检查 key 是否被包含在 maps 的每一个元素中
|[AnyKeyInAllMaps](#AnyKeyInAllMaps)|检查 maps 中的每一个元素是否均包含 keys 中任意一个元素
+|[ConvertSliceToBatches](#ConvertSliceToBatches)|将切片 s 转换为分批次的切片,当 batchSize 小于等于 0 或者 s 长度为 0 时,将会返回 nil
+|[ConvertMapKeysToBatches](#ConvertMapKeysToBatches)|将映射的键转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
+|[ConvertMapValuesToBatches](#ConvertMapValuesToBatches)|将映射的值转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
|[ConvertSliceToAny](#ConvertSliceToAny)|将切片转换为任意类型的切片
|[ConvertSliceToIndexMap](#ConvertSliceToIndexMap)|将切片转换为索引为键的映射
|[ConvertSliceToIndexOnlyMap](#ConvertSliceToIndexOnlyMap)|将切片转换为索引为键的映射
@@ -99,6 +106,17 @@ collection 定义了各种对于集合操作有用的各种函数
|[FindMin2MaxFromComparableMap](#FindMin2MaxFromComparableMap)|获取 map 中的最小值和最大值
|[FindMin2MaxFromMap](#FindMin2MaxFromMap)|获取 map 中的最小值和最大值
|[SwapSlice](#SwapSlice)|将切片中的两个元素进行交换
+|[LoopSlice](#LoopSlice)|迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数
+|[ReverseLoopSlice](#ReverseLoopSlice)|逆序迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数
+|[LoopMap](#LoopMap)|迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByOrderedKeyAsc](#LoopMapByOrderedKeyAsc)|按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByOrderedKeyDesc](#LoopMapByOrderedKeyDesc)|按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByOrderedValueAsc](#LoopMapByOrderedValueAsc)|按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByOrderedValueDesc](#LoopMapByOrderedValueDesc)|按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByKeyGetterAsc](#LoopMapByKeyGetterAsc)|按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByValueGetterAsc](#LoopMapByValueGetterAsc)|按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByKeyGetterDesc](#LoopMapByKeyGetterDesc)|按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+|[LoopMapByValueGetterDesc](#LoopMapByValueGetterDesc)|按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
|[MappingFromSlice](#MappingFromSlice)|将切片中的元素进行转换
|[MappingFromMap](#MappingFromMap)|将 map 中的元素进行转换
|[MergeSlices](#MergeSlices)|合并切片
@@ -491,6 +509,214 @@ func TestCloneMaps(t *testing.T) {
+***
+#### func EqualSlice\[S ~[]V, V any\](slice1 S, slice2 S, handler ComparisonHandler[V]) bool
+
+> 检查两个切片是否相等,当 handler 返回 true 时,表示 slice1 中的某个元素和 slice2 中的某个元素相匹配
+> - 当两个切片的容量不同时,不会影响最终的比较结果
+
+**示例代码:**
+
+```go
+
+func ExampleEqualSlice() {
+ s1 := []int{1, 2, 3}
+ s2 := []int{1}
+ s3 := []int{1, 2, 3}
+ fmt.Println(collection.EqualSlice(s1, s2, func(source, target int) bool {
+ return source == target
+ }))
+ fmt.Println(collection.EqualSlice(s1, s3, func(source, target int) bool {
+ return source == target
+ }))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestEqualSlice(t *testing.T) {
+ var cases = []struct {
+ name string
+ input []int
+ inputV []int
+ expected bool
+ }{{"TestEqualSlice_NonEmptySliceEqual", []int{1, 2, 3}, []int{1, 2, 3}, true}, {"TestEqualSlice_NonEmptySliceNotEqual", []int{1, 2, 3}, []int{1, 2}, false}, {"TestEqualSlice_EmptySlice", []int{}, []int{}, true}, {"TestEqualSlice_NilSlice", nil, nil, true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var actual = collection.EqualSlice(c.input, c.inputV, func(source, target int) bool {
+ return source == target
+ })
+ if actual != c.expected {
+ t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", c.name, c.expected, actual, "not as expected")
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func EqualComparableSlice\[S ~[]V, V comparable\](slice1 S, slice2 S) bool
+
+> 检查两个切片的值是否相同
+> - 当两个切片的容量不同时,不会影响最终的比较结果
+
+**示例代码:**
+
+```go
+
+func ExampleEqualComparableSlice() {
+ s1 := []int{1, 2, 3}
+ s2 := []int{1}
+ s3 := []int{1, 2, 3}
+ fmt.Println(collection.EqualComparableSlice(s1, s2))
+ fmt.Println(collection.EqualComparableSlice(s1, s3))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestEqualComparableSlice(t *testing.T) {
+ var cases = []struct {
+ name string
+ input []int
+ inputV []int
+ expected bool
+ }{{"TestEqualComparableSlice_NonEmptySliceEqual", []int{1, 2, 3}, []int{1, 2, 3}, true}, {"TestEqualComparableSlice_NonEmptySliceNotEqual", []int{1, 2, 3}, []int{1, 2}, false}, {"TestEqualComparableSlice_EmptySlice", []int{}, []int{}, true}, {"TestEqualComparableSlice_NilSlice", nil, nil, true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var actual = collection.EqualComparableSlice(c.input, c.inputV)
+ if actual != c.expected {
+ t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", c.name, c.expected, actual, "not as expected")
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func EqualMap\[M ~map[K]V, K comparable, V any\](map1 M, map2 M, handler ComparisonHandler[V]) bool
+
+> 检查两个 map 是否相等,当 handler 返回 true 时,表示 map1 中的某个元素和 map2 中的某个元素相匹配
+> - 当两个 map 的容量不同时,不会影响最终的比较结果
+
+**示例代码:**
+
+```go
+
+func ExampleEqualMap() {
+ m1 := map[string]int{"a": 1, "b": 2}
+ m2 := map[string]int{"a": 1}
+ m3 := map[string]int{"a": 1, "b": 2}
+ fmt.Println(collection.EqualMap(m1, m2, func(source, target int) bool {
+ return source == target
+ }))
+ fmt.Println(collection.EqualMap(m1, m3, func(source, target int) bool {
+ return source == target
+ }))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestEqualMap(t *testing.T) {
+ var cases = []struct {
+ name string
+ input map[int]int
+ inputV map[int]int
+ expected bool
+ }{{"TestEqualMap_NonEmptyMapEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}, true}, {"TestEqualMap_NonEmptyMapNotEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1}, false}, {"TestEqualMap_EmptyMap", map[int]int{}, map[int]int{}, true}, {"TestEqualMap_NilMap", nil, nil, true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var actual = collection.EqualMap(c.input, c.inputV, func(source, target int) bool {
+ return source == target
+ })
+ if actual != c.expected {
+ t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", c.name, c.expected, actual, "not as expected")
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func EqualComparableMap\[M ~map[K]V, K comparable, V comparable\](map1 M, map2 M) bool
+
+> 检查两个 map 的值是否相同
+> - 当两个 map 的容量不同时,不会影响最终的比较结果
+
+**示例代码:**
+
+```go
+
+func ExampleEqualComparableMap() {
+ m1 := map[string]int{"a": 1, "b": 2}
+ m2 := map[string]int{"a": 1}
+ m3 := map[string]int{"a": 1, "b": 2}
+ fmt.Println(collection.EqualComparableMap(m1, m2))
+ fmt.Println(collection.EqualComparableMap(m1, m3))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestEqualComparableMap(t *testing.T) {
+ var cases = []struct {
+ name string
+ input map[int]int
+ inputV map[int]int
+ expected bool
+ }{{"TestEqualComparableMap_NonEmptyMapEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}, true}, {"TestEqualComparableMap_NonEmptyMapNotEqual", map[int]int{1: 1, 2: 2}, map[int]int{1: 1}, false}, {"TestEqualComparableMap_EmptyMap", map[int]int{}, map[int]int{}, true}, {"TestEqualComparableMap_NilMap", nil, nil, true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var actual = collection.EqualComparableMap(c.input, c.inputV)
+ if actual != c.expected {
+ t.Fatalf("%s failed, expected: %v, actual: %v, error: %s", c.name, c.expected, actual, "not as expected")
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
***
#### func InSlice\[S ~[]V, V any\](slice S, v V, handler ComparisonHandler[V]) bool
@@ -1813,6 +2039,158 @@ func TestAnyKeyInAllMaps(t *testing.T) {
+***
+#### func ConvertSliceToBatches\[S ~[]V, V any\](s S, batchSize int) []S
+
+> 将切片 s 转换为分批次的切片,当 batchSize 小于等于 0 或者 s 长度为 0 时,将会返回 nil
+
+**示例代码:**
+
+```go
+
+func ExampleConvertSliceToBatches() {
+ result := collection.ConvertSliceToBatches([]int{1, 2, 3}, 2)
+ for _, v := range result {
+ fmt.Println(v)
+ }
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestConvertSliceToBatches(t *testing.T) {
+ var cases = []struct {
+ name string
+ input []int
+ batch int
+ expected [][]int
+ }{{name: "TestConvertSliceToBatches_NonEmpty", input: []int{1, 2, 3}, batch: 2, expected: [][]int{{1, 2}, {3}}}, {name: "TestConvertSliceToBatches_Empty", input: []int{}, batch: 2, expected: nil}, {name: "TestConvertSliceToBatches_Nil", input: nil, batch: 2, expected: nil}, {name: "TestConvertSliceToBatches_NonPositive", input: []int{1, 2, 3}, batch: 0, expected: nil}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ actual := collection.ConvertSliceToBatches(c.input, c.batch)
+ if len(actual) != len(c.expected) {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ for i := 0; i < len(actual); i++ {
+ av, ev := actual[i], c.expected[i]
+ if len(av) != len(ev) {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ for j := 0; j < len(av); j++ {
+ aj, ej := av[j], ev[j]
+ if reflect.TypeOf(aj).Kind() != reflect.TypeOf(ej).Kind() {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ if aj != ej {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ }
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func ConvertMapKeysToBatches\[M ~map[K]V, K comparable, V any\](m M, batchSize int) [][]K
+
+> 将映射的键转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
+
+**示例代码:**
+
+```go
+
+func ExampleConvertMapKeysToBatches() {
+ result := collection.ConvertMapKeysToBatches(map[int]int{1: 1, 2: 2, 3: 3}, 2)
+ fmt.Println(len(result))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestConvertMapKeysToBatches(t *testing.T) {
+ var cases = []struct {
+ name string
+ input map[int]int
+ batch int
+ expected [][]int
+ }{{name: "TestConvertMapKeysToBatches_NonEmpty", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 2, expected: [][]int{{1, 2}, {3}}}, {name: "TestConvertMapKeysToBatches_Empty", input: map[int]int{}, batch: 2, expected: nil}, {name: "TestConvertMapKeysToBatches_Nil", input: nil, batch: 2, expected: nil}, {name: "TestConvertMapKeysToBatches_NonPositive", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 0, expected: nil}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ actual := collection.ConvertMapKeysToBatches(c.input, c.batch)
+ if len(actual) != len(c.expected) {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func ConvertMapValuesToBatches\[M ~map[K]V, K comparable, V any\](m M, batchSize int) [][]V
+
+> 将映射的值转换为分批次的切片,当 batchSize 小于等于 0 或者 m 长度为 0 时,将会返回 nil
+
+**示例代码:**
+
+```go
+
+func ExampleConvertMapValuesToBatches() {
+ result := collection.ConvertMapValuesToBatches(map[int]int{1: 1, 2: 2, 3: 3}, 2)
+ fmt.Println(len(result))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestConvertMapValuesToBatches(t *testing.T) {
+ var cases = []struct {
+ name string
+ input map[int]int
+ batch int
+ expected [][]int
+ }{{name: "TestConvertMapValuesToBatches_NonEmpty", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 2, expected: [][]int{{1, 2}, {3}}}, {name: "TestConvertMapValuesToBatches_Empty", input: map[int]int{}, batch: 2, expected: nil}, {name: "TestConvertMapValuesToBatches_Nil", input: nil, batch: 2, expected: nil}, {name: "TestConvertMapValuesToBatches_NonPositive", input: map[int]int{1: 1, 2: 2, 3: 3}, batch: 0, expected: nil}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ actual := collection.ConvertMapValuesToBatches(c.input, c.batch)
+ if len(actual) != len(c.expected) {
+ t.Errorf("expected: %v, actual: %v", c.expected, actual)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
***
#### func ConvertSliceToAny\[S ~[]V, V any\](s S) []any
@@ -2090,6 +2468,7 @@ func TestConvertSliceToBoolMap(t *testing.T) {
func ExampleConvertMapKeysToSlice() {
result := collection.ConvertMapKeysToSlice(map[int]int{1: 1, 2: 2, 3: 3})
+ sort.Ints(result)
for i, v := range result {
fmt.Println(i, v)
}
@@ -4273,6 +4652,669 @@ func TestSwapSlice(t *testing.T) {
+***
+#### func LoopSlice\[S ~[]V, V any\](slice S, f func (i int, val V) bool)
+
+> 迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopSlice() {
+ var result []int
+ collection.LoopSlice([]int{1, 2, 3, 4, 5}, func(i int, val int) bool {
+ result = append(result, val)
+ if uint(i) == 1 {
+ return false
+ }
+ return true
+ })
+ fmt.Println(result)
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopSlice(t *testing.T) {
+ var cases = []struct {
+ name string
+ in []int
+ out []int
+ breakIndex uint
+ }{{"TestLoopSlice_Part", []int{1, 2, 3, 4, 5}, []int{1, 2}, 2}, {"TestLoopSlice_All", []int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}, 0}, {"TestLoopSlice_Empty", []int{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.LoopSlice(c.in, func(i int, val int) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopSlice(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func ReverseLoopSlice\[S ~[]V, V any\](slice S, f func (i int, val V) bool)
+
+> 逆序迭代切片 slice 中的每一个函数,并将索引和值传递给 f 函数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleReverseLoopSlice() {
+ var result []int
+ collection.ReverseLoopSlice([]int{1, 2, 3, 4, 5}, func(i int, val int) bool {
+ result = append(result, val)
+ if uint(i) == 1 {
+ return false
+ }
+ return true
+ })
+ fmt.Println(result)
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestReverseLoopSlice(t *testing.T) {
+ var cases = []struct {
+ name string
+ in []int
+ out []int
+ breakIndex uint
+ }{{"TestReverseLoopSlice_Part", []int{1, 2, 3, 4, 5}, []int{5, 4}, 2}, {"TestReverseLoopSlice_All", []int{1, 2, 3, 4, 5}, []int{5, 4, 3, 2, 1}, 0}, {"TestReverseLoopSlice_Empty", []int{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.ReverseLoopSlice(c.in, func(i int, val int) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == uint(len(c.in))-c.breakIndex {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("ReverseLoopSlice(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMap\[M ~map[K]V, K comparable, V any\](m M, f func (i int, key K, val V) bool)
+
+> 迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - m 的迭代顺序是不确定的,因此每次迭代的顺序可能不同
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMap() {
+ var result []int
+ collection.LoopMap(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMap(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out map[int]string
+ breakIndex uint
+ }{{"TestLoopMap_Part", map[int]string{1: "1", 2: "2", 3: "3"}, map[int]string{1: "1", 2: "2"}, 2}, {"TestLoopMap_All", map[int]string{1: "1", 2: "2", 3: "3"}, map[int]string{1: "1", 2: "2", 3: "3"}, 0}, {"TestLoopMap_Empty", map[int]string{}, map[int]string{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result = make(map[int]string)
+ collection.LoopMap(c.in, func(i int, key int, val string) bool {
+ result[key] = val
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableMap(result, c.out) {
+ t.Errorf("LoopMap(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByOrderedKeyAsc\[M ~map[K]V, K generic.Ordered, V any\](m M, f func (i int, key K, val V) bool)
+
+> 按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByOrderedKeyAsc() {
+ var result []int
+ collection.LoopMapByOrderedKeyAsc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByOrderedKeyAsc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []int
+ breakIndex uint
+ }{{"TestLoopMapByOrderedKeyAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2}, 2}, {"TestLoopMapByOrderedKeyAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2, 3}, 0}, {"TestLoopMapByOrderedKeyAsc_Empty", map[int]string{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.LoopMapByOrderedKeyAsc(c.in, func(i int, key int, val string) bool {
+ result = append(result, key)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByOrderedKeyAsc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByOrderedKeyDesc\[M ~map[K]V, K generic.Ordered, V any\](m M, f func (i int, key K, val V) bool)
+
+> 按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByOrderedKeyDesc() {
+ var result []int
+ collection.LoopMapByOrderedKeyDesc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByOrderedKeyDesc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []int
+ breakIndex uint
+ }{{"TestLoopMapByOrderedKeyDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2}, 2}, {"TestLoopMapByOrderedKeyDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2, 1}, 0}, {"TestLoopMapByOrderedKeyDesc_Empty", map[int]string{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.LoopMapByOrderedKeyDesc(c.in, func(i int, key int, val string) bool {
+ result = append(result, key)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByOrderedKeyDesc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByOrderedValueAsc\[M ~map[K]V, K comparable, V generic.Ordered\](m M, f func (i int, key K, val V) bool)
+
+> 按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByOrderedValueAsc() {
+ var result []int
+ collection.LoopMapByOrderedValueAsc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByOrderedValueAsc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []string
+ breakIndex uint
+ }{{"TestLoopMapByOrderedValueAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2"}, 2}, {"TestLoopMapByOrderedValueAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2", "3"}, 0}, {"TestLoopMapByOrderedValueAsc_Empty", map[int]string{}, []string{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []string
+ collection.LoopMapByOrderedValueAsc(c.in, func(i int, key int, val string) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByOrderedValueAsc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByOrderedValueDesc\[M ~map[K]V, K comparable, V generic.Ordered\](m M, f func (i int, key K, val V) bool)
+
+> 按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByOrderedValueDesc() {
+ var result []int
+ collection.LoopMapByOrderedValueDesc(map[string]int{"a": 1, "b": 2, "c": 3}, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByOrderedValueDesc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []string
+ breakIndex uint
+ }{{"TestLoopMapByOrderedValueDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2"}, 2}, {"TestLoopMapByOrderedValueDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2", "1"}, 0}, {"TestLoopMapByOrderedValueDesc_Empty", map[int]string{}, []string{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []string
+ collection.LoopMapByOrderedValueDesc(c.in, func(i int, key int, val string) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByOrderedValueDesc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByKeyGetterAsc\[M ~map[K]V, K comparable, V comparable, N generic.Ordered\](m M, getter func (k K) N, f func (i int, key K, val V) bool)
+
+> 按照键的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByKeyGetterAsc() {
+ var m = map[string]int{"a": 1, "b": 2, "c": 3}
+ var result []int
+ collection.LoopMapByKeyGetterAsc(m, func(k string) int {
+ return m[k]
+ }, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByKeyGetterAsc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []int
+ breakIndex uint
+ }{{"TestLoopMapByKeyGetterAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2}, 2}, {"TestLoopMapByKeyGetterAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{1, 2, 3}, 0}, {"TestLoopMapByKeyGetterAsc_Empty", map[int]string{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.LoopMapByKeyGetterAsc(c.in, func(key int) int {
+ return key
+ }, func(i int, key int, val string) bool {
+ result = append(result, key)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByKeyGetterAsc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByValueGetterAsc\[M ~map[K]V, K comparable, V any, N generic.Ordered\](m M, getter func (v V) N, f func (i int, key K, val V) bool)
+
+> 按照值的升序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByValueGetterAsc() {
+ var m = map[string]int{"a": 1, "b": 2, "c": 3}
+ var result []int
+ collection.LoopMapByValueGetterAsc(m, func(v int) int {
+ return v
+ }, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{1, 2, 3}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByValueGetterAsc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []string
+ breakIndex uint
+ }{{"TestLoopMapByValueGetterAsc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2"}, 2}, {"TestLoopMapByValueGetterAsc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"1", "2", "3"}, 0}, {"TestLoopMapByValueGetterAsc_Empty", map[int]string{}, []string{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []string
+ collection.LoopMapByValueGetterAsc(c.in, func(val string) string {
+ return val
+ }, func(i int, key int, val string) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByValueGetterAsc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByKeyGetterDesc\[M ~map[K]V, K comparable, V comparable, N generic.Ordered\](m M, getter func (k K) N, f func (i int, key K, val V) bool)
+
+> 按照键的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByKeyGetterDesc() {
+ var m = map[string]int{"a": 1, "b": 2, "c": 3}
+ var result []int
+ collection.LoopMapByKeyGetterDesc(m, func(k string) int {
+ return m[k]
+ }, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByKeyGetterDesc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []int
+ breakIndex uint
+ }{{"TestLoopMapByKeyGetterDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2}, 2}, {"TestLoopMapByKeyGetterDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []int{3, 2, 1}, 0}, {"TestLoopMapByKeyGetterDesc_Empty", map[int]string{}, []int{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []int
+ collection.LoopMapByKeyGetterDesc(c.in, func(key int) int {
+ return key
+ }, func(i int, key int, val string) bool {
+ result = append(result, key)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByKeyGetterDesc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+#### func LoopMapByValueGetterDesc\[M ~map[K]V, K comparable, V any, N generic.Ordered\](m M, getter func (v V) N, f func (i int, key K, val V) bool)
+
+> 按照值的降序迭代 m 中的每一个函数,并将键和值传递给 f 函数
+> - 该函数会在 f 中传入一个从 0 开始的索引,用于表示当前迭代的次数
+> - 迭代过程将在 f 函数返回 false 时中断
+
+**示例代码:**
+
+```go
+
+func ExampleLoopMapByValueGetterDesc() {
+ var m = map[string]int{"a": 1, "b": 2, "c": 3}
+ var result []int
+ collection.LoopMapByValueGetterDesc(m, func(v int) int {
+ return v
+ }, func(i int, key string, val int) bool {
+ result = append(result, val)
+ return true
+ })
+ fmt.Println(collection.AllInComparableSlice(result, []int{3, 2, 1}))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestLoopMapByValueGetterDesc(t *testing.T) {
+ var cases = []struct {
+ name string
+ in map[int]string
+ out []string
+ breakIndex uint
+ }{{"TestLoopMapByValueGetterDesc_Part", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2"}, 2}, {"TestLoopMapByValueGetterDesc_All", map[int]string{1: "1", 2: "2", 3: "3"}, []string{"3", "2", "1"}, 0}, {"TestLoopMapByValueGetterDesc_Empty", map[int]string{}, []string{}, 0}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var result []string
+ collection.LoopMapByValueGetterDesc(c.in, func(val string) string {
+ return val
+ }, func(i int, key int, val string) bool {
+ result = append(result, val)
+ if c.breakIndex != 0 && uint(i) == c.breakIndex-1 {
+ return false
+ }
+ return true
+ })
+ if !collection.EqualComparableSlice(result, c.out) {
+ t.Errorf("LoopMapByValueGetterDesc(%v) got %v, want %v", c.in, result, c.out)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
***
#### func MappingFromSlice\[S ~[]V, NS []N, V any, N any\](slice S, handler func (value V) N) NS
diff --git a/utils/huge/README.md b/utils/huge/README.md
index c79ece4..627fcaa 100644
--- a/utils/huge/README.md
+++ b/utils/huge/README.md
@@ -18,8 +18,7 @@
|:--|:--
|[NewFloat](#NewFloat)|创建一个 Float
|[NewFloatByString](#NewFloatByString)|通过字符串创建一个 Float
-|[NewInt](#NewInt)|创建一个 Int
-|[NewIntByString](#NewIntByString)|通过字符串创建一个 Int
+|[NewInt](#NewInt)|创建一个 Int 对象,该对象的值为 x
> 类型定义
@@ -45,15 +44,88 @@
> - 如果字符串不是一个合法的数字,则返回 0
***
-#### func NewInt\[T generic.Number\](x T) *Int
+#### func NewInt\[T generic.Basic\](x T) *Int
-> 创建一个 Int
+> 创建一个 Int 对象,该对象的值为 x
+
+**示例代码:**
+
+该案例展示了 NewInt 对各种基本类型的支持及用法
+
+
+```go
+
+func ExampleNewInt() {
+ fmt.Println(huge.NewInt("12345678900000000"))
+ fmt.Println(huge.NewInt(1234567890))
+ fmt.Println(huge.NewInt(true))
+ fmt.Println(huge.NewInt(123.123))
+ fmt.Println(huge.NewInt(byte(1)))
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestNewInt(t *testing.T) {
+ var cases = []struct {
+ name string
+ nil bool
+ in int64
+ mul int64
+ want string
+ }{{name: "TestNewIntNegative", in: -1, want: "-1"}, {name: "TestNewIntZero", in: 0, want: "0"}, {name: "TestNewIntPositive", in: 1, want: "1"}, {name: "TestNewIntMax", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestNewIntMin", in: -9223372036854775808, want: "-9223372036854775808"}, {name: "TestNewIntMulNegative", in: -9223372036854775808, mul: 10000000, want: "-92233720368547758080000000"}, {name: "TestNewIntMulPositive", in: 9223372036854775807, mul: 10000000, want: "92233720368547758070000000"}, {name: "TestNewIntNil", nil: true, want: "0"}, {name: "TestNewIntNilMul", nil: true, mul: 10000000, want: "0"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var got *huge.Int
+ switch {
+ case c.nil:
+ if c.mul > 0 {
+ got = huge.NewInt(0).MulInt64(c.mul)
+ }
+ case c.mul == 0:
+ got = huge.NewInt(c.in)
+ default:
+ got = huge.NewInt(c.in).MulInt64(c.mul)
+ }
+ if s := got.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, got.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+ t.Run("TestNewIntFromString", func(t *testing.T) {
+ if got := huge.NewInt("1234567890123456789012345678901234567890"); got.String() != "1234567890123456789012345678901234567890" {
+ t.Fatalf("want: %s, got: %s", "1234567890123456789012345678901234567890", got.String())
+ }
+ })
+ t.Run("TestNewIntFromInt", func(t *testing.T) {
+ if got := huge.NewInt(1234567890); got.String() != "1234567890" {
+ t.Fatalf("want: %s, got: %s", "1234567890", got.String())
+ }
+ })
+ t.Run("TestNewIntFromBool", func(t *testing.T) {
+ if got := huge.NewInt(true); got.String() != "1" {
+ t.Fatalf("want: %s, got: %s", "1", got.String())
+ }
+ })
+ t.Run("TestNewIntFromFloat", func(t *testing.T) {
+ if got := huge.NewInt(1234567890.1234567890); got.String() != "1234567890" {
+ t.Fatalf("want: %s, got: %s", "1234567890", got.String())
+ }
+ })
+}
+
+```
+
+
+
-***
-#### func NewIntByString(i string) *Int
-
-> 通过字符串创建一个 Int
-> - 如果字符串不是一个合法的数字,则返回 0
***
@@ -190,71 +262,689 @@ type Int big.Int
#### func (*Int) Copy() *Int
+> 拷贝当前 Int 对象
+
+**示例代码:**
+
+```go
+
+func ExampleInt_Copy() {
+ var a = huge.NewInt(1234567890)
+ var b = a.Copy().SetInt64(9876543210)
+ fmt.Println(a)
+ fmt.Println(b)
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_Copy(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want string
+ }{{name: "TestIntCopyNegative", in: -1, want: "-1"}, {name: "TestIntCopyZero", in: 0, want: "0"}, {name: "TestIntCopyPositive", in: 1, want: "1"}, {name: "TestIntCopyMax", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntCopyMin", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in = huge.NewInt(c.in)
+ var got = in.Copy()
+ if in.Int64() != c.in {
+ t.Fatalf("want: %d, got: %d", c.in, in.Int64())
+ }
+ if s := got.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, got.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) Set(i *Int) *Int
+> 设置当前 Int 对象的值为 i
+
+**示例代码:**
+
+```go
+
+func ExampleInt_Set() {
+ var a = huge.NewInt(1234567890)
+ var b = huge.NewInt(9876543210)
+ fmt.Println(a)
+ a.Set(b)
+ fmt.Println(a)
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_Set(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want string
+ }{{name: "TestIntSetNegative", in: -1, want: "-1"}, {name: "TestIntSetZero", in: 0, want: "0"}, {name: "TestIntSetPositive", in: 1, want: "1"}, {name: "TestIntSetMax", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntSetMin", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.Set(huge.NewInt(c.in))
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+
+
+#### func (*Int) SetString(i string) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetString(t *testing.T) {
+ var cases = []struct {
+ name string
+ in string
+ want string
+ }{{name: "TestIntSetStringNegative", in: "-1", want: "-1"}, {name: "TestIntSetStringZero", in: "0", want: "0"}, {name: "TestIntSetStringPositive", in: "1", want: "1"}, {name: "TestIntSetStringMax", in: "9223372036854775807", want: "9223372036854775807"}, {name: "TestIntSetStringMin", in: "-9223372036854775808", want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetString(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetInt(i int) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetInt(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want string
+ }{{name: "TestIntSetIntNegative", in: -1, want: "-1"}, {name: "TestIntSetIntZero", in: 0, want: "0"}, {name: "TestIntSetIntPositive", in: 1, want: "1"}, {name: "TestIntSetIntMax", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntSetIntMin", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetInt64(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetInt8(i int8) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetInt8(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int8
+ want string
+ }{{name: "TestIntSetInt8Negative", in: -1, want: "-1"}, {name: "TestIntSetInt8Zero", in: 0, want: "0"}, {name: "TestIntSetInt8Positive", in: 1, want: "1"}, {name: "TestIntSetInt8Max", in: 127, want: "127"}, {name: "TestIntSetInt8Min", in: -128, want: "-128"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetInt8(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetInt16(i int16) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetInt16(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int16
+ want string
+ }{{name: "TestIntSetInt16Negative", in: -1, want: "-1"}, {name: "TestIntSetInt16Zero", in: 0, want: "0"}, {name: "TestIntSetInt16Positive", in: 1, want: "1"}, {name: "TestIntSetInt16Max", in: 32767, want: "32767"}, {name: "TestIntSetInt16Min", in: -32768, want: "-32768"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetInt16(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetInt32(i int32) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetInt32(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int32
+ want string
+ }{{name: "TestIntSetInt32Negative", in: -1, want: "-1"}, {name: "TestIntSetInt32Zero", in: 0, want: "0"}, {name: "TestIntSetInt32Positive", in: 1, want: "1"}, {name: "TestIntSetInt32Max", in: 2147483647, want: "2147483647"}, {name: "TestIntSetInt32Min", in: -2147483648, want: "-2147483648"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetInt32(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetInt64(i int64) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetInt64(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want string
+ }{{name: "TestIntSetInt64Negative", in: -1, want: "-1"}, {name: "TestIntSetInt64Zero", in: 0, want: "0"}, {name: "TestIntSetInt64Positive", in: 1, want: "1"}, {name: "TestIntSetInt64Max", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntSetInt64Min", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetInt64(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetUint(i uint) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetUint(t *testing.T) {
+ var cases = []struct {
+ name string
+ in uint64
+ want string
+ }{{name: "TestIntSetUintNegative", in: 0, want: "0"}, {name: "TestIntSetUintZero", in: 0, want: "0"}, {name: "TestIntSetUintPositive", in: 1, want: "1"}, {name: "TestIntSetUintMax", in: 18446744073709551615, want: "18446744073709551615"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetUint64(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetUint8(i uint8) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetUint8(t *testing.T) {
+ var cases = []struct {
+ name string
+ in uint8
+ want string
+ }{{name: "TestIntSetUint8Negative", in: 0, want: "0"}, {name: "TestIntSetUint8Zero", in: 0, want: "0"}, {name: "TestIntSetUint8Positive", in: 1, want: "1"}, {name: "TestIntSetUint8Max", in: 255, want: "255"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetUint8(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetUint16(i uint16) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetUint16(t *testing.T) {
+ var cases = []struct {
+ name string
+ in uint16
+ want string
+ }{{name: "TestIntSetUint16Negative", in: 0, want: "0"}, {name: "TestIntSetUint16Zero", in: 0, want: "0"}, {name: "TestIntSetUint16Positive", in: 1, want: "1"}, {name: "TestIntSetUint16Max", in: 65535, want: "65535"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetUint16(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetUint32(i uint32) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetUint32(t *testing.T) {
+ var cases = []struct {
+ name string
+ in uint32
+ want string
+ }{{name: "TestIntSetUint32Negative", in: 0, want: "0"}, {name: "TestIntSetUint32Zero", in: 0, want: "0"}, {name: "TestIntSetUint32Positive", in: 1, want: "1"}, {name: "TestIntSetUint32Max", in: 4294967295, want: "4294967295"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetUint32(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) SetUint64(i uint64) *Int
+> 设置当前 Int 对象的值为 i
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetUint64(t *testing.T) {
+ var cases = []struct {
+ name string
+ in uint64
+ want string
+ }{{name: "TestIntSetUint64Negative", in: 0, want: "0"}, {name: "TestIntSetUint64Zero", in: 0, want: "0"}, {name: "TestIntSetUint64Positive", in: 1, want: "1"}, {name: "TestIntSetUint64Max", in: 18446744073709551615, want: "18446744073709551615"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetUint64(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+
+
+#### func (*Int) SetFloat32(i float32) *Int
+> 设置当前 Int 对象的值为 i 向下取整后的值
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetFloat32(t *testing.T) {
+ var cases = []struct {
+ name string
+ in float32
+ want string
+ }{{name: "TestIntSetFloat32Negative", in: -1.1, want: "-1"}, {name: "TestIntSetFloat32Zero", in: 0, want: "0"}, {name: "TestIntSetFloat32Positive", in: 1.1, want: "1"}, {name: "TestIntSetFloat32Max", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntSetFloat32Min", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetFloat32(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+
+
+#### func (*Int) SetFloat64(i float64) *Int
+> 设置当前 Int 对象的值为 i 向下取整后的值
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetFloat64(t *testing.T) {
+ var cases = []struct {
+ name string
+ in float64
+ want string
+ }{{name: "TestIntSetFloat64Negative", in: -1.1, want: "-1"}, {name: "TestIntSetFloat64Zero", in: 0, want: "0"}, {name: "TestIntSetFloat64Positive", in: 1.1, want: "1"}, {name: "TestIntSetFloat64Max", in: 9223372036854775807, want: "9223372036854775807"}, {name: "TestIntSetFloat64Min", in: -9223372036854775808, want: "-9223372036854775808"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetFloat64(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
+
+***
+
+
+#### func (*Int) SetBool(i bool) *Int
+> 设置当前 Int 对象的值为 i,当 i 为 true 时,值为 1,当 i 为 false 时,值为 0
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_SetBool(t *testing.T) {
+ var cases = []struct {
+ name string
+ in bool
+ want string
+ }{{name: "TestIntSetBoolFalse", in: false, want: "0"}, {name: "TestIntSetBoolTrue", in: true, want: "1"}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ var in *huge.Int
+ in = in.SetBool(c.in)
+ if s := in.String(); s != c.want {
+ t.Fatalf("want: %s, got: %s", c.want, in.String())
+ } else {
+ t.Log(s)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) IsZero() bool
+> 判断当前 Int 对象的值是否为 0
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_IsZero(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want bool
+ }{{name: "TestIntIsZeroNegative", in: -1, want: false}, {name: "TestIntIsZeroZero", in: 0, want: true}, {name: "TestIntIsZeroPositive", in: 1, want: false}, {name: "TestIntIsZeroMax", in: 9223372036854775807, want: false}, {name: "TestIntIsZeroMin", in: -9223372036854775808, want: false}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ if got := huge.NewInt(c.in).IsZero(); got != c.want {
+ t.Fatalf("want: %t, got: %t", c.want, got)
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func (*Int) ToBigint() *big.Int
+> 转换为 *big.Int
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestInt_ToBigint(t *testing.T) {
+ var cases = []struct {
+ name string
+ in int64
+ want *big.Int
+ }{{name: "TestIntToBigintNegative", in: -1, want: big.NewInt(-1)}, {name: "TestIntToBigintZero", in: 0, want: big.NewInt(0)}, {name: "TestIntToBigintPositive", in: 1, want: big.NewInt(1)}, {name: "TestIntToBigintMax", in: 9223372036854775807, want: big.NewInt(9223372036854775807)}, {name: "TestIntToBigintMin", in: -9223372036854775808, want: big.NewInt(-9223372036854775808)}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ if got := huge.NewInt(c.in).ToBigint(); got.Cmp(c.want) != 0 {
+ t.Fatalf("want: %s, got: %s", c.want.String(), got.String())
+ }
+ })
+ }
+}
+
+```
+
+
+
+
***
@@ -266,46 +956,49 @@ type Int big.Int
#### func (*Int) GreaterThan(i *Int) bool
-> 大于
+> 检查 slf 是否大于 i
***
#### func (*Int) GreaterThanOrEqualTo(i *Int) bool
-> 大于或等于
+> 检查 slf 是否大于或等于 i
***
#### func (*Int) LessThan(i *Int) bool
-> 小于
+> 检查 slf 是否小于 i
***
#### func (*Int) LessThanOrEqualTo(i *Int) bool
-> 小于或等于
+> 检查 slf 是否小于或等于 i
***
#### func (*Int) EqualTo(i *Int) bool
-> 等于
+> 检查 slf 是否等于 i
***
#### func (*Int) Int64() int64
+> 转换为 int64 类型进行返回
***
#### func (*Int) String() string
+> 转换为 string 类型进行返回
***
#### func (*Int) Add(i *Int) *Int
+> 使用 i 对 slf 进行加法运算,slf 的值会变为运算后的值。返回 slf
***
diff --git a/utils/super/README.md b/utils/super/README.md
index b0f1093..8b40832 100644
--- a/utils/super/README.md
+++ b/utils/super/README.md
@@ -19,6 +19,8 @@
|[NewBitSet](#NewBitSet)|通过指定的 Bit 位创建一个 BitSet
|[TryWriteChannel](#TryWriteChannel)|尝试写入 channel,如果 channel 无法写入则忽略,返回是否写入成功
|[TryWriteChannelByHandler](#TryWriteChannelByHandler)|尝试写入 channel,如果 channel 无法写入则执行 handler
+|[TryReadChannel](#TryReadChannel)|尝试读取 channel,如果 channel 无法读取则忽略,返回是否读取成功
+|[TryReadChannelByHandler](#TryReadChannelByHandler)|尝试读取 channel,如果 channel 无法读取则执行 handler
|[RegError](#RegError)|通过错误码注册错误,返回错误的引用
|[RegErrorRef](#RegErrorRef)|通过错误码注册错误,返回错误的引用
|[GetError](#GetError)|通过错误引用获取错误码和真实错误信息,如果错误不存在则返回 0,如果错误引用不存在则返回原本的错误
@@ -107,6 +109,50 @@
#### func NewBitSet\[Bit generic.Integer\](bits ...Bit) *BitSet[Bit]
> 通过指定的 Bit 位创建一个 BitSet
+> - 当指定的 Bit 位存在负数时,将会 panic
+
+**示例代码:**
+
+```go
+
+func ExampleNewBitSet() {
+ var bs = super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ bs.Set(10)
+ fmt.Println(bs.Bits())
+}
+
+```
+
+
+查看 / 收起单元测试
+
+
+```go
+
+func TestNewBitSet(t *testing.T) {
+ var cases = []struct {
+ name string
+ in []int
+ shouldPanic bool
+ }{{name: "normal", in: []int{1, 2, 3, 4, 5, 6, 7, 8, 9}}, {name: "empty", in: make([]int, 0)}, {name: "nil", in: nil}, {name: "negative", in: []int{-1, -2}, shouldPanic: true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil && !c.shouldPanic {
+ t.Fatalf("panic: %v", r)
+ }
+ }()
+ bs := super.NewBitSet(c.in...)
+ t.Log(bs)
+ })
+ }
+}
+
+```
+
+
+
+
***
#### func TryWriteChannel\[T any\](ch chan T, data T) bool
@@ -120,6 +166,18 @@
> 尝试写入 channel,如果 channel 无法写入则执行 handler
> - 无法写入的情况包括:channel 已满、channel 已关闭
+***
+#### func TryReadChannel\[T any\](ch chan T) (v T, suc bool)
+
+> 尝试读取 channel,如果 channel 无法读取则忽略,返回是否读取成功
+> - 无法读取的情况包括:channel 已空、channel 已关闭
+
+***
+#### func TryReadChannelByHandler\[T any\](ch chan T, handler func (ch chan T) T) (v T)
+
+> 尝试读取 channel,如果 channel 无法读取则执行 handler
+> - 无法读取的情况包括:channel 已空、channel 已关闭
+
***
#### func RegError(code int, message string) error
@@ -757,6 +815,18 @@ type BitSet[Bit generic.Integer] struct {
#### func (*BitSet) Set(bit Bit) *BitSet[Bit]
> 将指定的位 bit 设置为 1
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Set() {
+ var bs = super.NewBitSet[int]()
+ bs.Set(10)
+ fmt.Println(bs.Bits())
+}
+
+```
+
查看 / 收起单元测试
@@ -764,11 +834,29 @@ type BitSet[Bit generic.Integer] struct {
```go
func TestBitSet_Set(t *testing.T) {
- bs := super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
- bs.Set(11)
- bs.Set(12)
- bs.Set(13)
- t.Log(bs)
+ var cases = []struct {
+ name string
+ in []int
+ shouldPanic bool
+ }{{name: "normal", in: []int{1, 2, 3, 4, 5, 6, 7, 8, 9}}, {name: "empty", in: make([]int, 0)}, {name: "nil", in: nil}, {name: "negative", in: []int{-1, -2}, shouldPanic: true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil && !c.shouldPanic {
+ t.Fatalf("panic: %v", r)
+ }
+ }()
+ bs := super.NewBitSet[int]()
+ for _, bit := range c.in {
+ bs.Set(bit)
+ }
+ for _, bit := range c.in {
+ if !bs.Has(bit) {
+ t.Fatalf("bit %v not set", bit)
+ }
+ }
+ })
+ }
}
```
@@ -783,6 +871,18 @@ func TestBitSet_Set(t *testing.T) {
#### func (*BitSet) Del(bit Bit) *BitSet[Bit]
> 将指定的位 bit 设置为 0
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Del() {
+ var bs = super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ bs.Del(1)
+ fmt.Println(bs.Bits())
+}
+
+```
+
查看 / 收起单元测试
@@ -790,12 +890,32 @@ func TestBitSet_Set(t *testing.T) {
```go
func TestBitSet_Del(t *testing.T) {
- bs := super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
- bs.Del(11)
- bs.Del(12)
- bs.Del(13)
- bs.Del(10)
- t.Log(bs)
+ var cases = []struct {
+ name string
+ in []int
+ shouldPanic bool
+ }{{name: "normal", in: []int{1, 2, 3, 4, 5, 6, 7, 8, 9}}, {name: "empty", in: make([]int, 0)}, {name: "nil", in: nil}, {name: "negative", in: []int{-1, -2}, shouldPanic: true}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil && !c.shouldPanic {
+ t.Fatalf("panic: %v", r)
+ }
+ }()
+ bs := super.NewBitSet[int]()
+ for _, bit := range c.in {
+ bs.Set(bit)
+ }
+ for _, bit := range c.in {
+ bs.Del(bit)
+ }
+ for _, bit := range c.in {
+ if bs.Has(bit) {
+ t.Fatalf("bit %v not del", bit)
+ }
+ }
+ })
+ }
}
```
@@ -811,6 +931,21 @@ func TestBitSet_Del(t *testing.T) {
> 将 BitSet 中的比特位集合缩小到最小
> - 正常情况下当 BitSet 中的比特位超出 64 位时,将自动增长,当 BitSet 中的比特位数量减少时,可以使用该方法将 BitSet 中的比特位集合缩小到最小
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Shrink() {
+ var bs = super.NewBitSet(111, 222, 333, 444)
+ fmt.Println(bs.Cap())
+ bs.Del(444)
+ fmt.Println(bs.Cap())
+ bs.Shrink()
+ fmt.Println(bs.Cap())
+}
+
+```
+
查看 / 收起单元测试
@@ -818,13 +953,22 @@ func TestBitSet_Del(t *testing.T) {
```go
func TestBitSet_Shrink(t *testing.T) {
- bs := super.NewBitSet(63)
- t.Log(bs.Cap())
- bs.Set(200)
- t.Log(bs.Cap())
- bs.Del(200)
- bs.Shrink()
- t.Log(bs.Cap())
+ var cases = []struct {
+ name string
+ in []int
+ }{{name: "normal", in: []int{1, 2, 3, 4, 5, 6, 7, 8, 9}}, {name: "empty", in: make([]int, 0)}, {name: "nil", in: nil}}
+ for _, c := range cases {
+ t.Run(c.name, func(t *testing.T) {
+ bs := super.NewBitSet(c.in...)
+ for _, v := range c.in {
+ bs.Del(v)
+ }
+ bs.Shrink()
+ if bs.Cap() != 0 {
+ t.Fatalf("cap %v != 0", bs.Cap())
+ }
+ })
+ }
}
```
@@ -839,24 +983,70 @@ func TestBitSet_Shrink(t *testing.T) {
#### func (*BitSet) Cap() int
> 返回当前 BitSet 中可以表示的最大比特位数量
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Cap() {
+ var bs = super.NewBitSet(63)
+ fmt.Println(bs.Cap())
+}
+
+```
+
***
#### func (*BitSet) Has(bit Bit) bool
> 检查指定的位 bit 是否被设置为 1
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Has() {
+ var bs = super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ fmt.Println(bs.Has(1))
+ fmt.Println(bs.Has(10))
+}
+
+```
+
***
#### func (*BitSet) Clear() *BitSet[Bit]
> 清空所有的比特位
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Clear() {
+ var bs = super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ bs.Clear()
+ fmt.Println(bs.Bits())
+}
+
+```
+
***
#### func (*BitSet) Len() int
> 返回当前 BitSet 中被设置的比特位数量
+**示例代码:**
+
+```go
+
+func ExampleBitSet_Len() {
+ var bs = super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ fmt.Println(bs.Len())
+}
+
+```
+
***