Go IO && bufio

IO

  • IO包 是对数据流的操作。从哪里来, 怎么处理,再到哪里去。
    736597-20190105171004056-316652798.png

736597-20190105171011810-1870484024.png

图片来源 https://medium.com/learning-the-go-programming-language/streaming-io-in-go-d93507931185

  • IO包 对数据的读写 是通过接口的形式约定的。数据的来源或者去向可能是 网络,内存,文件。
type Reader interface {
     Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}
  • 应用层 只需要按照接口去调用接口 不用关心底层实现细节 非常方便
package main

import (
    "io"
    "net/http"
    "os"
    "strings"
)

type R struct {
    reader io.Reader
}

func NewReader(r io.Reader) *R {
    return &R{
        reader: r,
    }
}

func (r *R) Read(p []byte) (n int, err error) {
    if _, err = r.reader.Read(p); err != nil {
        return
    }
    return len(p), nil
}

func main() {
    netR, err := http.Get("https://www.bilibili.com/")
    if err != nil {
        panic(err)
    }
    defer netR.Body.Close()
    fileR, err := os.Open("/tmp/data.txt")
    if err != nil {
        panic(err)
    }
    //读内存
    r1 := NewReader(strings.NewReader(""))
    b := make([]byte, 10*1024)
    if _, err := r1.Read(b); err != nil {
        panic(err)
    }
    //读网络
    r2 := NewReader(netR.Body)
    if _, err := r2.Read(b); err != nil {
        panic(err)
    }
    //读文件
    r3 := NewReader(fileR)
    if _, err := r3.Read(b); err != nil {
        panic(err)
    }
}

bufio

  • 每次对磁盘的写入或者发起网络请求 都会给系统带来压力。
    将多次操作合并为一次 会减轻系统的压力
  • 更优的流程是 producer --> buffer -->io.Writer

参考:https://medium.com/golangspec/introduction-to-bufio-package-in-golang-ad7d1877f762

func buffer() {
    fmt.Println("IO")
    w := new(W)
    w.Write([]byte{'1'})
    w.Write([]byte{'2'})
    w.Write([]byte{'3'})
    w.Write([]byte{'4'})

    fmt.Println("Buffer IO")
    bw := bufio.NewWriterSize(w, 3)
    bw.Write([]byte{'1'})
    bw.Write([]byte{'2'})
    bw.Write([]byte{'3'})
    bw.Write([]byte{'4'})
    err := bw.Flush()
    if err != nil {
        panic(err)
    }
}

type W struct {
}

func (*W) Write(p []byte) (n int, err error) {
    fmt.Println("length is ", len(p))
    fmt.Println(string(p))
    return len(p), nil
}
  • 普通的IO操作 会直接输出
  • buffio 则会首先收集数据到缓存中 等判断buffer满了
    之后才会一次性将缓存中的数据 输出。缓存中可能有多余的数据
    所以需要 最后单独调用flush 函数 强制将未满的缓存 输出

ReadFrom

  • 写操作之前需要 读取数据。io.ReaderFrom interface 就是
    为了更加方便的 从一个reader中读取数据
type ReaderFrom interface {
        ReadFrom(r Reader) (n int64, err error)
}
func ReadFrom() {
    sr := strings.NewReader("read from strings reader")
    w := new(W)
    bw := bufio.NewWriterSize(w, 6)
    if _, err := bw.ReadFrom(sr); err != nil {
        panic(err)
    }
    if err := bw.Flush(); err != nil {
        panic(err)
    }
}
  • bufio.Writer实现了这个接口 从reader中读取数据 io.reader -> buffer -> io.writer

ReadSlice

  • 如果bufio的NewReaderSize 如果小于16个字符 会设置为默认长度16个字符
  • 读取过程中 会优先判断buffer的size是否足够大 不够的话就会抛出 bufio: buffer full错误
  • bufio的ReadSlice函数可以读取读取指定字符之前的字符串,如果读到字符串末尾,还没有找到指定字符串
    则会返回eof
    s := strings.NewReader("abc|defg\nhij")
    r := bufio.NewReader(s)
    b, err := r.ReadSlice('|')
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))

    b, err = r.ReadSlice('\n')
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))

转载于:https://www.cnblogs.com/alin-qu/p/10225268.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值