IO

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

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

  • IO包 对数据的读写 是通过接口的形式约定的。数据的来源或者去向可能是 网络,内存,文件。
  1. type Reader interface {
  2. Read(p []byte) (n int, err error)
  3. }
  4. type Writer interface {
  5. Write(p []byte) (n int, err error)
  6. }
  • 应用层 只需要按照接口去调用接口 不用关心底层实现细节 非常方便
  1. package main
  2. import (
  3. "io"
  4. "net/http"
  5. "os"
  6. "strings"
  7. )
  8. type R struct {
  9. reader io.Reader
  10. }
  11. func NewReader(r io.Reader) *R {
  12. return &R{
  13. reader: r,
  14. }
  15. }
  16. func (r *R) Read(p []byte) (n int, err error) {
  17. if _, err = r.reader.Read(p); err != nil {
  18. return
  19. }
  20. return len(p), nil
  21. }
  22. func main() {
  23. netR, err := http.Get("https://www.bilibili.com/")
  24. if err != nil {
  25. panic(err)
  26. }
  27. defer netR.Body.Close()
  28. fileR, err := os.Open("/tmp/data.txt")
  29. if err != nil {
  30. panic(err)
  31. }
  32. //读内存
  33. r1 := NewReader(strings.NewReader(""))
  34. b := make([]byte, 10*1024)
  35. if _, err := r1.Read(b); err != nil {
  36. panic(err)
  37. }
  38. //读网络
  39. r2 := NewReader(netR.Body)
  40. if _, err := r2.Read(b); err != nil {
  41. panic(err)
  42. }
  43. //读文件
  44. r3 := NewReader(fileR)
  45. if _, err := r3.Read(b); err != nil {
  46. panic(err)
  47. }
  48. }

bufio

  • 每次对磁盘的写入或者发起网络请求 都会给系统带来压力。

    将多次操作合并为一次 会减轻系统的压力
  • 更优的流程是 producer --> buffer -->io.Writer

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

  1. func buffer() {
  2. fmt.Println("IO")
  3. w := new(W)
  4. w.Write([]byte{'1'})
  5. w.Write([]byte{'2'})
  6. w.Write([]byte{'3'})
  7. w.Write([]byte{'4'})
  8. fmt.Println("Buffer IO")
  9. bw := bufio.NewWriterSize(w, 3)
  10. bw.Write([]byte{'1'})
  11. bw.Write([]byte{'2'})
  12. bw.Write([]byte{'3'})
  13. bw.Write([]byte{'4'})
  14. err := bw.Flush()
  15. if err != nil {
  16. panic(err)
  17. }
  18. }
  19. type W struct {
  20. }
  21. func (*W) Write(p []byte) (n int, err error) {
  22. fmt.Println("length is ", len(p))
  23. fmt.Println(string(p))
  24. return len(p), nil
  25. }
  • 普通的IO操作 会直接输出
  • buffio 则会首先收集数据到缓存中 等判断buffer满了

    之后才会一次性将缓存中的数据 输出。缓存中可能有多余的数据

    所以需要 最后单独调用flush 函数 强制将未满的缓存 输出

ReadFrom

  • 写操作之前需要 读取数据。io.ReaderFrom interface 就是

    为了更加方便的 从一个reader中读取数据
  1. type ReaderFrom interface {
  2. ReadFrom(r Reader) (n int64, err error)
  3. }
  1. func ReadFrom() {
  2. sr := strings.NewReader("read from strings reader")
  3. w := new(W)
  4. bw := bufio.NewWriterSize(w, 6)
  5. if _, err := bw.ReadFrom(sr); err != nil {
  6. panic(err)
  7. }
  8. if err := bw.Flush(); err != nil {
  9. panic(err)
  10. }
  11. }
  • bufio.Writer实现了这个接口 从reader中读取数据 io.reader -> buffer -> io.writer

ReadSlice

  • 如果bufio的NewReaderSize 如果小于16个字符 会设置为默认长度16个字符
  • 读取过程中 会优先判断buffer的size是否足够大 不够的话就会抛出 bufio: buffer full错误
  • bufio的ReadSlice函数可以读取读取指定字符之前的字符串,如果读到字符串末尾,还没有找到指定字符串

    则会返回eof
  1. s := strings.NewReader("abc|defg\nhij")
  2. r := bufio.NewReader(s)
  3. b, err := r.ReadSlice('|')
  4. if err != nil {
  5. panic(err)
  6. }
  7. fmt.Println(string(b))
  8. b, err = r.ReadSlice('\n')
  9. if err != nil {
  10. panic(err)
  11. }
  12. fmt.Println(string(b))

