• Go package(3):io包介绍和使用


    IO 操作的基本分类

    在计算机中,处理文件和网络通讯等,都需要进行 IO 操作,IO 即是 input/ouput,计算机的输入输出操作。

    Go语言中的 IO 操作封装在如下几个包中:

    当然除了上面这些,还有一些比如 json,xml,tar 等也属于文件操作。

    其中 io 包中的 io.Readerio.Writer 比较关键。io.Reader 接口实现了对文件、套接字等输入设备的抽象;io.Writer 接口则实现了对输出设备的抽象。

    io 包提供了很多功能,这个包可以以流式的方式高效处理数据,而不用考虑数据是什么,数据来自哪里,以及数据要发送到哪里去。只要你实现了这2个接口。这就是抽象的能力。

    IO包2个重要接口 Reader 和 Writer

    在 io 包中有 2 个重要的接口:io.Readerio.Writer
    实现了这2个接口,就可以使用 io 包的功能。

    Reader 接口

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

    Read() 方法将 len(p) 个字节读取到 p 中。它返回读取的字节数 n,以及发生错误时的错误信息。

    1. 如果读到了数据(n > 0),则 err 应该返回 nil。
    2. 如果数据被读空,没有数据可读(n == 0),则 err 应该返回 EOF。
    3. 如果遇到读取错误,则 err 应该返回相应的错误信息。
    4. n 可能小于 len(p),也就是说在 Go 读取 IO 时,是不会保证一次读取预期的所有数据的。
    5. 如果要保证读取所需的所有数据,就需要在一个循环里调用 Read,累加每次返回的数据。

    只要某个实例实现了接口 io.Reader 里的方法 Read() ,就满足了接口 io.Reader ,可以当做参数传入进来。

    io.EOF 变量的定义:var EOF = errors.New("EOF"),是 error 类型。根据 reader 接口的说明,在 n > 0 且数据被读完了的情况下,当次返回的 error 有可能是 EOF 也有可能是 nil。

    例子1: demo_reader.go 从标准输入中读取数据

    package main
    
    import (
    	"fmt"
    	"io"
    	"os"
    )
    
    func ReadFrom(reader io.Reader, num int) ([]byte, error) {
    	p := make([]byte, num)
    	n, err := reader.Read(p)
    
    	fmt.Println("n: ", n)
    
    	if n > 0 {
    		return p[:n], nil
    	}
    	return p, err
    }
    
    func main() {
    	for {
    		data, err := ReadFrom(os.Stdin, 4)
    		if err != nil {
    			if err == io.EOF {
    				break
    			}
    		} else {
    			fmt.Printf("receive: %X, %s
    ", data, string(data))
    		}
    	}
    }
    

    Writer 接口

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

    Write 方法将 len(p) 个字节从 p 中写入到对象数据流中。它返回从 p 中被写入的字节数 n,以及发生错误时返回的错误信息。

    1. 如果 p 中的数据全部被写入,则 err 应该返回 nil。
    2. 如果 p 中的数据无法被全部写入,则 err 应该返回相应的错误信息。

    例子1 :demo_writer.go

    package main
    
    import (
    	"bytes"
    	"fmt"
    	"os"
    )
    
    func main() {
    	// 创建 Buffer 暂存空间,并将一个字符串写入 Buffer
    	// 使用 io.Writer 的 Write 方法写入
    	var buf bytes.Buffer
    	buf.Write([]byte("hello world , "))
    
    	// 用 Fprintf 将一个字符串拼接到 Buffer 里
    	fmt.Fprintf(&buf, " welcome to golang !")
    
    	// 将 Buffer 的内容输出到标准输出设备
    	buf.WriteTo(os.Stdout)
    }
    

    bytes.Buffer 结构体:
    bytes.Buffer 是一个结构体类型,用来暂存写入的数据,这个结构体实现了 io.Writer 接口的 Write 方法。

    Fprintf 方法定义:

    func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
    

    第一个参数是 io.Writer 接口类型,bytes.Buffer 结构体实现了 io.Writer 接口里的 Write 方法,实现了 Write 方法的类型都可以作为参数(这里是 buf)传入。

    WriteTo 方法定义:

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

    WriteTo 方法第一个参数是 io.Writer 接口类型。

    例子1:file_write.go

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	strings := []string{
    		"hello, golang! 
    ",
    		"welcome to golang! 
    ",
    		"Go is a good lang. ",
    	}
    
    	file, err := os.Create("./writefile.txt")
    	if err != nil {
    		fmt.Println(err)
    		os.Exit(1)
    	}
    
    	defer file.Close()
    
    	for _, p := range strings {
    		// file 类型实现了 io.Writer
    		n, err := file.Write([]byte(p))
    		if err != nil {
    			fmt.Println(err)
    			os.Exit(1)
    		}
    		if n != len(p) {
    			fmt.Println("failed to write data")
    			os.Exit(1)
    		}
    	}
    
    	fmt.Println("file wirte done")
    }
    

    把 strings 这个 slice 结构中的字符串写入到名为 writefile.txt 的文件中。

    参考

  • 相关阅读:
    BZOJ 1834 Luogu P2604 [ZJOI2010]网络扩容 (最小费用最大流)
    BZOJ 1565 Luogu P2805 [NOI2009]植物大战僵尸 (Tarjan判环、最小割)
    BZOJ 3993 Luogu P3324 [SDOI2015]星际战争 (最大流、二分答案)
    BZOJ 3277 串 & BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析)
    BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)
    Mongodb的聚合和管道
    Mongodb文档查询
    Mongodb的基本操作-数据库 集合 文档的增删改查
    Linux下Mongodb的安装
    mongdb的优势和不足
  • 原文地址:https://www.cnblogs.com/jiujuan/p/14005731.html
Copyright © 2020-2023  润新知