funcExampleLines() { // 标准情况 text := "Hello\nWorld\nGo Programming\n" fmt.Println("1. Using for-range loop (recommended):") for line := range strings.Lines(text) { fmt.Printf("%q\n", line) }
// 末尾没有换行符 text2 := "First line\nSecond line" fmt.Println("\n2. Text without trailing newline:") for line := range strings.Lines(text2) { fmt.Printf("%q\n", line) }
// Output: // 1. Using for-range loop (recommended): // "Hello\n" // "World\n" // "Go Programming\n" // // 2. Text without trailing newline: // "First line\n" // "Second line" }
SplitSeq和SplitAfterSeq
SplitSeq 返回一个迭代器,遍历字符串 s 中由分隔符 sep 分隔的所有子字符串。迭代器生成的字符串与使用 Split(s, sep) 返回的字符串相同,但不构造切片。该迭代器为一次性使用。
funcExampleSplitSeq() { // 使用特定分隔符分割字符串 s := "a,b,c,d" fmt.Println("Split string by comma:") for part := range strings.SplitSeq(s, ",") { fmt.Printf("%q\n", part) }
// 使用空分隔符分割成字符 text := "Hello世界" fmt.Println("\nSplit into characters:") for char := range strings.SplitSeq(text, "") { fmt.Printf("%q\n", char) }
SplitAfterSeq 返回一个迭代器,遍历字符串 s 中每个分隔符 sep 后的子字符串。迭代器生成的字符串与使用 SplitAfter(s, sep) 返回的字符串相同,但不构造切片。该迭代器为一次性使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
funcExampleSplitAfterSeq() { // 使用分隔符分割(并会保留分隔符) s := "a,b,c,d" fmt.Println("Split string by comma (keeping separators):") for part := range strings.SplitAfterSeq(s, ",") { fmt.Printf("%q\n", part) }
funcExampleFieldsSeq() { // 通过空格分割 text := "The quick brown fox" fmt.Println("Split string into fields:") for word := range strings.FieldsSeq(text) { fmt.Printf("%q\n", word) }
// 通过多个空格来分割 textWithSpaces := " lots of spaces " fmt.Println("\nSplit string with multiple spaces:") for word := range strings.FieldsSeq(textWithSpaces) { fmt.Printf("%q\n", word) }
funcExampleFieldsFuncSeq() { // 使用空格分割 (和FieldsSeq效果类似) text := "The quick brown fox" fmt.Println("Split on whitespace:") for word := range strings.FieldsFuncSeq(text, unicode.IsSpace) { fmt.Printf("%q\n", word) }
// 根据数字切割 mixedText := "abc123def456ghi" fmt.Println("\nSplit on digits:") for word := range strings.FieldsFuncSeq(mixedText, unicode.IsDigit) { fmt.Printf("%q\n", word) }
funcExampleLines() { // Text with trailing newline text := "Hello\nWorld\nGo Programming\n" fmt.Println("1. Using for-range loop (recommended):") for line := range strings.Lines(text) { fmt.Printf("%q\n", line) }
// Text without trailing newline text2 := "First line\nSecond line" fmt.Println("\n2. Text without trailing newline:") for line := range strings.Lines(text2) { fmt.Printf("%q\n", line) }
// Processing first two lines only text3 := "One\nTwo\nThree\nFour\n" fmt.Println("\n3. Early exit using break:") count := 0 for line := range strings.Lines(text3) { fmt.Printf("%q\n", line) count++ if count >= 2 { break } }
funcExampleSplitSeq() { // Basic string splitting s := "a,b,c,d" fmt.Println("Split string by comma:") for part := range strings.SplitSeq(s, ",") { fmt.Printf("%q\n", part) }
// Split into characters (using empty separator) text := "Hello世界" fmt.Println("\nSplit into characters:") for char := range strings.SplitSeq(text, "") { fmt.Printf("%q\n", char) }
funcExampleSplitAfterSeq() { // Basic split after separator (keeping separators) s := "a,b,c,d" fmt.Println("Split string by comma (keeping separators):") for part := range strings.SplitAfterSeq(s, ",") { fmt.Printf("%q\n", part) }
funcExampleFieldsSeq() { // Basic whitespace splitting text := "The quick brown fox" fmt.Println("Split string into fields:") for word := range strings.FieldsSeq(text) { fmt.Printf("%q\n", word) }
// Handling multiple spaces textWithSpaces := " lots of spaces " fmt.Println("\nSplit string with multiple spaces:") for word := range strings.FieldsSeq(textWithSpaces) { fmt.Printf("%q\n", word) }
funcExampleFieldsFuncSeq() { // Split on whitespace (similar to FieldsSeq) text := "The quick brown fox" fmt.Println("Split on whitespace:") for word := range strings.FieldsFuncSeq(text, unicode.IsSpace) { fmt.Printf("%q\n", word) }
// Split on digits mixedText := "abc123def456ghi" fmt.Println("\nSplit on digits:") for word := range strings.FieldsFuncSeq(mixedText, unicode.IsDigit) { fmt.Printf("%q\n", word) }
// 模拟一个较长的 header 字符串 var header = strings.Repeat("text/html,application/json,application/xml,", 1000)
funcparseMediaRange(s string) (string, bool) { // 模拟解析逻辑 if s == "" { return"", false } return s, true }
funcBenchmarkSplit(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { var out []string for _, field := range strings.Split(header, ",") { if r, ok := parseMediaRange(field); ok { out = append(out, r) } } _ = out } }
funcBenchmarkSplitSeq(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { var out []string for field := range strings.SplitSeq(header, ",") { if r, ok := parseMediaRange(field); ok { out = append(out, r) } } _ = out } }
🧪 运行方式
在 Go ≥1.23 的环境中(因为 strings.SplitSeq 仅在 Go 1.23 及以上版本提供):
是否希望我帮你再生成一个 图表化可视化的 benchmark 结果 HTML 页面(自动显示执行耗时、内存对比)?这样可以一眼看出两种写法性能差距。
Sure! Here’s an English explanation you can include in your code comments, README, or performance report:
Benchmark Explanation
This benchmark compares two different ways of iterating over a comma‑separated header string in Go:
Using strings.Split This function eagerly splits the entire string at once and returns a slice of substrings. It allocates memory for all tokens upfront, which can be expensive for large input data or high‑frequency processing.
Using strings.SplitSeq(introduced in Go 1.23) This function returns a lazy sequence (strings.Seq), allowing you to iterate over tokens one by one without creating an intermediate slice. It significantly reduces memory allocations and can improve performance for long strings.
The benchmark results typically show that SplitSeq performs faster and allocates less memory, especially when the input string contains many separators. For small strings, both methods perform similarly.
Recommendation: Use strings.SplitSeq whenever you only need to iterate over the parts once. Use strings.Split if you need random access or to reuse the results multiple times.
strings.SplitSeq (introduced in Go 1.23) returns a lazy sequence (strings.Seq), allowing gopher to iterate over tokens one by one without creating an intermediate slice.
It significantly reduces memory allocations and can improve performance for long strings.