Golang 语言标准库 io 详解

简介: Golang 语言标准库 io 详解

介绍

Go 语言标准库 io 提供 I/O 原语的基本接口。所谓 I/O,顾名思义 inputoutput,即数据输入和输出。

本文我们通过阅读源码介绍 golang 语言标准库 io,限于篇幅,我们以介绍 io.Reader 接口为例。

标准库 io 的接口类型 Reader

我们阅读一下标准库 ioReader 源码:

Reader 源码:

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

阅读源码,我们可以发现标准库 ioReader 接口包含一个函数 Read(p []byte) (n int, err error)

在 Go 语言中,任意类型实现某一接口中的所有方法,即代表该类型实现了该接口。

所以,任意实现 Read(p []byte) (n int, err error) 的类型,即代表实现了 io.Reader 接口。

03

标准库中io.Reader 的实现类型

在 Golang 标准库 strings、bytes、bufio、和 os 中,都有实现 io.Reader 的类型。

标准库 strings

标准库 stringsReader 类型,实现了标准库 ioReader 接口,源码:

type Reader struct {
 s        string
 i        int64 // current reading index
 prevRune int   // index of previous rune; or < 0
}
// 省略代码 ...
func (r *Reader) Read(b []byte) (n int, err error) {
 if r.i >= int64(len(r.s)) {
  return 0, io.EOF
 }
 r.prevRune = -1
 n = copy(b, r.s[r.i:])
 r.i += int64(n)
 return
}

阅读源码,我们可以发现 strings.Reader 实现了 Read(b []byte) (n int, err error),即代表实现了 io.Reader 接口。

使用 strings 包提供的 NewReader 函数,可以创建一个 strings.Reader 类型的变量。

func NewReader(s string) *Reader { return &Reader{s, 0, -1} }

示例:

r := strings.NewReader("some io.Reader stream to be read\n")
if _, err := io.Copy(os.Stdout, r); err != nil {
    log.Fatal(err)
}

输出:

some io.Reader stream to be read

标准库 bytes

标准库 bytesReader 类型,也实现了标准库 ioReader 接口,源码:

type Reader struct {
 s        []byte
 i        int64 // current reading index
 prevRune int   // index of previous rune; or < 0
}
// 省略代码 ...
// Read implements the io.Reader interface.
func (r *Reader) Read(b []byte) (n int, err error) {
 if r.i >= int64(len(r.s)) {
  return 0, io.EOF
 }
 r.prevRune = -1
 n = copy(b, r.s[r.i:])
 r.i += int64(n)
 return
}

阅读源码,我们可以发现 bytes.Reader 实现了 Read(b []byte) (n int, err error),即代表实现了 io.Reader 接口。

使用 bytes 包提供的 NewReader 函数,可以创建一个 bytes.Reader 类型的变量。

// NewReader returns a new Reader reading from b.
func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }

示例:

r := bytes.NewReader([]byte("some io.Reader stream to be read"))
if _, err := io.Copy(os.Stdout, r); err != nil {
    log.Fatal(err)
}

输出:

some io.Reader stream to be read

标准库 bufio

标准库 bufio 的函数 NewReader,创建一个新的其缓冲区 Reader.buf 有默认大小的 *Reader,源码:

const (
 defaultBufSize = 4096
)
// 省略代码 ...
// Reader implements buffering for an io.Reader object.
type Reader struct {
 buf          []byte
 rd           io.Reader // reader provided by the client
 r, w         int       // buf read and write positions
 err          error
 lastByte     int // last byte read for UnreadByte; -1 means invalid
 lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
// 省略代码 ...
func NewReaderSize(rd io.Reader, size int) *Reader {
 // Is it already a Reader?
 b, ok := rd.(*Reader)
 if ok && len(b.buf) >= size {
  return b
 }
 if size < minReadBufferSize {
  size = minReadBufferSize
 }
 r := new(Reader)
 r.reset(make([]byte, size), rd)
 return r
}
// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) *Reader {
 return NewReaderSize(rd, defaultBufSize)
}

