go 不适合传统迭代器接口,因其原生不支持类、继承和强制接口实现,且惯用法强调数据结构自身提供遍历能力;推荐用回调函数(如 range)或切片/通道直接遍历。
Go 语言原生不支持类、继承和接口的强制实现,也没有 Iterator 接口或 for...of 语法,所以“标准迭代器模式”在 Go 里不能照搬 Java/C# 那套——直接返回一个带 Next()、HasNext() 的对象,反而容易写出难维护、易出错的代码。
为什么 Go 不适合传统迭代器接口
Go 的惯用法是让数据结构自己提供遍历能力,而不是把状态(如当前索引、是否结束)抽成独立对象。常见问题包括:
-
Next()返回值和状态耦合,调用者容易忘记检查是否已到末尾,导致 panic 或重复消费 - 多个 goroutine 并发调用同一个迭代器实例时,状态竞争难以避免,除非加锁——但这就违背了 Go “不要通过共享内存来通信”的哲学
- 泛型未普及前(Go 1.18 之前),为每种类型写一套
Iterator类型,冗余严重;泛型虽缓解了这点,但接口抽象仍不如直接暴露函数自然
用函数值(func)代替 Iterator 接口
最 Go 的做法是:把“遍历逻辑”封装成一个接受回调函数的遍历方法,由容器自身控制迭代过程。调用者只关心“对每个元素做什么”,不操心状态管理。
例如,为自定义链表实现遍历:
type ListNode struct {
Val int
Next *ListNode
}
<p>func (head *ListNode) Range(f func(int) bool) {
for node := head; node != nil; node = node.Next {
if !f(node.Val) {
break // 提前退出,类似 break 语句
}
}
}
使用时: