简析 Golang IO 包

io 包提供了 I/O 原语(primitives)的基本接口。io 包中定义了四个最基本接口 Reader、Writer、Closer、Seeker 用于表示二进制流的读、写、关闭和寻址操作。这些原语和接口是对底层操作的封装,因此如没有特殊说明,这些原语和接口都不能被视为线程安全的。

Reader

Reader 接口封装了基本的 Read 方法。Read 读取长度为 len(p) 字节的数据,并写入到 p。返回结果包含读取数据字节数(0 <= n <= len(p))和 error 信息。

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

当 Read 在读取 n > 0 个字节后遇到异常或 EOF 时,Read 会返回读取的字节数。在这次读取时,可能会返回非空 error。但再一次读取,会读空并返回 error。典型的例子是,Reader 读取完全部输入流,下一次 Read 就会返回 0, EOF:

func main() {
    r := strings.NewReader("some io.Reader stream to be read")

    b := make([]byte, 32)
    n, err := r.Read(b)
    // 32, some io.Reader stream to be read, <nil>
    fmt.Printf("%d, %s, %v", n, b, err)

    b = make([]byte, 32)
    n, err = r.Read(b)
    // 0, EOF
    fmt.Printf("%d, %v", n, err)
}

Read 的实现方法不建议返回 0 的同时,返回 nil error,除非 len(p) == 0。它并不代表 EOF。

常用的 Reader 接口实现有:

1.strings 包下的 Reader 类型

相关支持函数有:

  • func NewReader(s string) *Reader:生产字符串 s 对应的 Reader(Read-only,未实现 Write 方法)
  • func (r *Reader) Len() int:尚未被读取的字符串部分字节数
  • unc (r *Reader) Read(b []byte) (n int, err error):Read 实现方法

2.bytes 包下的 Buffer 类型和 Reader 类型

Buffer 类型和 Reader 类型不同之处在于,前者实现了 Writer 接口,而后者是 read-only。

Writer

Writer 接口封装了 Write 方法。实现从缓冲区取 len(p) 字节大小的数据,写入底层数据流。如果一切正常,Write 返回 写入字节大小(n == len(p))和 nil error。否则返回 non-nil error 且 n < len(p)。

type Writer interface {
    Write(p []byte) (n int, err error)
}

常用的 Writer 接口实现有:

1.strings 包下的 Builder 类型

Builder 用于高效地组建字符串,最小化消耗内存资源。

func main() {
    proverbs := []string{
        "Channels orchestrate mutexes serialize.",
        "Cgo is not Go.",
        "Errors are values.",
        "Don't panic.",
    }
    var writer strings.Builder

    for _, p := range proverbs {
        n, err := writer.Write([]byte(p))
        if err != nil {
            fmt.Println(err)
        }
        if n != len(p) {
            fmt.Println("failed to write data")
        }
    }

    // 打印 Channels orchestrate mutexes serialize.Cgo is not Go.Errors are values.Don't panic.
    fmt.Println(writer.String())
}

2.bytes 包下的 Buffer 类型

3.http 包下的 ResponseWriter 接口

type ResponseWriter interface {
    // 返回 Header 对象,可以通过它的 Set() 方法设置头部
    Header() Header

    // 写入数据到 HTTP 应答报文
    Write([]byte) (int, error)

    // 设置返回状态码。如果没有调用这个函数,默认设置为 http.StatusOK
    WriteHeader(statusCode int)
}

以下例子在 localhost:8080/handler 监听请求,并写回字符串 ”This is the HTTP response.“

