io.go库函数

该库函数主要是一些基础的抽象接口,这些接口都是未经过实现的抽象函数。其他的一些标准库使用这些接口完成了一些相关的功能,我们在实际工程中,需要实现这些接口,同时借助其他库函数对这些的接口的扩展,来实现代码的服用。复用接口的本质上是Duck Type,即只要实现了某个接口的所有函数,就可以使用该接口表示一个对象。

以下是两个个主要的抽象接口:

// Reader接口用于包装向p中读取len(p)个字节的数据的功能,返回读入的数据字节数n,其中0<=n<=len(p),
// 返回任何可能出现的错误。
type Reader interface {Read(p []byte) (n int, err error)
}// Writer包装了从p中向数据流写入len(p)个字节的功能,返回写入字节的个数n,其中0<=n<=len(p),
// 返回任何可能出现的错误。
type Writer interface {Write(p []byte) (n int, err error)
}

io.pipe库函数

这个库可以类似于OS中经典的线程同步问题:读者-写者问题。写者向数据池不断存放数据,读者不断从池中读取数据。当然,这与经典OS的读者写者有明显的差异,这是对于字节流的操作,不是某个资源的操作。以下是源代码库的笔记,源代码地址:https://golang.org/src/io/pipe.go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.// Pipe adapter to connect code expecting an io.Reader
// with code expecting an io.Writer.package ioimport ("errors""sync""sync/atomic"
)// atomicError is a type-safe atomic value for errors.
// We use a struct{ error } to ensure consistent use of a concrete type.
type atomicError struct{ v atomic.Value }func (a *atomicError) Store(err error) {a.v.Store(struct{ error }{err})
}
func (a *atomicError) Load() error {err, _ := a.v.Load().(struct{ error })return err.error
}// ErrClosedPipe is the error used for read or write operations on a closed pipe.
var ErrClosedPipe = errors.New("io: read/write on closed pipe")// A pipe is the shared pipe structure underlying PipeReader and PipeWriter.
type pipe struct {wrMu sync.Mutex    // 写入数据需要加锁保护,此时不能读写,因此用MutexwrCh chan []byte   // 存储外界写入的数据,可以看成数据池rdCh chan int      // 内部数据的空间容量once sync.Once     // 操作仅需要一次执行,调用Once即可done chan struct{} // pipe是否已经关闭,注意空结构体channel使用方式rerr atomicError   // read错误werr atomicError   // write错误
}// 外部的b读取pipe的数据,返回n是读取的字节数,err是任何可能的错误
// 注意理解Read是外部存储读取pipe内部的数据,这相当于读写模式读者
func (p *pipe) Read(b []byte) (n int, err error) {select {case <-p.done:  // pipe已经关闭了,读取错误return 0, p.readCloseError()default:       }select {case bw := <-p.wrCh:    // 读取数据,如果有数据正在写入数据池,则发生阻塞nr := copy(b, bw)   // 拷贝数据p.rdCh <- nr        // 获取读取数据的字节数return nr, nil      // 返回个数,没有错误case <-p.done:          // pipe已经关闭了,读取错误return 0, p.readCloseError()  // 个数为0,并记录错误}
}func (p *pipe) readCloseError() error {rerr := p.rerr.Load()if werr := p.werr.Load(); rerr == nil && werr != nil {return werr}return ErrClosedPipe
}func (p *pipe) CloseRead(err error) error {if err == nil {err = ErrClosedPipe}p.rerr.Store(err)p.once.Do(func() { close(p.done) })return nil
}// 把外部b中的数据写入内部的存储结构中,返回写入数据的个数,err是任何可能的错误
// 注意write是把外部b的数据写入内部,这相当于读写模式的写者
func (p *pipe) Write(b []byte) (n int, err error) {select {case <-p.done:  // pipe已经关闭,写入肯定发生错误return 0, p.writeCloseError()default:p.wrMu.Lock()          // 写入数据一定要先加锁,这是为了多线程服务defer p.wrMu.Unlock()  // 函数结束后解锁}// 循环的意义:新来的数据肯定要被读入,之后先写入数据,如果写入的数据量多于一次能读取的量,// 则一直循环等待下一次写入,期间可能会有阻塞状态for once := true; once || len(b) > 0; once = false {select {case p.wrCh <- b:    // 写入数据,如果之前的数据没有被读出,则一直处于阻塞状态nw := <-p.rdCh   // 内部的容量b = b[nw:]       // 返回未写入的数据,第一次写入数据肯定是全部写入n += nw          // 记录写入的个数case <-p.done:       // 如果pipe关闭,返回已经写入的数据个数和关闭错误return n, p.writeCloseError()}}return n, nil
}func (p *pipe) writeCloseError() error {werr := p.werr.Load()if rerr := p.rerr.Load(); werr == nil && rerr != nil {return rerr}return ErrClosedPipe
}func (p *pipe) CloseWrite(err error) error {if err == nil {err = EOF}p.werr.Store(err)p.once.Do(func() { close(p.done) })  // 关闭一次即可,使用Once进行操作return nil
} // PipeReader is the read half of a pipe.
// 只实现了pipe的read功能,相当于一个读者
type PipeReader struct {p *pipe  // 使用指针,说明是共享数据池
}// Read implements the standard Read interface:
// it reads data from the pipe, blocking until a writer
// arrives or the write end is closed.
// If the write end is closed with an error, that error is
// returned as err; otherwise err is EOF.
func (r *PipeReader) Read(data []byte) (n int, err error) {return r.p.Read(data)
}// Close closes the reader; subsequent writes to the
// write half of the pipe will return the error ErrClosedPipe.
func (r *PipeReader) Close() error {return r.CloseWithError(nil)
}// CloseWithError closes the reader; subsequent writes
// to the write half of the pipe will return the error err.
func (r *PipeReader) CloseWithError(err error) error {return r.p.CloseRead(err)
}// A PipeWriter is the write half of a pipe.
// 只实现了pipe的writer的功能,相当于写者
type PipeWriter struct {p *pipe  // 使用指针,说明是共享数据池
}// Write implements the standard Write interface:
// it writes data to the pipe, blocking until one or more readers
// have consumed all the data or the read end is closed.
// If the read end is closed with an error, that err is
// returned as err; otherwise err is ErrClosedPipe.
func (w *PipeWriter) Write(data []byte) (n int, err error) {return w.p.Write(data)
}// Close closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and EOF.
func (w *PipeWriter) Close() error {return w.CloseWithError(nil)
}// CloseWithError closes the writer; subsequent reads from the
// read half of the pipe will return no bytes and the error err,
// or EOF if err is nil.
//
// CloseWithError always returns nil.
func (w *PipeWriter) CloseWithError(err error) error {return w.p.CloseWrite(err)
}// Pipe creates a synchronous in-memory pipe.
// It can be used to connect code expecting an io.Reader
// with code expecting an io.Writer.
//
// Reads and Writes on the pipe are matched one to one
// except when multiple Reads are needed to consume a single Write.
// That is, each Write to the PipeWriter blocks until it has satisfied
// one or more Reads from the PipeReader that fully consume
// the written data.
// The data is copied directly from the Write to the corresponding
// Read (or Reads); there is no internal buffering.
//
// It is safe to call Read and Write in parallel with each other or with Close.
// Parallel calls to Read and parallel calls to Write are also safe:
// the individual calls will be gated sequentially.
func Pipe() (*PipeReader, *PipeWriter) {p := &pipe{wrCh: make(chan []byte),rdCh: make(chan int),done: make(chan struct{}),}return &PipeReader{p}, &PipeWriter{p}
}

Golang的io.go和io.pipe库的笔记相关推荐

  1. 标准库IO与系统调用IO区别与联系

    标准库IO接口: 一般程序运行起来,自动默认打开 标准输入文件  fd=0(scanf),标准输出文件  fd=1(printf),  标准错误文件  fd=2 fopen   打开文件 FILE* ...

  2. Golang实践录:命令行cobra库实例

    本文使用 cobra 库实现一个命令行工具,类似 git.docker.kubectl 这类的工具. 本文仅为一个初具模型的示例,但有实践参考意义. 起因 在编程中,很多时候,程序都会处理多个参数,特 ...

  3. mysql io depth_MySQL读写IO的操作过程解析

    数据库作为存储系统,所有业务访问数据的操作都会转化为底层数据库系统的IO行为(缓存系统也可以当做是key-value的数据库),本文主要介绍访问MySQL数据库的IO流程以及IO相关的参数. 一.My ...

  4. 【linux开发】IO端口和IO内存的区别及分别使用的函数接口

    IO端口和IO内存的区别及分别使用的函数接口 每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把 ...

  5. 5种网络IO模型:阻塞IO、非阻塞IO、异步IO、多路复用IO、信号驱动IO

    目录 前言 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) 模型间的区别 ...

  6. Linux下的TCP/IP编程----IO复用及IO复用服务端

    http://blog.csdn.net/wqc_csdn/article/details/51583901 在之前我们实现的并发服务端时通过床将多个进程来实现的,这种并实现并发的方式简单方便,但是进 ...

  7. go语言io reader_Go语言中的io.Reader和io.Writer以及它们的实现

    在使用Go语言的过程中,无论你是实现web应用程序,还是控制台输入输出,又或者是网络操作,不可避免的会遇到IO操作,使用到io.Reader和io.Writer接口.也也许对这两个接口和相关的一些接口 ...

  8. Go语言中的io.Reader和io.Writer以及它们的实现

    在使用Go语言的过程中,无论你是实现web应用程序,还是控制台输入输出,又或者是网络操作,不可避免的会遇到IO操作,使用到io.Reader和io.Writer接口.也也许对这两个接口和相关的一些接口 ...

  9. Reactor模型和Proactor模型:同步IO与异步IO

    Table of Contents 服务端的线程模型 2种fd 3种事件 Reactor模型-同步I/O 1.单Reactor单线程模型 2.单Reactor多线程模型 3.主从Reactor多线程模 ...

最新文章

  1. Python中多层List展平为一层
  2. 6. 函数参数 与 展开运算符
  3. Deep Learning论文笔记之(二)Sparse Filtering稀疏滤波
  4. C 语言运算符优先级
  5. boost::type_erasure模块Associated types相关的测试程序
  6. 产生随机数java_java产生随机数的几种方式
  7. 【 CDN 最佳实践】CDN 命中率优化思路
  8. bugku 杂项 就五层你能解开吗_9.65米解放龙V杂项危险废物厢式运输车62
  9. UI设计素材|卡券界面设计
  10. php 1个中文几个字节,PHP函数第15款:gbk中文截取,1个中文字节为2个英文字节 cn_substr...
  11. LINUX获取当前窗口的ID
  12. 攻防世界 crypto Railfence
  13. 电路基础和电路模拟——复习
  14. 《考研公共课复习指导》数学篇1:考研数学策略
  15. 【PyTorch 自然语言处理】传统 NLP 快速回顾(计算语言学)
  16. ps可以去视频水印h吗
  17. cf网络原因服务器无响应,CF老出现网络出现异常,与服务器断开
  18. Linux系统的权限管理
  19. 利用 FFMPEG 批量提取指定起止时间视频片段
  20. ED80/6电力液压推动器

热门文章

  1. Quartus II 9.0sp1之功能仿真
  2. L - Oil Deposits
  3. 蓝桥杯——阿尔法乘积
  4. 【五级流水线CPU】—— 8. 测试结果
  5. Python中判断两个字符串的内容是否相同
  6. C语言中 . 和 - 区别详解(举例解释)
  7. maven-dependencies插件的模拟实现
  8. windows平台下压缩tar.gz
  9. 剑指offer——26.树的子结构(不太熟)
  10. 记一次海洋cms任意代码执行漏洞拿shell(url一句话)