Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(instance): migrate instance containers to type-safe generics#4617

Merged
hailaz merged 11 commits intogogf:masterfrom
LanceAdd:fix/instances
Jan 16, 2026
Merged

feat(instance): migrate instance containers to type-safe generics#4617
hailaz merged 11 commits intogogf:masterfrom
LanceAdd:fix/instances

Conversation

@LanceAdd
Copy link
Member

@LanceAdd LanceAdd commented Jan 16, 2026

变更说明

本次重构将项目中用于实例管理的容器StrAnyMap/IntAnyMap 迁移到类型安全的泛型实现 KVMapWithChecker,同时将相关的 glist.Listgqueue.Queue 替换为对应的泛型版本,以提高实例管理的类型安全性。并且减少原先代码中的大量类型断言,提高性能。

前因

目前goframe中大量使用了包含any的容器,然后通过断言去转换类型,麻烦且影响性能,尤其是对gdb/gredis/glog等需要高频获取instance实例的组件影响较大。最近几个版本中gf完成了数据结构容器的泛型化改造,以及我最近解决了其中几个泛型容器对于typed nil过滤的问题,所以可以逐步迁移这些实例容器到泛型容器,减少断言优化性能

主要改进

1. 实例容器泛型化

以下模块的实例管理容器已迁移到泛型实现:

核心实例管理:

  • database/gdb: 数据库实例容器 → KVMap[string, DB]
  • database/gredis: Redis 实例容器 → KVMap[string, *Redis]
  • database/gredis: Redis 配置容器 → KVMap[string, *Config]
  • os/gcfg: 配置实例容器 → KVMap[string, *Config]
  • os/glog: 日志实例容器 → KVMap[string, *Logger]
  • os/gview: 视图实例容器 → KVMap[string, *View]
  • i18n/gi18n: 国际化实例容器 → KVMap[string, *Manager]

网络服务实例:

  • net/ghttp: HTTP 服务器容器 → KVMap[string, *Server]
  • net/gtcp: TCP 服务器容器 → KVMap[any, *Server]
  • net/gudp: UDP 服务器容器 → KVMap[string, *Server]

其他实例容器:

  • os/gres: 资源实例容器 → KVMap[string, *Resource]
  • os/gfpool: 文件池容器 → KVMap[string, *Pool]
  • os/gspath: 路径搜索容器 → KVMap[string, *SPath]
  • net/gtcp: 连接池容器 → KVMap[string, *gpool.Pool]

2. 相关数据结构泛型化

  • os/gfsnotify: 回调列表 → TList[*Callback],事件队列 → TQueue[*Event]
  • os/grpool: 任务队列 → TList[*localPoolItem]
  • os/gcache: 事件队列 → TList[*adapterMemoryEvent]
  • net/ghttp: 解析项列表 → TList[*HandlerItemParsed]
  • os/gproc: 消息队列 → TQueue[*MsgRequest]
  • os/gmlock: 锁映射 → KVMap[string, *sync.RWMutex]

技术实现

  1. 引入检查器函数: 为每个实例容器添加 checker 函数用于空值检测
  2. 消除类型断言: 实例获取时无需 v.(*Type) 转换
  3. 明确函数签名: GetOrSetFuncLock 的回调从 func() any 改为 func() T

使用示例

实例容器的变更

变更前:

// 旧的实例管理方式
var instances = gmap.NewStrAnyMap(true)

func Instance(name string) *Logger {
    v := instances.GetOrSetFuncLock(name, func() any {
        return New()
    })
    return v.(*Logger)  // 需要类型断言
}

变更后:

// 新的泛型实例容器
var (
    checker   = func(v *Logger) bool { return v == nil }
    instances = gmap.NewKVMapWithChecker[string, *Logger](checker, true)
)

func Instance(name string) *Logger {
    return instances.GetOrSetFuncLock(name, New)  // 直接返回,无需断言
}

队列容器的变更

变更前:

// 旧的队列方式
events := gqueue.New()
events.Push(&Event{Path: "/tmp/file"})

if v := events.Pop(); v != nil {
    event := v.(*Event)  // 需要类型断言
    handleEvent(event)
}

变更后:

// 新的泛型队列
events := gqueue.NewTQueue[*Event]()
events.Push(&Event{Path: "/tmp/file"})

if event := events.Pop(); event != nil {
    handleEvent(event)  // event 已是 *Event 类型
}

收益

  • 编译时类型安全: 实例容器的类型错误在编译期捕获
  • 消除运行时断言: 避免类型断言带来的 panic 风险
  • 提升代码可读性: 实例管理逻辑更清晰
  • 改善开发体验: IDE 类型提示和代码补全更准确

性能权衡

编译时:

  • 泛型实例化会增加编译时间和二进制体积
  • 预估编译时间增加 5-15%,二进制体积增加约 1-2MB

运行时:

  • 减少类型断言的反射开销
  • 提升实例获取等热点路径的性能

