Go io

article/2025/9/15 16:23:16

Golang中输入和输出操作使用原语实现,这些原语将数据模拟称为可读或可写的字节流。为此,Golang的io包提供了io.Readerio.Writer接口,分别用于数据的输入和输出。

io

Golang的io包提供了对I/O原语的基本接口,包装了原语的已有实现,使之成为共享的公共接口,抽象出泛用的函数并附加了相关的原语操作。这些接口和原语是对底层实现完全不同的低水平操作的包装,除非得到其它方面的通知,客户端不应该假设它们是并发执行安全的。

io.EOF

  • EOF是End-Of-File的缩写,根据Go惯例大写字母缩写表示常量,不过io.EOF被定义成了变量。
  • io.EOFio包中的一个变量,表示文件结束的错误。
1package io23var EOF = errors.New("EOF")
  • io.EOF是Go中最重要的错误变量,用于表示输入流的结尾,因为每个文件都有一个结尾,所以io.EOF很多时候并不能算是一个错误,更重要是表示输入流结束了。
var EOF = errors.New("EOF")

io.Reader

  • io.Reader表示一个读取器,将数据从某个资源读取到传输缓冲区。在缓冲区中,数据可以被流式传输和使用。
io.Reader
  • 对于要用作读取器的类型,必须实现io.Reader接口的唯一方法Read(p []byte)。只要实现了Read(p []byte)就是一个读取器
type Reader interface{Read(p []byte) (n int, err error)
}
  • Read()方法具有两个返回值,若资源内容全部读取完毕,应该返回io.EOF错误。
返回值类型描述
nint读取到的字节数
errerror发生错误时的错误

利用io.Reader可以实现流式数据传输,Reader方法内部是被循环调用的,每次迭代,会从数据源读取一块数据放入缓冲区p中,直到返回io.EOF错误时停止。

例如:创建字符串读取器,流式地按字节读取。

str := "clear is better than clever"
//创建字符串读取器
reader := strings.NewReader(str)
//字节缓存区
buf := make([]byte, 4)
//循环读取
for{//读取到缓存区n,err := reader.Read(buf)if err!=nil{//读取结束if err!=io.EOF{fmt.Println("EOF:", n)break}fmt.Println(err)os.Exit(1)}result := string(buf[:n])fmt.Println(n, result)
}
4 clea
4 r is
4  bet
4 ter 
4 than
4  cle
3 ver
EOF

例如:实现从流中过滤掉非字母字符

//过滤函数
func alpha(c byte) byte{if (c>='a'&&c<='z') || (c>='A'&&c<='Z'){return c}return 0
}
type AlphaReader struct{src string //资源i int//当前读取的位置
}
func NewAlphaReader(src string) *AlphaReader{return &AlphaReader{src:src}
}
func (r *AlphaReader) Read(p []byte) (int,error){//判断是否已经读取到结尾if r.i >= len(r.src){return 0, io.EOF}//剩余未读取长度x := len(r.src) - r.i//缓存区填满大小bound := 0//判断剩余长度是否超过缓存区大小if x >= len(p){//完全填满缓冲区bound = len(p)}else if x < len(p){//缓存区无法补满bound = x}//创建缓存区buf := make([]byte, bound)//迭代读取i := 0for bound > i {//每次读取一个字节char := r.src[r.i]//执行过滤函数if c := alpha(char); c!=0{buf[i] = c}i++r.i++}//将缓存内容赋值到copy(p, buf)return i,nil
}

测试

str := "Hello! It's 9am, where is the sun?"buf := make([]byte, 4)
reader := NewAlphaReader(str)
for {n,err := reader.Read(buf)if err==io.EOF{break}data := string(buf[:n])fmt.Print(data)
}
  • 组合多个Reader可重用和屏蔽下层实现的复杂度

标准库已经实现了多个Reader,可使用一个Reader作为另一个Reader的实现是一种常见用法,可让一个Reader重用另一个Reader的逻辑。

例如:修改AlphaReader以接受io.Reader作为其源

//过滤函数
func alpha(c byte) byte{if (c>='a'&&c<='z') || (c>='A'&&c<='Z'){return c}return 0
}
type AlphaReader struct{reader io.Reader//组合标准读取器
}
func NewAlphaReader(reader io.Reader) *AlphaReader{return &AlphaReader{reader:reader}
}
func (r *AlphaReader) Read(p []byte) (int,error){n,err := r.reader.Read(p)if err!=nil{return n,err}buf := make([]byte, n)for i:=0; i<n; i++{char := alpha(p[i])if char != 0{buf[i] = char}}copy(p, buf)return n,nil
}

测试

str := "Hello! It's 9am, where is the sun?"
reader := strings.NewReader(str)buf := make([]byte, 4)
r := NewAlphaReader(reader)
for {n,err := r.Read(buf)if err==io.EOF{break}data := string(buf[:n])fmt.Print(data)
}

例如:与os.File结束过滤掉文件中的非字母字符

