From fc14e7380125d6c4880e643ea01f1d2056b0ddc4 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Wed, 24 Jan 2024 11:12:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=AE=8C=E5=96=84=E6=A0=B9=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=20README.md=EF=BC=8C=E5=A2=9E=E5=8A=A0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=AE=9E=E8=B7=B5=E8=AE=B0=E5=BD=95=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E3=80=82=E7=94=9F=E6=88=90=E5=AD=90=E7=9B=AE=E5=BD=95=20README?= =?UTF-8?q?.md=20=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/images/pod.png | Bin 0 -> 2452 bytes .github/images/yc-cpu.png | Bin 0 -> 17830 bytes .github/images/yc-event.png | Bin 0 -> 23286 bytes .github/images/yc-memory.png | Bin 0 -> 29146 bytes .github/images/yc1.png | Bin 0 -> 30721 bytes .github/images/yc2.png | Bin 0 -> 30752 bytes README.md | 48 +- server/README.md | 25 + utils/collection/README.md | 1042 ++++++++++++++++++++++++++++++++++ utils/huge/README.md | 721 ++++++++++++++++++++++- utils/super/README.md | 226 +++++++- 11 files changed, 2027 insertions(+), 35 deletions(-) create mode 100644 .github/images/pod.png create mode 100644 .github/images/yc-cpu.png create mode 100644 .github/images/yc-event.png create mode 100644 .github/images/yc-memory.png create mode 100644 .github/images/yc1.png create mode 100644 .github/images/yc2.png diff --git a/.github/images/pod.png b/.github/images/pod.png new file mode 100644 index 0000000000000000000000000000000000000000..30a16c7768eda116fa1c56ec3001f31e62bbd7a6 GIT binary patch literal 2452 zcmai$dpOgJAIHB`XCWh9obWvzgkt0pSt|}hq+AX;n9McV9OgEftzwC}baW9Nii()R zB-Rj}CSo1rHkY}TrPvrFrpwihHN8?%-VR6Ehvkfw}=mY7z6aCZ*;iUN38_+*RY<$OWZXC#|ld;f@onyzr5U z0!5y(oGMP@1sUmDTX>u`nCjZB$!X{q#i`~oZ8^pQzk$ve;Uk5n!_b`6bi zKD>%_%$8b+gFKo+UxysD-^ftopd8hUnuO;+p(lxgwjgeImlHAiiN`QJYD9%n1#iUf zl6FFQW$Bm~7m8Ufk8v9HOu5yb&BHZ+b-<48`iefKAQm#w>HJm8!nzkQYSo= zT&lfBJs>T2M_Xp>5_7@0hx*9p)(w~m@Exi)8EorzH>xYT)TmzB1)ZwAUt~}P9>IIR zi-9m|-S*Q9nfX4g8P=V@`ae~f^FN%&`jSY@8pve$YIA>DFJ3ffFk9@LCHlyyJM0?2 z-(=X@7~E`r)II;OM6)P$#8qTE>6#6epVMu}A8x;mg~Vq!(kj6v4S%BrHMStcw~Ntt z6Rg0-it-Vj2VScx_pPR$i!vP5e9yUUa2$QuotTHeS$adR@$3HWz2s6voIu@$U3j?P zY7Zp||2=};T6TNK4~uOmt{(qKLI&?hn?)URe+^vo7s}u>Faz7(wMHO5E&9Cx5y#(t zs|0%=u|p_LG&RgEuSRK;#+C?W_sKu-S5+Dq^13XC#C=C&DCf^=u|OHZxA{-X`1&IT8COO zQ`onK&`-6gx^{Pm<}Imi*X7&x5D$7#i9ikE`0dk92UV|vnq=^lXZMWjJs#EdK_m|; z;S%73+qMg%`_(Ij742KE!^VF?^q7#`pB10%U0lk`y1DP|hZB9+ZSv|vGLyk%Q1@@s z;je%q*A~g5-evJ(`^4JG`TvNLzk>fOYyJj!B@rxhh0KXr$rk}DPj6)-J^=E<;C>5f zqcp}6o=Q=%tr4@+!l;tC@`A{ve`AZ$@KKXUq0j9qT%?#Sm)qg;>c zP=&v&!kGLvU)mOqg79gQcfvsvkr(2#&lqJYV zev~ZED{uBZ%S@Ut`XTrO3b0`bBxX^Nd|X-cIw=O^hA*E8jH7Z1ThQ!jC`3 zJ8Jd^!Nvy~8xn6^mK0(W-SF8hzuwP(v~urD;I4IsK(j=3V}lhD4$0lE!&_NJ$pm0C zz}}^4n*JijCgOY=>^RAG-Dm#A9$*|^F!TV{J;EzCYvtN2PgF2fI zPDZ|6oD5zXq;Kd`7ekuI%4Gc|*A3?TnvYa!bGBBX*_mM?_d7!F{0nJVtb1_B+&?!b zUn~&hx|8=>sx%FEv(6wmM7pK2i7i*>`8m@`>;+W6u;Y~3Cb80S^`Jb2!G+19~;GQiSzfFI=nZgO}_ zjdf|Y;kI}5h%~`5?kH(q(2$goRfqJ+%K4K}X=A^ZA88q{7>#XW^z5{%LpI7#O;mfM^nc94JN8A`-rt=LjtrVy&`kM%PtE@ZO}F(vs}pd5 T*EzfSZ2?a9E_PM60V)3gn|-v; literal 0 HcmV?d00001 diff --git a/.github/images/yc-cpu.png b/.github/images/yc-cpu.png new file mode 100644 index 0000000000000000000000000000000000000000..65a32e10fa73fb042a5d5acfbc6eb257eb1a0e60 GIT binary patch literal 17830 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 EACsU(3jhEB literal 0 HcmV?d00001 diff --git a/.github/images/yc-event.png b/.github/images/yc-event.png new file mode 100644 index 0000000000000000000000000000000000000000..ddfa32245fceb501bfb7d59daba4998415b51675 GIT binary patch literal 23286 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 l~E zf`L9oBP+9{J84zCkp#D4lj*2``0IqDIf0Vc*0>7e__I=nG(=Yj!x(757Yt<~SYe&9 zwbq!5>kf%Q<~B*%os-P*W(r@Cc>Go!@ILa7@9StHCDB0T`p#kzBo1U_)#S!8gty4^ z?2jt|MEX(6VhtpH8aRgiv@}sLt-}|7SnGe|LfT-B9>GyQQ4oaHO6qk;fSp7|MG>y% zbm6EQc{tI`FSOD;cly$@<}v)cN5OXE#v!7BT$%uK8Tg$(f6ZjpH^cUA>YRKc#t!L1 zdQ4{9p%_FS|BP*bb@gKE*pbX%3f99mp)$OQbW_XWt9aGfwz|n$x+6<)xw)qg?4AqV zq)VNFG>H>RU)ABD66hA(peX_4BY9C;NvH9BxL0m?739&ng+MK(f(jFw?|Q20eLr8y zvTX1A{TgZ7=MSUo|Ka-9(TCJ#lhc|Q)P~Na-i59{pNBx&3BZJ!34~=oTm&Wuy&73Q z>G$b&_#|ufvv1&}{dkkd3Vuq_qT9M?{VHBs#it~<%w^5Y%>;Zq1N;&TN3TyBuvdCw zW2FEBKw0Q|ODy>Crd8)9V0yoPVh?YYnK^OmHpfVDDj>jzf8DtEIPrB*c>vCTpAxvf zoqdRN2hIdYm}6!mZU~VFi@st0zv1_X4W#?;ZUC4=zoX}ScD%~@lKFgkf4ev~T0Ez; z)z8c;-lxoZz~l&T5!PSd_qA8&1Uog@{v^ekZ`Oa5Zr?g%<7#JZIqzZ!(Y#b4wV=y$ z2pi-rG?`Xw`Cesx4HeQI_RxOd@5CtWqEO#s4HvD%z{fi|&Rv5$?FqxoFaDCT_{Y54 zx|M-Lh#%1>86`09>5=RM$?wO$dbRlGs4#=dS>aZiE2A)WJ|n>jPzF=e)6x%nbXK$; zdQa}Mxki*xQ2Imi)`UtV)R?PRBPX*nHp{JELM2>$PeXnf+>;ida8s5NrUH)%J0S&l z18;G<;zhW^%$EygH4^qSdFmhsSkdEl>5FKnU+J~Qjzo6a&hDYPBDysXB*Ju!o28v? z3&OJ=-t&&$B?z71j#$l$0k874X`f9_JU%}(B60+ss-R15&}ZZp*yu1uum3-LtGwI) zVubr9Gso#%|A0+zfxg+ZZl5{(jQ8r6)!XODT9>^@SSa?=zGT+tQ|F}1>{{Jb<^PpH zr{G=)SI?Sj@Ts@3XpytMHUILPnGt)ZwDZevQ(pWo;)caX$=w&`C`44OnWbE*`ncrE z^4QYpGybZ%q1E8Mg^Gkf6ZYNY!b z`%mj~Y=cdsci#LHF=KY`q4WhC47E}{!`WTtt}Ds210FeN_k30O1>lt8=jiU1$+L5x zMVRW(teqlOR^k-Va%$4Lo5%l5%z0mG7bcdcE0lVCUad;_^R&b7g67u)Q+3PZWzVh^ zZT|Z$a&80r?E1U!&cFGYwwc?ndf}nJS~)%Lk-!ZS_n(??^9#Hnn-0ucXX_Sjo!YZ6 z{)XYFxl>OmZ+o+0%Wd|}HT!NplR0^eC06SPsC91vPX4bM693IwId$*sTRU&A36^kN zlw^NP^tJ!(sE4f_TMp?2-H_=2b@5>3!!MhcES`EfqQcaLXN`p;dG=ZqihSx}ZdXO8=hz!G5G-1O^JbLHK1x^0GU zuk_j|pg(>dzGOGaG=0f!>v{j@JBI)#u~6bh#y>Caj*VjO{`A+|7wud-{ZQ}a2;lzn z&n;W#_5-KJp18E{`+8AhvNUjA(Hqh0-g7rh&F=}YGk@M6TCCFjHD|_B=GVoI6Wh~H z$^vaF0-o?We^Fs^%4wiASAk`bcP%U#Ha|;aa9{-%Ge>}xKCon(0qS!PM)uX6Gr?y8 zv+mtFRh&V9*W47?3joeVE!YfdE`Sbw{zM$3=FgA+{7-ATW>m<=BmlKBc)I$ztaD0e F0sue5-$wud literal 0 HcmV?d00001 diff --git a/.github/images/yc-memory.png b/.github/images/yc-memory.png new file mode 100644 index 0000000000000000000000000000000000000000..bf73cfafdcacb4089b944ef14eec620566d5d8bb GIT binary patch literal 29146 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 literal 0 HcmV?d00001 diff --git a/.github/images/yc1.png b/.github/images/yc1.png new file mode 100644 index 0000000000000000000000000000000000000000..30a6f35bb1e07b99d85075609b559ceda92a890d GIT binary patch literal 30721 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 -Minotaur 是一个基于 Golang 1.20 编写的服务端开发支持库,其中采用了大量泛型设计,主要被用于游戏服务器开发,但由于拥有大量通用的功能,也常被用于 WEB 开发。 +![go version](https://img.shields.io/github/go-mod/go-version/kercylan98/minotaur?logo=go&style=flat) +![tag](https://img.shields.io/github/v/tag/kercylan98/minotaur?logo=github&style=flat) +![views](https://komarev.com/ghpvc/?username=kercylan98&color=blue&style=flat) + +![email](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat&logo=gmail&link=mailto:kercylan@gmail.com) +![qq-group](https://img.shields.io/badge/QQ%20Group-758219443-green.svg?style=flat&logo=tencent-qq&link=https://qm.qq.com/cgi-bin/qm/qr?k=WzRWJIDLzuJbH6-VjdFiTCd1_qA_Ug-D&jump_from=webapi&authKey=ktLEw3XyY9yO+i9rPbI6Fk0UA0uEhACcUidOFdblaiToZtbHcXyU7sFb31FEc9JJ&noverify=0) +![telegram](https://img.shields.io/badge/Telegram-ziv__siren-green.svg?style=flat&logo=telegram&link=https://telegram.me/ziv_siren) + +> - 这是支持快速搭建多功能游戏服务器及 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 配置参数** + +![pod](.github/images/pod.png) + +**压测结果** + +![压测数据](.github/images/yc1.png) +![压测数据](.github/images/yc2.png) + +**监控数据** + +![事件](./.github/images/yc-event.png) +![CPU](./.github/images/yc-cpu.png) +![内存](./.github/images/yc-memory.png) + +
+ +*** ## 特色内容 ```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()) +} + +``` + ***