
本文介绍如何利用 go 的接口机制,将针对不同结构体的重复方法(如获取内部切片长度)抽象为单一通用函数,避免代码冗余并提升可维护性。
本文介绍如何利用 go 的接口机制,将针对不同结构体的重复方法(如获取内部切片长度)抽象为单一通用函数,避免代码冗余并提升可维护性。
在 Go 语言中,当多个结构体具有相似行为(例如都需返回其内部切片的长度),不应通过编写多个同质化函数(如 lengthAA、lengthBB)来实现,而应采用接口驱动的设计模式:定义一个描述该行为的接口,让相关结构体实现该接口的方法,再通过接口参数统一调用。
具体而言,可定义一个 Lengther 接口,声明 Length() int 方法:
type Lengther interface {
Length() int
}
随后,为 AA 和 BB 分别实现该方法。注意:方法接收者应使用指针类型(*AA、*BB),以确保方法能访问结构体字段(尤其是当结构体较大时,也符合常见实践):
func (a *AA) Length() int {
return len(a.ids)
}
func (b *BB) Length() int {
return len(b.ids)
}
最终,通用函数只需接受 Lengther 接口类型参数:
func length(l Lengther) int {
return l.Length()
}
完整示例:
package main
import "fmt"
type Lengther interface {
Length() int
}
type A struct {
id string
}
type AA struct {
ids []A
}
func (a *AA) Length() int {
return len(a.ids)
}
type B struct {
id string
value bool
}
type BB struct {
ids []B
}
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
}
✅ 注意事项:
- 接口是隐式实现的,无需显式声明 AA implements Lengther;只要类型实现了接口所有方法,即自动满足该接口。
- 若后续新增结构体 CC,只需为其添加 Length() 方法,即可无缝接入 length() 函数,完全符合开闭原则。
- 避免将 len() 直接作用于结构体本身(如 len(aa)),这在 Go 中非法——len 只适用于 slice、map、channel、string 等内置类型,不能用于自定义结构体。
这种设计不仅消除了重复逻辑,还提升了扩展性与类型安全性,是 Go 中践行“组合优于继承”和“小接口”哲学的典型实践。