$ vim ./test.txt
Hello! It's 9am, where is the sun?
file,err := os.Open("./test.txt")
if err!=nil{fmt.Println(err)os.Exit(1)
}
defer file.Close()r := NewAlphaReader(file)
buf := make([]byte, 4)
for {n,err := r.Read(buf)if err==io.EOF{break}data := string(buf[:n])fmt.Print(data)
}

io.Writer

  • io.Writer表示一个编写器,从缓存区读取数据,并将数据写入目标资源。
io.Writer
  • 对于要作为编写器的类型必须实现io.Writer接口唯一的方法Write(p []byte),只要实现了Write(p []byte)就是一个编写器。
type Writer interface{Write(p []byte) (n int, err error)
}
  • Write()方法具有两个返回值,一个是写入到目标资源的字节数,一个是发生错误时的错误。
返回值类型描述
nint写入到目标资源的字节数
errerror发生错误时的错误

例如:使用bytes.Buffer类型作为io.Writer将数据写入内存缓存区

proverbs := []string{"many hands make light work","measure for measure","murder will out","never say die",
}var writer bytes.Buffer
for _,p := range proverbs{n,err := writer.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)}
}
result := writer.String()
fmt.Println(result)

例如:实现自定义的io.Writer将其内容作为字节序列写入通道

//ChanWriter 通道写入器
type ChanWriter struct{ch chan byte//目标资源
}
//NewChanWriter 创建通道写入器
func NewChanWriter() *ChanWriter{return &ChanWriter{ch:make(chan byte, 1024)}
}
//Chan 获取目标资源
func (w *ChanWriter) Chan() <-chan byte{return w.ch
}
//Close 关闭目标资源
func (w *ChanWriter) Close(){close(w.ch)
}
//Write 写入目标资源
func (w *ChanWriter) Write(p []byte) (int, error){n := 0//遍历输入数据按字节写入目标资源for _,b := range p{w.ch<-bn++}return n,nil
}

测试

writer := NewChanWriter()go func(){defer writer.Close()writer.Write([]byte("money can talk"))
}()for char := range writer.Chan(){fmt.Printf("%c\n", char)
}

io.Closer

  • Closer是包装基本Close()方法的接口用于关闭数据流,第一次调用后Closer的行为是未定义的。
  • 文件、归档(压缩包)、数据库连接、Socket等均需手动关闭的资源都实现了Closer接口。
  • 编程中经常会将Close方法的调用放在defer语句中
type Closer interface{Close() error //关闭数据流
}

例如:

file,err := os.Open("test.txt")
if err!=nil{}
defer file.Close()

io.ReadCloser

  • response.Body的类型为io.ReadCloser

io.WriteCloser

io.ReadWriteCloser


http://chatgpt.dhexx.cn/article/7ZbOMiuE.shtml

相关文章

json to go

简介 在对接第三方或者某些功能重写的情况下&#xff0c;有json字符串&#xff0c;需要Go的结构体定义&#xff1b;当字段特别多的时候&#xff0c;费时费力。 此时可以使用json to go的这个在线工具&#xff0c;自动生成对应的Go结构体&#xff0c;方便而且不出错 jsontogo…

Djando介绍

Django目录介绍 -day60 项目名 -app01 app的名字 -migrations 数据库变更相关记录&#xff08;你不要删&#xff0c;也不要改&#xff09; -admin.py 后台管理&#xff08;创建项目如果没有选&#xff0c;就没有&#xff09; -apps.py app的相关配置&#xff0c;不用管 -models…

Dubbo-go v3.0 正式发布 ——打造国内一流开源 Go 服务框架

简介&#xff1a;Dubbo-go 是常新的&#xff0c;每年都在不断进化。介绍 Dubbo-go 3.0 工作之前&#xff0c;先回顾其过往 6 年的发展历程&#xff0c;以明晰未来的方向。 作者 | 李志信 来源 | 阿里技术公众号 作者介绍&#xff1a; 李志信&#xff08;github laurencelizhix…

gojs(一)

前言 什么是 GoJs GoJs 是一个 JavaScript 和 typescript 库&#xff0c;用于构建交互式图表&#xff0c;可以轻易的实现日常开发中所需要的各种示意图、结构图、组织图、流程图、状态图、思维导图、树状图等。 它用自定义模板和布局组件简化了节点、链接和分组等复杂的 JS …

Java 不赚钱,要转 Go 吗?

发现一个 2021 年报告&#xff0c;显示 Go 是最想学习的编程语言 Go 到如今的火爆程度&#xff0c;不仅仅是因为有个好爹。上手快&#xff0c;一周就能入门上手&#xff0c;正常人写的 Go 都不会太差。有人说&#xff0c;它有一种迷人的气质&#xff0c;很难用语言表达&#xf…

Djago(18)

