Go语言将结构体方法重构为接口成员的实现合理性咨询
现有实现的问题
你当前的写法不符合Go的接口设计范式,存在两个核心错误:
- 你定义的
Formatting接口要求方法签名为format() string,但Formatter的实现是format(exe1 *MyExecuter) string,二者签名完全不匹配,Formatter实际上并没有实现Formatting接口,当前能正常运行只是因为你还没有用该接口做约束调用,后续做多态适配时必然会报错。 - 你的
format逻辑强依赖MyExecuter的私有属性attribut1,抽离到独立的空Formatter结构体没有任何实际意义,平白多了一层无意义的封装。
更合理的实现方案
根据你抽离format方法的不同目的,有两种标准实现方式:
场景1:要求所有实现Executing接口的类型都具备格式化能力
直接把format方法合并到原有Executing接口即可,Go是隐式实现接口,只要结构体包含对应方法就会自动满足接口约束:
import "fmt" type Executing interface { Execute() format() string // 直接将格式化方法加入原有接口 } type MyExecuter struct { attribut1 string } func (exe1 *MyExecuter) format() string { return fmt.Sprintf("formated : %s", exe1.attribut1) } func (exe1 *MyExecuter) Execute() { fmt.Println(exe1.format()) } // 注意:原代码方法是指针接收者,必须返回结构体指针才能满足接口约束 func GetExecuter () Executing{ return &MyExecuter{attribut1: "test"} }
场景2:需要格式化逻辑可独立替换,支持不同实例使用不同的格式化策略
这种情况才需要抽离独立的Formatting接口,采用依赖注入的方式将格式化实现注入到MyExecuter中,避免耦合:
import ( "fmt" "time" ) // 格式化接口定义,不耦合具体的Executer类型 type Formatting interface { Format(content string) string } // 默认格式化实现 type DefaultFormatter struct {} func (f *DefaultFormatter) Format(content string) string { return fmt.Sprintf("formated : %s", content) } // 可扩展其他格式化实现,比如带时间戳的版本 type TimeFormatter struct {} func (f *TimeFormatter) Format(content string) string { return fmt.Sprintf("[%s] formated : %s", time.Now().Format(time.RFC3339), content) } type Executing interface { Execute() } // MyExecuter新增formatter依赖字段 type MyExecuter struct { attribut1 string formatter Formatting } func (exe1 *MyExecuter) Execute() { fmt.Println(exe1.formatter.Format(exe1.attribut1)) } // 构造函数支持传入自定义格式化实现 func GetExecuter(formatter Formatting) Executing { if formatter == nil { formatter = &DefaultFormatter{} } return &MyExecuter{ attribut1: "test", formatter: formatter, } }
原代码的细节修正点
- Go中标准库方法都是大写开头导出,你写的
fmt.sprintf是错误的,正确写法是fmt.Sprintf - 小写开头的方法是包内私有,如果你需要跨包使用接口的格式化能力,需要把
format改成大写开头的Format - 指针接收者的方法,只有结构体指针才能满足接口约束,不能直接返回结构体值类型
内容的提问来源于stack exchange,提问作者Djoby
相关产品推荐
相关产品推荐