阅读源码,我们可以发现函数 NewReader 创建一个新的其缓冲区 Reader.buf 有默认大小的 *Reader

示例:

rd := strings.NewReader("some io.Reader stream to be read")
r := bufio.NewReader(rd)
if _, err := io.Copy(os.Stdout, r); err != nil {
    log.Fatal(err)
}

输出:

some io.Reader stream to be read

标准库 os

标准库 osos.File 类型,也实现了标准库 ioReader 接口,源码:

// File represents an open file descriptor.
type File struct {
 *file // os specific
}
// 省略代码 ...
// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and any error encountered.
// At end of file, Read returns 0, io.EOF.
func (f *File) Read(b []byte) (n int, err error) {
 if err := f.checkValid("read"); err != nil {
  return 0, err
 }
 n, e := f.read(b)
 return n, f.wrapErr("read", e)
}

阅读源码,我们可以发现 os.File 实现了 Read(b []byte) (n int, err error),即代表实现了 io.Reader 接口。

使用 os 包提供的 Open 函数,可以创建一个 os.File 类型的变量。

func Open(name string) (*File, error) {
 return OpenFile(name, O_RDONLY, 0)
}

示例:

f, _ := os.Open("service.log")
if _, err := io.Copy(os.Stdout, f); err != nil {
    log.Fatal(err)
}

输出:

some io.Reader stream to be read

04

总结

Go 语言标准库 io 提供 I/O 原语的基本接口。在 Go 语言标准库 strings、bytes、bufio、和 os 中,都有实现 io.Reader 的类型。

本文我们介绍了在 Go 语言标准库中实现 io.Reader 的类型的源码,及简单的使用示例。

建议感兴趣的读者朋友们,继续阅读 Go 语言标准库中实现 io.Writer  和 io.Closer 的类型的源码,并思考其使用场景。

通过阅读标准库 io 的代码,不仅可以熟悉标准库 io 的使用方式,还可以更加深入理解 golang 中接口的使用方式。

推荐阅读:

目录
相关文章
|
3月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
140 4
Golang语言之管道channel快速入门篇
|
3月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
71 4
Golang语言文件操作快速入门篇
|
3月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
112 3
Golang语言之gRPC程序设计示例
|
3月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
100 4
|
26天前
|
JSON Go 开发者
go-carbon v2.5.0 发布,轻量级、语义化、对开发者友好的 golang 时间处理库
carbon 是一个轻量级、语义化、对开发者友好的 Golang 时间处理库,提供了对时间穿越、时间差值、时间极值、时间判断、星座、星座、农历、儒略日 / 简化儒略日、波斯历 / 伊朗历的支持。
36 4
|
28天前
|
缓存 监控 前端开发
Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信
本文探讨了在 Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信。首先介绍了 WebSocket 和 Socket.IO 的基本概念及其优势,接着详细讲解了 Go 语言中 WebSocket 的实现方法,以及二者集成的重要意义和具体步骤。文章还讨论了集成过程中需要注意的问题,如协议兼容性、消息格式、并发处理等,并提供了实时聊天、数据监控和在线协作工具等应用案例,最后提出了性能优化策略,包括数据压缩、缓存策略和连接管理优化。旨在帮助开发者更好地理解并应用这些技术。
45 3
|
1月前
|
存储 Cloud Native Shell
go库介绍:Golang中的Viper库
Viper 是 Golang 中的一个强大配置管理库,支持环境变量、命令行参数、远程配置等多种配置来源。本文详细介绍了 Viper 的核心特点、应用场景及使用方法,并通过示例展示了其强大功能。无论是简单的 CLI 工具还是复杂的分布式系统,Viper 都能提供优雅的配置管理方案。
|
3月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
72 4
Golang语言goroutine协程篇
|
3月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
75 3
Golang语言之Prometheus的日志模块使用案例
|
2月前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
37 0