func main() {
    http.HandleFunc("/handler", func(w http.ResponseWriter, req *http.Request) {
        io.WriteString(w, "This is the HTTP response.\n")
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

4.go-restful 包下的 Response 类型

Response 类型封装了 http.ResponseWriter,它提供了很多便捷的方法支持写回数据。

type Response struct {
    http.ResponseWriter
    // contains filtered or unexported fields
}

Closer

Closer 接口封装 Close 方法。一般用于关闭文件,关闭通道,关闭连接,关闭数据库等

type Closer interface {
    Close() error
}

Seeker

Seeker 接口封装 Seeker 方法。Seek 方法用于设置偏移量(offset),下一次读写便从某个特定位置开始操作数据流。和 ReaderAt、WriteAt 接口有些类似,但 Seeker 接口更灵活,可以更好的控制读写数据流的位置。

type Seeker interface {
    Seek(offset int64, whence int) (int64, error)
}

偏移量 offset 的解读取决于 whence(= from where,从那里)。0 表示相对于起始位置,1 表示相对于当前的偏移,而 2 表示相对于其结尾处。以下例子,指针会移到右起倒数第五个字符的位置。所以 reader.Len() 会输出 5。

func main() {
    reader := strings.NewReader("This is a test")
    reader.Seek(-5, io.SeekEnd)
    fmt.Printf("The unread portion of the string: %d\n", reader.Len())
}

原语组合

通过上面的四种基本接口的组合,我们可以得到多种原语组合,比如:ReadWriter、ReadCloser、WriteCloser 等。

type ReadWriter interface {
    Reader
    Writer
}

参考文档:

golang io中io.go解读

简析 Golang IO 包的更多相关文章

  1. JDK框架简析--java.lang包中的基础类库、基础数据类型

    题记 JDK.Java Development Kit. 我们必须先认识到,JDK不过,不过一套Java基础类库而已,是Sun公司开发的基础类库,仅此而已,JDK本身和我们自行书写总结的类库,从技术含 ...

  2. 简析 Golang net/http 包

    net/http 包涵盖了与 HTTP 请求发送和处理的相关代码.虽然包中定义了大量类型.函数,但最重要.最基础的概念只有两个:ServeMux 和 Handler. ServeMux 是 HTTP ...

  3. Golang IO包的妙用

    Golang 标准库对 IO 的抽象非常精巧,各个组件可以随意组合,可以作为接口设计的典范.这篇文章结合一个实际的例子来和大家分享一下. 背景 以一个RPC的协议包来说,每个包有如下结构 type P ...

  4. golang io中io.go解读

    目录 1. 整体大纲 2. 接口 读 写 关闭 寻址 3. 函数 读 写 复制 4. 结构体 SectionReader LimitedReader teeReader 5. 备注 根据golang ...

  5. Golang学习 - io 包

    ------------------------------------------------------------ 先说一下接口,Go 语言中的接口很简单,在 Go 语言的 io 包中有这样一个 ...

  6. <摘自>飞:jxl简析2 [ http://www.emlog.net/fei ]

    [<摘自>飞:jxl简析:http://www.emlog.net/fei] (二)应用 在进行实践前 , 我们需要对 excel 有一个大致的了解 ,excel 文件由一个工作簿 (Wo ...

  7. 简析.NET Core 以及与 .NET Framework的关系

    简析.NET Core 以及与 .NET Framework的关系 一 .NET 的 Framework 们 二 .NET Core的到来 1. Runtime 2. Unified BCL 3. W ...

  8. 简析 .NET Core 构成体系

    简析 .NET Core 构成体系 Roslyn 编译器 RyuJIT 编译器 CoreCLR & CoreRT CoreFX(.NET Core Libraries) .NET Core 代 ...

  9. RecycleView + CardView 控件简析

    今天使用了V7包加入的RecycleView 和 CardView,写篇简析. 先上效果图: 原理图: 这是RecycleView的工作原理: 1.LayoutManager用来处理RecycleVi ...

随机推荐

  1. jQuery 源码解析(二十七) 样式操作模块 坐标详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下坐标这一块. 对于坐标来说,jQuery提供了一个offset方法用于获取第一个匹配元素的坐标或者设置所有匹配元素的坐标,还有offse ...

  2. 如何优雅规避NPE

    项目中尤其是在持久层,难免会有大量的针对集合,对象,字符串的操作,为了程序的健壮性,我们不得不进行判空,像下面箭头式编码吗? if(null!=person){ ... if(null!=addres ...

  3. Gerrit常见命令及最佳实践

    概述 本文记录了笔者在使用Gerrit(一种免费.开放源代码的代码审查软件)过程中的一些微小的经验,在这里做个简单的分享. 克隆工程 git clone ssh://tusi@xx.xx.cn:294 ...

  4. GO-逻辑判断(if,else if,else,switch)

    一.if逻辑判断 package main import "fmt" func main() { var a =10; if a>10 { //大括号前不能回车 fmt.Pr ...

  5. javaWeb核心技术第四篇之Javascript第二篇事件和正则表达式

    - 事件 - 表单提交(掌握) "onsubmit" - 单击事件(掌握) "onclick" - 页面加载成功事件(掌握) "onload" ...

  6. Prism_简介(1)

    Prism 6 Introduction介绍 Initializing初始化 Managing-Dependencies管理依赖 Modules模块 Implementing-MVVM实时MVVM A ...

  7. ABAP 字符串换行符处理

    今天发现BW系统从K3系统数据库抽取会计科目的描述时,转换出错. 从监控器上看是值2KO 845 412D#有问题,但不知道有什么问题,检查后感觉是符号#的问题. 在转换中添加代码,替换#,发现没有起 ...

  8. Android8.1 源码修改之通过黑名单屏蔽系统短信功能和来电功能

    前言 之前写过一篇Android6.0 的屏蔽系统短信功能和来电功能,具体看这里 同样的最近有个新需求,需要将8.1 设备的来电功能和短信功能都屏蔽掉,特殊产品就是特殊定制,那就开始吧. 屏蔽短信功能 ...

  9. Android进阶之绘制-自定义View完全掌握(三)

    自定义View系列的第三篇博客,我们来学习如何实现自定义下拉框. 今天的程序,我们来实现这样的一个效果. 布局非常简单,我们直接开始编码. 修改activity_main.xml文件的代码. < ...

  10. AudioRecord 录制播放PCM音频

    AudioRecord 与 MediaRecorder 区别 AudioRecord 基于字节流录制,输出的是pcm数据,未进行压缩,直接保存的pcm文件不能被播放器识别播放. 可以对音频文件进行实时 ...