Go语言灯光控制函数中闪烁模式可选参数的最优实现方案
灯光控制函数的可选参数实现方案
原实现代码
func (p *Printer) Light(light _light.Light, mode _light.Mode) error { // This light_mode is currently believed to be deprecated, leaving here commented in case it ends up being useful later. //command, err := mqtt.NewCommand(mqtt.System).AddCommandField("light_mode").AddParamField("on").JSON() //if err != nil { // return err //} // https://github.com/Doridian/OpenBambuAPI/blob/main/mqtt.md#systemledctrl command := mqtt.NewCommand(mqtt.System).AddCommandField("ledctrl").AddField("led_node", light).AddField("led_mode", mode) // Add fields only used for mode "flashing" but required nonetheless command.AddField("led_on_time", 500) command.AddField("led_off_time", 500) command.AddField("loop_times", 1) command.AddField("interval_time", 1000) if err := p.mqttClient.Publish(command); err != nil { return fmt.Errorf("error setting light %s: %w", light, err) } return nil }
需求描述
当输入模式为闪烁(flashing)时,希望允许调用者传入仅针对闪烁灯光所需的间隔时间、点亮时间、熄灭时间等参数。曾考虑使用可变参数,但担忧参数顺序带来的歧义,寻求最优实现方式。
最优实现方案:配置结构体+默认值填充
这种方式既解决参数歧义问题,又能灵活支持可选参数,完全符合Go语言的惯用写法。
1. 定义闪烁配置结构体并设置默认值
// LightFlashConfig 闪烁灯光的配置参数 type LightFlashConfig struct { OnTime int // 点亮时长(毫秒) OffTime int // 熄灭时长(毫秒) LoopTimes int // 循环次数 Interval int // 间隔时长(毫秒) } // DefaultLightFlashConfig 返回默认的闪烁配置 func DefaultLightFlashConfig() LightFlashConfig { return LightFlashConfig{ OnTime: 500, OffTime: 500, LoopTimes: 1, Interval: 1000, } }
2. 修改原函数支持可选配置
func (p *Printer) Light(light _light.Light, mode _light.Mode, flashConfig ...*LightFlashConfig) error { // 初始化配置为默认值 config := DefaultLightFlashConfig() // 如果调用者传入了配置,覆盖对应字段 if len(flashConfig) > 0 && flashConfig[0] != nil { cfg := flashConfig[0] if cfg.OnTime != 0 { config.OnTime = cfg.OnTime } if cfg.OffTime != 0 { config.OffTime = cfg.OffTime } if cfg.LoopTimes != 0 { config.LoopTimes = cfg.LoopTimes } if cfg.Interval != 0 { config.Interval = cfg.Interval } } command := mqtt.NewCommand(mqtt.System).AddCommandField("ledctrl").AddField("led_node", light).AddField("led_mode", mode) // 使用配置值填充命令字段 command.AddField("led_on_time", config.OnTime) command.AddField("led_off_time", config.OffTime) command.AddField("loop_times", config.LoopTimes) command.AddField("interval_time", config.Interval) if err := p.mqttClient.Publish(command); err != nil { return fmt.Errorf("error setting light %s: %w", light, err) } return nil }
3. 调用示例
- 使用默认闪烁参数(兼容原调用方式):
err := printer.Light(_light.FrontLight, _light.Flashing)
- 自定义部分闪烁参数:
err := printer.Light(_light.FrontLight, _light.Flashing, &LightFlashConfig{ OnTime: 300, OffTime: 700, })
- 自定义所有闪烁参数:
err := printer.Light(_light.FrontLight, _light.Flashing, &LightFlashConfig{ OnTime: 200, OffTime: 800, LoopTimes: 3, Interval: 1500, })
方案优势
- 无歧义:每个参数都有明确字段名,调用者无需记忆参数顺序
- 灵活性强:支持只修改需要调整的参数,无需传递所有可选值
- 兼容性好:原函数调用方式完全保留,无需修改旧代码
- 符合Go风格:这种配置结构体+默认值的模式在Go生态中广泛应用,可读性和可维护性高
注:如果需要更复杂的参数校验或动态配置,也可以考虑函数选项模式,但对于当前场景,配置结构体已经足够简洁高效,无需过度设计。
内容的提问来源于stack exchange,提问作者Torben Conto
相关产品推荐
相关产品推荐

