Ошибка bufio.ErrTooLong

Ошибка bufio.ErrTooLong возвращается функцией Scanner.Scan из пакета bufio, когда буфер для чтения превышает максимальную допустимую длину. По умолчанию Scanner использует буфер размером 64 КБ, и если очередной токен (например, строка) превышает этот размер, возникает указанная ошибка.

Синтаксис

govar scanner *bufio.Scanner
err := scanner.Err()

Ошибка доступна через метод Err объекта Scanner после завершения цикла сканирования или при возникновении проблемы во время чтения.

Пример возникновения ошибки

Давайте создадим пример, в котором строка превышает максимальную длину буфера:

gopackage main

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

func main() {
  // Создаем длинную строку из 100000 символов 'a'
  longLine := strings.Repeat("a", 100000)
  reader := strings.NewReader(longLine + "\n")
  scanner := bufio.NewScanner(reader)
  
  for scanner.Scan() {
    line := scanner.Text()
    fmt.Printf("Длина строки: %d\n", len(line))
  }
  
  if err := scanner.Err(); err != nil {
    fmt.Println("Ошибка:", err)
  }
}

Результат выполнения кода:

go"Ошибка: bufio.Scanner: token too long"

Увеличение размера буфера

Для решения проблемы необходимо увеличить размер буфера с помощью метода Buffer:

gopackage main

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

func main() {
  longLine := strings.Repeat("a", 100000)
  reader := strings.NewReader(longLine + "\n")
  scanner := bufio.NewScanner(reader)
  
  // Увеличиваем буфер до 200 КБ
  buf := make([]byte, 0, 200*1024)
  scanner.Buffer(buf, 200*1024)
  
  for scanner.Scan() {
    line := scanner.Text()
    fmt.Printf("Длина строки: %d\n", len(line))
  }
  
  if err := scanner.Err(); err != nil {
    fmt.Println("Ошибка:", err)
  }
}

Результат выполнения кода:

go"Длина строки: 100000"

Использование с пользовательской функцией разделения

При использовании пользовательской функции разделения, ошибка ErrTooLong также может возникнуть, если токен превышает размер буфера:

gopackage main

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

func main() {
  // Используем ScanWords с очень длинным словом
  longWord := strings.Repeat("b", 80000)
  data := "short " + longWord + " short"
  reader := strings.NewReader(data)
  scanner := bufio.NewScanner(reader)
  
  // Устанавливаем разделение по словам
  scanner.Split(bufio.ScanWords)
  
  for scanner.Scan() {
    word := scanner.Text()
    fmt.Printf("Слово длиной: %d\n", len(word))
  }
  
  if err := scanner.Err(); err != nil {
    fmt.Println("Ошибка:", err)
  }
}

Результат выполнения кода:

go"Слово длиной: 5"
"Ошибка: bufio.Scanner: token too long"

Смотрите также

  • функцию bufio.Scanner.Scan,
    которая выполняет сканирование токенов
  • функцию bufio.Scanner.Err,
    которая возвращает последнюю ошибку сканирования
  • функцию bufio.Scanner.Split,
    которая устанавливает функцию разделения токенов
  • функцию bufio.ScanLines,
    которая является стандартной функцией разделения по строкам