From 22449ff5c34d681d34c0b59d3fce1a8987278d5e Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Mon, 15 Jan 2024 17:27:02 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BC=98=E5=8C=96=20README.md=20?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/activity/README.md | 45 ++ game/fight/README.md | 39 ++ game/space/README.md | 150 ++++++ game/task/README.md | 96 ++++ notify/README.md | 6 + notify/notifies/README.md | 36 ++ notify/senders/README.md | 5 +- planner/pce/README.md | 267 ++++++++++ planner/pce/cs/README.md | 18 + planner/pce/tmpls/README.md | 15 + server/README.md | 718 +++++++++++++++++++++++++-- server/client/README.md | 66 +++ server/gateway/README.md | 36 ++ server/internal/dispatcher/README.md | 73 ++- server/internal/logger/README.md | 18 + server/lockstep/README.md | 48 ++ server/router/README.md | 15 + server/writeloop/README.md | 12 + utils/aoi/README.md | 18 + utils/arrangement/README.md | 69 +++ utils/buffer/README.md | 51 ++ utils/collection/README.md | 12 +- utils/collection/listings/README.md | 104 +++- utils/collection/mappings/README.md | 54 ++ utils/combination/README.md | 40 +- utils/deck/README.md | 66 +++ utils/fsm/README.md | 27 + utils/generator/astgo/README.md | 27 + utils/generator/genreadme/README.md | 3 + utils/geometry/README.md | 120 +++++ utils/geometry/astar/README.md | 3 + utils/geometry/dp/README.md | 18 + utils/geometry/matrix/README.md | 48 ++ utils/geometry/navmesh/README.md | 9 + utils/hub/README.md | 6 + utils/huge/README.md | 396 +++++++++++++++ utils/leaderboard/README.md | 54 ++ utils/log/README.md | 12 + utils/log/survey/README.md | 99 ++++ utils/memory/README.md | 3 + utils/moving/README.md | 27 + utils/offset/README.md | 9 + utils/random/README.md | 6 + utils/sole/README.md | 6 + utils/super/README.md | 141 ++++++ utils/timer/README.md | 45 ++ utils/times/README.md | 129 +++++ 47 files changed, 3219 insertions(+), 46 deletions(-) diff --git a/game/activity/README.md b/game/activity/README.md index 1727523..3156ecc 100644 --- a/game/activity/README.md +++ b/game/activity/README.md @@ -201,31 +201,61 @@ type Controller[Type generic.Basic, ID generic.Basic, Data any, EntityID generic mutex sync.RWMutex } ``` + + #### func (*Controller) GetGlobalData(activityId ID) Data > 获取特定活动全局数据 + *** + + #### func (*Controller) GetEntityData(activityId ID, entityId EntityID) EntityData > 获取特定活动实体数据 + *** + + #### func (*Controller) IsOpen(activityId ID) bool > 活动是否开启 + *** + + #### func (*Controller) IsShow(activityId ID) bool > 活动是否展示 + *** + + #### func (*Controller) IsOpenOrShow(activityId ID) bool > 活动是否开启或展示 + *** + + #### func (*Controller) Refresh(activityId ID) > 刷新活动 + *** + + #### func (*Controller) InitializeNoneData(handler func (activityId ID, data *DataMeta[Data])) NoneDataActivityController[Type, ID, Data, EntityID, EntityData] + *** + + #### func (*Controller) InitializeGlobalData(handler func (activityId ID, data *DataMeta[Data])) GlobalDataActivityController[Type, ID, Data, EntityID, EntityData] + *** + + #### func (*Controller) InitializeEntityData(handler func (activityId ID, entityId EntityID, data *EntityDataMeta[EntityData])) EntityDataActivityController[Type, ID, Data, EntityID, EntityData] + *** + + #### func (*Controller) InitializeGlobalAndEntityData(handler func (activityId ID, data *DataMeta[Data]), entityHandler func (activityId ID, entityId EntityID, data *EntityDataMeta[EntityData])) GlobalAndEntityDataActivityController[Type, ID, Data, EntityID, EntityData] + *** ### BasicActivityController `INTERFACE` @@ -313,19 +343,34 @@ type Options struct { Loop time.Duration } ``` + + #### func (*Options) WithUpcomingTime(t time.Time) *Options > 设置活动预告时间 + *** + + #### func (*Options) WithStartTime(t time.Time) *Options > 设置活动开始时间 + *** + + #### func (*Options) WithEndTime(t time.Time) *Options > 设置活动结束时间 + *** + + #### func (*Options) WithExtendedShowTime(t time.Time) *Options > 设置延长展示时间 + *** + + #### func (*Options) WithLoop(interval time.Duration) *Options > 设置活动循环,时间间隔小于等于 0 表示不循环 > - 当活动状态展示结束后,会根据该选项设置的时间间隔重新开始 + *** diff --git a/game/fight/README.md b/game/fight/README.md index fa9683d..f052730 100644 --- a/game/fight/README.md +++ b/game/fight/README.md @@ -65,18 +65,30 @@ type TurnBased[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], closed bool } ``` + + #### func (*TurnBased) Close() > 关闭回合制 + *** + + #### func (*TurnBased) AddCamp(camp Camp, entity Entity, entities ...Entity) > 添加阵营 + *** + + #### func (*TurnBased) SetActionTimeout(actionTimeoutHandler func ( Camp, Entity) time.Duration) > 设置行动超时时间处理函数 > - 默认情况下行动超时时间函数将始终返回 0 + *** + + #### func (*TurnBased) Run() > 运行 +
查看 / 收起单元测试 @@ -154,33 +166,60 @@ type TurnBasedController[CampID comparable, EntityID comparable, Camp generic.Id tb *TurnBased[CampID, EntityID, Camp, Entity] } ``` + + #### func (*TurnBasedController) GetRound() int > 获取当前回合数 + *** + + #### func (*TurnBasedController) GetCamp() Camp > 获取当前操作阵营 + *** + + #### func (*TurnBasedController) GetEntity() Entity > 获取当前操作实体 + *** + + #### func (*TurnBasedController) GetActionTimeoutDuration() time.Duration > 获取当前行动超时时长 + *** + + #### func (*TurnBasedController) GetActionStartTime() time.Time > 获取当前行动开始时间 + *** + + #### func (*TurnBasedController) GetActionEndTime() time.Time > 获取当前行动结束时间 + *** + + #### func (*TurnBasedController) Finish() > 结束当前操作,将立即切换到下一个操作实体 + *** + + #### func (*TurnBasedController) Stop() > 在当前回合执行完毕后停止回合进程 + *** + + #### func (*TurnBasedController) Refresh(duration time.Duration) time.Time > 刷新当前操作实体的行动超时时间 > - 当不在行动阶段时,将返回 time.Time 零值 + *** ### TurnBasedEntitySwitchEventHandler `STRUCT` diff --git a/game/space/README.md b/game/space/README.md index e93b2f7..84f0f65 100644 --- a/game/space/README.md +++ b/game/space/README.md @@ -70,131 +70,245 @@ type RoomController[EntityID comparable, RoomID comparable, Entity generic.IdR[E owner *EntityID } ``` + + #### func (*RoomController) HasOwner() bool > 判断是否有房主 + *** + + #### func (*RoomController) IsOwner(entityId EntityID) bool > 判断是否为房主 + *** + + #### func (*RoomController) GetOwner() Entity > 获取房主 + *** + + #### func (*RoomController) GetOwnerID() EntityID > 获取房主 ID + *** + + #### func (*RoomController) GetOwnerExist() ( Entity, bool) > 获取房间,并返回房主是否存在的状态 + *** + + #### func (*RoomController) SetOwner(entityId EntityID) > 设置房主 + *** + + #### func (*RoomController) DelOwner() > 删除房主,将房间设置为无主的状态 + *** + + #### func (*RoomController) JoinSeat(entityId EntityID, seat ...int) error > 设置特定对象加入座位,当具体的座位不存在的时候,将会自动分配座位 > - 当目标座位存在玩家或未添加到房间中的时候,将会返回错误 + *** + + #### func (*RoomController) LeaveSeat(entityId EntityID) > 离开座位 + *** + + #### func (*RoomController) GetSeat(entityId EntityID) int > 获取座位 + *** + + #### func (*RoomController) GetFirstNotEmptySeat() int > 获取第一个非空座位号,如果没有非空座位,将返回 UnknownSeat + *** + + #### func (*RoomController) GetFirstEmptySeatEntity() (entity Entity) > 获取第一个空座位上的实体,如果没有空座位,将返回空实体 + *** + + #### func (*RoomController) GetRandomEntity() (entity Entity) > 获取随机实体,如果房间中没有实体,将返回空实体 + *** + + #### func (*RoomController) GetNotEmptySeat() []int > 获取非空座位 + *** + + #### func (*RoomController) GetEmptySeat() []int > 获取空座位 > - 空座位需要在有对象离开座位后才可能出现 + *** + + #### func (*RoomController) HasSeat(entityId EntityID) bool > 判断是否有座位 + *** + + #### func (*RoomController) GetSeatEntityCount() int > 获取座位上的实体数量 + *** + + #### func (*RoomController) GetSeatEntities() map[EntityID]Entity > 获取座位上的实体 + *** + + #### func (*RoomController) GetSeatEntitiesByOrdered() []Entity > 有序的获取座位上的实体 + *** + + #### func (*RoomController) GetSeatEntitiesByOrderedAndContainsEmpty() []Entity > 获取有序的座位上的实体,包含空座位 + *** + + #### func (*RoomController) GetSeatEntity(seat int) (entity Entity) > 获取座位上的实体 + *** + + #### func (*RoomController) ContainEntity(id EntityID) bool > 房间内是否包含实体 + *** + + #### func (*RoomController) GetRoom() Room > 获取原始房间实例,该实例为被接管的房间的原始实例 + *** + + #### func (*RoomController) GetEntities() map[EntityID]Entity > 获取所有实体 + *** + + #### func (*RoomController) HasEntity(id EntityID) bool > 判断是否有实体 + *** + + #### func (*RoomController) GetEntity(id EntityID) Entity > 获取实体 + *** + + #### func (*RoomController) GetEntityExist(id EntityID) ( Entity, bool) > 获取实体,并返回实体是否存在的状态 + *** + + #### func (*RoomController) GetEntityIDs() []EntityID > 获取所有实体ID + *** + + #### func (*RoomController) GetEntityCount() int > 获取实体数量 + *** + + #### func (*RoomController) ChangePassword(password *string) > 修改房间密码 > - 当房间密码为 nil 时,将会取消密码 + *** + + #### func (*RoomController) AddEntity(entity Entity) error > 添加实体,如果房间存在密码,应使用 AddEntityByPassword 函数进行添加,否则将始终返回 ErrRoomPasswordNotMatch 错误 > - 当房间已满时,将会返回 ErrRoomFull 错误 + *** + + #### func (*RoomController) AddEntityByPassword(entity Entity, password string) error > 通过房间密码添加实体到该房间中 > - 当未设置房间密码时,password 参数将会被忽略 > - 当房间密码不匹配时,将会返回 ErrRoomPasswordNotMatch 错误 > - 当房间已满时,将会返回 ErrRoomFull 错误 + *** + + #### func (*RoomController) RemoveEntity(id EntityID) > 移除实体 > - 当实体被移除时如果实体在座位上,将会自动离开座位 > - 如果实体为房主,将会根据 RoomControllerOptions.WithOwnerInherit 函数的设置进行继承 + *** + + #### func (*RoomController) RemoveAllEntities() > 移除该房间中的所有实体 > - 当实体被移除时如果实体在座位上,将会自动离开座位 > - 如果实体为房主,将会根据 RoomControllerOptions.WithOwnerInherit 函数的设置进行继承 + *** + + #### func (*RoomController) Destroy() > 销毁房间,房间会从 RoomManager 中移除,同时所有房间的实体、座位等数据都会被清空 > - 该函数与 RoomManager.DestroyRoom 相同,RoomManager.DestroyRoom 函数为该函数的快捷方式 + *** + + #### func (*RoomController) GetRoomManager() *RoomManager[EntityID, RoomID, Entity, Room] > 获取该房间控制器所属的房间管理器 + *** + + #### func (*RoomController) GetRoomID() RoomID > 获取房间 ID + *** + + #### func (*RoomController) Broadcast(handler func ( Entity), conditions ...func ( Entity) bool) > 广播,该函数会将所有房间中满足 conditions 的对象传入 handler 中进行处理 + *** ### RoomManager `STRUCT` @@ -207,10 +321,13 @@ type RoomManager[EntityID comparable, RoomID comparable, Entity generic.IdR[Enti rooms map[RoomID]*RoomController[EntityID, RoomID, Entity, Room] } ``` + + #### func (*RoomManager) AssumeControl(room Room, options ...*RoomControllerOptions[EntityID, RoomID, Entity, Room]) *RoomController[EntityID, RoomID, Entity, Room] > 将房间控制权交由 RoomManager 接管,返回 RoomController 实例 > - 当任何房间需要被 RoomManager 管理时,都应该调用该方法获取到 RoomController 实例后进行操作 > - 房间被接管后需要在释放房间控制权时调用 RoomController.Destroy 方法,否则将会导致 RoomManager 一直持有房间资源 + **示例代码:** ```go @@ -228,31 +345,55 @@ func ExampleRoomManager_AssumeControl() { ``` *** + + #### func (*RoomManager) DestroyRoom(id RoomID) > 销毁房间,该函数为 RoomController.Destroy 的快捷方式 + *** + + #### func (*RoomManager) GetRoom(id RoomID) *RoomController[EntityID, RoomID, Entity, Room] > 通过房间 ID 获取对应房间的控制器 RoomController,当房间不存在时将返回 nil + *** + + #### func (*RoomManager) GetRooms() map[RoomID]*RoomController[EntityID, RoomID, Entity, Room] > 获取包含所有房间 ID 到对应控制器 RoomController 的映射 > - 返回值的 map 为拷贝对象,可安全的对其进行增删等操作 + *** + + #### func (*RoomManager) GetRoomCount() int > 获取房间管理器接管的房间数量 + *** + + #### func (*RoomManager) GetRoomIDs() []RoomID > 获取房间管理器接管的所有房间 ID + *** + + #### func (*RoomManager) HasEntity(entityId EntityID) bool > 判断特定对象是否在任一房间中,当对象不在任一房间中时将返回 false + *** + + #### func (*RoomManager) GetEntityRooms(entityId EntityID) map[RoomID]*RoomController[EntityID, RoomID, Entity, Room] > 获取特定对象所在的房间,返回值为房间 ID 到对应控制器 RoomController 的映射 > - 由于一个对象可能在多个房间中,因此返回值为 map 类型 + *** + + #### func (*RoomManager) Broadcast(handler func ( Entity), conditions ...func ( Entity) bool) > 向所有房间对象广播消息,该方法将会遍历所有房间控制器并调用 RoomController.Broadcast 方法 + *** ### RoomAssumeControlEventHandle `STRUCT` @@ -271,14 +412,23 @@ type RoomControllerOptions[EntityID comparable, RoomID comparable, Entity generi ownerInheritHandler func(controller *RoomController[EntityID, RoomID, Entity, Room]) *EntityID } ``` + + #### func (*RoomControllerOptions) WithOwnerInherit(inherit bool, inheritHandler ...func (controller *RoomController[EntityID, RoomID, Entity, Room]) *EntityID) *RoomControllerOptions[EntityID, RoomID, Entity, Room] > 设置房间所有者是否继承,默认为 false > - inherit: 是否继承,当未设置 inheritHandler 且 inherit 为 true 时,将会按照随机或根据座位号顺序继承房间所有者 > - inheritHandler: 继承处理函数,当 inherit 为 true 时,该函数将会被调用,传入当前房间中的所有实体,返回值为新的房间所有者 + *** + + #### func (*RoomControllerOptions) WithMaxEntityCount(maxEntityCount int) *RoomControllerOptions[EntityID, RoomID, Entity, Room] > 设置房间最大实体数量 + *** + + #### func (*RoomControllerOptions) WithPassword(password string) *RoomControllerOptions[EntityID, RoomID, Entity, Room] > 设置房间密码 + *** diff --git a/game/task/README.md b/game/task/README.md index 58902de..fe0196e 100644 --- a/game/task/README.md +++ b/game/task/README.md @@ -156,71 +156,137 @@ func TestCond(t *testing.T) { ```go type Condition map[any]any ``` + + #### func (Condition) Cond(k any, v any) Condition > 创建任务条件 + *** + + #### func (Condition) GetString(key any) string > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetInt(key any) int > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetInt8(key any) int8 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetInt16(key any) int16 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetInt32(key any) int32 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetInt64(key any) int64 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetUint(key any) uint > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetUint8(key any) uint8 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetUint16(key any) uint16 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetUint32(key any) uint32 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetUint64(key any) uint64 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetFloat32(key any) float32 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetFloat64(key any) float64 > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetBool(key any) bool > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetTime(key any) time.Time > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetDuration(key any) time.Duration > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetByte(key any) byte > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetBytes(key any) []byte > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetRune(key any) rune > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetRunes(key any) []rune > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** + + #### func (Condition) GetAny(key any) any > 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值 + *** ### RefreshTaskCounterEventHandler `STRUCT` @@ -240,7 +306,10 @@ type Option func(task *Task) ```go type Status byte ``` + + #### func (Status) String() string + *** ### Task `STRUCT` @@ -259,33 +328,60 @@ type Task struct { LimitedDuration time.Duration } ``` + + #### func (*Task) IsComplete() bool > 判断任务是否已完成 + *** + + #### func (*Task) IsFailed() bool > 判断任务是否已失败 + *** + + #### func (*Task) IsReward() bool > 判断任务是否已领取奖励 + *** + + #### func (*Task) ReceiveReward() bool > 领取任务奖励,当任务状态为已完成时,才能领取奖励,此时返回 true,并且任务状态变更为已领取奖励 + *** + + #### func (*Task) IncrementCounter(incr int64) *Task > 增加计数器的值,当 incr 为负数时,计数器的值不会发生变化 > - 如果需要溢出计数器,可通过 WithOverflowCounter 设置可溢出的任务计数器 + *** + + #### func (*Task) DecrementCounter(decr int64) *Task > 减少计数器的值,当 decr 为负数时,计数器的值不会发生变化 + *** + + #### func (*Task) AssignConditionValueAndRefresh(key any, value any) *Task > 分配条件值并刷新任务状态 + *** + + #### func (*Task) AssignConditionValueAndRefreshByCondition(condition Condition) *Task > 分配条件值并刷新任务状态 + *** + + #### func (*Task) ResetStatus() *Task > 重置任务状态 > - 该函数会将任务状态重置为已接受状态后,再刷新任务状态 > - 当任务条件变更,例如任务计数要求为 10,已经完成的情况下,将任务计数要求变更为 5 或 20,此时任务状态由于是已完成或已领取状态,不会自动刷新,需要调用该函数刷新任务状态 + *** diff --git a/notify/README.md b/notify/README.md index ea293bb..91b960f 100644 --- a/notify/README.md +++ b/notify/README.md @@ -47,11 +47,17 @@ type Manager struct { closeChannel chan struct{} } ``` + + #### func (*Manager) PushNotify(notify Notify) > 推送通知 + *** + + #### func (*Manager) Release() > 释放通知管理器 + *** ### Notify `INTERFACE` diff --git a/notify/notifies/README.md b/notify/notifies/README.md index 17c6322..eb15f92 100644 --- a/notify/notifies/README.md +++ b/notify/notifies/README.md @@ -156,8 +156,11 @@ type FeiShu struct { MsgType string } ``` + + #### func (*FeiShu) Format() ( string, error) > 格式化通知内容 + *** ### FeiShuMessage `STRUCT` @@ -173,8 +176,11 @@ type FeiShuRichText struct { content map[string]*FeiShuRichTextContent } ``` + + #### func (*FeiShuRichText) Create(lang string, title string) *FeiShuRichTextContent > 创建一个特定语言和标题的富文本内容 + *** ### FeiShuRichTextContent `STRUCT` @@ -186,45 +192,75 @@ type FeiShuRichTextContent struct { Content [][]map[string]any } ``` + + #### func (*FeiShuRichTextContent) AddText(text string, styles ...string) *FeiShuRichTextContent > 添加文本 + *** + + #### func (*FeiShuRichTextContent) AddUnescapeText(text string, styles ...string) *FeiShuRichTextContent > 添加 unescape 解码的文本 + *** + + #### func (*FeiShuRichTextContent) AddLink(text string, href string, styles ...string) *FeiShuRichTextContent > 添加超链接文本 > - 请确保链接地址的合法性,否则消息会发送失败 + *** + + #### func (*FeiShuRichTextContent) AddAt(userId string, styles ...string) *FeiShuRichTextContent > 添加@的用户 > - @单个用户时,userId 字段必须是有效值 > - @所有人填"all"。 + *** + + #### func (*FeiShuRichTextContent) AddAtWithUsername(userId string, username string, styles ...string) *FeiShuRichTextContent > 添加包含用户名的@用户 > - @单个用户时,userId 字段必须是有效值 > - @所有人填"all"。 + *** + + #### func (*FeiShuRichTextContent) AddImg(imageKey string) *FeiShuRichTextContent > 添加图片 > - imageKey 表示图片的唯一标识,可通过上传图片接口获取 + *** + + #### func (*FeiShuRichTextContent) AddMedia(fileKey string) *FeiShuRichTextContent > 添加视频 > - fileKey 表示视频文件的唯一标识,可通过上传文件接口获取 + *** + + #### func (*FeiShuRichTextContent) AddMediaWithCover(fileKey string, imageKey string) *FeiShuRichTextContent > 添加包含封面的视频 > - fileKey 表示视频文件的唯一标识,可通过上传文件接口获取 > - imageKey 表示图片的唯一标识,可通过上传图片接口获取 + *** + + #### func (*FeiShuRichTextContent) AddEmotion(emojiType string) *FeiShuRichTextContent > 添加表情 > - emojiType 表示表情类型,部分可选值请参见表情文案。 > > 表情文案:https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce + *** + + #### func (*FeiShuRichTextContent) Ok() *FeiShuRichText > 确认完成,将返回 FeiShuRichText 可继续创建多语言富文本 + *** diff --git a/notify/senders/README.md b/notify/senders/README.md index 593f597..3045153 100644 --- a/notify/senders/README.md +++ b/notify/senders/README.md @@ -44,8 +44,11 @@ type FeiShu struct { webhook string } ``` + + #### func (*FeiShu) Push(notify notify.Notify) error > 推送通知 +
查看 / 收起单元测试 @@ -53,7 +56,7 @@ type FeiShu struct { ```go func TestFeiShu_Push(t *testing.T) { - fs := NewFeiShu("https://open.feishu.cn/open-apis/bot/v2/hook/d886f30f-814c-47b1-aeb0-b508da0f7f22") + fs := NewFeiShu("https://open.feishu.cn/open-apis/bot/v2/hook/bid") rt := notifies.NewFeiShu(notifies.FeiShuMessageWithRichText(notifies.NewFeiShuRichText().Create("zh_cn", "标题咯").AddText("哈哈哈").Ok())) if err := fs.Push(rt); err != nil { panic(err) diff --git a/planner/pce/README.md b/planner/pce/README.md index 485242c..cf4d54b 100644 --- a/planner/pce/README.md +++ b/planner/pce/README.md @@ -135,11 +135,17 @@ type DataTmpl interface { ```go type Exporter struct{} ``` + + #### func (*Exporter) ExportStruct(tmpl Tmpl, tmplStruct ...*TmplStruct) ( []byte, error) > 导出结构 + *** + + #### func (*Exporter) ExportData(tmpl DataTmpl, data map[any]any) ( []byte, error) > 导出数据 + *** ### Field `INTERFACE` @@ -157,11 +163,20 @@ type Field interface { ```go type Int int ``` + + #### func (Int) TypeName() string + *** + + #### func (Int) Zero() any + *** + + #### func (Int) Parse(value string) any + *** ### Int8 `STRUCT` @@ -169,11 +184,20 @@ type Int int ```go type Int8 int8 ``` + + #### func (Int8) TypeName() string + *** + + #### func (Int8) Zero() any + *** + + #### func (Int8) Parse(value string) any + *** ### Int16 `STRUCT` @@ -181,11 +205,20 @@ type Int8 int8 ```go type Int16 int16 ``` + + #### func (Int16) TypeName() string + *** + + #### func (Int16) Zero() any + *** + + #### func (Int16) Parse(value string) any + *** ### Int32 `STRUCT` @@ -193,11 +226,20 @@ type Int16 int16 ```go type Int32 int32 ``` + + #### func (Int32) TypeName() string + *** + + #### func (Int32) Zero() any + *** + + #### func (Int32) Parse(value string) any + *** ### Int64 `STRUCT` @@ -205,11 +247,20 @@ type Int32 int32 ```go type Int64 int64 ``` + + #### func (Int64) TypeName() string + *** + + #### func (Int64) Zero() any + *** + + #### func (Int64) Parse(value string) any + *** ### Uint `STRUCT` @@ -217,11 +268,20 @@ type Int64 int64 ```go type Uint uint ``` + + #### func (Uint) TypeName() string + *** + + #### func (Uint) Zero() any + *** + + #### func (Uint) Parse(value string) any + *** ### Uint8 `STRUCT` @@ -229,11 +289,20 @@ type Uint uint ```go type Uint8 uint8 ``` + + #### func (Uint8) TypeName() string + *** + + #### func (Uint8) Zero() any + *** + + #### func (Uint8) Parse(value string) any + *** ### Uint16 `STRUCT` @@ -241,11 +310,20 @@ type Uint8 uint8 ```go type Uint16 uint16 ``` + + #### func (Uint16) TypeName() string + *** + + #### func (Uint16) Zero() any + *** + + #### func (Uint16) Parse(value string) any + *** ### Uint32 `STRUCT` @@ -253,11 +331,20 @@ type Uint16 uint16 ```go type Uint32 uint32 ``` + + #### func (Uint32) TypeName() string + *** + + #### func (Uint32) Zero() any + *** + + #### func (Uint32) Parse(value string) any + *** ### Uint64 `STRUCT` @@ -265,11 +352,20 @@ type Uint32 uint32 ```go type Uint64 uint64 ``` + + #### func (Uint64) TypeName() string + *** + + #### func (Uint64) Zero() any + *** + + #### func (Uint64) Parse(value string) any + *** ### Float32 `STRUCT` @@ -277,11 +373,20 @@ type Uint64 uint64 ```go type Float32 float32 ``` + + #### func (Float32) TypeName() string + *** + + #### func (Float32) Zero() any + *** + + #### func (Float32) Parse(value string) any + *** ### Float64 `STRUCT` @@ -289,11 +394,20 @@ type Float32 float32 ```go type Float64 float64 ``` + + #### func (Float64) TypeName() string + *** + + #### func (Float64) Zero() any + *** + + #### func (Float64) Parse(value string) any + *** ### String `STRUCT` @@ -301,11 +415,20 @@ type Float64 float64 ```go type String string ``` + + #### func (String) TypeName() string + *** + + #### func (String) Zero() any + *** + + #### func (String) Parse(value string) any + *** ### Bool `STRUCT` @@ -313,11 +436,20 @@ type String string ```go type Bool bool ``` + + #### func (Bool) TypeName() string + *** + + #### func (Bool) Zero() any + *** + + #### func (Bool) Parse(value string) any + *** ### Byte `STRUCT` @@ -325,11 +457,20 @@ type Bool bool ```go type Byte byte ``` + + #### func (Byte) TypeName() string + *** + + #### func (Byte) Zero() any + *** + + #### func (Byte) Parse(value string) any + *** ### Rune `STRUCT` @@ -337,11 +478,20 @@ type Byte byte ```go type Rune rune ``` + + #### func (Rune) TypeName() string + *** + + #### func (Rune) Zero() any + *** + + #### func (Rune) Parse(value string) any + *** ### Complex64 `STRUCT` @@ -349,11 +499,20 @@ type Rune rune ```go type Complex64 complex64 ``` + + #### func (Complex64) TypeName() string + *** + + #### func (Complex64) Zero() any + *** + + #### func (Complex64) Parse(value string) any + *** ### Complex128 `STRUCT` @@ -361,11 +520,20 @@ type Complex64 complex64 ```go type Complex128 complex128 ``` + + #### func (Complex128) TypeName() string + *** + + #### func (Complex128) Zero() any + *** + + #### func (Complex128) Parse(value string) any + *** ### Uintptr `STRUCT` @@ -373,11 +541,20 @@ type Complex128 complex128 ```go type Uintptr uintptr ``` + + #### func (Uintptr) TypeName() string + *** + + #### func (Uintptr) Zero() any + *** + + #### func (Uintptr) Parse(value string) any + *** ### Double `STRUCT` @@ -385,11 +562,20 @@ type Uintptr uintptr ```go type Double float64 ``` + + #### func (Double) TypeName() string + *** + + #### func (Double) Zero() any + *** + + #### func (Double) Parse(value string) any + *** ### Float `STRUCT` @@ -397,11 +583,20 @@ type Double float64 ```go type Float float32 ``` + + #### func (Float) TypeName() string + *** + + #### func (Float) Zero() any + *** + + #### func (Float) Parse(value string) any + *** ### Long `STRUCT` @@ -409,11 +604,20 @@ type Float float32 ```go type Long int64 ``` + + #### func (Long) TypeName() string + *** + + #### func (Long) Zero() any + *** + + #### func (Long) Parse(value string) any + *** ### Short `STRUCT` @@ -421,11 +625,20 @@ type Long int64 ```go type Short int16 ``` + + #### func (Short) TypeName() string + *** + + #### func (Short) Zero() any + *** + + #### func (Short) Parse(value string) any + *** ### Char `STRUCT` @@ -433,11 +646,20 @@ type Short int16 ```go type Char int8 ``` + + #### func (Char) TypeName() string + *** + + #### func (Char) Zero() any + *** + + #### func (Char) Parse(value string) any + *** ### Number `STRUCT` @@ -445,11 +667,20 @@ type Char int8 ```go type Number float64 ``` + + #### func (Number) TypeName() string + *** + + #### func (Number) Zero() any + *** + + #### func (Number) Parse(value string) any + *** ### Integer `STRUCT` @@ -457,11 +688,20 @@ type Number float64 ```go type Integer int64 ``` + + #### func (Integer) TypeName() string + *** + + #### func (Integer) Zero() any + *** + + #### func (Integer) Parse(value string) any + *** ### Boolean `STRUCT` @@ -469,11 +709,20 @@ type Integer int64 ```go type Boolean bool ``` + + #### func (Boolean) TypeName() string + *** + + #### func (Boolean) Zero() any + *** + + #### func (Boolean) Parse(value string) any + *** ### Loader `STRUCT` @@ -483,11 +732,17 @@ type Loader struct { fields map[string]Field } ``` + + #### func (*Loader) LoadStruct(config Config) *TmplStruct > 加载结构 + *** + + #### func (*Loader) LoadData(config Config) map[any]any > 加载配置并得到配置数据 + *** ### DataInfo `STRUCT` @@ -532,14 +787,23 @@ type TmplField struct { isIndex bool } ``` + + #### func (*TmplField) IsIndex() bool > 是否是索引字段 + *** + + #### func (*TmplField) IsStruct() bool > 是否是结构类型 + *** + + #### func (*TmplField) IsSlice() bool > 是否是切片类型 + *** ### TmplStruct `STRUCT` @@ -552,6 +816,9 @@ type TmplStruct struct { IndexCount int } ``` + + #### func (*TmplStruct) AllChildren() []*TmplStruct > 获取所有子结构 + *** diff --git a/planner/pce/cs/README.md b/planner/pce/cs/README.md index 4c9d347..1af49eb 100644 --- a/planner/pce/cs/README.md +++ b/planner/pce/cs/README.md @@ -50,15 +50,33 @@ type Xlsx struct { exportType XlsxExportType } ``` + + #### func (*Xlsx) GetConfigName() string + *** + + #### func (*Xlsx) GetDisplayName() string + *** + + #### func (*Xlsx) GetDescription() string + *** + + #### func (*Xlsx) GetIndexCount() int + *** + + #### func (*Xlsx) GetFields() []pce.DataField + *** + + #### func (*Xlsx) GetData() [][]pce.DataInfo + *** diff --git a/planner/pce/tmpls/README.md b/planner/pce/tmpls/README.md index ac56c86..cd38f58 100644 --- a/planner/pce/tmpls/README.md +++ b/planner/pce/tmpls/README.md @@ -50,13 +50,25 @@ type Golang struct { Templates []*pce.TmplStruct } ``` + + #### func (*Golang) Render(templates ...*pce.TmplStruct) ( string, error) + *** + + #### func (*Golang) GetVariable(config *pce.TmplStruct) string + *** + + #### func (*Golang) GetConfigName(config *pce.TmplStruct) string + *** + + #### func (*Golang) HasIndex(config *pce.TmplStruct) bool + *** ### JSON `STRUCT` @@ -66,5 +78,8 @@ type JSON struct { jsonIter.API } ``` + + #### func (*JSON) Render(data map[any]any) ( string, error) + *** diff --git a/server/README.md b/server/README.md index fe320bc..bb0d216 100644 --- a/server/README.md +++ b/server/README.md @@ -70,10 +70,10 @@ server 提供了包含多种网络类型的服务器实现 |`STRUCT`|[MessageType](#struct_MessageType)|暂无描述... |`STRUCT`|[Message](#struct_Message)|服务器消息 |`STRUCT`|[MultipleServer](#struct_MultipleServer)|暂无描述... -|`STRUCT`|[Network](#struct_Network)|暂无描述... +|`STRUCT`|[Network](#struct_Network)|服务器运行的网络模式 |`STRUCT`|[Option](#struct_Option)|暂无描述... |`STRUCT`|[Server](#struct_Server)|网络服务器 -|`INTERFACE`|[Service](#struct_Service)|兼容传统 service 设计模式的接口 +|`INTERFACE`|[Service](#struct_Service)|兼容传统 service 设计模式的接口,通过该接口可以实现更简洁、更具有可读性的服务绑定
@@ -174,6 +174,84 @@ func TestNewBot(t *testing.T) { > - 默认值为 DefaultLowMessageDuration > - 当 duration <= 0 时,表示关闭慢消息检测 +**示例代码:** + +服务器在启动时将阻塞 1s,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息 + - 该示例中,将在收到慢消息时关闭服务器 + + +```go + +func ExampleWithLowMessageDuration() { + srv := server.New(server.NetworkNone, server.WithLowMessageDuration(time.Second)) + srv.RegStartFinishEvent(func(srv *server.Server) { + time.Sleep(time.Second) + }) + srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) { + srv.Shutdown() + fmt.Println(times.GetSecond(cost)) + }) + if err := srv.RunNone(); err != nil { + panic(err) + } +} + +``` + +
+查看 / 收起单元测试 + + +```go + +func TestWithLowMessageDuration(t *testing.T) { + var cases = []struct { + name string + duration time.Duration + }{{name: "TestWithLowMessageDuration", duration: server.DefaultLowMessageDuration}, {name: "TestWithLowMessageDuration_Zero", duration: 0}, {name: "TestWithLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration}} + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + networks := server.GetNetworks() + for i := 0; i < len(networks); i++ { + low := false + network := networks[i] + srv := server.New(network, server.WithLowMessageDuration(c.duration)) + srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) { + low = true + srv.Shutdown() + }) + srv.RegStartFinishEvent(func(srv *server.Server) { + if c.duration <= 0 { + srv.Shutdown() + return + } + time.Sleep(server.DefaultLowMessageDuration) + }) + var lis string + switch network { + case server.NetworkNone, server.NetworkUnix: + lis = "addr" + default: + lis = fmt.Sprintf(":%d", random.UsablePort()) + } + if err := srv.Run(lis); err != nil { + t.Fatalf("%s run error: %s", network, err) + } + if !low && c.duration > 0 { + t.Fatalf("%s low message not exec", network) + } + } + }) + } +} + +``` + + +
+ + *** #### func WithAsyncLowMessageDuration(duration time.Duration) Option @@ -181,6 +259,89 @@ func TestNewBot(t *testing.T) { > - 默认值为 DefaultAsyncLowMessageDuration > - 当 duration <= 0 时,表示关闭慢消息检测 +**示例代码:** + +服务器在启动时将发布一条阻塞 1s 的异步消息,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息 + - 该示例中,将在收到慢消息时关闭服务器 + + +```go + +func ExampleWithAsyncLowMessageDuration() { + srv := server.New(server.NetworkNone, server.WithAsyncLowMessageDuration(time.Second)) + srv.RegStartFinishEvent(func(srv *server.Server) { + srv.PushAsyncMessage(func() error { + time.Sleep(time.Second) + return nil + }, nil) + }) + srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) { + srv.Shutdown() + fmt.Println(times.GetSecond(cost)) + }) + if err := srv.RunNone(); err != nil { + panic(err) + } +} + +``` + +
+查看 / 收起单元测试 + + +```go + +func TestWithAsyncLowMessageDuration(t *testing.T) { + var cases = []struct { + name string + duration time.Duration + }{{name: "TestWithAsyncLowMessageDuration", duration: time.Millisecond * 100}, {name: "TestWithAsyncLowMessageDuration_Zero", duration: 0}, {name: "TestWithAsyncLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration}} + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + networks := server.GetNetworks() + for i := 0; i < len(networks); i++ { + low := false + network := networks[i] + srv := server.New(network, server.WithAsyncLowMessageDuration(c.duration)) + srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) { + low = true + srv.Shutdown() + }) + srv.RegStartFinishEvent(func(srv *server.Server) { + if c.duration <= 0 { + srv.Shutdown() + return + } + srv.PushAsyncMessage(func() error { + time.Sleep(c.duration) + return nil + }, nil) + }) + var lis string + switch network { + case server.NetworkNone, server.NetworkUnix: + lis = fmt.Sprintf("%s%d", "addr", random.Int(0, 9999)) + default: + lis = fmt.Sprintf(":%d", random.UsablePort()) + } + if err := srv.Run(lis); err != nil { + t.Fatalf("%s run error: %s", network, err) + } + if !low && c.duration > 0 { + t.Fatalf("%s low message not exec", network) + } + } + }) + } +} + +``` + + +
+ + *** #### func WithWebsocketConnInitializer(initializer func (writer http.ResponseWriter, request *http.Request, conn *websocket.Conn) error) Option @@ -302,16 +463,17 @@ func TestNewBot(t *testing.T) { **示例代码:** +该案例将创建一个简单的 WebSocket 服务器,如果需要更多的服务器类型可参考 [` Network `](#struct_Network) 部分 + - server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭 + +该案例的输出结果为 true + + ```go func ExampleNew() { srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond)) - srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) { - conn.Write(packet) - }) - if err := srv.Run(":9999"); err != nil { - panic(err) - } + fmt.Println(srv != nil) } ``` @@ -320,24 +482,30 @@ func ExampleNew() { 查看 / 收起单元测试 +该单元测试用于测试以不同的基本参数创建服务器是否存在异常 + + ```go func TestNew(t *testing.T) { - srv := server.New(server.NetworkWebsocket, server.WithPProf()) - srv.RegStartBeforeEvent(func(srv *server.Server) { - fmt.Println("启动前") - }) - srv.RegStartFinishEvent(func(srv *server.Server) { - fmt.Println("启动完成") - }) - srv.RegConnectionClosedEvent(func(srv *server.Server, conn *server.Conn, err any) { - fmt.Println("关闭", conn.GetID(), err, "IncrCount", srv.GetOnlineCount()) - }) - srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) { - conn.Write(packet) - }) - if err := srv.Run(":9999"); err != nil { - panic(err) + var cases = []struct { + name string + network server.Network + addr string + shouldPanic bool + }{{name: "TestNew_Unknown", addr: "", network: "Unknown", shouldPanic: true}, {name: "TestNew_None", addr: "", network: server.NetworkNone, shouldPanic: false}, {name: "TestNew_None_Addr", addr: "addr", network: server.NetworkNone, shouldPanic: false}, {name: "TestNew_Tcp_AddrEmpty", addr: "", network: server.NetworkTcp, shouldPanic: true}, {name: "TestNew_Tcp_AddrIllegal", addr: "addr", network: server.NetworkTcp, shouldPanic: true}, {name: "TestNew_Tcp_Addr", addr: ":9999", network: server.NetworkTcp, shouldPanic: false}, {name: "TestNew_Tcp4_AddrEmpty", addr: "", network: server.NetworkTcp4, shouldPanic: true}, {name: "TestNew_Tcp4_AddrIllegal", addr: "addr", network: server.NetworkTcp4, shouldPanic: true}, {name: "TestNew_Tcp4_Addr", addr: ":9999", network: server.NetworkTcp4, shouldPanic: false}, {name: "TestNew_Tcp6_AddrEmpty", addr: "", network: server.NetworkTcp6, shouldPanic: true}, {name: "TestNew_Tcp6_AddrIllegal", addr: "addr", network: server.NetworkTcp6, shouldPanic: true}, {name: "TestNew_Tcp6_Addr", addr: ":9999", network: server.NetworkTcp6, shouldPanic: false}, {name: "TestNew_Udp_AddrEmpty", addr: "", network: server.NetworkUdp, shouldPanic: true}, {name: "TestNew_Udp_AddrIllegal", addr: "addr", network: server.NetworkUdp, shouldPanic: true}, {name: "TestNew_Udp_Addr", addr: ":9999", network: server.NetworkUdp, shouldPanic: false}, {name: "TestNew_Udp4_AddrEmpty", addr: "", network: server.NetworkUdp4, shouldPanic: true}, {name: "TestNew_Udp4_AddrIllegal", addr: "addr", network: server.NetworkUdp4, shouldPanic: true}, {name: "TestNew_Udp4_Addr", addr: ":9999", network: server.NetworkUdp4, shouldPanic: false}, {name: "TestNew_Udp6_AddrEmpty", addr: "", network: server.NetworkUdp6, shouldPanic: true}, {name: "TestNew_Udp6_AddrIllegal", addr: "addr", network: server.NetworkUdp6, shouldPanic: true}, {name: "TestNew_Udp6_Addr", addr: ":9999", network: server.NetworkUdp6, shouldPanic: false}, {name: "TestNew_Unix_AddrEmpty", addr: "", network: server.NetworkUnix, shouldPanic: true}, {name: "TestNew_Unix_AddrIllegal", addr: "addr", network: server.NetworkUnix, shouldPanic: true}, {name: "TestNew_Unix_Addr", addr: "addr", network: server.NetworkUnix, shouldPanic: false}, {name: "TestNew_Websocket_AddrEmpty", addr: "", network: server.NetworkWebsocket, shouldPanic: true}, {name: "TestNew_Websocket_AddrIllegal", addr: "addr", network: server.NetworkWebsocket, shouldPanic: true}, {name: "TestNew_Websocket_Addr", addr: ":9999/ws", network: server.NetworkWebsocket, shouldPanic: false}, {name: "TestNew_Http_AddrEmpty", addr: "", network: server.NetworkHttp, shouldPanic: true}, {name: "TestNew_Http_AddrIllegal", addr: "addr", network: server.NetworkHttp, shouldPanic: true}, {name: "TestNew_Http_Addr", addr: ":9999", network: server.NetworkHttp, shouldPanic: false}, {name: "TestNew_Kcp_AddrEmpty", addr: "", network: server.NetworkKcp, shouldPanic: true}, {name: "TestNew_Kcp_AddrIllegal", addr: "addr", network: server.NetworkKcp, shouldPanic: true}, {name: "TestNew_Kcp_Addr", addr: ":9999", network: server.NetworkKcp, shouldPanic: false}, {name: "TestNew_GRPC_AddrEmpty", addr: "", network: server.NetworkGRPC, shouldPanic: true}, {name: "TestNew_GRPC_AddrIllegal", addr: "addr", network: server.NetworkGRPC, shouldPanic: true}, {name: "TestNew_GRPC_Addr", addr: ":9999", network: server.NetworkGRPC, shouldPanic: false}} + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + defer func() { + if err := super.RecoverTransform(recover()); err != nil && !c.shouldPanic { + debug.PrintStack() + t.Fatal("not should panic, err:", err) + } + }() + if err := server.New(c.network, server.WithLimitLife(time.Millisecond*10)).Run(""); err != nil { + panic(err) + } + }) } } @@ -354,6 +522,34 @@ func TestNew(t *testing.T) { **示例代码:** +这个案例中我们将 `TestService` 绑定到了 `srv` 服务器中,当服务器启动时,将会对 `TestService` 进行初始化 + +其中 `TestService` 的定义如下: +```go + + type TestService struct{} + + func (ts *TestService) OnInit(srv *server.Server) { + srv.RegStartFinishEvent(onStartFinish) + + srv.RegStopEvent(func(srv *server.Server) { + fmt.Println("server stop") + }) + } + + func (ts *TestService) onStartFinish(srv *server.Server) { + fmt.Println("server start finish") + } + +``` + +可以看出,在服务初始化时,该服务向服务器注册了启动完成事件及停止事件。这是我们推荐的编码方式,这样编码有以下好处: + - 具备可控制的初始化顺序,避免 init 产生的各种顺序导致的问题,如配置还未加载完成,即开始进行数据库连接等操作 + - 可以方便的将不同的服务拆分到不同的包中进行管理 + - 当不需要某个服务时,可以直接删除该服务的绑定,而不需要修改其他代码 + - ... + + ```go func ExampleBindService() { @@ -373,10 +569,15 @@ func ExampleBindService() { ```go func TestBindService(t *testing.T) { - srv := server.New(server.NetworkNone, server.WithLimitLife(time.Second)) - server.BindService(srv, new(TestService)) - if err := srv.RunNone(); err != nil { - t.Fatal(err) + var cases = []struct{ name string }{{name: "TestBindService"}} + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + srv := server.New(server.NetworkNone, server.WithLimitLife(time.Millisecond)) + server.BindService(srv, new(TestService)) + if err := srv.RunNone(); err != nil { + t.Fatal(err) + } + }) } } @@ -396,25 +597,43 @@ type Bot struct { joined atomic.Bool } ``` + + #### func (*Bot) JoinServer() > 加入服务器 + *** + + #### func (*Bot) LeaveServer() > 离开服务器 + *** + + #### func (*Bot) SetNetworkDelay(delay time.Duration, fluctuation time.Duration) > 设置网络延迟和波动范围 > - delay 延迟 > - fluctuation 波动范围 + *** + + #### func (*Bot) SetWriter(writer io.Writer) > 设置写入器 + *** + + #### func (*Bot) SendPacket(packet []byte) > 发送数据包到服务器 + *** + + #### func (*Bot) SendWSPacket(wst int, packet []byte) > 发送 WebSocket 数据包到服务器 + *** ### BotOption `STRUCT` @@ -432,79 +651,148 @@ type Conn struct { ctx context.Context } ``` + + #### func (*Conn) Ticker() *timer.Ticker > 获取定时器 + *** + + #### func (*Conn) GetServer() *Server > 获取服务器 + *** + + #### func (*Conn) GetOpenTime() time.Time > 获取连接打开时间 + *** + + #### func (*Conn) GetOnlineTime() time.Duration > 获取连接在线时长 + *** + + #### func (*Conn) GetWebsocketRequest() *http.Request > 获取websocket请求 + *** + + #### func (*Conn) IsBot() bool > 是否是机器人连接 + *** + + #### func (*Conn) RemoteAddr() net.Addr > 获取远程地址 + *** + + #### func (*Conn) GetID() string > 获取连接ID > - 为远程地址的字符串形式 + *** + + #### func (*Conn) GetIP() string > 获取连接IP + *** + + #### func (*Conn) IsClosed() bool > 是否已经关闭 + *** + + #### func (*Conn) SetData(key any, value any) *Conn > 设置连接数据,该数据将在连接关闭前始终存在 + *** + + #### func (*Conn) GetData(key any) any > 获取连接数据 + *** + + #### func (*Conn) ViewData() map[any]any > 查看只读的连接数据 + *** + + #### func (*Conn) SetMessageData(key any, value any) *Conn > 设置消息数据,该数据将在消息处理完成后释放 + *** + + #### func (*Conn) GetMessageData(key any) any > 获取消息数据 + *** + + #### func (*Conn) ReleaseData() *Conn > 释放数据 + *** + + #### func (*Conn) IsWebsocket() bool > 是否是websocket连接 + *** + + #### func (*Conn) GetWST() int > 获取本次 websocket 消息类型 > - 默认将与发送类型相同 + *** + + #### func (*Conn) SetWST(wst int) *Conn > 设置本次 websocket 消息类型 + *** + + #### func (*Conn) PushAsyncMessage(caller func () error, callback func (err error), mark ...log.Field) > 推送异步消息,该消息将通过 Server.PushShuntAsyncMessage 函数推送 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Conn) PushUniqueAsyncMessage(name string, caller func () error, callback func (err error), mark ...log.Field) > 推送唯一异步消息,该消息将通过 Server.PushUniqueShuntAsyncMessage 函数推送 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 > - 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息 + *** + + #### func (*Conn) Write(packet []byte, callback ...func (err error)) > 向连接中写入数据 + *** + + #### func (*Conn) Close(err ...error) > 关闭连接 + *** ### ConsoleParams `STRUCT` @@ -512,26 +800,47 @@ type Conn struct { ```go type ConsoleParams map[string][]string ``` + + #### func (ConsoleParams) Get(key string) string > 获取参数值 + *** + + #### func (ConsoleParams) GetValues(key string) []string > 获取参数值 + *** + + #### func (ConsoleParams) GetValueNum(key string) int > 获取参数值数量 + *** + + #### func (ConsoleParams) Has(key string) bool > 是否存在参数 + *** + + #### func (ConsoleParams) Add(key string, value string) > 添加参数 + *** + + #### func (ConsoleParams) Del(key string) > 删除参数 + *** + + #### func (ConsoleParams) Clear() > 清空参数 + *** ### MessageReadyEventHandler `STRUCT` @@ -549,7 +858,10 @@ type Http[Context any] struct { *HttpRouter[Context] } ``` + + #### func (*Http) Gin() *gin.Engine + *** ### HttpContext `STRUCT` @@ -559,11 +871,17 @@ type HttpContext struct { *gin.Context } ``` + + #### func (*HttpContext) Gin() *gin.Context > 获取 gin.Context + *** + + #### func (*HttpContext) ReadTo(dest any) error > 读取请求数据到指定结构体,如果失败则返回错误 + *** ### HandlerFunc `STRUCT` @@ -587,69 +905,123 @@ type HttpRouter[Context any] struct { packer ContextPacker[Context] } ``` + + #### func (*HttpRouter) Handle(httpMethod string, relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 使用给定的路径和方法注册新的请求句柄和中间件 > - 最后一个处理程序应该是真正的处理程序,其他处理程序应该是可以而且应该在不同路由之间共享的中间件。 + *** + + #### func (*HttpRouter) POST(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("POST", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) GET(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("GET", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) DELETE(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("DELETE", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) PATCH(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("PATCH", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) PUT(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("PUT", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) OPTIONS(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("OPTIONS", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) HEAD(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("HEAD", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) CONNECT(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("CONNECT", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) TRACE(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 是 Handle("TRACE", path, handlers) 的快捷方式 + *** + + #### func (*HttpRouter) Any(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 注册一个匹配所有 HTTP 方法的路由 > - GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. + *** + + #### func (*HttpRouter) Match(methods []string, relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 注册一个匹配指定 HTTP 方法的路由 > - GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. + *** + + #### func (*HttpRouter) StaticFile(relativePath string, filepath string) *HttpRouter[Context] > 注册单个路由以便为本地文件系统的单个文件提供服务。 > - 例如: StaticFile("favicon.ico", "./resources/favicon.ico") + *** + + #### func (*HttpRouter) StaticFileFS(relativePath string, filepath string, fs http.FileSystem) *HttpRouter[Context] > 与 `StaticFile` 类似,但可以使用自定义的 `http.FileSystem` 代替。 > - 例如: StaticFileFS("favicon.ico", "./resources/favicon.ico", Dir{".", false}) > - 由于依赖于 gin.Engine 默认情况下使用:gin.Dir + *** + + #### func (*HttpRouter) Static(relativePath string, root string) *HttpRouter[Context] > 提供来自给定文件系统根目录的文件。 > - 例如: Static("/static", "/var/www") + *** + + #### func (*HttpRouter) StaticFS(relativePath string, fs http.FileSystem) *HttpRouter[Context] > 与 `Static` 类似,但可以使用自定义的 `http.FileSystem` 代替。 > - 例如: StaticFS("/static", Dir{"/var/www", false}) > - 由于依赖于 gin.Engine 默认情况下使用:gin.Dir + *** + + #### func (*HttpRouter) Group(relativePath string, handlers ...HandlerFunc[Context]) *HttpRouter[Context] > 创建一个新的路由组。您应该添加所有具有共同中间件的路由。 > - 例如: v1 := slf.Group("/v1") + *** + + #### func (*HttpRouter) Use(middleware ...HandlerFunc[Context]) *HttpRouter[Context] > 将中间件附加到路由组。 + *** ### HttpWrapperHandleFunc `STRUCT` @@ -666,56 +1038,107 @@ type HttpWrapper[CTX any] struct { packHandle func(ctx *gin.Context) CTX } ``` + + #### func (*HttpWrapper) Handle(httpMethod string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 处理请求 + *** + + #### func (*HttpWrapper) Use(middleware ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 使用中间件 + *** + + #### func (*HttpWrapper) GET(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 GET 请求 + *** + + #### func (*HttpWrapper) POST(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 POST 请求 + *** + + #### func (*HttpWrapper) DELETE(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 DELETE 请求 + *** + + #### func (*HttpWrapper) PATCH(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 PATCH 请求 + *** + + #### func (*HttpWrapper) PUT(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 PUT 请求 + *** + + #### func (*HttpWrapper) OPTIONS(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 OPTIONS 请求 + *** + + #### func (*HttpWrapper) HEAD(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 HEAD 请求 + *** + + #### func (*HttpWrapper) Trace(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 Trace 请求 + *** + + #### func (*HttpWrapper) Connect(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 Connect 请求 + *** + + #### func (*HttpWrapper) Any(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册 Any 请求 + *** + + #### func (*HttpWrapper) Match(methods []string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapper[CTX] > 注册与您声明的指定方法相匹配的路由。 + *** + + #### func (*HttpWrapper) StaticFile(relativePath string, filepath string) *HttpWrapper[CTX] > 注册 StaticFile 请求 + *** + + #### func (*HttpWrapper) Static(relativePath string, root string) *HttpWrapper[CTX] > 注册 Static 请求 + *** + + #### func (*HttpWrapper) StaticFS(relativePath string, fs http.FileSystem) *HttpWrapper[CTX] > 注册 StaticFS 请求 + *** + + #### func (*HttpWrapper) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 创建一个新的路由组。您应该添加所有具有共同中间件的路由。 + *** ### HttpWrapperGroup `STRUCT` @@ -726,32 +1149,59 @@ type HttpWrapperGroup[CTX any] struct { group *gin.RouterGroup } ``` + + #### func (*HttpWrapperGroup) Handle(httpMethod string, relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 处理请求 + *** + + #### func (*HttpWrapperGroup) Use(middleware ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 使用中间件 + *** + + #### func (*HttpWrapperGroup) GET(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 GET 请求 + *** + + #### func (*HttpWrapperGroup) POST(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 POST 请求 + *** + + #### func (*HttpWrapperGroup) DELETE(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 DELETE 请求 + *** + + #### func (*HttpWrapperGroup) PATCH(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 PATCH 请求 + *** + + #### func (*HttpWrapperGroup) PUT(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 PUT 请求 + *** + + #### func (*HttpWrapperGroup) OPTIONS(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 注册 OPTIONS 请求 + *** + + #### func (*HttpWrapperGroup) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX] > 创建分组 + *** ### MessageType `STRUCT` @@ -759,8 +1209,11 @@ type HttpWrapperGroup[CTX any] struct { ```go type MessageType byte ``` + + #### func (MessageType) String() string > 返回消息类型的字符串表示 + *** ### Message `STRUCT` @@ -780,13 +1233,22 @@ type Message struct { t MessageType } ``` + + #### func (*Message) GetProducer() string + *** + + #### func (*Message) MessageType() MessageType > 返回消息类型 + *** + + #### func (*Message) String() string > 返回消息的字符串表示 + *** ### MultipleServer `STRUCT` @@ -798,21 +1260,57 @@ type MultipleServer struct { exitEventHandles []func() } ``` + + #### func (*MultipleServer) Run() + *** + + #### func (*MultipleServer) RegExitEvent(handle func ()) > 注册退出事件 + *** + + #### func (*MultipleServer) OnExitEvent() + *** ### Network `STRUCT` +服务器运行的网络模式 + - 根据不同的网络模式,服务器将会产生不同的行为,该类型将在服务器创建时候指定 +服务器支持的网络模式如下: + - NetworkNone 该模式下不监听任何网络端口,仅开启消息队列,适用于纯粹的跨服服务器等情况 + - NetworkTcp 该模式下将会监听 TCP 协议的所有地址,包括 IPv4 和 IPv6 + - NetworkTcp4 该模式下将会监听 TCP 协议的 IPv4 地址 + - NetworkTcp6 该模式下将会监听 TCP 协议的 IPv6 地址 + - NetworkUdp 该模式下将会监听 UDP 协议的所有地址,包括 IPv4 和 IPv6 + - NetworkUdp4 该模式下将会监听 UDP 协议的 IPv4 地址 + - NetworkUdp6 该模式下将会监听 UDP 协议的 IPv6 地址 + - NetworkUnix 该模式下将会监听 Unix 协议的地址 + - NetworkHttp 该模式下将会监听 HTTP 协议的地址 + - NetworkWebsocket 该模式下将会监听 Websocket 协议的地址 + - NetworkKcp 该模式下将会监听 KCP 协议的地址 + - NetworkGRPC 该模式下将会监听 GRPC 协议的地址 ```go type Network string ``` + + #### func (Network) IsSocket() bool -> 返回当前服务器的网络模式是否为 Socket 模式 +> 返回当前服务器的网络模式是否为 Socket 模式,目前为止仅有如下几种模式为 Socket 模式: +> - NetworkTcp +> - NetworkTcp4 +> - NetworkTcp6 +> - NetworkUdp +> - NetworkUdp4 +> - NetworkUdp6 +> - NetworkUnix +> - NetworkKcp +> - NetworkWebsocket + *** ### Option `STRUCT` @@ -849,6 +1347,8 @@ type Server struct { services []func() } ``` + + #### func (*Server) Run(addr string) (err error) > 使用特定地址运行服务器 > - server.NetworkTcp (addr:":8888") @@ -862,15 +1362,18 @@ type Server struct { > - server.NetworkWebsocket (addr:":8888/ws") > - server.NetworkKcp (addr:":8888") > - server.NetworkNone (addr:"") + **示例代码:** +该案例将创建一个简单的 WebSocket 服务器并启动监听 `:9999/` 作为 WebSocket 监听地址,如果需要更多的服务器类型可参考 [` Network `](#struct_Network) 部分 + - 当服务器启动失败后,将会返回错误信息并触发 panic + - server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭 + + ```go func ExampleServer_Run() { srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond)) - srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) { - conn.Write(packet) - }) if err := srv.Run(":9999"); err != nil { panic(err) } @@ -879,76 +1382,199 @@ func ExampleServer_Run() { ``` *** + + #### func (*Server) IsSocket() bool -> 是否是 Socket 模式 +> 通过执行 Network.IsSocket 函数检查该服务器是否是 Socket 模式 + +**示例代码:** + +该案例将创建两个不同类型的服务器,其中 WebSocket 是一个 Socket 服务器,而 Http 是一个非 Socket 服务器 + +可知案例输出结果为: + - true + - false + + +```go + +func ExampleServer_IsSocket() { + srv1 := server.New(server.NetworkWebsocket) + fmt.Println(srv1.IsSocket()) + srv2 := server.New(server.NetworkHttp) + fmt.Println(srv2.IsSocket()) +} + +``` + +
+查看 / 收起单元测试 + + +这个测试检查了各个类型的服务器是否为 Socket 模式。如需查看为 Socket 模式的网络类型,请参考 [` Network.IsSocket` ](#struct_Network_IsSocket) + + +```go + +func TestServer_IsSocket(t *testing.T) { + var cases = []struct { + name string + network server.Network + expect bool + }{{name: "TestServer_IsSocket_None", network: server.NetworkNone, expect: false}, {name: "TestServer_IsSocket_Tcp", network: server.NetworkTcp, expect: true}, {name: "TestServer_IsSocket_Tcp4", network: server.NetworkTcp4, expect: true}, {name: "TestServer_IsSocket_Tcp6", network: server.NetworkTcp6, expect: true}, {name: "TestServer_IsSocket_Udp", network: server.NetworkUdp, expect: true}, {name: "TestServer_IsSocket_Udp4", network: server.NetworkUdp4, expect: true}, {name: "TestServer_IsSocket_Udp6", network: server.NetworkUdp6, expect: true}, {name: "TestServer_IsSocket_Unix", network: server.NetworkUnix, expect: true}, {name: "TestServer_IsSocket_Http", network: server.NetworkHttp, expect: false}, {name: "TestServer_IsSocket_Websocket", network: server.NetworkWebsocket, expect: true}, {name: "TestServer_IsSocket_Kcp", network: server.NetworkKcp, expect: true}, {name: "TestServer_IsSocket_GRPC", network: server.NetworkGRPC, expect: false}} + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + s := server.New(c.network) + if s.IsSocket() != c.expect { + t.Fatalf("expect: %v, got: %v", c.expect, s.IsSocket()) + } + }) + } +} + +``` + + +
+ + *** + + #### func (*Server) RunNone() error > 是 Run("") 的简写,仅适用于运行 NetworkNone 服务器 + +**示例代码:** + +RunNone 函数并没有特殊的意义,该函数内部调用了 `srv.Run("")` 函数,仅是一个语法糖,用来表示服务器不需要监听任何地址 + + +```go + +func ExampleServer_RunNone() { + srv := server.New(server.NetworkNone) + if err := srv.RunNone(); err != nil { + panic(err) + } +} + +``` + *** + + #### func (*Server) Context() context.Context > 获取服务器上下文 + *** + + #### func (*Server) TimeoutContext(timeout time.Duration) ( context.Context, context.CancelFunc) > 获取服务器超时上下文,context.WithTimeout 的简写 + *** + + #### func (*Server) Ticker() *timer.Ticker > 获取服务器定时器 + *** + + #### func (*Server) Shutdown() > 主动停止运行服务器 + *** + + #### func (*Server) GRPCServer() *grpc.Server > 当网络类型为 NetworkGRPC 时将被允许获取 grpc 服务器,否则将会发生 panic + *** + + #### func (*Server) HttpRouter() gin.IRouter > 当网络类型为 NetworkHttp 时将被允许获取路由器进行路由注册,否则将会发生 panic > - 通过该函数注册的路由将无法在服务器关闭时正常等待请求结束 > > Deprecated: 从 Minotaur 0.0.29 开始,由于设计原因已弃用,该函数将直接返回 *gin.Server 对象,导致无法正常的对请求结束时进行处理 + *** + + #### func (*Server) HttpServer() *Http[*HttpContext] > 替代 HttpRouter 的函数,返回一个 *Http[*HttpContext] 对象 > - 通过该函数注册的路由将在服务器关闭时正常等待请求结束 > - 如果需要自行包装 Context 对象,可以使用 NewHttpHandleWrapper 方法 + *** + + #### func (*Server) GetMessageCount() int64 > 获取当前服务器中消息的数量 + *** + + #### func (*Server) UseShunt(conn *Conn, name string) > 切换连接所使用的消息分流渠道,当分流渠道 name 不存在时将会创建一个新的分流渠道,否则将会加入已存在的分流渠道 > - 默认情况下,所有连接都使用系统通道进行消息分发,当指定消息分流渠道且为分流消息类型时,将会使用指定的消息分流渠道进行消息分发 > - 分流渠道会在连接断开时标记为驱逐状态,当分流渠道中的所有消息处理完毕且没有新连接使用时,将会被清除 + *** + + #### func (*Server) HasShunt(name string) bool > 检查特定消息分流渠道是否存在 + *** + + #### func (*Server) GetConnCurrShunt(conn *Conn) string > 获取连接当前所使用的消息分流渠道 + *** + + #### func (*Server) GetShuntNum() int > 获取消息分流渠道数量 + *** + + #### func (*Server) PushSystemMessage(handler func (), mark ...log.Field) > 向服务器中推送 MessageTypeSystem 消息 > - 系统消息仅包含一个可执行函数,将在系统分发器中执行 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Server) PushAsyncMessage(caller func () error, callback func (err error), mark ...log.Field) > 向服务器中推送 MessageTypeAsync 消息 > - 异步消息将在服务器的异步消息队列中进行处理,处理完成 caller 的阻塞操作后,将会通过系统消息执行 callback 函数 > - callback 函数将在异步消息处理完成后进行调用,无论过程是否产生 err,都将被执行,允许为 nil > - 需要注意的是,为了避免并发问题,caller 函数请仅处理阻塞操作,其他操作应该在 callback 函数中进行 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Server) PushShuntAsyncMessage(conn *Conn, caller func () error, callback func (err error), mark ...log.Field) > 向特定分发器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致 > - 需要注意的是,当未指定 UseShunt 时,将会通过 PushAsyncMessage 进行转发 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Server) PushPacketMessage(conn *Conn, wst int, packet []byte, mark ...log.Field) > 向服务器中推送 MessageTypePacket 消息 > - 当存在 UseShunt 的选项时,将会根据选项中的 shuntMatcher 进行分发,否则将在系统分发器中处理消息 + *** + + #### func (*Server) PushTickerMessage(name string, caller func (), mark ...log.Field) > 向服务器中推送 MessageTypeTicker 消息 > - 通过该函数推送定时消息,当消息触发时将在系统分发器中处理消息 @@ -957,40 +1583,66 @@ func ExampleServer_Run() { > > 定时消息执行不会有特殊的处理,仅标记为定时任务,也就是允许将各类函数通过该消息发送处理,但是并不建议 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Server) PushShuntTickerMessage(conn *Conn, name string, caller func (), mark ...log.Field) > 向特定分发器中推送 MessageTypeTicker 消息,消息执行与 MessageTypeTicker 一致 > - 需要注意的是,当未指定 UseShunt 时,将会通过 PushTickerMessage 进行转发 > - mark 为可选的日志标记,当发生异常时,将会在日志中进行体现 + *** + + #### func (*Server) PushUniqueAsyncMessage(unique string, caller func () error, callback func (err error), mark ...log.Field) > 向服务器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致 > - 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息 + *** + + #### func (*Server) PushUniqueShuntAsyncMessage(conn *Conn, unique string, caller func () error, callback func (err error), mark ...log.Field) > 向特定分发器中推送 MessageTypeAsync 消息,消息执行与 MessageTypeAsync 一致 > - 需要注意的是,当未指定 UseShunt 时,将会通过系统分流渠道进行转发 > - 不同的是当上一个相同的 unique 消息未执行完成时,将会忽略该消息 + *** + + #### func (*Server) PushShuntMessage(conn *Conn, caller func (), mark ...log.Field) > 向特定分发器中推送 MessageTypeShunt 消息,消息执行与 MessageTypeSystem 一致,不同的是将会在特定分发器中执行 + *** + + #### func (*Server) GetDurationMessageCount() int64 > 获取当前 WithMessageStatistics 设置的 duration 期间的消息量 + *** + + #### func (*Server) GetDurationMessageCountByOffset(offset int) int64 > 获取特定偏移次数的 WithMessageStatistics 设置的 duration 期间的消息量 > - 该值小于 0 时,将与 GetDurationMessageCount 无异,否则将返回 +n 个期间的消息量,例如 duration 为 1 分钟,limit 为 10,那么 offset 为 1 的情况下,获取的则是上一分钟消息量 + *** + + #### func (*Server) GetAllDurationMessageCount() []int64 > 获取所有 WithMessageStatistics 设置的 duration 期间的消息量 + *** + + #### func (*Server) HasMessageStatistics() bool > 是否了开启消息统计 + *** ### Service `INTERFACE` -兼容传统 service 设计模式的接口 +兼容传统 service 设计模式的接口,通过该接口可以实现更简洁、更具有可读性的服务绑定 + - 在这之前,我们在实现功能上会将 Server 进行全局存储,之后通过 init 函数进行初始化,这样的顺序是不可控的。 ```go type Service interface { OnInit(srv *Server) diff --git a/server/client/README.md b/server/client/README.md index 1d7658e..25293ce 100644 --- a/server/client/README.md +++ b/server/client/README.md @@ -78,23 +78,38 @@ type Client struct { block chan struct{} } ``` + + #### func (*Client) Run(block ...bool) error > 运行客户端,当客户端已运行时,会先关闭客户端再重新运行 > - block 以阻塞方式运行 + *** + + #### func (*Client) RunByBufferSize(size int, block ...bool) error > 指定写入循环缓冲区大小运行客户端,当客户端已运行时,会先关闭客户端再重新运行 > - block 以阻塞方式运行 + *** + + #### func (*Client) IsConnected() bool > 是否已连接 + *** + + #### func (*Client) Close(err ...error) > 关闭 + *** + + #### func (*Client) WriteWS(wst int, packet []byte, callback ...func (err error)) > 向连接中写入指定 websocket 数据类型 > - wst: websocket模式中指定消息类型 +
查看 / 收起单元测试 @@ -133,11 +148,17 @@ func TestClient_WriteWS(t *testing.T) { *** + + #### func (*Client) Write(packet []byte, callback ...func (err error)) > 向连接中写入数据 + *** + + #### func (*Client) GetServerAddr() string > 获取服务器地址 + *** ### Core `INTERFACE` @@ -177,15 +198,30 @@ type TCP struct { closed bool } ``` + + #### func (*TCP) Run(runState chan error, receive func (wst int, packet []byte)) + *** + + #### func (*TCP) Write(packet *Packet) error + *** + + #### func (*TCP) Close() + *** + + #### func (*TCP) GetServerAddr() string + *** + + #### func (*TCP) Clone() Core + *** ### UnixDomainSocket `STRUCT` @@ -197,9 +233,15 @@ type UnixDomainSocket struct { closed bool } ``` + + #### func (*UnixDomainSocket) Run(runState chan error, receive func (wst int, packet []byte)) + *** + + #### func (*UnixDomainSocket) Write(packet *Packet) error +
查看 / 收起单元测试 @@ -243,11 +285,20 @@ func TestUnixDomainSocket_Write(t *testing.T) { *** + + #### func (*UnixDomainSocket) Close() + *** + + #### func (*UnixDomainSocket) GetServerAddr() string + *** + + #### func (*UnixDomainSocket) Clone() Core + *** ### Websocket `STRUCT` @@ -260,13 +311,28 @@ type Websocket struct { mu sync.Mutex } ``` + + #### func (*Websocket) Run(runState chan error, receive func (wst int, packet []byte)) + *** + + #### func (*Websocket) Write(packet *Packet) error + *** + + #### func (*Websocket) Close() + *** + + #### func (*Websocket) GetServerAddr() string + *** + + #### func (*Websocket) Clone() Core + *** diff --git a/server/gateway/README.md b/server/gateway/README.md index e647ee3..a0b776b 100644 --- a/server/gateway/README.md +++ b/server/gateway/README.md @@ -129,18 +129,30 @@ type Endpoint struct { cps int } ``` + + #### func (*Endpoint) GetName() string > 获取端点名称 + *** + + #### func (*Endpoint) GetAddress() string > 获取端点地址 + *** + + #### func (*Endpoint) GetState() float64 > 获取端点健康值 + *** + + #### func (*Endpoint) Forward(conn *server.Conn, packet []byte, callback ...func (err error)) > 转发数据包到该端点 > - 端点在处理数据包时,应区分数据包为普通直连数据包还是网关数据包。可通过 UnmarshalGatewayOutPacket 进行数据包解析,当解析失败且无其他数据包协议时,可认为该数据包为普通直连数据包。 + *** ### EndpointOption `STRUCT` @@ -186,8 +198,11 @@ type Gateway struct { cceLock sync.RWMutex } ``` + + #### func (*Gateway) Run(addr string) error > 运行网关 +
查看 / 收起单元测试 @@ -217,23 +232,38 @@ func TestGateway_Run(t *testing.T) { *** + + #### func (*Gateway) Shutdown() > 关闭网关 + *** + + #### func (*Gateway) Server() *server.Server > 获取网关服务器核心 + *** + + #### func (*Gateway) GetEndpoint(name string) ( *Endpoint, error) > 获取一个可用的端点 > - name: 端点名称 + *** + + #### func (*Gateway) GetConnEndpoint(name string, conn *server.Conn) ( *Endpoint, error) > 获取一个可用的端点,如果客户端已经连接到了某个端点,将优先返回该端点 > - 当连接到的端点不可用或没有连接记录时,效果同 GetEndpoint 相同 > - 当连接行为为有状态时,推荐使用该方法 + *** + + #### func (*Gateway) SwitchEndpoint(source *Endpoint, dest *Endpoint) > 将端点端点的所有连接切换到另一个端点 + *** ### Option `STRUCT` @@ -250,7 +280,13 @@ type Scanner interface { GetInterval() time.Duration } ``` + + #### func (*Scanner) GetEndpoints() ( []*gateway.Endpoint, error) + *** + + #### func (*Scanner) GetInterval() time.Duration + *** diff --git a/server/internal/dispatcher/README.md b/server/internal/dispatcher/README.md index 4325cdf..bda4852 100644 --- a/server/internal/dispatcher/README.md +++ b/server/internal/dispatcher/README.md @@ -176,14 +176,23 @@ type Action[P Producer, M Message[P]] struct { d *Dispatcher[P, M] } ``` + + #### func (*Action) Name() string > 获取消息分发器名称 + *** + + #### func (*Action) UnExpel() > 取消特定生产者的驱逐计划 + *** + + #### func (*Action) Expel() > 设置该消息分发器即将被驱逐,当消息分发器中没有任何消息时,会自动关闭 + *** ### Handler `STRUCT` @@ -221,11 +230,12 @@ type Dispatcher[P Producer, M Message[P]] struct { abort chan struct{} } ``` + + #### func (*Dispatcher) SetProducerDoneHandler(p P, handler func (p P, dispatcher *Action[P, M])) *Dispatcher[P, M] -> 设置特定生产者所有消息处理完成时的回调函数 +> 设置特定生产者的所有消息处理完成时的回调函数 > - 如果 handler 为 nil,则会删除该生产者的回调函数 -> -> 需要注意的是,该 handler 中 +
查看 / 收起单元测试 @@ -271,8 +281,11 @@ func TestDispatcher_SetProducerDoneHandler(t *testing.T) { *** + + #### func (*Dispatcher) SetClosedHandler(handler func (dispatcher *Action[P, M])) *Dispatcher[P, M] > 设置消息分发器关闭时的回调函数 +
查看 / 收起单元测试 @@ -319,8 +332,11 @@ func TestDispatcher_SetClosedHandler(t *testing.T) { *** + + #### func (*Dispatcher) Name() string > 获取消息分发器名称 +
查看 / 收起单元测试 @@ -348,14 +364,23 @@ func TestDispatcher_Name(t *testing.T) { *** + + #### func (*Dispatcher) Unique(name string) bool > 设置唯一消息键,返回是否已存在 + *** + + #### func (*Dispatcher) AntiUnique(name string) > 取消唯一消息键 + *** + + #### func (*Dispatcher) Expel() > 设置该消息分发器即将被驱逐,当消息分发器中没有任何消息时,会自动关闭 +
查看 / 收起单元测试 @@ -402,8 +427,11 @@ func TestDispatcher_Expel(t *testing.T) { *** + + #### func (*Dispatcher) UnExpel() > 取消特定生产者的驱逐计划 +
查看 / 收起单元测试 @@ -452,12 +480,18 @@ func TestDispatcher_UnExpel(t *testing.T) { *** + + #### func (*Dispatcher) IncrCount(producer P, i int64) > 主动增量设置特定生产者的消息计数,这在等待异步消息完成后再关闭消息分发器时非常有用 > - 如果 i 为负数,则会减少消息计数 + *** + + #### func (*Dispatcher) Put(message M) > 将消息放入分发器 +
查看 / 收起单元测试 @@ -498,8 +532,11 @@ func TestDispatcher_Put(t *testing.T) { *** + + #### func (*Dispatcher) Start() *Dispatcher[P, M] > 以非阻塞的方式开始进行消息分发,当消息分发器中没有任何消息并且处于驱逐计划 Expel 时,将会自动关闭 +
查看 / 收起单元测试 @@ -540,8 +577,11 @@ func TestDispatcher_Start(t *testing.T) { *** + + #### func (*Dispatcher) Closed() bool > 判断消息分发器是否已关闭 +
查看 / 收起单元测试 @@ -594,11 +634,17 @@ type Manager[P Producer, M Message[P]] struct { createdHandler func(name string) } ``` + + #### func (*Manager) Wait() > 等待所有消息分发器关闭 + *** + + #### func (*Manager) SetDispatcherClosedHandler(handler func (name string)) *Manager[P, M] > 设置消息分发器关闭时的回调函数 +
查看 / 收起单元测试 @@ -637,8 +683,11 @@ func TestManager_SetDispatcherClosedHandler(t *testing.T) { *** + + #### func (*Manager) SetDispatcherCreatedHandler(handler func (name string)) *Manager[P, M] > 设置消息分发器创建时的回调函数 +
查看 / 收起单元测试 @@ -677,8 +726,11 @@ func TestManager_SetDispatcherCreatedHandler(t *testing.T) { *** + + #### func (*Manager) HasDispatcher(name string) bool > 检查是否存在指定名称的消息分发器 +
查看 / 收起单元测试 @@ -714,8 +766,11 @@ func TestManager_HasDispatcher(t *testing.T) { *** + + #### func (*Manager) GetDispatcherNum() int > 获取当前正在工作的消息分发器数量 +
查看 / 收起单元测试 @@ -758,8 +813,11 @@ func TestManager_GetDispatcherNum(t *testing.T) { *** + + #### func (*Manager) GetSystemDispatcher() *Dispatcher[P, M] > 获取系统消息分发器 +
查看 / 收起单元测试 @@ -786,8 +844,11 @@ func TestManager_GetSystemDispatcher(t *testing.T) { *** + + #### func (*Manager) GetDispatcher(p P) *Dispatcher[P, M] > 获取生产者正在使用的消息分发器,如果生产者没有绑定消息分发器,则会返回系统消息分发器 +
查看 / 收起单元测试 @@ -818,8 +879,11 @@ func TestManager_GetDispatcher(t *testing.T) { *** + + #### func (*Manager) BindProducer(p P, name string) > 绑定生产者使用特定的消息分发器,如果生产者已经绑定了消息分发器,则会先解绑 +
查看 / 收起单元测试 @@ -850,8 +914,11 @@ func TestManager_BindProducer(t *testing.T) { *** + + #### func (*Manager) UnBindProducer(p P) > 解绑生产者使用特定的消息分发器 +
查看 / 收起单元测试 diff --git a/server/internal/logger/README.md b/server/internal/logger/README.md index ca79363..4b644d8 100644 --- a/server/internal/logger/README.md +++ b/server/internal/logger/README.md @@ -30,7 +30,10 @@ ```go type Ants struct{} ``` + + #### func (*Ants) Printf(format string, args ...interface {}) + *** ### GNet `STRUCT` @@ -38,13 +41,28 @@ type Ants struct{} ```go type GNet struct{} ``` + + #### func (*GNet) Debugf(format string, args ...interface {}) + *** + + #### func (*GNet) Infof(format string, args ...interface {}) + *** + + #### func (*GNet) Warnf(format string, args ...interface {}) + *** + + #### func (*GNet) Errorf(format string, args ...interface {}) + *** + + #### func (*GNet) Fatalf(format string, args ...interface {}) + *** diff --git a/server/lockstep/README.md b/server/lockstep/README.md index 3452107..7c74cfc 100644 --- a/server/lockstep/README.md +++ b/server/lockstep/README.md @@ -152,58 +152,106 @@ type Lockstep[ClientID comparable, Command any] struct { lockstepStoppedEventHandles []StoppedEventHandle[ClientID, Command] } ``` + + #### func (*Lockstep) JoinClient(client Client[ClientID]) > 将客户端加入到广播队列中,通常在开始广播前使用 > - 如果客户端在开始广播后加入,将丢失之前的帧数据,如要从特定帧开始追帧请使用 JoinClientWithFrame + *** + + #### func (*Lockstep) JoinClientWithFrame(client Client[ClientID], frameIndex int64) > 加入客户端到广播队列中,并从特定帧开始追帧 > - 可用于重连及状态同步、帧同步混用的情况 > - 混用:服务端记录指令时同时做一次状态计算,新客户端加入时直接同步当前状态,之后从特定帧开始广播 + *** + + #### func (*Lockstep) GetClientCount() int > 获取客户端数量 + *** + + #### func (*Lockstep) DropCache(handler func (frame int64) bool) > 丢弃特定帧的缓存,当 handler 返回 true 时将丢弃缓存 + *** + + #### func (*Lockstep) LeaveClient(clientId ClientID) > 将客户端从广播队列中移除 + *** + + #### func (*Lockstep) StartBroadcast() > 开始广播 > - 在开始广播后将持续按照设定的帧率进行帧数推进,并在每一帧推进时向客户端进行同步,需提前将客户端加入广播队列 JoinClient > - 广播过程中使用 AddCommand 将该帧数据追加到当前帧中 + *** + + #### func (*Lockstep) StopBroadcast() > 停止广播 + *** + + #### func (*Lockstep) IsRunning() bool > 是否正在广播 + *** + + #### func (*Lockstep) AddCommand(command Command) > 添加命令到当前帧 + *** + + #### func (*Lockstep) AddCommands(commands []Command) > 添加命令到当前帧 + *** + + #### func (*Lockstep) GetCurrentFrame() int64 > 获取当前帧 + *** + + #### func (*Lockstep) GetClientCurrentFrame(clientId ClientID) int64 > 获取客户端当前帧 + *** + + #### func (*Lockstep) GetFrameLimit() int64 > 获取帧上限 > - 未设置时将返回0 + *** + + #### func (*Lockstep) GetCurrentCommands() []Command > 获取当前帧还未结束时的所有指令 + *** + + #### func (*Lockstep) RegLockstepStoppedEvent(handle StoppedEventHandle[ClientID, Command]) > 当广播停止时将触发被注册的事件处理函数 + *** + + #### func (*Lockstep) OnLockstepStoppedEvent() + *** ### Option `STRUCT` diff --git a/server/router/README.md b/server/router/README.md index 993cbc5..f248399 100644 --- a/server/router/README.md +++ b/server/router/README.md @@ -60,8 +60,11 @@ func ExampleNewMultistage() { ```go type MultistageBind[HandleFunc any] func(HandleFunc) ``` + + #### func (MultistageBind) Bind(handleFunc HandleFunc) > 将处理函数绑定到预设的路由中 + *** ### Multistage `STRUCT` @@ -74,9 +77,12 @@ type Multistage[HandleFunc any] struct { trim func(route any) any } ``` + + #### func (*Multistage) Register(routes ...any) MultistageBind[HandleFunc] > 注册路由是结合 Sub 和 Route 的快捷方式,用于一次性注册多级路由 > - 该函数将返回一个注册函数,可通过调用其将路由绑定到特定处理函数,例如:router.Register("a", "b").Bind(onExec()) + **示例代码:** ```go @@ -90,8 +96,11 @@ func ExampleMultistage_Register() { ``` *** + + #### func (*Multistage) Route(route any, handleFunc HandleFunc) > 为特定路由绑定处理函数,被绑定的处理函数将可以通过 Match 函数进行匹配 + **示例代码:** ```go @@ -105,9 +114,12 @@ func ExampleMultistage_Route() { ``` *** + + #### func (*Multistage) Match(routes ...any) HandleFunc > 匹配已绑定处理函数的路由,返回处理函数 > - 如果未找到将会返回空指针 + **示例代码:** ```go @@ -156,8 +168,11 @@ func TestMultistage_Match(t *testing.T) { *** + + #### func (*Multistage) Sub(route any) *Multistage[HandleFunc] > 获取子路由器 + **示例代码:** ```go diff --git a/server/writeloop/README.md b/server/writeloop/README.md index 3395e2d..649cb94 100644 --- a/server/writeloop/README.md +++ b/server/writeloop/README.md @@ -115,11 +115,17 @@ type Channel[T any] struct { c chan T } ``` + + #### func (*Channel) Put(message T) > 将数据放入写循环,message 应该来源于 hub.ObjectPool + *** + + #### func (*Channel) Close() > 关闭写循环 + *** ### Unbounded `STRUCT` @@ -130,8 +136,11 @@ type Unbounded[Message any] struct { buf *buffer.Unbounded[Message] } ``` + + #### func (*Unbounded) Put(message Message) > 将数据放入写循环,message 应该来源于 hub.ObjectPool +
查看 / 收起单元测试 @@ -189,8 +198,11 @@ func BenchmarkUnbounded_Put(b *testing.B) { *** + + #### func (*Unbounded) Close() > 关闭写循环 +
查看 / 收起单元测试 diff --git a/utils/aoi/README.md b/utils/aoi/README.md index b710b34..eb25601 100644 --- a/utils/aoi/README.md +++ b/utils/aoi/README.md @@ -83,17 +83,35 @@ type TwoDimensional[EID generic.Basic, PosType generic.SignedNumber, E TwoDimens repartitionQueue []func() } ``` + + #### func (*TwoDimensional) AddEntity(entity E) + *** + + #### func (*TwoDimensional) DeleteEntity(entity E) + *** + + #### func (*TwoDimensional) Refresh(entity E) + *** + + #### func (*TwoDimensional) GetFocus(id EID) map[EID]E + *** + + #### func (*TwoDimensional) SetSize(width int, height int) + *** + + #### func (*TwoDimensional) SetAreaSize(width int, height int) + *** ### TwoDimensionalEntity `INTERFACE` diff --git a/utils/arrangement/README.md b/utils/arrangement/README.md index e6fb97d..6694668 100644 --- a/utils/arrangement/README.md +++ b/utils/arrangement/README.md @@ -127,24 +127,42 @@ type Area[ID comparable, AreaInfo any] struct { evaluate AreaEvaluateHandle[ID, AreaInfo] } ``` + + #### func (*Area) GetAreaInfo() AreaInfo > 获取编排区域的信息 + *** + + #### func (*Area) GetItems() map[ID]Item[ID] > 获取编排区域中的所有成员 + *** + + #### func (*Area) IsAllow(item Item[ID]) (constraintErr error, conflictItems map[ID]Item[ID], allow bool) > 检测一个成员是否可以被添加到该编排区域中 + *** + + #### func (*Area) IsConflict(item Item[ID]) bool > 检测一个成员是否会造成冲突 + *** + + #### func (*Area) GetConflictItems(item Item[ID]) map[ID]Item[ID] > 获取与一个成员产生冲突的所有其他成员 + *** + + #### func (*Area) GetScore(extra ...Item[ID]) float64 > 获取该编排区域的评估分数 > - 当 extra 不为空时,将会将 extra 中的内容添加到 items 中进行评估 + *** ### AreaOption `STRUCT` @@ -176,14 +194,23 @@ type Arrangement[ID comparable, AreaInfo any] struct { conflictHandles []ConflictHandle[ID, AreaInfo] } ``` + + #### func (*Arrangement) AddArea(areaInfo AreaInfo, options ...AreaOption[ID, AreaInfo]) > 添加一个编排区域 + *** + + #### func (*Arrangement) AddItem(item Item[ID]) > 添加一个成员 + *** + + #### func (*Arrangement) Arrange() (areas []*Area[ID, AreaInfo], noSolution map[ID]Item[ID]) > 编排 +
查看 / 收起单元测试 @@ -247,47 +274,89 @@ type Editor[ID comparable, AreaInfo any] struct { retryCount int } ``` + + #### func (*Editor) GetPendingCount() int > 获取待编排的成员数量 + *** + + #### func (*Editor) RemoveAreaItem(area *Area[ID, AreaInfo], item Item[ID]) > 从编排区域中移除一个成员到待编排队列中,如果该成员不存在于编排区域中,则不进行任何操作 + *** + + #### func (*Editor) AddAreaItem(area *Area[ID, AreaInfo], item Item[ID]) > 将一个成员添加到编排区域中,如果该成员已经存在于编排区域中,则不进行任何操作 + *** + + #### func (*Editor) GetAreas() []*Area[ID, AreaInfo] > 获取所有的编排区域 + *** + + #### func (*Editor) GetAreasWithScoreAsc(extra ...Item[ID]) []*Area[ID, AreaInfo] > 获取所有的编排区域,并按照分数升序排序 + *** + + #### func (*Editor) GetAreasWithScoreDesc(extra ...Item[ID]) []*Area[ID, AreaInfo] > 获取所有的编排区域,并按照分数降序排序 + *** + + #### func (*Editor) GetRetryCount() int > 获取重试次数 + *** + + #### func (*Editor) GetThresholdProgressRate() float64 > 获取重试次数阈值进度 + *** + + #### func (*Editor) GetAllowAreas(item Item[ID]) []*Area[ID, AreaInfo] > 获取允许的编排区域 + *** + + #### func (*Editor) GetNoAllowAreas(item Item[ID]) []*Area[ID, AreaInfo] > 获取不允许的编排区域 + *** + + #### func (*Editor) GetBestAllowArea(item Item[ID]) *Area[ID, AreaInfo] > 获取最佳的允许的编排区域,如果不存在,则返回 nil + *** + + #### func (*Editor) GetBestNoAllowArea(item Item[ID]) *Area[ID, AreaInfo] > 获取最佳的不允许的编排区域,如果不存在,则返回 nil + *** + + #### func (*Editor) GetWorstAllowArea(item Item[ID]) *Area[ID, AreaInfo] > 获取最差的允许的编排区域,如果不存在,则返回 nil + *** + + #### func (*Editor) GetWorstNoAllowArea(item Item[ID]) *Area[ID, AreaInfo] > 获取最差的不允许的编排区域,如果不存在,则返回 nil + *** ### Item `INTERFACE` diff --git a/utils/buffer/README.md b/utils/buffer/README.md index 1470178..81cd797 100644 --- a/utils/buffer/README.md +++ b/utils/buffer/README.md @@ -94,8 +94,11 @@ type Ring[T any] struct { w int } ``` + + #### func (*Ring) Read() ( T, error) > 读取数据 +
查看 / 收起基准测试 @@ -120,14 +123,23 @@ func BenchmarkRing_Read(b *testing.B) { *** + + #### func (*Ring) ReadAll() []T > 读取所有数据 + *** + + #### func (*Ring) Peek() (t T, err error) > 查看数据 + *** + + #### func (*Ring) Write(v T) > 写入数据 +
查看 / 收起基准测试 @@ -149,17 +161,29 @@ func BenchmarkRing_Write(b *testing.B) { *** + + #### func (*Ring) IsEmpty() bool > 是否为空 + *** + + #### func (*Ring) Cap() int > 返回缓冲区容量 + *** + + #### func (*Ring) Len() int > 返回缓冲区长度 + *** + + #### func (*Ring) Reset() > 重置缓冲区 + *** ### RingUnbounded `STRUCT` @@ -175,8 +199,11 @@ type RingUnbounded[T any] struct { closedSignal chan struct{} } ``` + + #### func (*RingUnbounded) Write(v T) > 写入数据 +
查看 / 收起基准测试 @@ -198,8 +225,11 @@ func BenchmarkRingUnbounded_Write(b *testing.B) { *** + + #### func (*RingUnbounded) Read() chan T > 读取数据 +
查看 / 收起基准测试 @@ -224,11 +254,17 @@ func BenchmarkRingUnbounded_Read(b *testing.B) { *** + + #### func (*RingUnbounded) Closed() bool > 判断缓冲区是否已关闭 + *** + + #### func (*RingUnbounded) Close() chan struct {} > 关闭缓冲区,关闭后将不再接收新数据,但是已有数据仍然可以读取 +
查看 / 收起单元测试 @@ -268,15 +304,24 @@ type Unbounded[V any] struct { backlog []V } ``` + + #### func (*Unbounded) Put(t V) > 将数据放入缓冲区 + *** + + #### func (*Unbounded) Load() > 将缓冲区中的数据发送到读取通道中,如果缓冲区中没有数据,则不会发送 > - 在每次 Get 后都应该执行该函数 + *** + + #### func (*Unbounded) Get() chan V > 获取读取通道 +
查看 / 收起单元测试 @@ -299,9 +344,15 @@ func TestUnbounded_Get(t *testing.T) { *** + + #### func (*Unbounded) Close() > 关闭 + *** + + #### func (*Unbounded) IsClosed() bool > 是否已关闭 + *** diff --git a/utils/collection/README.md b/utils/collection/README.md index 355a9b8..4c5f566 100644 --- a/utils/collection/README.md +++ b/utils/collection/README.md @@ -147,7 +147,7 @@ collection 定义了各种对于集合操作有用的各种函数 **示例代码:** -slice 克隆后将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 +在该示例中,将 slice 克隆后将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 - 示例中的结果将会输出 [1 2 3] @@ -202,7 +202,7 @@ func TestCloneSlice(t *testing.T) { **示例代码:** -map 克隆后将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 +在该示例中,将 map 克隆后将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 - 示例中的结果将会输出 3 @@ -257,7 +257,7 @@ func TestCloneMap(t *testing.T) { **示例代码:** -slice 克隆为 2 个新的 slice,将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 +通过将 slice 克隆为 2 个新的 slice,将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 - result 的结果为 [[1 2 3] [1 2 3]] - 示例中的结果将会输出 2 @@ -319,7 +319,7 @@ func TestCloneSliceN(t *testing.T) { **示例代码:** -map 克隆为 2 个新的 map,将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 +通过将 map 克隆为 2 个新的 map,将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 - result 的结果为 [map[1:1 2:2 3:3] map[1:1 2:2 3:3]] `无序的 Key-Value 对` - 示例中的结果将会输出 2 @@ -382,7 +382,7 @@ func TestCloneMapN(t *testing.T) { **示例代码:** -slice 克隆为 2 个新的 slice,将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 +通过将多个 slice 克隆为 2 个新的 slice,将会得到一个新的 slice result,而 result 和 slice 将不会有任何关联,但是如果 slice 中的元素是引用类型,那么 result 中的元素将会和 slice 中的元素指向同一个地址 - result 的结果为 [[1 2 3] [1 2 3]] @@ -441,7 +441,7 @@ func TestCloneSlices(t *testing.T) { **示例代码:** -map 克隆为 2 个新的 map,将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 +通过将多个 map 克隆为 2 个新的 map,将会得到一个新的 map result,而 result 和 map 将不会有任何关联,但是如果 map 中的元素是引用类型,那么 result 中的元素将会和 map 中的元素指向同一个地址 - result 的结果为 [map[1:1 2:2 3:3] map[1:1 2:2 3:3]] `无序的 Key-Value 对` diff --git a/utils/collection/listings/README.md b/utils/collection/listings/README.md index 6d0a0dd..6ff9276 100644 --- a/utils/collection/listings/README.md +++ b/utils/collection/listings/README.md @@ -65,17 +65,29 @@ type Matrix[V any] struct { data []V } ``` + + #### func (*Matrix) Get(index ...int) *V > 获取矩阵中给定索引的元素。 + *** + + #### func (*Matrix) Set(index []int, value V) > 设置矩阵中给定索引的元素。 + *** + + #### func (*Matrix) Dimensions() []int > 返回矩阵的维度大小。 + *** + + #### func (*Matrix) Clear() > 清空矩阵。 + *** ### PagedSlice `STRUCT` @@ -88,23 +100,41 @@ type PagedSlice[T any] struct { lenLast int } ``` + + #### func (*PagedSlice) Add(value T) > 添加一个元素到 PagedSlice 中。 + *** + + #### func (*PagedSlice) Get(index int) *T > 获取 PagedSlice 中给定索引的元素。 + *** + + #### func (*PagedSlice) Set(index int, value T) > 设置 PagedSlice 中给定索引的元素。 + *** + + #### func (*PagedSlice) Len() int > 返回 PagedSlice 中元素的数量。 + *** + + #### func (*PagedSlice) Clear() > 清空 PagedSlice。 + *** + + #### func (*PagedSlice) Range(f func (index int, value T) bool) > 迭代 PagedSlice 中的所有元素。 + *** ### PrioritySlice `STRUCT` @@ -114,17 +144,29 @@ type PrioritySlice[V any] struct { items []*priorityItem[V] } ``` + + #### func (*PrioritySlice) Len() int > 返回切片长度 + *** + + #### func (*PrioritySlice) Cap() int > 返回切片容量 + *** + + #### func (*PrioritySlice) Clear() > 清空切片 + *** + + #### func (*PrioritySlice) Append(v V, p int) > 添加元素 +
查看 / 收起单元测试 @@ -145,44 +187,83 @@ func TestPrioritySlice_Append(t *testing.T) { *** + + #### func (*PrioritySlice) Appends(priority int, vs ...V) > 添加元素 + *** + + #### func (*PrioritySlice) Get(index int) ( V, int) > 获取元素 + *** + + #### func (*PrioritySlice) GetValue(index int) V > 获取元素值 + *** + + #### func (*PrioritySlice) GetPriority(index int) int > 获取元素优先级 + *** + + #### func (*PrioritySlice) Set(index int, value V, priority int) > 设置元素 + *** + + #### func (*PrioritySlice) SetValue(index int, value V) > 设置元素值 + *** + + #### func (*PrioritySlice) SetPriority(index int, priority int) > 设置元素优先级 + *** + + #### func (*PrioritySlice) Action(action func (items []*priorityItem[V]) []*priorityItem[V]) > 直接操作切片,如果返回值不为 nil,则替换切片 + *** + + #### func (*PrioritySlice) Range(action func (index int, item *priorityItem[V]) bool) > 遍历切片,如果返回值为 false,则停止遍历 + *** + + #### func (*PrioritySlice) RangeValue(action func (index int, value V) bool) > 遍历切片值,如果返回值为 false,则停止遍历 + *** + + #### func (*PrioritySlice) RangePriority(action func (index int, priority int) bool) > 遍历切片优先级,如果返回值为 false,则停止遍历 + *** + + #### func (*PrioritySlice) Slice() []V -> 返回切片 +> SyncSlice 返回切片 + *** + + #### func (*PrioritySlice) String() string > 返回切片字符串 + *** ### SyncSlice `STRUCT` @@ -193,17 +274,38 @@ type SyncSlice[V any] struct { data []V } ``` + + #### func (*SyncSlice) Get(index int) V + *** + + #### func (*SyncSlice) GetWithRange(start int, end int) []V + *** + + #### func (*SyncSlice) Set(index int, value V) + *** + + #### func (*SyncSlice) Append(values ...V) + *** + + #### func (*SyncSlice) Release() + *** + + #### func (*SyncSlice) Clear() + *** + + #### func (*SyncSlice) GetData() []V + *** diff --git a/utils/collection/mappings/README.md b/utils/collection/mappings/README.md index 4084040..17546e1 100644 --- a/utils/collection/mappings/README.md +++ b/utils/collection/mappings/README.md @@ -46,55 +46,109 @@ type SyncMap[K comparable, V any] struct { atom bool } ``` + + #### func (*SyncMap) Set(key K, value V) > 设置一个值 + *** + + #### func (*SyncMap) Get(key K) V > 获取一个值 + *** + + #### func (*SyncMap) Atom(handle func (m map[K]V)) > 原子操作 + *** + + #### func (*SyncMap) Exist(key K) bool > 判断是否存在 + *** + + #### func (*SyncMap) GetExist(key K) ( V, bool) > 获取一个值并判断是否存在 + *** + + #### func (*SyncMap) Delete(key K) > 删除一个值 + *** + + #### func (*SyncMap) DeleteGet(key K) V > 删除一个值并返回 + *** + + #### func (*SyncMap) DeleteGetExist(key K) ( V, bool) > 删除一个值并返回是否存在 + *** + + #### func (*SyncMap) DeleteExist(key K) bool > 删除一个值并返回是否存在 + *** + + #### func (*SyncMap) Clear() > 清空 + *** + + #### func (*SyncMap) ClearHandle(handle func (key K, value V)) > 清空并处理 + *** + + #### func (*SyncMap) Range(handle func (key K, value V) bool) > 遍历所有值,如果 handle 返回 true 则停止遍历 + *** + + #### func (*SyncMap) Keys() []K > 获取所有的键 + *** + + #### func (*SyncMap) Slice() []V > 获取所有的值 + *** + + #### func (*SyncMap) Map() map[K]V > 转换为普通 map + *** + + #### func (*SyncMap) Size() int > 获取数量 + *** + + #### func (*SyncMap) MarshalJSON() ( []byte, error) + *** + + #### func (*SyncMap) UnmarshalJSON(bytes []byte) error + *** diff --git a/utils/combination/README.md b/utils/combination/README.md index 089fb4d..ec27303 100644 --- a/utils/combination/README.md +++ b/utils/combination/README.md @@ -44,7 +44,7 @@ combination 包提供了一些实用的组合函数。 |[WithValidatorHandleContinuousNot](#WithValidatorHandleContinuousNot)|校验组合成员是否不连续 |[WithValidatorHandleGroupContinuous](#WithValidatorHandleGroupContinuous)|校验组合成员是否能够按类型分组并且连续 |[WithValidatorHandleGroupContinuousN](#WithValidatorHandleGroupContinuousN)|校验组合成员是否能够按分组为 n 组类型并且连续 -|[WithValidatorHandleNCarryM](#WithValidatorHandleNCarryM)| 校验组合成员是否匹配 N 携带相同的 M 的组合 +|[WithValidatorHandleNCarryM](#WithValidatorHandleNCarryM)|校验组合成员是否匹配 N 携带相同的 M 的组合 |[WithValidatorHandleNCarryIndependentM](#WithValidatorHandleNCarryIndependentM)|校验组合成员是否匹配 N 携带独立的 M 的组合 @@ -227,7 +227,7 @@ combination 包提供了一些实用的组合函数。 *** #### func WithValidatorHandleNCarryM\[T Item, E generic.Ordered\](n int, m int, getType func (item T) E) ValidatorOption[T] -> 校验组合成员是否匹配 N 携带相同的 M 的组合 +> 校验组合成员是否匹配 N 携带相同的 M 的组合 > - n: 组合中元素的数量,表示需要匹配的组合数量,n 的类型需要全部相同 > - m: 组合中元素的数量,表示需要匹配的组合数量,m 的类型需要全部相同 > - getType: 用于获取组合中元素的类型,用于判断是否相同 @@ -251,23 +251,41 @@ type Combination[T Item] struct { priority []string } ``` + + #### func (*Combination) NewMatcher(name string, options ...MatcherOption[T]) *Combination[T] > 添加一个新的匹配器 + *** + + #### func (*Combination) AddMatcher(name string, matcher *Matcher[T]) *Combination[T] > 添加一个匹配器 + *** + + #### func (*Combination) RemoveMatcher(name string) *Combination[T] > 移除一个匹配器 + *** + + #### func (*Combination) Combinations(items []T) (result [][]T) > 从一组数据中提取所有符合匹配器规则的组合 + *** + + #### func (*Combination) CombinationsToName(items []T) (result map[string][][]T) > 从一组数据中提取所有符合匹配器规则的组合,并返回匹配器名称 + *** + + #### func (*Combination) Best(items []T) (name string, result []T) > 从一组数据中提取符合匹配器规则的最佳组合 +
查看 / 收起单元测试 @@ -302,8 +320,11 @@ func TestCombination_Best(t *testing.T) { *** + + #### func (*Combination) Worst(items []T) (name string, result []T) > 从一组数据中提取符合匹配器规则的最差组合 + *** ### Option `STRUCT` @@ -326,18 +347,30 @@ type Matcher[T Item] struct { filter []func(items []T) [][]T } ``` + + #### func (*Matcher) AddFilter(filter func (items []T) [][]T) > 添加一个筛选器 > - 筛选器用于对组合进行筛选,返回一个二维数组,每个数组内的元素都是一个组合 + *** + + #### func (*Matcher) Combinations(items []T) [][]T > 从一组数据中提取所有符合筛选器规则的组合 + *** + + #### func (*Matcher) Best(items []T) []T > 从一组数据中提取符筛选器规则的最佳组合 + *** + + #### func (*Matcher) Worst(items []T) []T > 从一组数据中提取符筛选器规则的最差组合 + *** ### MatcherOption `STRUCT` @@ -353,8 +386,11 @@ type Validator[T Item] struct { vh []func(items []T) bool } ``` + + #### func (*Validator) Validate(items []T) bool > 校验组合是否符合要求 +
查看 / 收起单元测试 diff --git a/utils/deck/README.md b/utils/deck/README.md index 4dd3712..b34c7f8 100644 --- a/utils/deck/README.md +++ b/utils/deck/README.md @@ -52,26 +52,47 @@ type Deck[I Item] struct { sort []int64 } ``` + + #### func (*Deck) AddGroup(group *Group[I]) > 将一个组添加到甲板中 + *** + + #### func (*Deck) RemoveGroup(guid int64) > 移除甲板中的一个组 + *** + + #### func (*Deck) GetCount() int > 获取甲板中的组数量 + *** + + #### func (*Deck) GetGroups() map[int64]*Group[I] > 获取所有组 + *** + + #### func (*Deck) GetGroupsSlice() []*Group[I] > 获取所有组 + *** + + #### func (*Deck) GetNext(guid int64) *Group[I] > 获取特定组的下一个组 + *** + + #### func (*Deck) GetPrev(guid int64) *Group[I] > 获取特定组的上一个组 + *** ### Group `STRUCT` @@ -83,50 +104,95 @@ type Group[I Item] struct { items []I } ``` + + #### func (*Group) GetGuid() int64 > 获取组的 guid + *** + + #### func (*Group) Fill() > 将该组的数据填充为 WithGroupFillHandle 中设置的内容 + *** + + #### func (*Group) Pop() (item I) > 从顶部获取一个内容 + *** + + #### func (*Group) PopN(n int) (items []I) > 从顶部获取指定数量的内容 + *** + + #### func (*Group) PressOut() (item I) > 从底部压出一个内容 + *** + + #### func (*Group) PressOutN(n int) (items []I) > 从底部压出指定数量的内容 + *** + + #### func (*Group) Push(item I) > 向顶部压入一个内容 + *** + + #### func (*Group) PushN(items []I) > 向顶部压入指定数量的内容 + *** + + #### func (*Group) Insert(item I) > 向底部插入一个内容 + *** + + #### func (*Group) InsertN(items []I) > 向底部插入指定数量的内容 + *** + + #### func (*Group) Pull(index int) (item I) > 从特定位置拔出一个内容 + *** + + #### func (*Group) Thrust(index int, item I) > 向特定位置插入一个内容 + *** + + #### func (*Group) IsFree() bool > 检查组是否为空 + *** + + #### func (*Group) GetCount() int > 获取组中剩余的内容数量 + *** + + #### func (*Group) GetItem(index int) I > 获取组中的指定内容 + *** ### Item `INTERFACE` diff --git a/utils/fsm/README.md b/utils/fsm/README.md index ab18674..12625fb 100644 --- a/utils/fsm/README.md +++ b/utils/fsm/README.md @@ -85,32 +85,59 @@ type FSM[State comparable, Data any] struct { exitAfterEventHandles map[State][]func(state *FSM[State, Data]) } ``` + + #### func (*FSM) Update() > 触发当前状态 + *** + + #### func (*FSM) Register(state State, options ...Option[State, Data]) > 注册状态 + *** + + #### func (*FSM) Unregister(state State) > 反注册状态 + *** + + #### func (*FSM) HasState(state State) bool > 检查状态机是否存在特定状态 + *** + + #### func (*FSM) Change(state State) > 改变状态机状态到新的状态 + *** + + #### func (*FSM) Current() (state State) > 获取当前状态 + *** + + #### func (*FSM) GetData() Data > 获取状态机数据 + *** + + #### func (*FSM) IsZero() bool > 检查状态机是否无状态 + *** + + #### func (*FSM) PrevIsZero() bool > 检查状态机上一个状态是否无状态 + *** ### Option `STRUCT` diff --git a/utils/generator/astgo/README.md b/utils/generator/astgo/README.md index 3d775cb..3433548 100644 --- a/utils/generator/astgo/README.md +++ b/utils/generator/astgo/README.md @@ -93,7 +93,10 @@ type File struct { Comment *Comment } ``` + + #### func (*File) Package() string + *** ### Function `STRUCT` @@ -114,7 +117,10 @@ type Function struct { Test bool } ``` + + #### func (*Function) Code() string + *** ### Package `STRUCT` @@ -128,19 +134,40 @@ type Package struct { Functions map[string]*Function } ``` + + #### func (*Package) StructFunc(name string) []*Function + *** + + #### func (*Package) PackageFunc() []*Function + *** + + #### func (*Package) Structs() []*Struct + *** + + #### func (*Package) FileComments() *Comment + *** + + #### func (*Package) GetUnitTest(f *Function) *Function + *** + + #### func (*Package) GetExampleTest(f *Function) *Function + *** + + #### func (*Package) GetBenchmarkTest(f *Function) *Function + *** ### Struct `STRUCT` diff --git a/utils/generator/genreadme/README.md b/utils/generator/genreadme/README.md index 04c96d0..cbfe512 100644 --- a/utils/generator/genreadme/README.md +++ b/utils/generator/genreadme/README.md @@ -44,7 +44,10 @@ type Builder struct { o string } ``` + + #### func (*Builder) Generate() error +
查看 / 收起单元测试 diff --git a/utils/geometry/README.md b/utils/geometry/README.md index ad08194..1f5b0d0 100644 --- a/utils/geometry/README.md +++ b/utils/geometry/README.md @@ -878,23 +878,41 @@ type Circle[V generic.SignedNumber] struct { Shape[V] } ``` + + #### func (Circle) Radius() V > 获取圆形半径 + *** + + #### func (Circle) Centroid() Point[V] > 获取圆形质心位置 + *** + + #### func (Circle) Overlap(circle Circle[V]) bool > 与另一个圆是否发生重叠 + *** + + #### func (Circle) Area() V > 获取圆形面积 + *** + + #### func (Circle) Length() V > 获取圆的周长 + *** + + #### func (Circle) CentroidDistance(circle Circle[V]) V > 计算与另一个圆的质心距离 + *** ### FloorPlan `STRUCT` @@ -902,17 +920,29 @@ type Circle[V generic.SignedNumber] struct { ```go type FloorPlan []string ``` + + #### func (FloorPlan) IsFree(point Point[int]) bool > 检查位置是否为空格 + *** + + #### func (FloorPlan) IsInBounds(point Point[int]) bool > 检查位置是否在边界内 + *** + + #### func (FloorPlan) Put(point Point[int], c rune) > 设置平面图特定位置的字符 + *** + + #### func (FloorPlan) String() string > 获取平面图结果 + *** ### Direction `STRUCT` @@ -926,17 +956,29 @@ type Direction uint8 ```go type LineSegment[V generic.SignedNumber] [2]Point[V] ``` + + #### func (LineSegment) GetPoints() [2]Point[V] > 获取该线段的两个点 + *** + + #### func (LineSegment) GetStart() Point[V] > 获取该线段的开始位置 + *** + + #### func (LineSegment) GetEnd() Point[V] > 获取该线段的结束位置 + *** + + #### func (LineSegment) GetLength() V > 获取该线段的长度 + *** ### LineSegmentCap `STRUCT` @@ -947,7 +989,10 @@ type LineSegmentCap[V generic.SignedNumber, Data any] struct { Data Data } ``` + + #### func (*LineSegmentCap) GetData() Data + *** ### Point `STRUCT` @@ -955,53 +1000,101 @@ type LineSegmentCap[V generic.SignedNumber, Data any] struct { ```go type Point[V generic.SignedNumber] [2]V ``` + + #### func (Point) GetX() V > 返回该点的 x 坐标 + *** + + #### func (Point) GetY() V > 返回该点的 y 坐标 + *** + + #### func (Point) GetXY() (x V, y V) > 返回该点的 x、y 坐标 + *** + + #### func (Point) GetPos(width V) V > 返回该点位于特定宽度的二维数组的顺序位置 + *** + + #### func (Point) GetOffset(x V, y V) Point[V] > 获取偏移后的新坐标 + *** + + #### func (Point) Negative() bool > 返回该点是否是一个负数坐标 + *** + + #### func (Point) OutOf(minWidth V, minHeight V, maxWidth V, maxHeight V) bool > 返回该点在特定宽高下是否越界f + *** + + #### func (Point) Equal(point Point[V]) bool > 返回两个点是否相等 + *** + + #### func (Point) Copy() Point[V] > 复制一个点位置 + *** + + #### func (Point) Add(point Point[V]) Point[V] > 得到加上 point 后的点 + *** + + #### func (Point) Sub(point Point[V]) Point[V] > 得到减去 point 后的点 + *** + + #### func (Point) Mul(point Point[V]) Point[V] > 得到乘以 point 后的点 + *** + + #### func (Point) Div(point Point[V]) Point[V] > 得到除以 point 后的点 + *** + + #### func (Point) Abs() Point[V] > 返回位置的绝对值 + *** + + #### func (Point) Max(point Point[V]) Point[V] > 返回两个位置中每个维度的最大值组成的新的位置 + *** + + #### func (Point) Min(point Point[V]) Point[V] > 返回两个位置中每个维度的最小值组成的新的位置 + *** ### PointCap `STRUCT` @@ -1012,8 +1105,11 @@ type PointCap[V generic.SignedNumber, D any] struct { Data D } ``` + + #### func (PointCap) GetData() D > 获取数据 + *** ### Shape `STRUCT` @@ -1021,8 +1117,11 @@ type PointCap[V generic.SignedNumber, D any] struct { ```go type Shape[V generic.SignedNumber] []Point[V] ``` + + #### func (Shape) Points() []Point[V] > 获取这个形状的所有点 + **示例代码:** ```go @@ -1059,8 +1158,11 @@ func TestShape_Points(t *testing.T) { *** + + #### func (Shape) PointCount() int > 获取这个形状的点数量 + **示例代码:** ```go @@ -1092,15 +1194,24 @@ func TestShape_PointCount(t *testing.T) { *** + + #### func (Shape) Contains(point Point[V]) bool > 返回该形状中是否包含点 + *** + + #### func (Shape) ToCircle() Circle[V] > 将形状转换为圆形进行处理 > - 当形状非圆形时将会产生意外情况 + *** + + #### func (Shape) String() string > 将该形状转换为可视化的字符串进行返回 + **示例代码:** ```go @@ -1133,6 +1244,8 @@ func TestShape_String(t *testing.T) { *** + + #### func (Shape) ShapeSearch(options ...ShapeSearchOption) (result []Shape[V]) > 获取该形状中包含的所有图形组合及其位置 > - 需要注意的是,即便图形最终表示为相同的,但是只要位置组合顺序不同,那么也将被认定为一种图形组合 @@ -1140,6 +1253,7 @@ func TestShape_String(t *testing.T) { > - 返回的坐标为原始形状的坐标 > > 可通过可选项对搜索结果进行过滤 + **示例代码:** ```go @@ -1155,12 +1269,18 @@ func ExampleShape_ShapeSearch() { ``` *** + + #### func (Shape) Edges() (edges []LineSegment[V]) > 获取该形状每一条边 > - 该形状需要最少由3个点组成,否则将不会返回任意一边 + *** + + #### func (Shape) IsPointOnEdge(point Point[V]) bool > 检查点是否在该形状的一条边上 + *** ### ShapeSearchOption `STRUCT` diff --git a/utils/geometry/astar/README.md b/utils/geometry/astar/README.md index 63809a3..b5e8753 100644 --- a/utils/geometry/astar/README.md +++ b/utils/geometry/astar/README.md @@ -86,5 +86,8 @@ type Graph[Node comparable] interface { Neighbours(node Node) []Node } ``` + + #### func (Graph) Neighbours(point geometry.Point[int]) []geometry.Point[int] + *** diff --git a/utils/geometry/dp/README.md b/utils/geometry/dp/README.md index 1eaf3ce..bbec081 100644 --- a/utils/geometry/dp/README.md +++ b/utils/geometry/dp/README.md @@ -81,29 +81,47 @@ type DistributionPattern[Item any] struct { usePos bool } ``` + + #### func (*DistributionPattern) GetLinks(pos int) (result []Link[Item]) > 获取关联的成员 > - 其中包含传入的 pos 成员 + *** + + #### func (*DistributionPattern) HasLink(pos int) bool > 检查一个位置是否包含除它本身外的其他关联成员 + *** + + #### func (*DistributionPattern) LoadMatrix(matrix [][]Item) > 通过二维矩阵加载分布图 > - 通过该函数加载的分布图使用的矩阵是复制后的矩阵,因此无法直接通过刷新(Refresh)来更新分布关系 > - 需要通过直接刷新的方式请使用 LoadMatrixWithPos + *** + + #### func (*DistributionPattern) LoadMatrixWithPos(width int, matrix []Item) > 通过二维矩阵加载分布图 + *** + + #### func (*DistributionPattern) Refresh(pos int) > 刷新特定位置的分布关系 > - 由于 LoadMatrix 的矩阵是复制后的矩阵,所以任何外部的改动都不会影响到分布图的变化,在这种情况下,刷新将没有任何意义 > - 需要通过直接刷新的方式请使用 LoadMatrixWithPos 加载矩阵,或者通过 RefreshWithItem 函数进行刷新 + *** + + #### func (*DistributionPattern) RefreshWithItem(pos int, item Item) > 通过特定的成员刷新特定位置的分布关系 > - 如果矩阵通过 LoadMatrixWithPos 加载,将会重定向至 Refresh + *** ### Link `STRUCT` diff --git a/utils/geometry/matrix/README.md b/utils/geometry/matrix/README.md index c8972d1..7ed208c 100644 --- a/utils/geometry/matrix/README.md +++ b/utils/geometry/matrix/README.md @@ -47,52 +47,100 @@ type Matrix[T any] struct { m []T } ``` + + #### func (*Matrix) GetWidth() int > 获取二维矩阵宽度 + *** + + #### func (*Matrix) GetHeight() int > 获取二维矩阵高度 + *** + + #### func (*Matrix) GetWidth2Height() (width int, height int) > 获取二维矩阵的宽度和高度 + *** + + #### func (*Matrix) GetMatrix() [][]T > 获取二维矩阵 > - 通常建议使用 GetMatrixWithPos 进行处理这样将拥有更高的效率 + *** + + #### func (*Matrix) GetMatrixWithPos() []T > 获取顺序的矩阵 + *** + + #### func (*Matrix) Get(x int, y int) (value T) > 获取特定坐标的内容 + *** + + #### func (*Matrix) GetExist(x int, y int) (value T, exist bool) > 获取特定坐标的内容,如果不存在则返回 false + *** + + #### func (*Matrix) GetWithPos(pos int) (value T) > 获取特定坐标的内容 + *** + + #### func (*Matrix) Set(x int, y int, data T) > 设置特定坐标的内容 + *** + + #### func (*Matrix) SetWithPos(pos int, data T) > 设置特定坐标的内容 + *** + + #### func (*Matrix) Swap(x1 int, y1 int, x2 int, y2 int) > 交换两个位置的内容 + *** + + #### func (*Matrix) SwapWithPos(pos1 int, pos2 int) > 交换两个位置的内容 + *** + + #### func (*Matrix) TrySwap(x1 int, y1 int, x2 int, y2 int, expressionHandle func (matrix *Matrix[T]) bool) > 尝试交换两个位置的内容,交换后不满足表达式时进行撤销 + *** + + #### func (*Matrix) TrySwapWithPos(pos1 int, pos2 int, expressionHandle func (matrix *Matrix[T]) bool) > 尝试交换两个位置的内容,交换后不满足表达式时进行撤销 + *** + + #### func (*Matrix) FillFull(generateHandle func (x int) T) > 根据提供的生成器填充整个矩阵 + *** + + #### func (*Matrix) FillFullWithPos(generateHandle func (pos int) T) > 根据提供的生成器填充整个矩阵 + *** diff --git a/utils/geometry/navmesh/README.md b/utils/geometry/navmesh/README.md index af138da..301e2ed 100644 --- a/utils/geometry/navmesh/README.md +++ b/utils/geometry/navmesh/README.md @@ -63,9 +63,14 @@ type NavMesh[V generic.SignedNumber] struct { meshShrinkAmount V } ``` + + #### func (*NavMesh) Neighbours(node *shape[V]) []*shape[V] > 实现 astar.Graph 的接口,用于向 A* 算法提供相邻图形 + *** + + #### func (*NavMesh) Find(point geometry.Point[V], maxDistance V) (distance V, findPoint geometry.Point[V], findShape geometry.Shape[V]) > 用于在 NavMesh 中查找离给定点最近的形状,并返回距离、找到的点和找到的形状。 > @@ -83,7 +88,10 @@ type NavMesh[V generic.SignedNumber] struct { > - 如果给定点不在任何形状内部或者形状的边上,将计算给定点到每个形状的距离,并找到最近的形状和对应的点。 > - 距离的计算采用几何学中的投影点到形状的距离。 > - 函数返回离给定点最近的形状的距离、找到的点和找到的形状。 + *** + + #### func (*NavMesh) FindPath(start geometry.Point[V], end geometry.Point[V]) (result []geometry.Point[V]) > 函数用于在 NavMesh 中查找从起点到终点的路径,并返回路径上的点序列。 > @@ -99,6 +107,7 @@ type NavMesh[V generic.SignedNumber] struct { > - 如果起点或终点不在任何形状内部,且 NavMesh 的 meshShrinkAmount 大于0,则会考虑缩小的形状。 > - 使用 A* 算法在 NavMesh 上搜索从起点形状到终点形状的最短路径。 > - 使用漏斗算法对路径进行优化,以得到最终的路径点序列。 + **示例代码:** ```go diff --git a/utils/hub/README.md b/utils/hub/README.md index e518202..a89558d 100644 --- a/utils/hub/README.md +++ b/utils/hub/README.md @@ -100,8 +100,11 @@ type ObjectPool[T any] struct { releaser func(data T) } ``` + + #### func (*ObjectPool) Get() T > 获取一个对象 +
查看 / 收起单元测试 @@ -137,8 +140,11 @@ func TestObjectPool_Get(t *testing.T) { *** + + #### func (*ObjectPool) Release(data T) > 将使用完成的对象放回缓冲区 +
查看 / 收起单元测试 diff --git a/utils/huge/README.md b/utils/huge/README.md index 1f8e8a6..c79ece4 100644 --- a/utils/huge/README.md +++ b/utils/huge/README.md @@ -62,61 +62,124 @@ ```go type Float big.Float ``` + + #### func (*Float) Copy() *Float + *** + + #### func (*Float) Set(i *Float) *Float + *** + + #### func (*Float) IsZero() bool + *** + + #### func (*Float) ToBigFloat() *big.Float + *** + + #### func (*Float) Cmp(i *Float) int > 比较,当 slf > i 时返回 1,当 slf < i 时返回 -1,当 slf == i 时返回 0 + *** + + #### func (*Float) GreaterThan(i *Float) bool > 大于 + *** + + #### func (*Float) GreaterThanOrEqualTo(i *Float) bool > 大于或等于 + *** + + #### func (*Float) LessThan(i *Float) bool > 小于 + *** + + #### func (*Float) LessThanOrEqualTo(i *Float) bool > 小于或等于 + *** + + #### func (*Float) EqualTo(i *Float) bool > 等于 + *** + + #### func (*Float) Float64() float64 + *** + + #### func (*Float) String() string + *** + + #### func (*Float) Add(i *Float) *Float + *** + + #### func (*Float) Sub(i *Float) *Float + *** + + #### func (*Float) Mul(i *Float) *Float + *** + + #### func (*Float) Div(i *Float) *Float + *** + + #### func (*Float) Sqrt() *Float > 平方根 + *** + + #### func (*Float) Abs() *Float > 返回数字的绝对值 + *** + + #### func (*Float) Sign() int > 返回数字的符号 > - 1:正数 > - 0:零 > - -1:负数 + *** + + #### func (*Float) IsPositive() bool > 是否为正数 + *** + + #### func (*Float) IsNegative() bool > 是否为负数 + *** ### Int `STRUCT` @@ -124,258 +187,591 @@ type Float big.Float ```go type Int big.Int ``` + + #### func (*Int) Copy() *Int + *** + + #### func (*Int) Set(i *Int) *Int + *** + + #### func (*Int) SetInt(i int) *Int + *** + + #### func (*Int) SetInt8(i int8) *Int + *** + + #### func (*Int) SetInt16(i int16) *Int + *** + + #### func (*Int) SetInt32(i int32) *Int + *** + + #### func (*Int) SetInt64(i int64) *Int + *** + + #### func (*Int) SetUint(i uint) *Int + *** + + #### func (*Int) SetUint8(i uint8) *Int + *** + + #### func (*Int) SetUint16(i uint16) *Int + *** + + #### func (*Int) SetUint32(i uint32) *Int + *** + + #### func (*Int) SetUint64(i uint64) *Int + *** + + #### func (*Int) IsZero() bool + *** + + #### func (*Int) ToBigint() *big.Int + *** + + #### func (*Int) Cmp(i *Int) int > 比较,当 slf > i 时返回 1,当 slf < i 时返回 -1,当 slf == i 时返回 0 + *** + + #### func (*Int) GreaterThan(i *Int) bool > 大于 + *** + + #### func (*Int) GreaterThanOrEqualTo(i *Int) bool > 大于或等于 + *** + + #### func (*Int) LessThan(i *Int) bool > 小于 + *** + + #### func (*Int) LessThanOrEqualTo(i *Int) bool > 小于或等于 + *** + + #### func (*Int) EqualTo(i *Int) bool > 等于 + *** + + #### func (*Int) Int64() int64 + *** + + #### func (*Int) String() string + *** + + #### func (*Int) Add(i *Int) *Int + *** + + #### func (*Int) AddInt(i int) *Int + *** + + #### func (*Int) AddInt8(i int8) *Int + *** + + #### func (*Int) AddInt16(i int16) *Int + *** + + #### func (*Int) AddInt32(i int32) *Int + *** + + #### func (*Int) AddInt64(i int64) *Int + *** + + #### func (*Int) AddUint(i uint) *Int + *** + + #### func (*Int) AddUint8(i uint8) *Int + *** + + #### func (*Int) AddUint16(i uint16) *Int + *** + + #### func (*Int) AddUint32(i uint32) *Int + *** + + #### func (*Int) AddUint64(i uint64) *Int + *** + + #### func (*Int) Mul(i *Int) *Int + *** + + #### func (*Int) MulInt(i int) *Int + *** + + #### func (*Int) MulInt8(i int8) *Int + *** + + #### func (*Int) MulInt16(i int16) *Int + *** + + #### func (*Int) MulInt32(i int32) *Int + *** + + #### func (*Int) MulInt64(i int64) *Int + *** + + #### func (*Int) MulUint(i uint) *Int + *** + + #### func (*Int) MulUint8(i uint8) *Int + *** + + #### func (*Int) MulUint16(i uint16) *Int + *** + + #### func (*Int) MulUint32(i uint32) *Int + *** + + #### func (*Int) MulUint64(i uint64) *Int + *** + + #### func (*Int) Sub(i *Int) *Int + *** + + #### func (*Int) SubInt(i int) *Int + *** + + #### func (*Int) SubInt8(i int8) *Int + *** + + #### func (*Int) SubInt16(i int16) *Int + *** + + #### func (*Int) SubInt32(i int32) *Int + *** + + #### func (*Int) SubInt64(i int64) *Int + *** + + #### func (*Int) SubUint(i uint) *Int + *** + + #### func (*Int) SubUint8(i uint8) *Int + *** + + #### func (*Int) SubUint16(i uint16) *Int + *** + + #### func (*Int) SubUint32(i uint32) *Int + *** + + #### func (*Int) SubUint64(i uint64) *Int + *** + + #### func (*Int) Div(i *Int) *Int + *** + + #### func (*Int) DivInt(i int) *Int + *** + + #### func (*Int) DivInt8(i int8) *Int + *** + + #### func (*Int) DivInt16(i int16) *Int + *** + + #### func (*Int) DivInt32(i int32) *Int + *** + + #### func (*Int) DivInt64(i int64) *Int + *** + + #### func (*Int) DivUint(i uint) *Int + *** + + #### func (*Int) DivUint8(i uint8) *Int + *** + + #### func (*Int) DivUint16(i uint16) *Int + *** + + #### func (*Int) DivUint32(i uint32) *Int + *** + + #### func (*Int) DivUint64(i uint64) *Int + *** + + #### func (*Int) Mod(i *Int) *Int + *** + + #### func (*Int) ModInt(i int) *Int + *** + + #### func (*Int) ModInt8(i int8) *Int + *** + + #### func (*Int) ModInt16(i int16) *Int + *** + + #### func (*Int) ModInt32(i int32) *Int + *** + + #### func (*Int) ModInt64(i int64) *Int + *** + + #### func (*Int) ModUint(i uint) *Int + *** + + #### func (*Int) ModUint8(i uint8) *Int + *** + + #### func (*Int) ModUint16(i uint16) *Int + *** + + #### func (*Int) ModUint32(i uint32) *Int + *** + + #### func (*Int) ModUint64(i uint64) *Int + *** + + #### func (*Int) Pow(i *Int) *Int + *** + + #### func (*Int) PowInt(i int) *Int + *** + + #### func (*Int) PowInt8(i int8) *Int + *** + + #### func (*Int) PowInt16(i int16) *Int + *** + + #### func (*Int) PowInt32(i int32) *Int + *** + + #### func (*Int) PowInt64(i int64) *Int + *** + + #### func (*Int) PowUint(i uint) *Int + *** + + #### func (*Int) PowUint8(i uint8) *Int + *** + + #### func (*Int) PowUint16(i uint16) *Int + *** + + #### func (*Int) PowUint32(i uint32) *Int + *** + + #### func (*Int) PowUint64(i uint64) *Int + *** + + #### func (*Int) Lsh(i int) *Int > 左移 + *** + + #### func (*Int) Rsh(i int) *Int > 右移 + *** + + #### func (*Int) And(i *Int) *Int > 与 + *** + + #### func (*Int) AndNot(i *Int) *Int > 与非 + *** + + #### func (*Int) Or(i *Int) *Int > 或 + *** + + #### func (*Int) Xor(i *Int) *Int > 异或 + *** + + #### func (*Int) Not() *Int > 非 + *** + + #### func (*Int) Sqrt() *Int > 平方根 + *** + + #### func (*Int) GCD(i *Int) *Int > 最大公约数 + *** + + #### func (*Int) LCM(i *Int) *Int > 最小公倍数 + *** + + #### func (*Int) ModInverse(i *Int) *Int > 模反元素 + *** + + #### func (*Int) ModSqrt(i *Int) *Int > 模平方根 + *** + + #### func (*Int) BitLen() int > 二进制长度 + *** + + #### func (*Int) Bit(i int) uint > 二进制位 + *** + + #### func (*Int) SetBit(i int, v uint) *Int > 设置二进制位 + *** + + #### func (*Int) Neg() *Int > 返回数字的相反数 + *** + + #### func (*Int) Abs() *Int > 返回数字的绝对值 + *** + + #### func (*Int) Sign() int > 返回数字的符号 > - 1:正数 > - 0:零 > - -1:负数 + *** + + #### func (*Int) IsPositive() bool > 是否为正数 + *** + + #### func (*Int) IsNegative() bool > 是否为负数 + *** + + #### func (*Int) IsEven() bool > 是否为偶数 + *** + + #### func (*Int) IsOdd() bool > 是否为奇数 + *** + + #### func (*Int) ProportionalCalc(proportional *Int, formula func (v *Int) *Int) *Int > 比例计算,该函数会再 formula 返回值的基础上除以 proportional > - formula 为计算公式,该公式的参数为调用该函数的 Int 的拷贝 + *** diff --git a/utils/leaderboard/README.md b/utils/leaderboard/README.md index 2d8b992..1576b6c 100644 --- a/utils/leaderboard/README.md +++ b/utils/leaderboard/README.md @@ -76,9 +76,12 @@ type BinarySearch[CompetitorID comparable, Score generic.Ordered] struct { rankClearBeforeEventHandles []BinarySearchRankClearBeforeEventHandle[CompetitorID, Score] } ``` + + #### func (*BinarySearch) Competitor(competitorId CompetitorID, score Score) > 声明排行榜竞争者 > - 如果竞争者存在的情况下,会更新已有成绩,否则新增竞争者 + **示例代码:** ```go @@ -97,8 +100,11 @@ func ExampleBinarySearch_Competitor() { ``` *** + + #### func (*BinarySearch) RemoveCompetitor(competitorId CompetitorID) > 删除特定竞争者 + **示例代码:** ```go @@ -118,16 +124,25 @@ func ExampleBinarySearch_RemoveCompetitor() { ``` *** + + #### func (*BinarySearch) Size() int > 获取竞争者数量 + *** + + #### func (*BinarySearch) GetRankDefault(competitorId CompetitorID, defaultValue int) int > 获取竞争者排名,如果竞争者不存在则返回默认值 > - 排名从 0 开始 + *** + + #### func (*BinarySearch) GetRank(competitorId CompetitorID) ( int, error) > 获取竞争者排名 > - 排名从 0 开始 + **示例代码:** ```go @@ -144,38 +159,77 @@ func ExampleBinarySearch_GetRank() { ``` *** + + #### func (*BinarySearch) GetCompetitor(rank int) (competitorId CompetitorID, err error) > 获取特定排名的竞争者 + *** + + #### func (*BinarySearch) GetCompetitorWithRange(start int, end int) ( []CompetitorID, error) > 获取第start名到第end名竞争者 + *** + + #### func (*BinarySearch) GetScore(competitorId CompetitorID) (score Score, err error) > 获取竞争者成绩 + *** + + #### func (*BinarySearch) GetScoreDefault(competitorId CompetitorID, defaultValue Score) Score > 获取竞争者成绩,不存在时返回默认值 + *** + + #### func (*BinarySearch) GetAllCompetitor() []CompetitorID > 获取所有竞争者ID > - 结果为名次有序的 + *** + + #### func (*BinarySearch) Clear() > 清空排行榜 + *** + + #### func (*BinarySearch) Cmp(s1 Score, s2 Score) int + *** + + #### func (*BinarySearch) UnmarshalJSON(bytes []byte) error + *** + + #### func (*BinarySearch) MarshalJSON() ( []byte, error) + *** + + #### func (*BinarySearch) RegRankChangeEvent(handle BinarySearchRankChangeEventHandle[CompetitorID, Score]) + *** + + #### func (*BinarySearch) OnRankChangeEvent(competitorId CompetitorID, oldRank int, newRank int, oldScore Score, newScore Score) + *** + + #### func (*BinarySearch) RegRankClearBeforeEvent(handle BinarySearchRankClearBeforeEventHandle[CompetitorID, Score]) + *** + + #### func (*BinarySearch) OnRankClearBeforeEvent() + *** ### BinarySearchRankChangeEventHandle `STRUCT` diff --git a/utils/log/README.md b/utils/log/README.md index 16682a5..a743124 100644 --- a/utils/log/README.md +++ b/utils/log/README.md @@ -415,13 +415,25 @@ type MultiHandler struct { handlers []slog.Handler } ``` + + #### func (MultiHandler) Enabled(ctx context.Context, level slog.Level) bool + *** + + #### func (MultiHandler) Handle(ctx context.Context, record slog.Record) (err error) + *** + + #### func (MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler + *** + + #### func (MultiHandler) WithGroup(name string) slog.Handler + *** ### Option `STRUCT` diff --git a/utils/log/survey/README.md b/utils/log/survey/README.md index f852995..18084d7 100644 --- a/utils/log/survey/README.md +++ b/utils/log/survey/README.md @@ -166,32 +166,58 @@ type Analyzer struct { m sync.Mutex } ``` + + #### func (*Analyzer) Sub(key string) *Analyzer > 获取子分析器 + *** + + #### func (*Analyzer) SetFormat(key string, format func (v any) any) > 设置格式化函数 + *** + + #### func (*Analyzer) SetValueIfGreaterThan(key string, value float64) > 设置指定 key 的值,当新值大于旧值时 > - 当已有值不为 float64 时,将会被忽略 + *** + + #### func (*Analyzer) SetValueIfLessThan(key string, value float64) > 设置指定 key 的值,当新值小于旧值时 > - 当已有值不为 float64 时,将会被忽略 + *** + + #### func (*Analyzer) SetValueIf(key string, expression bool, value float64) > 当表达式满足的时候将设置指定 key 的值为 value + *** + + #### func (*Analyzer) SetValueStringIf(key string, expression bool, value string) > 当表达式满足的时候将设置指定 key 的值为 value + *** + + #### func (*Analyzer) SetValue(key string, value float64) > 设置指定 key 的值 + *** + + #### func (*Analyzer) SetValueString(key string, value string) > 设置指定 key 的值 + *** + + #### func (*Analyzer) Increase(key string, record R, recordKey string) > 在指定 key 现有值的基础上增加 recordKey 的值 > - 当分析器已经记录过相同 key 的值时,会根据已有的值类型进行不同处理 @@ -199,21 +225,37 @@ type Analyzer struct { > 处理方式: > - 当已有值类型为 string 时,将会使用新的值的 string 类型进行覆盖 > - 当已有值类型为 float64 时,当新的值类型不为 float64 时,将会被忽略 + *** + + #### func (*Analyzer) IncreaseValue(key string, value float64) > 在指定 key 现有值的基础上增加 value + *** + + #### func (*Analyzer) IncreaseNonRepeat(key string, record R, recordKey string, dimension ...string) > 在指定 key 现有值的基础上增加 recordKey 的值,但是当去重维度 dimension 相同时,不会增加 + *** + + #### func (*Analyzer) IncreaseValueNonRepeat(key string, record R, value float64, dimension ...string) > 在指定 key 现有值的基础上增加 value,但是当去重维度 dimension 相同时,不会增加 + *** + + #### func (*Analyzer) GetValue(key string) float64 > 获取当前记录的值 + *** + + #### func (*Analyzer) GetValueString(key string) string > 获取当前记录的值 + *** ### Flusher `INTERFACE` @@ -236,9 +278,15 @@ type FileFlusher struct { layoutLen int } ``` + + #### func (*FileFlusher) Flush(records []string) + *** + + #### func (*FileFlusher) Info() string + *** ### Option `STRUCT` @@ -258,33 +306,60 @@ type Result gjson.Result ```go type R string ``` + + #### func (R) GetTime(layout string) time.Time > 获取该记录的时间 + *** + + #### func (R) Get(key string) Result > 获取指定 key 的值 > - 当 key 为嵌套 key 时,使用 . 进行分割,例如:a.b.c > - 更多用法参考:https://github.com/tidwall/gjson + *** + + #### func (R) Exist(key string) bool > 判断指定 key 是否存在 + *** + + #### func (R) GetString(key string) string > 该函数为 Get(key).String() 的简写 + *** + + #### func (R) GetInt64(key string) int64 > 该函数为 Get(key).Int() 的简写 + *** + + #### func (R) GetInt(key string) int > 该函数为 Get(key).Int() 的简写,但是返回值为 int 类型 + *** + + #### func (R) GetFloat64(key string) float64 > 该函数为 Get(key).Float() 的简写 + *** + + #### func (R) GetBool(key string) bool > 该函数为 Get(key).Bool() 的简写 + *** + + #### func (R) String() string + *** ### Report `STRUCT` @@ -298,26 +373,50 @@ type Report struct { Subs []*Report } ``` + + #### func (*Report) Avg(key string) float64 > 计算平均值 + *** + + #### func (*Report) Count(key string) int64 > 获取特定 key 的计数次数 + *** + + #### func (*Report) Sum(keys ...string) float64 > 获取特定 key 的总和 + *** + + #### func (*Report) Sub(name string) *Report > 获取特定名称的子报告 + *** + + #### func (*Report) ReserveSubByPrefix(prefix string) *Report > 仅保留特定前缀的子报告 + *** + + #### func (*Report) ReserveSub(names ...string) *Report > 仅保留特定名称子报告 + *** + + #### func (*Report) FilterSub(names ...string) *Report > 将特定名称的子报告过滤掉 + *** + + #### func (*Report) String() string + *** diff --git a/utils/memory/README.md b/utils/memory/README.md index 81e1057..4410a5e 100644 --- a/utils/memory/README.md +++ b/utils/memory/README.md @@ -107,10 +107,13 @@ type Option struct { delay time.Duration } ``` + + #### func (*Option) WithPeriodicity(ticker *timer.Ticker, firstDelay time.Duration, interval time.Duration, delay time.Duration) *Option > 设置持久化周期 > - ticker 定时器,通常建议使用服务器的定时器,这样可以降低多线程的程序复杂性 > - firstDelay 首次持久化延迟,当首次持久化为 0 时,将会在下一个持久化周期开始时持久化 > - interval 持久化间隔 > - delay 每条数据持久化间隔,适当的设置该值可以使持久化期间尽量降低对用户体验的影响,如果为0,将会一次性持久化所有数据 + *** diff --git a/utils/moving/README.md b/utils/moving/README.md index 6606faf..48538d6 100644 --- a/utils/moving/README.md +++ b/utils/moving/README.md @@ -115,8 +115,11 @@ type TwoDimensional[EID generic.Basic, PosType generic.SignedNumber] struct { position2DStopMoveEventHandles []Position2DStopMoveEventHandle[EID, PosType] } ``` + + #### func (*TwoDimensional) MoveTo(entity TwoDimensionalEntity[EID, PosType], x PosType, y PosType) > 设置对象移动到特定位置 + **示例代码:** ```go @@ -140,8 +143,11 @@ func ExampleTwoDimensional_MoveTo() { ``` *** + + #### func (*TwoDimensional) StopMove(id EID) > 停止特定对象的移动 + **示例代码:** ```go @@ -215,23 +221,44 @@ func TestTwoDimensional_StopMove(t *testing.T) { *** + + #### func (*TwoDimensional) RegPosition2DChangeEvent(handle Position2DChangeEventHandle[EID, PosType]) > 在对象位置改变时将执行注册的事件处理函数 + *** + + #### func (*TwoDimensional) OnPosition2DChangeEvent(entity TwoDimensionalEntity[EID, PosType], oldX PosType, oldY PosType) + *** + + #### func (*TwoDimensional) RegPosition2DDestinationEvent(handle Position2DDestinationEventHandle[EID, PosType]) > 在对象到达终点时将执行被注册的事件处理函数 + *** + + #### func (*TwoDimensional) OnPosition2DDestinationEvent(entity TwoDimensionalEntity[EID, PosType]) + *** + + #### func (*TwoDimensional) RegPosition2DStopMoveEvent(handle Position2DStopMoveEventHandle[EID, PosType]) > 在对象停止移动时将执行被注册的事件处理函数 + *** + + #### func (*TwoDimensional) OnPosition2DStopMoveEvent(entity TwoDimensionalEntity[EID, PosType]) + *** + + #### func (*TwoDimensional) Release() > 释放对象移动对象所占用的资源 + *** ### TwoDimensionalEntity `INTERFACE` diff --git a/utils/offset/README.md b/utils/offset/README.md index 4c11c00..a25117d 100644 --- a/utils/offset/README.md +++ b/utils/offset/README.md @@ -67,12 +67,21 @@ type Time struct { offset time.Duration } ``` + + #### func (*Time) SetOffset(offset time.Duration) > 设置时间偏移 + *** + + #### func (*Time) Now() time.Time > 获取当前时间偏移后的时间 + *** + + #### func (*Time) Since(t time.Time) time.Duration > 获取当前时间偏移后的时间自从 t 以来经过的时间 + *** diff --git a/utils/random/README.md b/utils/random/README.md index ee9e3a9..d4e92fc 100644 --- a/utils/random/README.md +++ b/utils/random/README.md @@ -20,6 +20,7 @@ |[DiceN](#DiceN)|掷骰子 |[NetIP](#NetIP)|返回一个随机的IP地址 |[Port](#Port)|返回一个随机的端口号 +|[UsablePort](#UsablePort)|随机返回一个可用的端口号,如果没有可用端口号则返回 -1 |[IPv4](#IPv4)|返回一个随机产生的IPv4地址。 |[IPv4Port](#IPv4Port)|返回一个随机产生的IPv4地址和端口。 |[Int64](#Int64)|返回一个介于min和max之间的int64类型的随机数。 @@ -73,6 +74,11 @@ > 返回一个随机的端口号 +*** +#### func UsablePort() int + +> 随机返回一个可用的端口号,如果没有可用端口号则返回 -1 + *** #### func IPv4() string diff --git a/utils/sole/README.md b/utils/sole/README.md index 040be62..0bfd023 100644 --- a/utils/sole/README.md +++ b/utils/sole/README.md @@ -133,9 +133,15 @@ type Once[V any] struct { r map[any]struct{} } ``` + + #### func (*Once) Get(key any, value V, defaultValue V) V > 获取一个值,当该值已经被获取过的时候,返回 defaultValue,否则返回 value + *** + + #### func (*Once) Reset(key ...any) > 当 key 数量大于 0 时,将会重置对应 key 的记录,否则重置所有记录 + *** diff --git a/utils/super/README.md b/utils/super/README.md index 90754cc..b0f1093 100644 --- a/utils/super/README.md +++ b/utils/super/README.md @@ -752,8 +752,11 @@ type BitSet[Bit generic.Integer] struct { set []uint64 } ``` + + #### func (*BitSet) Set(bit Bit) *BitSet[Bit] > 将指定的位 bit 设置为 1 +
查看 / 收起单元测试 @@ -775,8 +778,11 @@ func TestBitSet_Set(t *testing.T) { *** + + #### func (*BitSet) Del(bit Bit) *BitSet[Bit] > 将指定的位 bit 设置为 0 +
查看 / 收起单元测试 @@ -799,9 +805,12 @@ func TestBitSet_Del(t *testing.T) { *** + + #### func (*BitSet) Shrink() *BitSet[Bit] > 将 BitSet 中的比特位集合缩小到最小 > - 正常情况下当 BitSet 中的比特位超出 64 位时,将自动增长,当 BitSet 中的比特位数量减少时,可以使用该方法将 BitSet 中的比特位集合缩小到最小 +
查看 / 收起单元测试 @@ -825,92 +834,179 @@ func TestBitSet_Shrink(t *testing.T) { *** + + #### func (*BitSet) Cap() int > 返回当前 BitSet 中可以表示的最大比特位数量 + *** + + #### func (*BitSet) Has(bit Bit) bool > 检查指定的位 bit 是否被设置为 1 + *** + + #### func (*BitSet) Clear() *BitSet[Bit] > 清空所有的比特位 + *** + + #### func (*BitSet) Len() int > 返回当前 BitSet 中被设置的比特位数量 + *** + + #### func (*BitSet) Bits() []Bit > 返回当前 BitSet 中被设置的比特位 + *** + + #### func (*BitSet) Reverse() *BitSet[Bit] > 反转当前 BitSet 中的所有比特位 + *** + + #### func (*BitSet) Not() *BitSet[Bit] > 返回当前 BitSet 中所有比特位的反转 + *** + + #### func (*BitSet) And(other *BitSet[Bit]) *BitSet[Bit] > 将当前 BitSet 与另一个 BitSet 进行按位与运算 + *** + + #### func (*BitSet) Or(other *BitSet[Bit]) *BitSet[Bit] > 将当前 BitSet 与另一个 BitSet 进行按位或运算 + *** + + #### func (*BitSet) Xor(other *BitSet[Bit]) *BitSet[Bit] > 将当前 BitSet 与另一个 BitSet 进行按位异或运算 + *** + + #### func (*BitSet) Sub(other *BitSet[Bit]) *BitSet[Bit] > 将当前 BitSet 与另一个 BitSet 进行按位减运算 + *** + + #### func (*BitSet) IsZero() bool > 检查当前 BitSet 是否为空 + *** + + #### func (*BitSet) Clone() *BitSet[Bit] > 返回当前 BitSet 的副本 + *** + + #### func (*BitSet) Equal(other *BitSet[Bit]) bool > 检查当前 BitSet 是否与另一个 BitSet 相等 + *** + + #### func (*BitSet) Contains(other *BitSet[Bit]) bool > 检查当前 BitSet 是否包含另一个 BitSet + *** + + #### func (*BitSet) ContainsAny(other *BitSet[Bit]) bool > 检查当前 BitSet 是否包含另一个 BitSet 中的任意比特位 + *** + + #### func (*BitSet) ContainsAll(other *BitSet[Bit]) bool > 检查当前 BitSet 是否包含另一个 BitSet 中的所有比特位 + *** + + #### func (*BitSet) Intersect(other *BitSet[Bit]) bool > 检查当前 BitSet 是否与另一个 BitSet 有交集 + *** + + #### func (*BitSet) Union(other *BitSet[Bit]) bool > 检查当前 BitSet 是否与另一个 BitSet 有并集 + *** + + #### func (*BitSet) Difference(other *BitSet[Bit]) bool > 检查当前 BitSet 是否与另一个 BitSet 有差集 + *** + + #### func (*BitSet) SymmetricDifference(other *BitSet[Bit]) bool > 检查当前 BitSet 是否与另一个 BitSet 有对称差集 + *** + + #### func (*BitSet) Subset(other *BitSet[Bit]) bool > 检查当前 BitSet 是否为另一个 BitSet 的子集 + *** + + #### func (*BitSet) Superset(other *BitSet[Bit]) bool > 检查当前 BitSet 是否为另一个 BitSet 的超集 + *** + + #### func (*BitSet) Complement(other *BitSet[Bit]) bool > 检查当前 BitSet 是否为另一个 BitSet 的补集 + *** + + #### func (*BitSet) Max() Bit > 返回当前 BitSet 中最大的比特位 + *** + + #### func (*BitSet) Min() Bit > 返回当前 BitSet 中最小的比特位 + *** + + #### func (*BitSet) String() string > 返回当前 BitSet 的字符串表示 + *** + + #### func (*BitSet) MarshalJSON() ( []byte, error) > 实现 json.Marshaler 接口 + *** + + #### func (*BitSet) UnmarshalJSON(data []byte) error > 实现 json.Unmarshaler 接口 + *** ### LossCounter `STRUCT` @@ -922,13 +1018,22 @@ type LossCounter struct { lossKey []string } ``` + + #### func (*LossCounter) Record(name string) > 记录一次损耗 + *** + + #### func (*LossCounter) GetLoss(handler func (step int, name string, loss time.Duration)) > 获取损耗 + *** + + #### func (*LossCounter) String() string + *** ### Matcher `STRUCT` @@ -940,11 +1045,17 @@ type Matcher[Value any, Result any] struct { d bool } ``` + + #### func (*Matcher) Case(value Value, result Result) *Matcher[Value, Result] > 匹配 + *** + + #### func (*Matcher) Default(value Result) Result > 默认 + *** ### Permission `STRUCT` @@ -955,17 +1066,29 @@ type Permission[Code generic.Integer, EntityID comparable] struct { l sync.RWMutex } ``` + + #### func (*Permission) HasPermission(entityId EntityID, permission Code) bool > 是否有权限 + *** + + #### func (*Permission) AddPermission(entityId EntityID, permission ...Code) > 添加权限 + *** + + #### func (*Permission) RemovePermission(entityId EntityID, permission ...Code) > 移除权限 + *** + + #### func (*Permission) SetPermission(entityId EntityID, permission ...Code) > 设置权限 + *** ### StackGo `STRUCT` @@ -978,19 +1101,28 @@ type StackGo struct { collect chan []byte } ``` + + #### func (*StackGo) Wait() > 等待收集消息堆栈 > - 在调用 Wait 函数后,当前协程将会被挂起,直到调用 Stack 或 GiveUp 函数 + *** + + #### func (*StackGo) Stack() []byte > 获取消息堆栈 > - 在调用 Wait 函数后调用该函数,将会返回上一个协程的堆栈信息 > - 在调用 GiveUp 函数后调用该函数,将会 panic + *** + + #### func (*StackGo) GiveUp() > 放弃收集消息堆栈 > - 在调用 Wait 函数后调用该函数,将会放弃收集消息堆栈并且释放资源 > - 在调用 GiveUp 函数后调用 Stack 函数,将会 panic + *** ### VerifyHandle `STRUCT` @@ -1002,13 +1134,22 @@ type VerifyHandle[V any] struct { hit bool } ``` + + #### func (*VerifyHandle) PreCase(expression func () bool, value V, caseHandle func (verify *VerifyHandle[V]) bool) bool > 先决校验用例,当 expression 成立时,将跳过 caseHandle 的执行,直接执行 handle 并返回 false > - 常用于对前置参数的空指针校验,例如当 a 为 nil 时,不执行 a.B(),而是直接返回 false + *** + + #### func (*VerifyHandle) Case(expression bool, value V) *VerifyHandle[V] > 校验用例,当 expression 成立时,将忽略后续 Case,并将在 Do 时执行 handle,返回 false + *** + + #### func (*VerifyHandle) Do() bool > 执行校验,当校验失败时,将执行 handle,并返回 false + *** diff --git a/utils/timer/README.md b/utils/timer/README.md index ab9b2f2..38d3129 100644 --- a/utils/timer/README.md +++ b/utils/timer/README.md @@ -115,16 +115,25 @@ type Pool struct { closed bool } ``` + + #### func (*Pool) ChangePoolSize(size int) error > 改变定时器池大小 > - 当传入的大小小于或等于 0 时,将会返回错误,并且不会发生任何改变 + *** + + #### func (*Pool) GetTicker(size int, options ...Option) *Ticker > 获取一个新的定时器 + *** + + #### func (*Pool) Release() > 释放定时器池的资源,释放后由其产生的 Ticker 在 Ticker.Release 后将不再回到池中,而是直接释放 > - 虽然定时器池已被释放,但是依旧可以产出 Ticker + *** ### Scheduler `STRUCT` @@ -145,14 +154,23 @@ type Scheduler struct { expr *cronexpr.Expression } ``` + + #### func (*Scheduler) Name() string > 获取调度器名称 + *** + + #### func (*Scheduler) Next(prev time.Time) time.Time > 获取下一次执行的时间 + *** + + #### func (*Scheduler) Caller() > 可由外部发起调用的执行函数 + *** ### Ticker `STRUCT` @@ -167,24 +185,42 @@ type Ticker struct { mark string } ``` + + #### func (*Ticker) Mark() string > 获取定时器的标记 > - 通常用于鉴别定时器来源 + *** + + #### func (*Ticker) Release() > 释放定时器,并将定时器重新放回 Pool 池中 + *** + + #### func (*Ticker) StopTimer(name string) > 停止特定名称的调度器 + *** + + #### func (*Ticker) IsStopped(name string) bool > 特定名称的调度器是否已停止 + *** + + #### func (*Ticker) GetSchedulers() []string > 获取所有调度器名称 + *** + + #### func (*Ticker) Cron(name string, expression string, handleFunc interface {}, args ...interface {}) > 通过 cron 表达式设置一个调度器,当 cron 表达式错误时,将会引发 panic +
查看 / 收起单元测试 @@ -212,12 +248,21 @@ func TestTicker_Cron(t *testing.T) { *** + + #### func (*Ticker) CronByInstantly(name string, expression string, handleFunc interface {}, args ...interface {}) > 与 Cron 相同,但是会立即执行一次 + *** + + #### func (*Ticker) After(name string, after time.Duration, handleFunc interface {}, args ...interface {}) > 设置一个在特定时间后运行一次的调度器 + *** + + #### func (*Ticker) Loop(name string, after time.Duration, interval time.Duration, times int, handleFunc interface {}, args ...interface {}) > 设置一个在特定时间后反复运行的调度器 + *** diff --git a/utils/times/README.md b/utils/times/README.md index 091682e..90dc59c 100644 --- a/utils/times/README.md +++ b/utils/times/README.md @@ -410,6 +410,8 @@ type StateLine[State generic.Basic] struct { trigger [][]func() } ``` + + #### func (*StateLine) Check(missingAllowed bool, states ...State) bool > 根据状态顺序检查时间线是否合法 > - missingAllowed: 是否允许状态缺失,如果为 true,则状态可以不连续,如果为 false,则状态必须连续 @@ -417,76 +419,146 @@ type StateLine[State generic.Basic] struct { > 状态不连续表示时间线中存在状态缺失,例如: > - 状态为 [1, 2, 3, 4, 5] 的时间线,如果 missingAllowed 为 true,则状态为 [1, 3, 5] 也是合法的 > - 状态为 [1, 2, 3, 4, 5] 的时间线,如果 missingAllowed 为 false,则状态为 [1, 3, 5] 是不合法的 + *** + + #### func (*StateLine) GetMissingStates(states ...State) []State > 获取缺失的状态 + *** + + #### func (*StateLine) HasState(state State) bool > 检查时间线中是否包含指定状态 + *** + + #### func (*StateLine) String() string > 获取时间线的字符串表示 + *** + + #### func (*StateLine) AddState(state State, t time.Time, onTrigger ...func ()) *StateLine[State] > 添加一个状态到时间线中,状态不能与任一时间点重合,否则将被忽略 > - onTrigger: 该状态绑定的触发器,该触发器不会被主动执行,需要主动获取触发器执行 + *** + + #### func (*StateLine) GetTimeByState(state State) time.Time > 获取指定状态的时间点 + *** + + #### func (*StateLine) GetNextTimeByState(state State) time.Time > 获取指定状态的下一个时间点 + *** + + #### func (*StateLine) GetLastState() State > 获取最后一个状态 + *** + + #### func (*StateLine) GetPrevTimeByState(state State) time.Time > 获取指定状态的上一个时间点 + *** + + #### func (*StateLine) GetIndexByState(state State) int > 获取指定状态的索引 + *** + + #### func (*StateLine) GetStateByTime(t time.Time) State > 获取指定时间点的状态 + *** + + #### func (*StateLine) GetTimeByIndex(index int) time.Time > 获取指定索引的时间点 + *** + + #### func (*StateLine) Move(d time.Duration) *StateLine[State] > 时间线整体移动 + *** + + #### func (*StateLine) GetNextStateTimeByIndex(index int) time.Time > 获取指定索引的下一个时间点 + *** + + #### func (*StateLine) GetPrevStateTimeByIndex(index int) time.Time > 获取指定索引的上一个时间点 + *** + + #### func (*StateLine) GetStateIndexByTime(t time.Time) int > 获取指定时间点的索引 + *** + + #### func (*StateLine) GetStateCount() int > 获取状态数量 + *** + + #### func (*StateLine) GetStateByIndex(index int) State > 获取指定索引的状态 + *** + + #### func (*StateLine) GetTriggerByTime(t time.Time) []func () > 获取指定时间点的触发器 + *** + + #### func (*StateLine) GetTriggerByIndex(index int) []func () > 获取指定索引的触发器 + *** + + #### func (*StateLine) GetTriggerByState(state State) []func () > 获取指定状态的触发器 + *** + + #### func (*StateLine) AddTriggerToState(state State, onTrigger ...func ()) *StateLine[State] > 给指定状态添加触发器 + *** + + #### func (*StateLine) Range(handler func (index int, state State, t time.Time) bool) > 按照时间顺序遍历时间线 + *** + + #### func (*StateLine) RangeReverse(handler func (index int, state State, t time.Time) bool) > 按照时间逆序遍历时间线 + *** ### Period `STRUCT` @@ -494,61 +566,118 @@ type StateLine[State generic.Basic] struct { ```go type Period [2]time.Time ``` + + #### func (Period) Start() time.Time > 返回时间段的开始时间 + *** + + #### func (Period) End() time.Time > 返回时间段的结束时间 + *** + + #### func (Period) Duration() time.Duration > 返回时间段的持续时间 + *** + + #### func (Period) Day() int > 返回时间段的持续天数 + *** + + #### func (Period) Hour() int > 返回时间段的持续小时数 + *** + + #### func (Period) Minute() int > 返回时间段的持续分钟数 + *** + + #### func (Period) Seconds() int > 返回时间段的持续秒数 + *** + + #### func (Period) Milliseconds() int > 返回时间段的持续毫秒数 + *** + + #### func (Period) Microseconds() int > 返回时间段的持续微秒数 + *** + + #### func (Period) Nanoseconds() int > 返回时间段的持续纳秒数 + *** + + #### func (Period) IsZero() bool > 判断时间段是否为零值 + *** + + #### func (Period) IsInvalid() bool > 判断时间段是否无效 + *** + + #### func (Period) IsBefore(t time.Time) bool > 判断时间段是否在指定时间之前 + *** + + #### func (Period) IsAfter(t time.Time) bool > 判断时间段是否在指定时间之后 + *** + + #### func (Period) IsBetween(t time.Time) bool > 判断指定时间是否在时间段之间 + *** + + #### func (Period) IsOngoing(t time.Time) bool > 判断指定时间是否正在进行时 > - 如果时间段的开始时间在指定时间之前或者等于指定时间,且时间段的结束时间在指定时间之后,则返回 true + *** + + #### func (Period) IsBetweenOrEqual(t time.Time) bool > 判断指定时间是否在时间段之间或者等于时间段的开始或结束时间 + *** + + #### func (Period) IsBetweenOrEqualPeriod(t Period) bool > 判断指定时间是否在时间段之间或者等于时间段的开始或结束时间 + *** + + #### func (Period) IsOverlap(t Period) bool > 判断时间段是否与指定时间段重叠 + ***