Skip to content

Stream split results with SplitSeq and FieldsSeq Has Fix

Description

Go 1.24 added SplitSeq and FieldsSeq to strings and bytes. When a range loop discards the slice index, these helpers stream each part without first allocating the complete result slice. The rule preserves the loop body and deliberately ignores loops that use the index.

It assumes strings and bytes are the canonical standard-library package names and does not manage imports.

YAML

yaml
id: use-split-seq
language: Go
severity: hint
message: Stream split results with a Seq helper.
rule:
  pattern:
    context: |
      func f() {
        for _, $ITEM := range $PACKAGE.$FUNCTION($$$ARGS) {
          $$$BODY
        }
      }
    selector: for_statement
constraints:
  PACKAGE:
    regex: '^(strings|bytes)$'
  FUNCTION:
    regex: '^(Split|Fields)$'
  ITEM:
    all:
      - kind: identifier
      - not:
          regex: '^_$'
transform:
  SEQ_FUNCTION:
    replace:
      source: $FUNCTION
      replace: '$'
      by: Seq
fix: |-
  for $ITEM := range $PACKAGE.$SEQ_FUNCTION($$$ARGS) {
    $$$BODY
  }

Example

go
import (
  "bytes"
  "strings"
)

func visit(text string, data []byte) {
  for _, part := range strings.Split(text, ",") {
    useString(part)
  }
  for _, field := range bytes.Fields(data) {
    useBytes(field)
  }
}

Diff

go
import (
  "bytes"
  "strings"
)

func visit(text string, data []byte) {
  for _, part := range strings.Split(text, ",") { 
  for part := range strings.SplitSeq(text, ",") { 
    useString(part)
  }
  for _, field := range bytes.Fields(data) { 
  for field := range bytes.FieldsSeq(data) { 
    useBytes(field)
  }
}

Credits

Based on JetBrains' Go Modern Guidelines.

Made with ❤️ with Rust