zoukankan      html  css  js  c++  java
  • 简析 Golang IO 包

    简析 Golang IO 包

    io 包提供了 I/O 原语(primitives)的基本接口。io 包中定义了四个最基本接口 Reader、Writer、Closer、Seeker 用于表示二进制流的读、写、关闭和寻址操作。这些原语和接口是对底层操作的封装,因此如没有特殊说明,这些原语和接口都不能被视为线程安全的。

    Reader

    Reader 接口封装了基本的 Read 方法。Read 读取长度为 len(p) 字节的数据,并写入到 p。返回结果包含读取数据字节数(0 <= n <= len(p))和 error 信息。

    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    

    当 Read 在读取 n > 0 个字节后遇到异常或 EOF 时,Read 会返回读取的字节数。在这次读取时,可能会返回非空 error。但再一次读取,会读空并返回 error。典型的例子是,Reader 读取完全部输入流,下一次 Read 就会返回 0, EOF:

    func main() {
    	r := strings.NewReader("some io.Reader stream to be read")
    
    	b := make([]byte, 32)
    	n, err := r.Read(b)
    	// 32, some io.Reader stream to be read, <nil>
    	fmt.Printf("%d, %s, %v", n, b, err)
    
    	b = make([]byte, 32)
    	n, err = r.Read(b) 
    	// 0, EOF
    	fmt.Printf("%d, %v", n, err)
    }
    

    Read 的实现方法不建议返回 0 的同时,返回 nil error,除非 len(p) == 0。它并不代表 EOF。

    常用的 Reader 接口实现有:

    1.strings 包下的 Reader 类型

    相关支持函数有:

    • func NewReader(s string) *Reader:生产字符串 s 对应的 Reader(Read-only,未实现 Write 方法)
    • func (r *Reader) Len() int:尚未被读取的字符串部分字节数
    • unc (r *Reader) Read(b []byte) (n int, err error):Read 实现方法

    2.bytes 包下的 Buffer 类型和 Reader 类型

    Buffer 类型和 Reader 类型不同之处在于,前者实现了 Writer 接口,而后者是 read-only。

    Writer

    Writer 接口封装了 Write 方法。实现从缓冲区取 len(p) 字节大小的数据,写入底层数据流。如果一切正常,Write 返回 写入字节大小(n == len(p))和 nil error。否则返回 non-nil error 且 n < len(p)。

    type Writer interface {
        Write(p []byte) (n int, err error)
    }
    

    常用的 Writer 接口实现有:

    1.strings 包下的 Builder 类型

    Builder 用于高效地组建字符串,最小化消耗内存资源。

    func main() {
    	proverbs := []string{
    		"Channels orchestrate mutexes serialize.",
    		"Cgo is not Go.",
    		"Errors are values.",
    		"Don't panic.",
    	}
    	var writer strings.Builder
    
    	for _, p := range proverbs {
    		n, err := writer.Write([]byte(p))
    		if err != nil {
    			fmt.Println(err)
    		}
    		if n != len(p) {
    			fmt.Println("failed to write data")
    		}
    	}
    
    	// 打印 Channels orchestrate mutexes serialize.Cgo is not Go.Errors are values.Don't panic.
    	fmt.Println(writer.String())
    }
    

    2.bytes 包下的 Buffer 类型

    3.http 包下的 ResponseWriter 接口

    type ResponseWriter interface {
        // 返回 Header 对象,可以通过它的 Set() 方法设置头部
        Header() Header
    
        // 写入数据到 HTTP 应答报文
        Write([]byte) (int, error)
    
        // 设置返回状态码。如果没有调用这个函数,默认设置为 http.StatusOK
        WriteHeader(statusCode int)
    }
    

    以下例子在 localhost:8080/handler 监听请求,并写回字符串 ”This is the HTTP response.“

    func main() {
    	http.HandleFunc("/handler", func(w http.ResponseWriter, req *http.Request) {
    		io.WriteString(w, "This is the HTTP response.
    ")
    	})
    
    	log.Fatal(http.ListenAndServe(":8080", nil))
    }
    

    4.go-restful 包下的 Response 类型

    Response 类型封装了 http.ResponseWriter,它提供了很多便捷的方法支持写回数据。

    type Response struct {
        http.ResponseWriter
        // contains filtered or unexported fields
    }
    

    Closer

    Closer 接口封装 Close 方法。一般用于关闭文件,关闭通道,关闭连接,关闭数据库等

    type Closer interface {
        Close() error
    }
    

    Seeker

    Seeker 接口封装 Seeker 方法。Seek 方法用于设置偏移量(offset),下一次读写便从某个特定位置开始操作数据流。和 ReaderAt、WriteAt 接口有些类似,但 Seeker 接口更灵活,可以更好的控制读写数据流的位置。

    type Seeker interface {
        Seek(offset int64, whence int) (int64, error)
    }
    

    偏移量 offset 的解读取决于 whence(= from where,从那里)。0 表示相对于起始位置,1 表示相对于当前的偏移,而 2 表示相对于其结尾处。以下例子,指针会移到右起倒数第五个字符的位置。所以 reader.Len() 会输出 5。

    func main() {
    	reader := strings.NewReader("This is a test")
    	reader.Seek(-5, io.SeekEnd)
    	fmt.Printf("The unread portion of the string: %d
    ", reader.Len())
    }
    

    原语组合

    通过上面的四种基本接口的组合,我们可以得到多种原语组合,比如:ReadWriter、ReadCloser、WriteCloser 等。

    type ReadWriter interface {
        Reader
        Writer
    }
    

    参考文档:

    golang io中io.go解读

  • 相关阅读:
    自己实现的一个简单的C# IOC 容器
    C# 内存缓存工具类 MemoryCacheUtil
    使用触发器和C#程序实现数据同步
    Maven 命令安装指定 jar 包到本地仓库
    C# RSA 非对称加密
    JS可选链操作符?.和双问号??
    Learn D3 入门文档: Introduction
    Lerna 基本概念
    图片 src 为二进制的处理
    ASCII 和 Base64
  • 原文地址:https://www.cnblogs.com/huanggze/p/11595143.html
Copyright © 2011-2022 走看看