9. session会话 因为因特网HTTP协议的特性&#xff0c;每一次来自于用户浏览器的请求&#xff08;request&#xff09;都是无状态的、独立的。通俗地说&#xff0c;就是无法保存用户状态&#xff0c;后台服务器根本就不知道当前请求和以前及以后请求是否来自同一用户。对于静态…

java 自动转 golang_JAVA转Golang

GO语言因其并行机制出现在大众的视野中&#xff0c;Go编译到机器码非常的快速&#xff0c;它是快速的、静态类型编译语言&#xff0c;但是感觉上是动态类型&#xff0c;解释型语言&#xff0c;要说响应式编程应该reactive&#xff0c;webflux&#xff0c;RXJava&#xff0c;net…

Go Go Go!

一、概述 本文为Go语言学习入门第一篇&#xff0c;《Go语言入门》如何在Windows下安装Go语言编程环境 。主要讲Go语言编译环境的安装以及基于Notepad&#xff08;Go语言插件、语法高亮&#xff09;的开发环境配置。 先鼓吹一下Go语言&#xff1a; GO是强类型语言&#xff0c…

idea String报错问题

一、下载问题 1.版本安装错误&#xff1b; 二、问题解决 1.彻底删除下载错误的idea &#xff08;1&#xff09;. 注册表清理 windows R 输入 regedit 打开注册表 点击一级菜单 HKEY_CURRENT_USER&#xff0c; 右键查找&#xff0c;输入idea&#xff0c;会找到jetbrains&…

Navicat 连接 mysql 报错

当我们用Navicat 连接数据库的时候&#xff0c;可能会遇到这个问题 &#xff1a; 这个问题主要是因为 5 和 8 的加密方式不一样&#xff0c;才导致报错&#xff01; 解决方法 1、进入mysql的安装目录下的 bin 目录 2、mysql -h localhost -P3306 -uroot -p 3、执行 alter user…

安装tensorflow报错

安装tensorflow 使用管理员身份运行cmd 然后根据你的python版本安装对应的tensorflow &#xff08;查看Python版本&#xff1a;python --version&#xff09; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple tensorflow-gpu2.3.0如果上面的遇到403错误&#xff0…

yum makecache 报错

使用yum的时候总是提示The requested URL returned error: 404这个错误&#xff0c;经过一番折腾总算解决了。 首先说下yum源&#xff0c;使用的是163的源。http://mirrors.163.com/.help/CentOS7-Base-163.repo [base] nameCentOS-$releasever - Base - 163.com baseurlhtt…

ADS报错整理

ADS报错整理&#xff1a; 软件版本为&#xff1a;ADS2017 报错1&#xff1a;A virtual resistance of 1 TOhms was added between each node and ground, and a virtual resistance of 1 pOhms was inserted in each current branch, and a virtual resistance of 1 pOhms was…

Navicat连接MySQL数据库报错1045

数据库创建后直接使用navicat工具进行连接报错1045 在保证你输入的账号密码都正确的情况下&#xff1b; 可能是因为你的正好没有权限 权限不够&#xff0c;因为MySQL默认数据库创建的账号权限仅限于localhost 需要进行授权 grant all privileges on *.* to username% identif…

前端报错404

情况一&#xff1a; 错误截图&#xff1a; 错误原因&#xff1a;前端页面链接部分忘写了一个斜杠。 修改方法&#xff1a;加上斜杠 情况二&#xff1a; 错误截图&#xff1a; 错误原因&#xff1a;访问public文件夹时加上public&#xff0c;加了会导致资源无法找到。

安装weditor报错

weditor是app的定位工具&#xff0c;安装weditor报错如下&#xff1a; 跟着提示要更新一下pip c:\users\acer\appdata\local\programs\python\python38-32\python.exe -m pip install --upgrade pip Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple更新pip之后…

【web安全】——报错注入

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a; 主页传送门 创作初心&#xff1a; 一切为了她 座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀 专研方向&#xff1a; web安全&#xff0c;后渗透技术 每日emo&#xff1a; 内心的爱意逐渐被时间冲淡 今天给大家讲…

SpringBoot打包报错

一、对springBoot打包 package 报错的情况 处理方法&#xff1a;对文件目录下的pom.xml文件进行修改 ① 修改编码 配置编码格式为 UTF-8 具体的操作就是在pom.xml文件中的<properties></properties>标签下增加一行配置编码格式的代码&#xff1a; <propertie…

pip list 报错

使用到的具体命令&#xff1a; 1、python -m ensurepip 2、python -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple 项目场景&#xff1a; pip list 报错 问题描述 报错如上图所示 原因分析&#xff1a; pip 更新时关闭窗口、断网、没有使用国…

pnpm报错问题

在使用模板练习项目的时候遇到了一个问题&#xff0c;只要打开编辑器进入项目就会疯狂报错&#xff0c;每一个页面都有报错。这次的方向就是解决这个问题。 首先&#xff0c;打开编辑器,这里我使用的是vscode&#xff0c;winj打开编辑器命令行&#xff0c;输入npm i npm i 缓存…