非常教程

Go参考手册

缓冲区 | bufio

缓存 | bufio

  • import "bufio"
  • 概述
  • 索引
  • 示例

概述

软件包 bufio 实现了缓冲 I/O 。它包装一个 io.Reader 或io.Writer 对象,创建另一个对象(Reader 或 Writer),它也实现了接口,但提供缓冲和文本 I/O 的一些帮助。

Index

Contants(常量)

Variables(变量)

func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)

func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)

func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)

type ReadWriter

  • func NewReadWriter(r *Reader, w *Writer) *ReadWriter

type Reader

  • func NewReader(rd io.Reader) *Reader
  • func NewReaderSize(rd io.Reader, size int) *Reader
  • func (b *Reader) Buffered() int
  • func (b *Reader) Discard(n int) (discarded int, err error)
  • func (b *Reader) Peek(n int) ([]byte, error)
  • func (b *Reader) Read(p []byte) (n int, err error)
  • func (b *Reader) ReadByte() (byte, error)
  • func (b *Reader) ReadBytes(delim byte) ([]byte, error)
  • func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
  • func (b *Reader) ReadRune() (r rune, size int, err error)
  • func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
  • func (b *Reader) ReadString(delim byte) (string, error)
  • func (b *Reader) Reset(r io.Reader)
  • func (b *Reader) UnreadByte() error
  • func (b *Reader) UnreadRune() error
  • func (b *Reader) WriteTo(w io.Writer) (n int64, err error)

type Scanner

  • func NewScanner(r io.Reader) *Scanner
  • func (s *Scanner) Buffer(buf []byte, max int)
  • func (s *Scanner) Bytes() []byte
  • func (s *Scanner) Err() error
  • func (s *Scanner) Scan() bool
  • func (s *Scanner) Split(split SplitFunc)
  • func (s *Scanner) Text() string

type SplitFunc

type Writer

  • func NewWriter(w io.Writer) *Writer
  • func NewWriterSize(w io.Writer, size int) *Writer
  • func (b *Writer) Available() int
  • func (b *Writer) Buffered() int
  • func (b *Writer) Flush() error
  • func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
  • func (b *Writer) Reset(w io.Writer)
  • func (b *Writer) Write(p []byte) (nn int, err error)
  • func (b *Writer) WriteByte(c byte) error
  • func (b *Writer) WriteRune(r rune) (size int, err error)
  • func (b *Writer) WriteString(s string) (int, error)

示例

Scanner (Custom) Scanner (EmptyFinalToken) Scanner (Lines) Scanner (Words) Writer

包文件

bufio.go scan.go

常量

const (
        // MaxScanTokenSize是用于缓冲令牌的最大大小
        // 除非用户使用Scan.Buffer提供一个明确的缓冲区。
        // 缓冲区的实际最大标记大小可能较小
        // 可能需要包含一个换行符。
        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")
)

ErrFinalToken 是一个特殊的 sentinel 错误值。它旨在通过 Split 函数返回,以指示随错误交付的令牌是最后一个令牌,并且在此之后应该停止扫描。扫描收到 ErrFinalToken 后,扫描(没有错误)停止。该值对于提前停止处理或需要传递最终空令牌时非常有用。可以用自定义的错误值实现相同的行为,但是在这里提供一个更整齐的。查看 emptyFinalToken 示例以了解该值的用法。

var ErrFinalToken = errors.New("final token")

func ScanBytes(查看源代码)

func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)

ScanBytes 是 Scanner 的分割函数,它将每个字节作为标记返回。

func ScanLines(查看源代码)

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)

ScanLines 是扫描仪的分离功能,可以返回每一行文本,并将任何尾随行尾标记剥离。返回的行可能为空。行尾标记是一个可选的回车符,后跟一个强制换行符。在正则表达式中,它是\r?\n。即使没有换行,也会返回最后一个非空行输入。

func ScanRunes(查看源代码)

func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)

ScanRunes 是扫描仪的分离功能,可以将每个UTF-8编码符文作为标记返回。返回的符文序列与输入中的范围循环相当于一个字符串,这意味着错误的UTF-8编码转换为 U+FFFD = "\xef\xbf\xbd"。由于Scan界面,这使得客户端无法区分正确编码的替换符文和编码错误。

func ScanWords(查看源代码)

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 对象实现缓冲。

type Reader struct {
        // 包含过滤或未导出的字段
}

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(查看源代码)

func (b *Reader) Discard(n int) (discarded int, err error)

丢弃跳过下 n 个字节,返回丢弃的字节数。

