| Josh Bleecher Snyder | 31785ae | 2025-05-06 01:50:58 +0000 | [diff] [blame] | 1 | `strings.Lines` — added in Go 1.24 |
| 2 | |
| 3 | - `func Lines(s string) iter.Seq[string]` |
| 4 | - Lazily yields successive newline-terminated substrings of `s`. *Includes* the exact trailing `\n`/`\r\n`; if the input ends without a newline the final element is unterminated. |
| 5 | - Zero copying: each value is just a slice header into `s`, so iteration is O(1) memory. |
| 6 | |
| 7 | Idiomatic loop: |
| 8 | |
| 9 | ```go |
| 10 | for line := range strings.Lines(buf) { |
| 11 | handle(line) |
| 12 | } |
| 13 | ``` |
| 14 | |
| 15 | ### How it differs from common alternatives |
| 16 | |
| 17 | - strings.Split – eager `[]string` allocation; caller chooses the separator (newline usually `"\n"`); separator *removed*, so you lose information about line endings and trailing newline presence. |
| 18 | - strings.SplitSeq – same lazy `iter.Seq[string]` style as `Lines`, but again the caller supplies the separator and it is dropped; use this for arbitrary delimiters. |
| 19 | - bufio.Scanner – token-oriented reader for any `io.Reader`. Default split function treats `\n` as the delimiter and strips it, so newline bytes are not preserved. Each token is copied into new memory, and there is a 64 KiB default token-size cap (adjustable). Scanner is the choice when the data is coming from a stream rather than an in-memory string. |
| 20 | |
| 21 | Use `strings.Lines` by default when the data is already in a string. (bytes.Lines provides the []byte equivalent.) |
| 22 | |
| 23 | Fallback to `Split` if you need a slice of lines in memory, to `SplitSeq` for lazy iteration over other separators, and to `bufio.Scanner` for streaming input where newline bytes are irrelevant. |