io

最后更新于:2022-04-02 02:44:21

[TOC] ## io ### Reader 接口 ``` type Reader interface { Read(p []byte) (n int, err error) } ``` 示例1: 字符串生成 reader 接口 ``` reader := strings.NewReader("hello world") b := make([]byte, 1) _, err := reader.Read(b) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", b) ``` 示例2:写一个 Reader 接口
main.go ``` type User struct { s string i int } func NewUser(s string) *User { return &User{s: s} } func (u *User) Len() int { return len(u.s) - u.i } func (u *User) Read(p []byte) (n int, err error) { // i 还没到结尾 && n 的大小不大于p 的切片长度 for u.i < len(u.s) && n < len(p) { p[n] = u.s[u.i] n++ u.i++ } if n == 0 { return 0, io.EOF } return n, nil } func main() { user := NewUser("hello world") b := make([]byte, 5) n, err := io.ReadFull(user, b) if err != nil { log.Fatal(err) } fmt.Printf("%+v\n", n) fmt.Printf("%+v\n", string(b)) //hello world } ```

### Writer 接口 ``` // Writer 接口包装了基本的 Write 方法,用于将数据存入自身。 // Write 方法用于将 p 中的数据写入到对象的数据流中, // 返回写入的字节数和遇到的错误。 // 如果 p 中的数据全部被写入,则 err 应该返回 nil。 // 如果 p 中的数据无法被全部写入,则 err 应该返回相应的错误信息。 type Writer interface { Write(p []byte) (n int, err error) } ``` ### Seeker 偏移量 ``` const ( SeekStart = 0 // 相对开始位置的偏移量 SeekCurrent = 1 // 相对当前位置的偏移量 SeekEnd = 2 // 相对结束位置的偏移量 ) type Seeker interface { Seek(offset int64, whence int) (ret int64, err error) } ``` ``` r := strings.NewReader("some io.Reader stream to be read\n") r.Seek(5, io.SeekStart) // move to the 5th char from the start if _, err := io.Copy(os.Stdout, r); err != nil { log.Fatal(err) } r.Seek(-5, io.SeekEnd) if _, err := io.Copy(os.Stdout, r); err != nil { log.Fatal(err) } // Output: // io.Reader stream to be read // read ``` ### Closer接口 ``` // Closer 接口包装了基本的 Close 方法,用于关闭数据读写。 // Close 一般用于关闭文件,关闭通道,关闭连接,关闭数据库等 type Closer interface { Close() error } ``` ### ReadAtLeast 至少读取多少字节 ``` // ReadAtLeast 从 r 中读取数据到 buf 中,要求至少读取 min 个字节。 // 返回读取的字节数和遇到的错误。 // 如果 min 超出了 buf 的容量,则 err 返回 io.ErrShortBuffer,否则: // 1、读出的数据长度 == 0 ,则 err 返回 EOF。 // 2、读出的数据长度 < min,则 err 返回 io.ErrUnexpectedEOF。 // 3、读出的数据长度 >= min,则 err 返回 nil。 func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) ``` ### ReadFull ``` // ReadFull 的功能和 ReadAtLeast 一样,只不过 min = len(buf) func ReadFull(r Reader, buf []byte) (n int, err error) ``` 示例: ``` reader := strings.NewReader("abcdefg") b := make([]byte, 3) io.ReadFull(reader, b) fmt.Printf("%s\n", b) io.ReadFull(reader, b) fmt.Printf("%s\n", b) ``` ### io.Pipe() 一方读,一方写 ``` func ioWrite(w io.Writer) { for { _, err := w.Write([]byte("hello\n")) if err != nil { fmt.Printf("%+v\n", err) } time.Sleep(1 * time.Second) } } func ioRead(r io.Reader) { reader := bufio.NewReader(r) for { line, _, err := reader.ReadLine() if err != nil { fmt.Printf("%+v\n", err) } fmt.Printf("line: %s\n", line) } } func main() { pr, pw := io.Pipe() go ioWrite(pw) ioRead(pr) pr.Close() pw.Close() } ``` ### Copy ``` io.Copy(os.Stdout, strings.NewReader("Go语言中文网")) ``` ### CopyN 拷贝指定数字节 ``` io.CopyN(os.Stdout, strings.NewReader("hello wored"), 3) ``` ### CopyBuffer 带一个缓存的copy ``` // CopyBuffer 相当于 Copy,只不 Copy 在执行的过程中会创建一个临时的缓冲区来中 // 转数据,而 CopyBuffer 则可以单独提供一个缓冲区,让多个复制操作共用同一个缓 // 冲区,避免每次复制操作都创建新的缓冲区。如果 buf == nil,则 CopyBuffer 会 // 自动创建缓冲区。 func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) ``` ### WriteString Writer接口写入string ``` func WriteString(w Writer, s string) (n int, err error) ``` 示例 ``` file, _ := os.OpenFile("abc", os.O_RDWR, 0777) io.WriteString(file, "aaaaa22222") ``` ### LimitReader 限制被Reader 长度 ``` r := strings.NewReader("Hello World!") lr := io.LimitReader(r, 5) n, err := io.Copy(os.Stdout, lr) // Hello fmt.Printf("\n%d %v\n", n, err) // 5 n, err = io.Copy(os.Stdout, lr) // fmt.Printf("\n%d %v\n", n, err) // 0 ``` ### NewSectionReader 对 Reader 限制 offset 与 length ``` // NewSectionReader 对 r 进行封装,使其只能从 off 位置开始读取,最多只能读取 n // 个字节的的数据。相当于对 r 做了一个切片 r[off:off+n] 返回。 // 底层实现是一个 *SectionReader。 func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader ``` 示例 ``` r := strings.NewReader("abcdef") sr := io.NewSectionReader(r, 2, 3) io.Copy(os.Stdout, sr) // ced io.Copy(os.Stdout, sr) // 空 ``` ### MultiReader ``` readers := []io.Reader{ bytes.NewBufferString("123"), strings.NewReader("abc"), } reader := io.MultiReader(readers...) p := make([]byte, 50) reader.Read(p) fmt.Println(string(p)) //123 reader.Read(p) fmt.Println(string(p)) //abc ``` 说明 `MultiReader`只是把多个reader 作为切片连接,并不能一次获取所有的reader,只有当第一个获取完才可以获取第二个 ### MultiWriter ``` r := strings.NewReader("hello world\n") f, _ := os.Create("t.txt") defer f.Close() //同事输出和写入文件 writer := io.MultiWriter(os.Stdout, os.Stdout, f) r.WriteTo(writer) // console: // hello world // hello world // cat t.txt // hello world ```
';