bufio.Scanner.Split în Go

Alege cum împarte Scanner-ul datele: pe rânduri (implicit), cuvinte, caractere, octeți sau după o regulă proprie.

Sintaxă
func (s *Scanner) Split(split SplitFunc)

// funcții gata făcute: bufio.ScanLines, bufio.ScanWords, bufio.ScanRunes, bufio.ScanBytes

Ce face bufio.Scanner.Split

Split setează funcția de împărțire și trebuie apelată înainte de primul Scan. Funcțiile gata făcute: bufio.ScanLines (rânduri, implicit), bufio.ScanWords (cuvinte separate de spații, tab-uri, rânduri noi), bufio.ScanRunes (câte un caracter UTF-8), bufio.ScanBytes (câte un octet).

Poți scrie și o funcție proprie, cu semnătura func(data []byte, atEOF bool) (advance int, token []byte, err error): primește datele disponibile și spune câți octeți să sară și ce bucată să returneze.

Parametri

Parametru Descriere
split Funcția de împărțire: bufio.ScanWords, bufio.ScanRunes sau una proprie.

Ce returnează

Nimic. Dă panică dacă e apelată după ce scanarea a început.

Exemple

Exemplul 1: Numărarea cuvintelor

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    text := "Ana are mere.\n  Mihai are\tpere și prune."
    s := bufio.NewScanner(strings.NewReader(text))
    s.Split(bufio.ScanWords)
    n := 0
    for s.Scan() {
        n++
        fmt.Printf("[%s] ", s.Text())
    }
    fmt.Println("\ncuvinte:", n)
}

Rezultat

[Ana] [are] [mere.] [Mihai] [are] [pere] [și] [prune.] 
cuvinte: 8

Exemplul 2: Caracter cu caracter

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    s := bufio.NewScanner(strings.NewReader("Brașov"))
    s.Split(bufio.ScanRunes)
    for s.Scan() {
        fmt.Printf("%s|", s.Text())
    }
    fmt.Println()
}

Rezultat

B|r|a|ș|o|v|

Exemplul 3: Împărțire proprie, după virgulă

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "strings"
)

func dupaVirgula(data []byte, atEOF bool) (int, []byte, error) {
    if i := bytes.IndexByte(data, ','); i >= 0 {
        return i + 1, bytes.TrimSpace(data[:i]), nil
    }
    if atEOF && len(data) > 0 {
        return len(data), bytes.TrimSpace(data), nil
    }
    return 0, nil, nil // cere mai multe date
}

func main() {
    s := bufio.NewScanner(strings.NewReader("Iași, Cluj,Timișoara , Constanța"))
    s.Split(dupaVirgula)
    for s.Scan() {
        fmt.Printf("%q\n", s.Text())
    }
}

Rezultat

"Iași"
"Cluj"
"Timișoara"
"Constanța"

Greșeli frecvente

  • Apelezi Split după primul Scan: programul se oprește cu panică.
  • Folosești ScanWords și te aștepți ca punctuația să fie separată. „mere.” rămâne un singur cuvânt, cu punct.

Comenzi înrudite

  • bufio.NewScanner: Creează un bufio.Scanner, cel mai simplu mod de a citi un text rând cu rând (sau cuvânt cu cuvânt).
  • bufio.Scanner.Scan: Trece la următoarea bucată (rând, cuvânt) din sursă; returnează false când nu mai sunt date sau a apărut o eroare.
  • bufio.Scanner.Buffer: Setează buffer-ul inițial și dimensiunea maximă a unei bucăți, ca să poți citi rânduri mai lungi de 64 KB.