如果放弃跳过少于 n 个字节,它也会返回一个错误。如果 0 <= n <= b.Buffered(),则 Discard 保证在不读取底层 io.Reader 的情况下成功。

func (*Reader) Peek(查看源代码)

func (b *Reader) Peek(n int) ([]byte, error)

Peek 返回接下来的n个字节,而不会推进阅读器。字节在下次读取呼叫时停止有效。如果 Peek 返回少于 n 个字节,它也会返回一个错误,解释为什么读取很短。如果 n 大于 b 的缓冲区大小,则错误为 ErrBufferFull。

func (*Reader) Read(查看源代码)

func (b *Reader) Read(p []byte) (n int, err error)

读取数据到页面。它返回读入p的字节数。这些字节是从底层读取器读取的,因此 n 可能小于 len(p) 。在 EOF 时,计数将为零,err 将为 io.EOF 。

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 。对于简单的用途,扫描仪可能更方便。

func (*Reader) ReadLine(查看源代码)

func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

ReadLine 是一个低级的 line-reading 取原语。大多数调用者应该使用 ReadBytes('\n') 或 ReadString('\n') 来代替或使用扫描器。

ReadLine 尝试返回一行,不包括行尾字节。如果该行对于缓冲区太长,则设置 isPrefix 并返回该行的开头。该行的其余部分将从未来的调用中返回。返回该行的最后一个片段时,isPrefix 将为false。返回的缓冲区仅在下一次调用 ReadLine 之前有效。ReadLine 也可以返回一个非零行,或者返回一个错误,从来不是两者一起。

从 ReadLine 返回的文本不包含行尾("\r\n" 或 "\n")。如果输入没有最后一行结束,则没有提示或错误。在 ReadLine 之后调用 UnreadByte 将始终读取最后读取的字节(可能是属于行结束的字符),即使该字节不是由 ReadLine 返回的行的一部分。

func (*Reader) ReadRune(查看源代码)

func (b *Reader) ReadRune() (r rune, size int, err error)

ReadRune 读取单个 UTF-8 编码的 Unicode 字符,并以字节为单位返回符文及其大小。如果编码的符文无效,它将消耗一个字节并返回大小为1的 unicode.ReplacementChar (U+FFFD)。

func (*Reader) ReadSlice(查看源代码)

func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

ReadSlice 读取直到输入中第一次出现 delim,返回指向缓冲区中字节的片段。字节在下次读取时停止有效。如果ReadSlice在查找分隔符之前遇到错误,它将返回缓冲区中的所有数据和错误本身(通常为 io.EOF)。如果缓冲区没有分隔符,则ReadSlice将失败并返回错误 ErrBufferFull 。因为从 ReadSlice 返回的数据将被下一个I/O操作覆盖,所以大多数客户端应该使用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。对于简单的用途,扫描仪可能更方便。

func (*Reader) Reset(查看源代码)

func (b *Reader) Reset(r io.Reader)

重置放弃任何缓冲数据,重置所有状态,并将缓冲读取器从 r 读取。

func (*Reader) UnreadByte(查看源代码)

func (b *Reader) UnreadByte() error

UnreadByte 未读取最后一个字节。只有最近读取的字节可以是未读的。

func (*Reader) UnreadRune(查看源代码)

func (b *Reader) UnreadRune() error

UnreadRune 未阅读最后的符文。如果缓冲区上的最新读取操作不是 ReadRune,则 UnreadRune 会返回错误。(在这方面,它比 UnreadByte 更严格,它将读取任何读操作的最后一个字节。)

func (*Reader) WriteTo(查看源代码)

func (b *Reader) WriteTo(w io.Writer) (n int64, err error)

WriteTo 实现 io.WriterTo。这可能会多次调用底层 Reader 的Read 方法。

type Scanner(查看源代码)

Scanner 为阅读数据提供了一个方便的界面,例如文本换行符分隔的文本。连续调用 Scan 方法将跳过文件的“令牌”,跳过令牌之间的字节。令牌的规范由 SplitFunc 类型的分割函数定义;默认的分割功能将输入分割为行终止的行。在此包中定义了分割函数,用于将文件扫描为行,字节,UTF-8 编码的符文和空格分隔的文字。客户端可以改为提供自定义分割功能。

扫描在 EOF 处无法恢复,第一个 I/O 错误或太大而无法放入缓冲区的令牌。当扫描停止时,读者可能已经远离最后一个标记任意地前进了。需要对错误处理或大标记进行更多控制的程序,或者必须在阅读器上运行顺序扫描的程序应改为使用 bufio.Reader。