Go IO && bufio的更多相关文章

  1. go 文件操作 io

    package main import ( "fmt" "os" ) func main() { //打开文件 //概念说明: file 的叫法 //1. fi ...

  2. go 常用包

    标准的 Go 代码库中包含了大量的包,并且在安装 Go 的时候多数会伴随一起安 装.浏览 $GOROOT/src/pkg 目录并且查看那些包会非常有启发. fmt:包 fmt 实现了格式化的 I/O ...

  3. go linux 学习记录

    1 yum install mercurial 安装mercurial包 2 yum install git 安装git包 3 yum install gcc 安装gcc 4  然后就可以下载gola ...

  4. 使用GO语言灵活批量ssh登录服务器执行操作

    摘要: 在工作中时常需要登录服务器做一系列操作,每次输入ssh xxx总是很麻烦.这时候为什么不考虑写一个通用的小脚本呢? go语言是一门新兴语言,能够在很多地方发挥总用.初学go语言,做了这么一个小 ...

  5. GO语言的进阶之路-网络编程之socket

    GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...

  6. Go 中包导入声明

    Go中的程序由软件包组成.通常,软件包依赖于其他软件包,或者内置于标准库或第三方的软件包.包需要先导入才能使用其导出的标识符.本文将翻译一篇国外的文章,用于介绍包导入的原理以及几种常用的导入方式. & ...

  7. Go_18: Golang 中三种读取文件发放性能对比

    Golang 中读取文件大概有三种方法,分别为: 1. 通过原生态 io 包中的 read 方法进行读取 2. 通过 io/ioutil 包提供的 read 方法进行读取 3. 通过 bufio 包提 ...

  8. Golang 中三种读取文件发放性能对比

    Golang 中读取文件大概有三种方法,分别为: 1. 通过原生态 io 包中的 read 方法进行读取 2. 通过 io/ioutil 包提供的 read 方法进行读取 3. 通过 bufio 包提 ...

  9. Go 语言为Fibonacci函数实现Read方法

    Go语言非常灵活,只要为对象实现了相应的方法就可以把他看成实现了某个接口,类似于Durk Type, 为Fibonacci实现Read方法,就可以像读取文件一样,去读取下一个Fibonacci值. 示 ...

随机推荐

  1. UVa1471

    保留有价值的数字的做法,实际上这道题因为n只有1e5,所以不需要这种优化. #include<bits/stdc++.h> #define inf 0x3f3f3f3f ; using n ...

  2. c++11 右值的学习

    从4行代码看右值引用 概述 简单的左值和右值的判断就是  看是否可以取得地址   可取得地址 是左值     不能则  是右值! c++98/03中的左值引用是这样的: int i = 0; int& ...

  3. STM32之ADC(内部基准电压,参考电压)

    转 STM32内部参照电压VREFIN的使用 https://blog.csdn.net/uncle_guo/article/details/50625660 每个STM32芯片都有一个内部的参照电压 ...

  4. scut 125. 笔芯回文

    https://scut.online/p/125 看数据量,这题可能是O(n^2)的dp 也可能是区间dp,但是区间dp一般复杂度是O(n^3),虽然也可以优化,但是比赛的时候那么多人“秒”了,应该 ...

  5. 关于float和double类型能表示的数据范围和精度分析

    来自教材<计算机组成原理>p16 float:6--7位 double:15--16位 意思就是double类型的数据,你确实能表达出很大的数字,但是其只有15位是精确的. 1.计算机中, ...

  6. HDU 1087 E - Super Jumping! Jumping! Jumping! DP

    http://acm.hdu.edu.cn/showproblem.php?pid=1087 设dp[i]表示去到这个位置时的最大和值.(就是以第i个为结尾的时候的最大值) 那么只要扫描一遍dp数组, ...

  7. sql server replace函数巧妙完成字符串联结

    示例一: 需求:将'1,2,3,4,5,6,7,8,9,10'转成:'1','2','3','4','5','6','7','8','9','10' ),) set @s='1,2,3,4,5,6,7 ...

  8. 持续集成~Jenkins构建GitHub项目的实现

    有了前两讲的基础,这回我们就可以把github上的项目做到CI(jenkins)里了,让它自动去集成部署,持续集成~Jenkins里的NuGet和MSBuild插件,持续集成~Jenkins里的pow ...

  9. Ubuntu常用指令集

    Ubuntu Linux 操作系统常用命令详细介绍 ( 1)Udo apt-get install 软件名 安装软件命令 sudo nautilus 打开文件(有 root 权限)su root 切换 ...

  10. css实现瀑布流

    <style>      .container{           column-width:250px;           -webkit-column-width:250px;   ...