В стандартной библиотеке Go уже давно есть паттерн
callback-итерации - тот же sync.Map или fs.WalkDir. Теперь это фактически закрепили через iter.Seq.Но проблема в том, что такой подход ломает привычную для Go структуру.
Go - язык максимально императивный и прямолинейный.
Разраб по дефолты планирует контролировать поток выполнения, а не передавать его внутрь
callback и надеяться, что всё сработает как надо.Поэтому для итерации гораздо естественнее выглядит явный
iterator object:
.Iter() → for it.Next() → .Key() / .Value()
Это тот же паттерн, который уже много лет существует в stdlib:
• bufio.Scanner
• sql.Rows И он отлично себя показал - простой, понятный, без скрытого поведения.
В отличие от
callback-подхода:• control flow остаётся линейным
• defer ведёт себя ожидаемо
• early return не превращается в квест
• panic не теряется по дороге
Именно поэтому многие сознательно выбирают этот паттерн как стандарт.
Например, в Solod - подмножестве Go с компиляцией в C - используется именно iterator object.
И это решение ощущается гораздо ближе к духу Go.
Вопрос в том, что важнее: жёсткий контроль над выполнением или универсальная композиция через callbacks.