type Scanner struct {
        // 包含过滤或未导出的字段
}

示例(自定义)

使用具有自定义拆分功能的 Scanner(通过封装 ScanWords 构建)来验证32位十进制输入。

代码:

// 人为输入源。
const input = "1234 5678 1234567901234567890"
scanner := bufio.NewScanner(strings.NewReader(input))
// 通过包装现有的ScanWords函数来创建自定义拆分功能。
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
}
// 设置扫描操作的分割功能。
scanner.Split(split)
// 验证输入
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

示例(EmptyFinalToken)

使用具有自定义拆分功能的扫描仪可以用空的最终值分析逗号分隔的列表。

package main

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

func main() {
	// 逗号分隔的列表; 最后一项是空的。
	const input = "1,2,3,4,"
	scanner := bufio.NewScanner(strings.NewReader(input))
	// 定义一个以逗号分隔的分割函数。
	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
			}
		}
		// 有一个最终的令牌要交付,可能是空字符串。
		// 在这里返回bufio.ErrFinalToken告诉Scan,在此之后没有更多的标记
		// 但不会触发从扫描本身返回的错误。
		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)
	}
}

示例(行)

最简单的 Scanner 使用,可以将标准输入读取为一组行。

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		fmt.Println(scanner.Text()) // Println将添加最后的'\n'
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

示例(词)

使用扫描程序通过将输入扫描为一系列空格分隔的令牌来实现简单的字数统计实用程序。

package main

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

func main() {
	// 人为输入源。
	const input = "Now is the winter of our discontent,\nMade glorious summer by this sun of York.\n"
	scanner := bufio.NewScanner(strings.NewReader(input))
	// 设置扫描操作的分割功能。
	scanner.Split(bufio.ScanWords)
	// 计算单词。
	count := 0
	for scanner.Scan() {
		count++
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}
	fmt.Printf("%d\n", count)
}

func NewScanner(查看源代码)

func NewScanner(r io.Reader) *Scanner

NewScanner 返回一个新的扫描仪来从 r 读取内容。分割功能默认为 ScanLines。

func (*Scanner) Buffer(查看源代码)

func (s *Scanner) Buffer(buf []byte, max int)

缓冲区设置扫描时要使用的初始缓冲区以及扫描期间可能分配的最大缓冲区大小。最大令牌大小是 max 和 cap(buf) 中较大的一个。如果 max <= cap(buf),扫描将仅使用此缓冲区并且不进行分配。

默认情况下,Scan 使用内部缓冲区并将最大标记大小设置为MaxScanTokenSize 。

如果在扫描开始后调用缓冲区,则会发生混乱。

func (*Scanner) Bytes(查看源代码)

func (s *Scanner) Bytes() []byte

字节返回由扫描调用产生的最新令牌。底层数组可能指向将被随后的扫描调用覆盖的数据。它没有分配。

func (*Scanner) Err(查看源代码)

func (s *Scanner) Err() error

Err 返回扫描器遇到的第一个非EOF错误。

func (*Scanner) Scan(查看源代码)

func (s *Scanner) Scan() bool

扫描将扫描仪推进到下一个标记,然后通过字节或文本方法使用该标记。当扫描停止时,它会返回 false,通过到达输入末尾或错误。在 Scan 返回 false 后,Err 方法将返回扫描期间发生的任何错误,除了如果它是 io.EOF,Err 将返回 nil。如果分割函数返回100个空令牌而不提前输入,则扫描恐慌。这是扫描仪的常见错误模式。

func (*Scanner) Split(查看源代码)

func (s *Scanner) Split(split SplitFunc)

分割设定扫描仪的分割功能。默认的分割功能是 ScanLines 。

如果在扫描开始后调用它,则会将其分割。

func (*Scanner) Text(查看源代码)

func (s *Scanner) Text() string

文本将通过调用 Scan 生成的最新令牌返回为保存其字节的新分配的字符串。

type SplitFunc(查看源代码)

SplitFunc 是用于标记输入的分割函数的签名。参数是剩余的未处理数据的初始子字符串和 atEOF 标志,该标志报告 Reader 是否没有更多数据可供使用。返回值是提前输入的字节数和返回给用户的下一个标记,以及一个错误(如果有的话)。如果数据还没有保存一个完整的标记,例如在扫描行时没有换行符,SplitFunc可以返回 (0, nil, nil) 来指示扫描器向切片中读入更多数据,并用较长的切片再次尝试从输入中的相同点开始。

