
本文介绍如何通过定义接口和方法,将针对多个相似结构体(如 aa、bb)的重复长度计算逻辑抽象为单一通用函数,提升代码复用性与可维护性。
本文介绍如何通过定义接口和方法,将针对多个相似结构体(如 aa、bb)的重复长度计算逻辑抽象为单一通用函数,提升代码复用性与可维护性。
在 Go 中,当多个结构体具有相似行为(例如都需提供“元素数量”这一能力),不应通过编写多个同质函数(如 lengthAA、lengthBB)来实现,而应借助接口(Interface) 进行抽象。核心思路是:定义一个包含 Length() int 方法的接口(如 Lengther),让各目标结构体为该接口实现对应方法;随后,通用函数只需接收该接口类型参数,即可统一调用。
以下是一个完整、可运行的示例:
package main
import "fmt"
// 定义统一的行为契约:能返回内部切片长度
type Lengther interface {
Length() int
}
type A struct {
id string
}
type AA struct {
ids []A
}
// AA 实现 Lengther 接口
func (a *AA) Length() int {
return len(a.ids)
}
type B struct {
id string
value bool
}
type BB struct {
ids []B
}
// BB 同样实现 Lengther 接口
func (b *BB) Length() int {
return len(b.ids)
}
// 通用函数:只依赖接口,不关心具体类型
func length(l Lengther) int {
return l.Length()
}
func main() {
aa := &AA{ids: make([]A, 10)}
bb := &BB{ids: make([]B, 34)}
fmt.Println(length(aa)) // 输出: 10
fmt.Println(length(bb)) // 输出: 34
}
✅ 关键要点说明:
- 接口 Lengther 是轻量契约,仅声明所需行为,不涉及数据存储或实现细节;
- 方法接收者使用指针(*AA、*BB)是为了保持一致性(尤其当后续需修改内部状态时),若仅读取字段且结构体较小,值接收者(func (a AA) Length())亦可;
- 通用函数 length 参数类型为接口,完全解耦于具体结构体,未来新增 CC 类型只需实现 Length() 方法,无需修改已有函数;
- 此模式天然支持扩展——例如还可为 []int、自定义集合类型等实现同一接口,真正实现“一处定义、多处适用”。
这种基于接口的抽象方式,正是 Go “组合优于继承” 和 “小接口、高复用” 设计哲学的典型实践。











