Пакет bufio
Обзор
Пакет bufio реализует буферизованный ввод-вывод. Он оборачивает объект io.Reader или io.Writer, создавая другой объект (Reader или Writer), который также реализует этот интерфейс, но обеспечивает буферизацию и некоторые возможности для работы с текстовым вводом-выводом.
Указатель
Примеры
Файлы пакета
bufio.go scan.go
Константы
const (
// MaxScanTokenSize is the maximum size used to buffer a token
// unless the user provides an explicit buffer with [Scanner.Buffer].
// The actual maximum token size may be smaller as the buffer
// may need to include, for instance, a newline.
MaxScanTokenSize = 64 * 1024
) Переменные
var (
ErrInvalidUnreadByte = errors.New("bufio: invalid use of UnreadByte")
ErrInvalidUnreadRune = errors.New("bufio: invalid use of UnreadRune")
ErrBufferFull = errors.New("bufio: buffer full")
ErrNegativeCount = errors.New("bufio: negative count")
) Ошибки, возвращаемые Scanner.
var (
ErrTooLong = errors.New("bufio.Scanner: token too long")
ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
ErrAdvanceTooFar = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
ErrBadReadCount = errors.New("bufio.Scanner: Read returned impossible count")
) ErrFinalToken — специальное значение ошибки-маркера. Функция Split должна возвращать его, чтобы указать, что сканирование следует остановить без ошибки. Если токен, передаваемый вместе с этой ошибкой, не равен nil, он является последним токеном.
Это значение полезно для досрочного прекращения обработки или когда необходимо передать последний пустой токен (который отличается от токена nil). Такого же поведения можно добиться с помощью пользовательского значения ошибки, но предоставленное здесь значение делает код аккуратнее. Пример использования этого значения см. в примере emptyFinalToken.
var ErrFinalToken = errors.New("final token") func ScanBytes 1.1
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanBytes — функция разделения для Scanner, которая возвращает каждый байт в виде токена.
func ScanLines 1.1
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanLines — функция разделения для Scanner, которая возвращает каждую строку текста без завершающего маркера конца строки. Возвращаемая строка может быть пустой. Маркер конца строки состоит из необязательного символа возврата каретки, за которым следует обязательный символ новой строки. В обозначениях регулярных выражений это `\r?\n`. Последняя непустая строка ввода будет возвращена, даже если она не заканчивается символом новой строки.
func ScanRunes 1.1
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanRunes — функция разделения для Scanner, которая возвращает каждую кодированную в UTF-8 руну в виде токена. Последовательность возвращаемых рун эквивалентна последовательности, полученной в цикле range по входным данным как по строке; это означает, что некорректные кодировки UTF-8 преобразуются в U+FFFD = "\xef\xbf\xbd". Из-за интерфейса Scan клиент не может отличить корректно закодированные руны-замены от ошибок кодирования.
func ScanWords 1.1
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
ScanWords — функция разделения для Scanner, которая возвращает каждое слово текста, отделённое пробелами, удаляя окружающие пробелы. Она никогда не возвращает пустую строку. Определение пробела задаётся функцией unicode.IsSpace.
type ReadWriter
ReadWriter хранит указатели на Reader и Writer. Он реализует интерфейс io.ReadWriter.
type ReadWriter struct {
*Reader
*Writer
}
func NewReadWriter
func NewReadWriter(r *Reader, w *Writer) *ReadWriter
NewReadWriter выделяет память для нового ReadWriter, который перенаправляет вызовы к r и w.
type Reader
Reader реализует буферизацию для объекта io.Reader. Новый Reader создаётся вызовом NewReader или NewReaderSize; также можно использовать нулевое значение Reader, предварительно вызвав для него Reader.Reset.
type Reader struct {
// contains filtered or unexported fields
}
func NewReader
func NewReader(rd io.Reader) *Reader
NewReader возвращает новый Reader с буфером стандартного размера.
func NewReaderSize
func NewReaderSize(rd io.Reader, size int) *Reader
NewReaderSize возвращает новый Reader, размер буфера которого не меньше указанного. Если аргумент io.Reader уже является Reader с буфером достаточного размера, возвращается исходный Reader.
func (*Reader) Buffered
func (b *Reader) Buffered() int
Buffered возвращает количество байтов, которые можно прочитать из текущего буфера.
func (*Reader) Discard 1.5
func (b *Reader) Discard(n int) (discarded int, err error)
Discard пропускает следующие n байтов и возвращает количество пропущенных байтов.
Если Discard пропускает меньше n байтов, он также возвращает ошибку. Если 0 <= n <= b.Buffered(), гарантируется, что Discard завершится успешно, не читая данные из исходного io.Reader.
func (*Reader) Peek
func (b *Reader) Peek(n int) ([]byte, error)
Peek возвращает следующие n байтов, не сдвигая позицию чтения. Эти байты перестают быть допустимыми при следующем вызове чтения. При необходимости Peek прочитает в буфер дополнительные байты, чтобы сделать доступными n байтов. Если Peek возвращает меньше n байтов, он также возвращает ошибку с объяснением причины неполного чтения. Если n больше размера буфера b, возвращается ошибка ErrBufferFull.
Вызов Peek не позволит успешно вызвать Reader.UnreadByte или Reader.UnreadRune до следующей операции чтения.
func (*Reader) Read
func (b *Reader) Read(p []byte) (n int, err error)
Read читает данные в p. Он возвращает количество байтов, прочитанных в p. Данные считываются не более чем за один вызов Read исходного Reader, поэтому n может быть меньше len(p). Чтобы прочитать ровно len(p) байтов, используйте io.ReadFull(b, p). Если исходный Reader может возвращать ненулевое количество байтов вместе с io.EOF, этот метод Read тоже может так поступить; см. документацию io.Reader.
func (*Reader) ReadByte
func (b *Reader) ReadByte() (byte, error)
ReadByte читает и возвращает один байт. Если байтов нет, возвращается ошибка.
func (*Reader) ReadBytes
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
ReadBytes читает данные до первого вхождения delim и возвращает срез, содержащий данные вплоть до разделителя включительно. Если ReadBytes встречает ошибку до обнаружения разделителя, он возвращает данные, прочитанные до ошибки, и саму ошибку (часто io.EOF). ReadBytes возвращает err != nil тогда и только тогда, когда возвращённые данные не заканчиваются на delim. Для простых случаев может быть удобнее использовать Scanner.
func (*Reader) ReadLine
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
ReadLine — низкоуровневая примитивная функция чтения строк. В большинстве случаев вместо неё следует использовать Reader.ReadBytes('\n'), Reader.ReadString('\n') или Scanner.
ReadLine пытается вернуть одну строку без байтов конца строки. Если строка слишком длинная для буфера, устанавливается isPrefix и возвращается начало строки. Оставшаяся часть строки будет возвращена при последующих вызовах. При возврате последнего фрагмента строки isPrefix будет равен false. Возвращённый буфер действителен только до следующего вызова ReadLine. ReadLine возвращает либо ненулевую строку, либо ошибку, но не то и другое одновременно.
Текст, возвращаемый ReadLine, не включает символы конца строки ("\r\n" или "\n"). Если входные данные заканчиваются без завершающего символа конца строки, об этом не сообщается и ошибка не возвращается. Вызов Reader.UnreadByte после ReadLine всегда отменяет чтение последнего прочитанного байта (возможно, символа конца строки), даже если этот байт не входит в строку, возвращённую ReadLine.
func (*Reader) ReadRune
func (b *Reader) ReadRune() (r rune, size int, err error)
ReadRune читает один символ Unicode в кодировке UTF-8 и возвращает руну и её размер в байтах. Если закодированная руна некорректна, функция потребляет один байт и возвращает unicode.ReplacementChar (U+FFFD) с размером 1.
func (*Reader) ReadSlice
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
ReadSlice читает данные до первого вхождения delim и возвращает срез, указывающий на байты в буфере. Эти байты перестают быть допустимыми при следующем чтении. Если ReadSlice встречает ошибку до обнаружения разделителя, он возвращает все данные из буфера и саму ошибку (часто io.EOF). ReadSlice завершается с ошибкой ErrBufferFull, если буфер заполняется до появления delim. Поскольку данные, возвращённые ReadSlice, будут перезаписаны при следующей операции ввода-вывода, большинству клиентов следует использовать Reader.ReadBytes или ReadString. ReadSlice возвращает err != nil тогда и только тогда, когда строка не заканчивается на delim.
func (*Reader) ReadString
func (b *Reader) ReadString(delim byte) (string, error)
ReadString читает данные до первого вхождения delim и возвращает строку, содержащую данные вплоть до разделителя включительно. Если ReadString встречает ошибку до обнаружения разделителя, он возвращает данные, прочитанные до ошибки, и саму ошибку (часто io.EOF). ReadString возвращает err != nil тогда и только тогда, когда возвращённые данные не заканчиваются на delim. Для простых случаев может быть удобнее использовать Scanner.
func (*Reader) Reset 1.2
func (b *Reader) Reset(r io.Reader)
Reset отбрасывает все буферизованные данные, сбрасывает состояние и переключает буферизованный ридер на чтение из r. Вызов Reset для нулевого значения Reader инициализирует внутренний буфер стандартного размера. Вызов b.Reset(b) (то есть сброс Reader на самого себя) ничего не делает.
func (*Reader) Size 1.10
func (b *Reader) Size() int
Size возвращает размер исходного буфера в байтах.
func (*Reader) UnreadByte
func (b *Reader) UnreadByte() error
UnreadByte отменяет чтение последнего байта. Отменить чтение можно только для байта, прочитанного последним.
UnreadByte возвращает ошибку, если последний вызванный метод Reader не был операцией чтения. В частности, Reader.Peek, Reader.Discard и Reader.WriteTo не считаются операциями чтения.
func (*Reader) UnreadRune
func (b *Reader) UnreadRune() error
UnreadRune отменяет чтение последней руны. Если последним вызванным для Reader методом был не Reader.ReadRune, Reader.UnreadRune возвращает ошибку. (В этом отношении он строже, чем Reader.UnreadByte, который отменяет чтение последнего байта при любой операции чтения.)
func (*Reader) WriteTo 1.1
func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
WriteTo реализует io.WriterTo. Этот метод может несколько раз вызвать метод Reader.Read базового Reader. Если базовый reader поддерживает метод Reader.WriteTo, этот метод вызывает базовый Reader.WriteTo без буферизации.
type Scanner 1.1
Scanner предоставляет удобный интерфейс для чтения данных, например строк текстового файла, разделённых символами новой строки. Последовательные вызовы метода Scanner.Scan проходят по «токенам» файла, пропуская байты между ними. Правила определения токена задаются функцией разделения типа SplitFunc; функция разделения по умолчанию разбивает входные данные на строки, удаляя символ завершения строки. В этом пакете определены функции Scanner.Split для сканирования файла с разбиением на строки, байты, руны в кодировке UTF-8 и слова, разделённые пробелами. Вместо этого вызывающая сторона может предоставить собственную функцию разделения.
Сканирование без возможности восстановления останавливается при достижении EOF, первой ошибке ввода-вывода или обнаружении токена, слишком большого для Scanner.Buffer. При остановке сканирования reader может произвольно продвинуться за последний токен. Программам, которым требуется более строгий контроль над обработкой ошибок или большими токенами либо нужно последовательно выполнять несколько сканирований reader, следует использовать bufio.Reader.
type Scanner struct {
// contains filtered or unexported fields
}
Пример (Пользовательский)
Используйте Scanner с пользовательской функцией разделения (созданной на основе ScanWords), чтобы проверить десятичное число, помещающееся в 32 бита.
Код:
// An artificial input source.
const input = "1234 5678 1234567901234567890"
scanner := bufio.NewScanner(strings.NewReader(input))
// Create a custom split function by wrapping the existing ScanWords function.
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
advance, token, err = bufio.ScanWords(data, atEOF)
if err == nil && token != nil {
_, err = strconv.ParseInt(string(token), 10, 32)
}
return
}
// Set the split function for the scanning operation.
scanner.Split(split)
// Validate the input
for scanner.Scan() {
fmt.Printf("%s\n", scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Printf("Invalid input: %s", err)
}
Вывод:
1234 5678 Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range
Пример (Ранняя остановка)
Используйте Scanner с пользовательской функцией разделения для разбора списка значений, разделённых запятыми, с пустым последним значением; сканирование останавливается на токене "STOP".
Код:
onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
i := bytes.IndexByte(data, ',')
if i == -1 {
if !atEOF {
return 0, nil, nil
}
// If we have reached the end, return the last token.
return 0, data, bufio.ErrFinalToken
}
// If the token is "STOP", stop the scanning and ignore the rest.
if string(data[:i]) == "STOP" {
return i + 1, nil, bufio.ErrFinalToken
}
// Otherwise, return the token before the comma.
return i + 1, data[:i], nil
}
const input = "1,2,STOP,4,"
scanner := bufio.NewScanner(strings.NewReader(input))
scanner.Split(onComma)
for scanner.Scan() {
fmt.Printf("Got a token %q\n", scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading input:", err)
}
Вывод:
Got a token "1" Got a token "2"
Пример (Пустой последний токен)
Используйте Scanner с пользовательской функцией разделения для разбора списка значений, разделённых запятыми, с пустым последним значением.
Код:
// Comma-separated list; last entry is empty.
const input = "1,2,3,4,"
scanner := bufio.NewScanner(strings.NewReader(input))
// Define a split function that separates on commas.
onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
for i := 0; i < len(data); i++ {
if data[i] == ',' {
return i + 1, data[:i], nil
}
}
if !atEOF {
return 0, nil, nil
}
// There is one final token to be delivered, which may be the empty string.
// Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this
// but does not trigger an error to be returned from Scan itself.
return 0, data, bufio.ErrFinalToken
}
scanner.Split(onComma)
// Scan.
for scanner.Scan() {
fmt.Printf("%q ", scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading input:", err)
}
Вывод:
"1" "2" "3" "4" ""
Пример (Строки)
Простейший способ использовать Scanner — читать стандартный ввод как набор строк.
Код:
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Println(scanner.Text()) // Println will add back the final '\n'
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
Пример (Слова)
Используйте Scanner для реализации простого средства подсчёта слов, сканируя входные данные как последовательность токенов, разделённых пробелами.
Код:
// An artificial input source.
const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n"
scanner := bufio.NewScanner(strings.NewReader(input))
// Set the split function for the scanning operation.
scanner.Split(bufio.ScanWords)
// Count the words.
count := 0
for scanner.Scan() {
count++
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading input:", err)
}
fmt.Printf("%d\n", count)
Вывод:
15
func NewScanner 1.1
func NewScanner(r io.Reader) *Scanner
NewScanner возвращает новый Scanner для чтения из r. По умолчанию используется функция разделения ScanLines.
func (*Scanner) Buffer 1.6
func (s *Scanner) Buffer(buf []byte, max int)
Buffer управляет выделением памяти Scanner. Он задаёт начальный буфер для сканирования и максимальный размер буфера, который может быть выделен во время сканирования. Содержимое буфера игнорируется.
Максимальный размер токена должен быть меньше большего из значений max и cap(buf). Если max <= cap(buf), Scanner.Scan будет использовать только этот буфер и не станет выделять память.
По умолчанию Scanner.Scan использует внутренний буфер и устанавливает максимальный размер токена, равный MaxScanTokenSize.
Buffer вызывает панику, если его вызвать после начала сканирования.
func (*Scanner) Bytes 1.1
func (s *Scanner) Bytes() []byte
Bytes возвращает последний токен, созданный вызовом Scanner.Scan. Базовый массив может указывать на данные, которые будут перезаписаны при следующем вызове Scan. Память не выделяется.
Пример
Верните результат последнего вызова Scan в виде []byte.
Код:
scanner := bufio.NewScanner(strings.NewReader("gopher"))
for scanner.Scan() {
fmt.Println(len(scanner.Bytes()) == 6)
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "shouldn't see an error scanning a string")
}
Вывод:
true
func (*Scanner) Err 1.1
func (s *Scanner) Err() error
Err возвращает первую ошибку, отличную от EOF, обнаруженную Scanner.
func (*Scanner) Scan 1.1
func (s *Scanner) Scan() bool
Scan перемещает Scanner к следующему токену, который затем будет доступен через метод Scanner.Bytes или Scanner.Text. Метод возвращает false, когда токенов больше нет — при достижении конца входных данных или возникновении ошибки. После того как Scan вернёт false, метод Scanner.Err вернёт любую ошибку, возникшую во время сканирования, за исключением случая, когда это была io.EOF: тогда Scanner.Err вернёт nil. Scan вызывает панику, если функция разделения возвращает слишком много пустых токенов, не продвигаясь по входным данным. Это распространённая причина ошибок при использовании сканеров.
func (*Scanner) Split 1.1
func (s *Scanner) Split(split SplitFunc)
Split задаёт функцию разделения для Scanner. По умолчанию используется функция разделения ScanLines.
Split вызывает панику, если его вызвать после начала сканирования.
func (*Scanner) Text 1.1
func (s *Scanner) Text() string
Text возвращает последний токен, созданный вызовом Scanner.Scan, в виде новой строки, содержащей его байты.
type SplitFunc 1.1
SplitFunc — это сигнатура функции разделения, используемой для разбиения входных данных на токены. Аргументы — начальная подстрока оставшихся необработанных данных и флаг atEOF, указывающий, остались ли у Reader данные для чтения. Возвращаемые значения — количество байтов, на которое нужно продвинуться во входных данных, следующий токен для возврата пользователю (если он есть) и ошибка (если она есть).
Сканирование останавливается, если функция возвращает ошибку; в этом случае часть входных данных может быть отброшена. Если этой ошибкой является ErrFinalToken, сканирование останавливается без ошибки. Ненулевой токен, возвращённый вместе с ErrFinalToken, будет последним токеном, а nil-токен вместе с ErrFinalToken немедленно останавливает сканирование.
В противном случае Scanner продвигается по входным данным. Если токен не nil, Scanner возвращает его пользователю. Если токен равен nil, Scanner считывает дополнительные данные и продолжает сканирование; если данных больше нет — если atEOF имеет значение true, — Scanner завершает работу. Если данные пока не содержат полного токена, например если при сканировании строк в них нет символа новой строки, SplitFunc может вернуть (0, nil, nil), чтобы сообщить Scanner, что нужно считать в срез дополнительные данные и повторить попытку с более длинным срезом, начинающимся в той же точке входных данных.
Функция никогда не вызывается с пустым срезом данных, если только atEOF не имеет значение true. Однако если atEOF имеет значение true, данные могут быть непустыми и, как всегда, содержать ещё не обработанный текст.
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
type Writer
Writer реализует буферизацию для объекта io.Writer. Если при записи в Writer возникает ошибка, новые данные больше не принимаются, а все последующие операции записи и вызовы Writer.Flush будут возвращать эту ошибку. После записи всех данных клиенту следует вызвать метод Writer.Flush, чтобы гарантировать передачу всех данных нижележащему объекту io.Writer.
type Writer struct {
// contains filtered or unexported fields
}
Пример
Код:
w := bufio.NewWriter(os.Stdout) fmt.Fprint(w, "Hello, ") fmt.Fprint(w, "world!") w.Flush() // Don't forget to flush!
Вывод:
Hello, world!
func NewWriter
func NewWriter(w io.Writer) *Writer
NewWriter возвращает новый Writer с буфером размера по умолчанию. Если аргумент io.Writer уже является Writer с буфером достаточного размера, возвращается нижележащий Writer.
func NewWriterSize
func NewWriterSize(w io.Writer, size int) *Writer
NewWriterSize возвращает новый Writer с буфером не меньше указанного размера. Если аргумент io.Writer уже является Writer достаточного размера, возвращается нижележащий Writer.
func (*Writer) Available
func (b *Writer) Available() int
Available возвращает количество свободных байтов в буфере.
func (*Writer) AvailableBuffer 1.18
func (b *Writer) AvailableBuffer() []byte
AvailableBuffer возвращает пустой буфер ёмкостью b.Available(). Этот буфер предназначен для добавления данных и передачи непосредственно следующему вызову Writer.Write. Буфер действителен только до следующей операции записи в b.
Пример
Код:
w := bufio.NewWriter(os.Stdout)
for _, i := range []int64{1, 2, 3, 4} {
b := w.AvailableBuffer()
b = strconv.AppendInt(b, i, 10)
b = append(b, ' ')
w.Write(b)
}
w.Flush()
Вывод:
1 2 3 4
func (*Writer) Buffered
func (b *Writer) Buffered() int
Buffered возвращает количество байтов, записанных в текущий буфер.
func (*Writer) Flush
func (b *Writer) Flush() error
Flush записывает все буферизованные данные в нижележащий объект io.Writer.
func (*Writer) ReadFrom 1.1
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
ReadFrom реализует io.ReaderFrom. Если нижележащий писатель поддерживает метод ReadFrom, вызывается этот метод нижележащего писателя. Если имеются буферизованные данные и нижележащий писатель поддерживает ReadFrom, данные сначала записываются после заполнения буфера, а затем вызывается ReadFrom.
Пример
ExampleWriter_ReadFrom демонстрирует использование метода ReadFrom типа Writer.
Код:
var buf bytes.Buffer
writer := bufio.NewWriter(&buf)
data := "Hello, world!\nThis is a ReadFrom example."
reader := strings.NewReader(data)
n, err := writer.ReadFrom(reader)
if err != nil {
fmt.Println("ReadFrom Error:", err)
return
}
if err = writer.Flush(); err != nil {
fmt.Println("Flush Error:", err)
return
}
fmt.Println("Bytes written:", n)
fmt.Println("Buffer contents:", buf.String())
Вывод:
Bytes written: 41 Buffer contents: Hello, world! This is a ReadFrom example.
func (*Writer) Reset 1.2
func (b *Writer) Reset(w io.Writer)
Reset отбрасывает все не записанные из буфера данные, сбрасывает ошибку и перенаправляет вывод b в w. Вызов Reset для нулевого значения Writer инициализирует внутренний буфер размером по умолчанию. Вызов w.Reset(w) (то есть сброс Writer в самого себя) ничего не делает.
func (*Writer) Size 1.10
func (b *Writer) Size() int
Size возвращает размер нижележащего буфера в байтах.
func (*Writer) Write
func (b *Writer) Write(p []byte) (nn int, err error)
Write записывает содержимое p в буфер. Метод возвращает количество записанных байтов. Если nn < len(p), он также возвращает ошибку с объяснением причины неполной записи.
func (*Writer) WriteByte
func (b *Writer) WriteByte(c byte) error
WriteByte записывает один байт.
func (*Writer) WriteRune
func (b *Writer) WriteRune(r rune) (size int, err error)
WriteRune записывает одну кодовую точку Unicode и возвращает количество записанных байтов и возможную ошибку.
func (*Writer) WriteString
func (b *Writer) WriteString(s string) (int, error)
WriteString записывает строку. Метод возвращает количество записанных байтов. Если это количество меньше len(s), он также возвращает ошибку с объяснением причины неполной записи.
© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/bufio/