Golang如何自动收集interface的所有实现并填充到slice中
方案1:init 函数全局注册(最常用,无额外依赖)
这是Go生态最通用的插件注册模式,无需硬编码切片,新增插件仅需补充注册逻辑,不需要修改主程序代码。
实现步骤
- 定义全局注册列表和注册函数
package main import "fmt" type Plugin interface { Run() bool } // 全局存储所有已注册的插件 var pluginRegistry []Plugin // 注册插件的公共方法,供插件实现侧调用 func RegisterPlugin(p Plugin) { pluginRegistry = append(pluginRegistry, p) }
- 每个插件实现侧添加init函数自动注册
// Plugin1 实现 type Plugin1 struct{} func (p Plugin1) Run() bool { fmt.Println("Plugin1::Run()") return true } // 包初始化时自动注册插件 func init() { RegisterPlugin(Plugin1{}) } // Plugin2 实现 type Plugin2 struct{} func (p Plugin2) Run() bool { fmt.Println("Plugin2::Run()") return true } func init() { RegisterPlugin(Plugin2{}) }
- 主程序直接使用注册列表,无需硬编码切片
func main() { for _, plugin := range pluginRegistry { plugin.Run() } }
方案2:代码自动生成
如果不想依赖init函数执行逻辑,可以通过go generate实现静态生成切片:
- 编写小工具扫描当前项目下所有实现了
Plugin接口的结构体 - 工具自动生成
plugins_gen.go文件,内容为自动拼接的插件切片定义 - 在代码中添加
//go:generate go run 你的生成工具路径注释,每次新增插件后执行go generate即可自动更新切片
方案3:动态加载插件
如果需要插件独立于主程序编译、支持热插拔,可以使用Go标准库的plugin包:
- 每个插件单独编译为
.so动态链接库 - 主程序启动时扫描指定目录下的所有
.so文件,动态加载后查找导出的插件实例,转为Plugin接口加入调用列表 - 注意:
plugin包仅支持Unix-like系统,且主程序和插件的编译环境、依赖版本必须完全一致,否则会加载失败。
内容的提问来源于stack exchange,提问作者daisy
相关产品推荐
相关产品推荐

