Golang中如何动态选择接口的实现?
在Go中动态选择接口实现的方案
当然可以实现动态选择接口的实现,核心思路是用注册表模式,通过一个映射表存储运算符与对应operation实现的关联,后续扩展新运算符时仅需新增实现并注册即可,无需修改原有逻辑。
具体实现步骤
定义全局注册表
用一个map来保存运算符到operation实例的映射:import "fmt" var ErrDivisionByZero = fmt.Errorf("division by zero") type operation interface { do(operand1, operand2 int) (int, error) } // 全局注册表:运算符 -> 对应的operation实现 var operationRegistry = make(map[byte]operation)实现注册函数
提供一个注册函数,用于将新的运算符实现加入注册表:func RegisterOperation(op byte, opImpl operation) { operationRegistry[op] = opImpl }注册现有运算符实现
在init函数中完成现有运算符的注册(每个实现结构体只需注册一次):type sum struct { operator byte } func (s sum) do(operand1, operand2 int) (int, error) { return operand1 + operand2, nil } type subtract struct { operator byte } func (s subtract) do(operand1, operand2 int) (int, error) { return operand1 - operand2, nil } type multiplication struct { operator byte } func (s multiplication) do(operand1, operand2 int) (int, error) { return operand1 * operand2, nil } type division struct { operator byte } func (s division) do(operand1, operand2 int) (int, error) { if operand2 == 0 { return 0, ErrDivisionByZero } return operand1 / operand2, nil } type power struct { operator byte } func (s power) do(operand1, operand2 int) (int, error) { // 注意:原代码中^是按位异或,若需数学幂运算需替换为自定义实现或math.Pow // 示例幂运算实现(仅支持正整数指数): // result := 1 // for i := 0; i < operand2; i++ { // result *= operand1 // } // return result, nil return operand1 ^ operand2, nil } // 注册所有运算符 func init() { RegisterOperation('+', sum{operator: '+'}) RegisterOperation('-', subtract{operator: '-'}) RegisterOperation('*', multiplication{operator: '*'}) RegisterOperation('/', division{operator: '/'}) RegisterOperation('^', power{operator: '^'}) }动态调用实现
编写计算函数,根据提取的运算符从注册表中获取对应实现并调用do方法:func Calculate(expr string) (int, error) { // 这里简化表达式解析逻辑,实际需根据需求实现字符串拆分/正则匹配 // 示例:假设已从"2 + 3"中提取出操作数和运算符 operand1 := 2 op := '+' operand2 := 3 // 从注册表中获取对应实现 opImpl, exists := operationRegistry[byte(op)] if !exists { return 0, fmt.Errorf("unsupported operator: %c", op) } return opImpl.do(operand1, operand2) }
扩展新运算符的方式
如果需要新增运算符(比如取模%),只需两步:
- 定义实现
operation接口的结构体并实现do方法:type modulus struct { operator byte } func (m modulus) do(operand1, operand2 int) (int, error) { if operand2 == 0 { return 0, fmt.Errorf("modulus by zero") } return operand1 % operand2, nil } - 在
init函数中注册该实现:func init() { // ... 原有注册代码 RegisterOperation('%', modulus{operator: '%'}) }
整个过程无需修改Calculate函数或原有逻辑,完全符合开闭原则。
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