如果返回的错误不为零,则扫描停止并将错误返回给客户端。

除非 atEOF 为真,否则该函数绝不会用空数据切片调用。但是,如果 atEOF 为真,则数据可能非空,并且一如既往地保留未处理的文本。

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

type Writer(查看源代码)

编写器为 io.Writer 对象实现缓冲。如果写入写入器时发生错误,则不会接受更多数据,并且所有后续写入和刷新都将返回错误。完成所有数据写入后,客户端应调用 Flush 方法以确保所有数据已转发到基础 io.Writer。

type Writer struct {
        // 包含过滤或未导出的字段
}

示例

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	w := bufio.NewWriter(os.Stdout)
	fmt.Fprint(w, "Hello, ")
	fmt.Fprint(w, "world!")
	w.Flush() // 不要忘记刷新!
}

func NewWriter(查看源代码)

func NewWriter(w io.Writer) *Writer

NewWriter 返回一个新的 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

可用返回缓冲区中未使用的字节数。

func (*Writer) Buffered(查看源代码)

func (b *Writer) Buffered() int

Buffered 返回已写入当前缓冲区的字节数。

func (*Writer) Flush(查看源代码)

func (b *Writer) Flush() error

Flush 将任何缓冲的数据写入底层的 io.Writer。

func (*Writer) ReadFrom(查看源代码)

func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)

ReadFrom 实现了 io.ReaderFrom。

func (*Writer) Reset(查看源代码)

func (b *Writer) Reset(w io.Writer)

重置放弃任何未刷新的缓冲数据,清除任何错误,并重置b以将其输出写入 w。

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),它也会返回一个错误,解释为什么写入很短。

缓冲区 | bufio相关

Go

Go 是一种编译型语言,它结合了解释型语言的游刃有余,动态类型语言的开发效率,以及静态类型的安全性。它也打算成为现代的,支持网络与多核计算的语言。要满足这些目标,需要解决一些语言上的问题:一个富有表达能力但轻量级的类型系统,并发与垃圾回收机制,严格的依赖规范等等。这些无法通过库或工具解决好,因此Go也就应运而生了。

主页 https://golang.org/
源码 https://go.googlesource.com/go
发布版本 1.9.2

Go目录

1.档案 | archive
2.缓冲区 | bufio
3.内置 | builtin
4.字节 | bytes
5.压缩 | compress
6.容器 | container
7.上下文 | context
8.加密 | crypto
9.数据库 | database
10.调试 | debug
11.编码 | encoding
12.错误 | errors
13. expvar
14.flag
15. fmt
16. go
17.散列 | hash
18.html
19.图像 | image
20.索引 | index
21.io
22.日志 | log
23.数学 | math
24. math/big
25.math/bits
26.math/cmplx
27.math/rand
28.拟态 | mime
29.net
30.net/http
31. net/mail
32. net/rpc
33.net/smtp
34. net/textproto
35. net/url
36.os
37.路径 | path
38.插件 | plugin
39.反射 | reflect
40.正则表达式 | regexp
41.运行时 | runtime
42.排序算法 | sort
43.转换 | strconv
44.字符串 | strings
45.同步 | sync
46.系统调用 | syscall
47.测试 | testing
48.文本 | text
49.时间戳 | time
50.unicode
51.不安全性 | unsafe
52.Go 语言数据类型
53.Go 语言基础语法
54.Go 语言结构
55.Go 语言 select 语句
56.Go 语言 switch 语句
57.Go 语言 if 语句嵌套
58.Go 语言 if…else 语句
59.Go 语言 if 语句
60.Go 语言运算符
61.Go 语言常量
62.Go 语言函数闭包
63.Go 语言函数作为实参
64.Go 语言函数引用传递值
65.Go 语言函数值传递值
66.Go 语言函数
67.Go 语言 goto 语句
68.Go 语言 continue 语句
69.Go 语言 break 语句
70.Go 语言循环嵌套
71.Go 语言 for 循环
72.Go 语言结构体
73.Go 语言指针作为函数参数
74.Go 语言指向指针的指针
75.Go 语言指针数组
76.Go 语言指针
77.Go 语言向函数传递数组
78.Go 语言多维数组
79.Go 语言变量作用域
80.Go 语言函数方法
81.Go 错误处理
82.Go 语言接口
83.Go 语言类型转换
84.Go 语言递归函数
85.Go 语言Map(集合)
86.Go 语言范围(Range)
87.Go 语言切片(Slice)
88.Go 并发
89.Go fmt.Sprintf 格式化字符串