- 将数据库实例管理从泛型 map 替换为类型安全的 KVMapWithChecker
- 为 Redis 实例管理引入检查器函数确保空值验证
- 更新配置模块的实例存储以提高类型转换安全性
- 简化日志和视图模块的实例获取逻辑
- 移除不必要的类型断言操作
- 统一各模块实例创建的返回值处理方式
- 将 serverMapping 从 StrAnyMap 改为泛型 KVMapWithChecker
- 添加 nil 检查器函数用于类型安全的值验证
- 统一各网络协议服务器的实例获取逻辑
- 简化 GetOrSetFuncLock 的返回值类型转换
- 移除不必要的类型断言操作
- 在 gredis 配置管理中使用 KVMapWithChecker 替代 StrAnyMap
- 在 i18n 实例管理中使用 KVMapWithChecker 替代 StrAnyMap
- 在 tcp 连接池中使用 KVMapWithChecker 替代 StrAnyMap
- 在文件指针池中使用 KVMapWithChecker 替代 StrAnyMap
- 在进程通信中使用 KVMapWithChecker 和 TQueue 替代原始队列
- 移除不必要的类型断言操作提高代码安全性
- 添加配置检查器函数确保 nil 值检测机制
- 将 gqueue.Queue 替换为泛型队列 gqueue.TQueue[*Event]
- 将 gmap.StrAnyMap 回调映射替换为类型安全的 KVMap[string, *glist.List]
- 添加 nil 检查器函数用于缓存管理
- 移除不必要的类型断言操作提高运行时性能
- 更新 Locker 结构体使用泛型映射类型
- 在 gview 模块中应用相同的类型安全改进
- 简化事件循环中的类型转换逻辑
- 将 lastMiddlewareElem 类型从 *glist.Element 更新为 *glist.TElement[*HandlerItemParsed]
- 将 parsedItemList 类型从 glist.New() 更新为 glist.NewT[*HandlerItemParsed]()
- 移除了类型断言 e.Value.(*HandlerItemParsed),直接使用 e.Value

refactor(gcache): 更新缓存适配器中的泛型类型定义

- 将 eventList 类型从 *glist.List 更新为 *glist.TList[*adapterMemoryEvent]
- 将 eventList 初始化从 glist.New(true) 更新为 glist.NewT[*adapterMemoryEvent](true)
- 移除了类型断言 v.(*adapterMemoryEvent),直接使用 PopFront() 返回值
- 删除了未使用的 event 变量声明
- 将 glist.List 替换为类型安全的 glist.TList[*Callback]
- 修改 Watcher 结构体中的 callbacks 字段类型定义
- 更新 Callback 结构体中的 elem 字段类型为 glist.TElement[*Callback]
- 重构全局变量 callbackIdMap 使用 KVMapWithChecker 泛型实现
- 简化回调函数查找逻辑,移除冗余的类型断言操作
- 更新 grpool 包中的列表实现为类型安全的 TList[*localPoolItem]
- 将 gmap.Map 替换为类型安全的 gmap.KVMap[any, *glist.Element]
- 使用 NewKVMapWithChecker 创建带检查器的映射以提高类型安全
- 简化了值转换逻辑,移除了不必要的类型断言
- 添加了空值检查函数用于验证元素有效性
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request migrates instance management containers across the GoFrame codebase from non-generic maps (StrAnyMap/IntAnyMap) to type-safe generic implementations (KVMapWithChecker). The refactoring also updates related data structures like glist.List and gqueue.Queue to their generic typed variants (TList, TQueue).

Changes:

  • Replaced instance containers in 15+ modules with type-safe generics to eliminate runtime type assertions
  • Migrated internal data structures (lists, queues) to generic versions for better type safety
  • Added checker functions to each module to validate nil values for generic containers

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
database/gdb/gdb.go Migrated DB instance container to KVMap[string, DB] with type-safe generics
database/gredis/gredis_instance.go Migrated Redis instance container to KVMap[string, *Redis]
database/gredis/gredis_config.go Migrated Redis config container to KVMap[string, *Config]
os/gcfg/*.go Migrated config instance containers and updated test infrastructure
os/glog/glog_instance.go Migrated logger instance container to type-safe generics
os/gview/*.go Migrated view and file cache containers to generic implementations
os/gres/gres_instance.go Migrated resource instance container to generics
os/gspath/gspath.go Migrated path search container to type-safe generics
os/gfpool/*.go Migrated file pool containers to generic implementation
os/gmlock/gmlock_locker.go Migrated lock mapping to KVMap[string, *sync.RWMutex]
os/gfsnotify/*.go Migrated callback lists to TList[*Callback] and event queues to TQueue[*Event]
os/grpool/*.go Migrated task queues to TList[*localPoolItem]
os/gcache/*.go Migrated event lists to TList[*adapterMemoryEvent] and LRU data to generic maps
os/gproc/*.go Migrated message queues to TQueue[*MsgRequest]
net/ghttp/*.go Migrated HTTP server containers and handler item lists to generics
net/gtcp/*.go Migrated TCP server mapping and connection pools to generics
net/gudp/gudp_server.go Migrated UDP server container to type-safe generics
i18n/gi18n/gi18n_instance.go Migrated i18n manager instance container to generics

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@hailaz hailaz changed the title fix(instance): migrate instance containers to type-safe generics feat(instance): migrate instance containers to type-safe generics Jan 16, 2026
@hailaz hailaz merged commit d8a173d into gogf:master Jan 16, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants