Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungRelease Notes for Safari Technology Preview 253(23.09.2026 um 23:46 Uhr)
Sichere ProgrammierungNode 20 is no longer available in GitHub Actions(23.09.2026 um 22:46 Uhr)
Sichere ProgrammierungMore ways to request and configure Copilot code reviews(23.09.2026 um 23:25 Uhr)
Sichere ProgrammierungApache Data Lakehouse Weekly: September 15 to 23, 2026(23.09.2026 um 23:14 Uhr)
Sichere ProgrammierungObservatorio de gastos públicos(23.09.2026 um 23:15 Uhr)
Sichere ProgrammierungRelease Notes for Safari Technology Preview 253(23.09.2026 um 23:46 Uhr)
Sichere ProgrammierungNode 20 is no longer available in GitHub Actions(23.09.2026 um 22:46 Uhr)
Sichere ProgrammierungMore ways to request and configure Copilot code reviews(23.09.2026 um 23:25 Uhr)
Sichere ProgrammierungApache Data Lakehouse Weekly: September 15 to 23, 2026(23.09.2026 um 23:14 Uhr)
Sichere ProgrammierungObservatorio de gastos públicos(23.09.2026 um 23:15 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Go Iterators (range-over-func): the yield contract and the traps

I wanted to turn a pagination helper into a "clean" iterator with Go 1.23's range syntax. Thirty seconds later: panic: range function continued iteration after function call returned false. The kind of message that says nothing until you…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

I wanted to turn a pagination helper into a "clean" iterator with Go 1.23's range syntax. Thirty seconds later: panic: range function continued iteration after function call returned false. The kind of message that says nothing until you understand the underlying contract. range-over-func iterators are elegant, but they shift part of the responsibility from the compiler to you — and that's where it breaks.



Here's how they actually work, and the three traps that turn a "clean" iterator into a production bug: the yield contract, cleanup on break, and the iter.Pull leak.






An iterator is a function that takes a yield



Since Go 1.23, you can range over a function. The iter package standardizes two signatures: iter.Seq[V] (one value) and iter.Seq2[K, V] (two, like key/value). An iterator is a function that receives a yield and calls it for each element:




// iter.Seq[int] = func(yield func(int) bool)
func Count(n int) iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; i < n; i++ {
if !yield(i) {
return // the consumer stopped → we stop
}
}
}
}

// caller side: the range syntax hides the whole mechanism
for i := range Count(3) {
fmt.Println(i) // 0, 1, 2
}






When you write for i := range Count(3), the compiler turns your loop body into a yield closure that it passes to the iterator. Each yield(i) runs one iteration of your loop. The return value of yield is the key to everything: true = keep going, false = the consumer did a break or a return.






The yield contract: honor the false, always



This is the trap, the one behind my panic. When yield returns false, your iterator must stop immediately and never call yield again. If you keep going, the runtime panics to stop you from producing into a consumer that's no longer listening.




// ❌ ignores yield's return → panic on the consumer's first break
func Bad(n int) iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; i < n; i++ {
yield(i) // we NEVER look at the returned bool
}
}
}

// ✅ honors the contract
func Good(n int) iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; i < n; i++ {
if !yield(i) {
return
}
}
}
}






The rule is mechanical: every call to yield must be guarded by an if !yield(...) { return }. If you produce in several branches, each one must honor the contract. That's the price of the sugar syntax: the compiler can't check it for you, so it checks it at runtime — brutally.






Cleanup when the consumer breaks



An iterator that holds a resource — a file, a connection, a DB cursor — must release it even if the consumer stops halfway. And since a break on the caller side makes yield return false then exits your function, a simple defer inside the iterator is enough — as long as you write it:




func Lines(path string) iter.Seq[string] {
return func(yield func(string) bool) {
f, err := os.Open(path)
if err != nil {
return
}
defer f.Close() // ✅ runs even if the consumer breaks

sc := bufio.NewScanner(f)
for sc.Scan() {
if !yield(sc.Text()) {
return // defer f.Close() fires here too
}
}
}
}

// the defer closes the file whether the loop finishes or stops at line 2
for line := range Lines("big.log") {
if strings.Contains(line, "FATAL") {
break
}
}






The classic mistake is opening the resource outside the iterator function (when building the iter.Seq), where the defer no longer covers the break case. Open the resource inside the closure, close it with defer right after. Same cancellation discipline as not leaking a goroutine: plan the early exit from the design.






iter.Pull: pulling on demand, and never forgetting stop()



range is a "push" model: the iterator pushes values. Sometimes you want to "pull": advance two sequences in parallel, or consume one value at a time on a decision. iter.Pull converts a push iterator into two functions — next() and stop():




next, stop := iter.Pull(Count(1000))
defer stop() // ✅ MANDATORY — otherwise a leak

for {
v, ok := next()
if !ok {
break
}
if v == 42 {
break // early stop: stop() (via defer) releases the iterator
}
}






iter.Pull runs the iterator in a dedicated goroutine. If you don't consume to the end and you don't call stop(), that goroutine stays blocked forever: a pure goroutine leak. The reflex is invariable: next, stop := iter.Pull(...) immediately followed by defer stop(). No exception.






When NOT to write an iterator



The hype pushes you to turn everything into an iter.Seq. That's a mistake. A range-over-func has a cost: indirect function calls, closures, inlining limits the compiler doesn't always cross. For a small collection already in memory, a slice is simpler and faster.




// ❌ pointless: the data fits in memory, the iterator only adds overhead
func Names() iter.Seq[string] { /* ... */ }

// ✅ return a slice: simpler to call, to test, to compose
func Names() []string { return []string{"a", "b", "c"} }






Iterators shine at what a slice does badly: lazy sequences (computed on demand), infinite ones (a counter, a stream), expensive ones (API pagination, reading a big file line by line), or composed ones (chained filters and maps without materializing the intermediates). If none of these apply, return a slice. It's the Go spirit of simplicity by default: the cleverest feature isn't always the right one.






Conclusion



range-over-func iterators are a real addition to the language, but they introduce a contract the compiler only enforces at runtime: honor yield's false, close resources inside the closure, call stop() on an iter.Pull. Three rules, three traps. Once internalized, they become automatic.



The question to ask before writing one isn't "can I?" but "is the sequence lazy, infinite, expensive or composed?". If yes, the iterator is elegant and justified. If not, you're adding complexity and overhead to return a slice — and a slice never panics.

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
IR-PLAYBOOK-RCE
HIGH
SOC Incident Playbook: Remote Code Execution (RCE) Defense
1-Click Detection Engineering: Sigma & YARA Rules
SOC Ready
title: Detect Exploitation - Go Iterators (range-over-func): the yield contract and the traps
id: d2f33a31-8d2e-4217-ac35-83e7affe8baf
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-23
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-23"
        description = "YARA Signature for "
    strings:
        $str = "Go Iterators (range-over-func)" ascii wide
    condition:
        any of them
}
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Go Iterators (range-over-func): the yield contract and the traps

Thematisch verwandte Begriffe: Iterators, rangeoverfunc, yield, contract · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-82405 | Klever-Go Account takeover: `kleverUpdateAccountPermission` authorizes o…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick