Golang中不同struct共用同一函数避免代码重复的最佳实践
Go中避免同逻辑多结构体重复代码的最佳实践
方案1:定义统一接口(Go语言首选惯用法)
利用Go的鸭子类型特性,定义包含所需语义方法的统一接口,不同结构体分别实现该接口,通用逻辑仅需编写一次,接收接口类型作为入参即可。
// 定义统一语义接口 type AppDetailer interface { AppName() string Version() string } // mobile结构体实现接口 func (m mobile) AppName() string { return m.appName } func (m mobile) Version() string { return m.version } // other结构体实现接口 func (o other) AppName() string { return o.app_name } func (o other) Version() string { return o.release } // 通用详情方法仅实现一次 func GetAppDetails(app AppDetailer) string { message := fmt.Sprintf("Here is the details of the *%s* with the version %s", app.AppName(), app.Version()) // 所有复杂逻辑统一在此实现,无需重复编写 return message }
该方案完全符合Go的接口设计哲学,类型安全,无额外运行时开销,后续新增同语义结构体只需实现接口方法即可直接复用通用逻辑。
方案2:中间结构体转换(适配无法修改原结构体的场景)
如果原有结构体定义不可修改(比如是第三方依赖提供的类型),可以定义语义统一的中间结构体,编写极简的转换方法将原结构体映射为中间结构体,再基于中间结构体实现通用逻辑。
// 语义统一的中间结构体 type AppInfo struct { AppName string Version string } // 转换逻辑代码量远少于重复的业务逻辑 func MobileToAppInfo(m mobile) AppInfo { return AppInfo{ AppName: m.appName, Version: m.version, } } func OtherToAppInfo(o other) AppInfo { return AppInfo{ AppName: o.app_name, Version: o.release, } } // 通用业务逻辑 func GetAppDetails(info AppInfo) string { message := fmt.Sprintf("Here is the details of the *%s* with the version %s", info.AppName, info.Version) // 复杂逻辑统一实现 return message }
方案3:反射实现(非必要不推荐)
如果涉及的结构体数量极多,且字段映射规则有明确规律(比如驼峰转下划线、固定别名映射表),可以用反射实现通用字段映射,但会损失编译时类型校验,存在额外运行时开销,仅适合极端场景使用。
内容的提问来源于stack exchange,提问作者kuzua
相关产品推荐
相关产品推荐

