我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Go语言io pipe源码分析详情

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Go语言io pipe源码分析详情

pipe.go分析:

  • 这个文件使用到了errors包,也是用到了sync库.
  • 文件说明:pipe是一个适配器,用于连接Reader和Writer.

1.结构分析

对外暴露的是一个构造函数和构造的两个对象. 两个对象分别暴露了方法,同时这两个对象还有一个共同的底层对象. 实际上,这两个对象暴露的方法是直接调用底层对象的, 那么核心还是在底层对象上,只是通过两个对象和一个构造方法将底层对象的细节隐藏了.

2.pipe sruct分析

pipe的方法不多,新的写法却不少.   

 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
    }

atomicError提供了error的原子读写. 

  type pipe struct {
      wrMu sync.Mutex // Serializes Write operations
      wrCh chan []byte
      rdCh chan int

      once sync.Once // Protects closing done
      done chan struct{}
      rerr atomicError
      werr atomicError
    }

可以看到pipe结构体中主要分两块:

  • 读写信道
    • 两个无缓冲信道
    • 一个互斥量(保护暴露的写函数)
  • 结束标识
    • once保证done的关闭只执行一次
    • done标志整个读写的结束
    • 剩下两个用于存储读写错误
    • PipeReader/PipeWriter的分析

3.PipeReader对外暴露的是读/关闭

    type PipeReader struct {
      p *pipe
    }

    func (r *PipeReader) Read(data []byte) (n int, err error) {
      return r.p.Read(data)
    }

    func (r *PipeReader) Close() error {
      return r.CloseWithError(nil)
    }

    func (r *PipeReader) CloseWithError(err error) error {
      return r.p.CloseRead(err)
    }

PipeWriter对外暴露的是写/关闭 

    type PipeWriter struct {
       p *pipe
     }

    func (w *PipeWriter) Write(data []byte) (n int, err error) {
      return w.p.Write(data)
    }

    func (w *PipeWriter) Close() error {
      return w.CloseWithError(nil)
    }

    func (w *PipeWriter) CloseWithError(err error) error {
      return w.p.CloseWrite(err)
    }

他们的方法集都是指针接收者.具体方法的实现是通过pipe的方法完成的. pipe的方法更加明确:读/获取读错误/结束读写并设置读错误; 写/获取写错误/结束读写并设置写错误.思路相当明确.

下面主要分析pipe的读写 

   func (p *pipe) Read(b []byte) (n int, err error) {
      select {
      case <-p.done:
        return 0, p.readCloseError()
      default:
      }

      select {
      case bw := <-p.wrCh:
        nr := copy(b, bw)
        p.rdCh <- nr
        return nr, nil
      case <-p.done:
        return 0, p.readCloseError()
      }
    }

    func (p *pipe) Write(b []byte) (n int, err error) {
      select {
      case <-p.done:
        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:
          return n, p.writeCloseError()
        }
      }
      return n, nil
    }

读写都是利用两个阶段的select来完成,第一个阶段的select是判断读写有没有结束, 第二阶段处理实际的读写.

Read

  • 每次将读的数量写到读信道

Write

  • 先将缓冲写到写信道,再从读信道中获取读字节数,最后调整缓冲
  • 如果缓冲太大,一次读没读完,就将写的过程多来几遍,知道缓冲全部写完

4.写法

PipeWriter/PipeReader对外暴露的关闭,其实只可以保留一个CloseWithError, 但是为了方便客户(调用者),还是拆成两个,其实可以做测试比较一下. 性能测试发现拆成两个或写成一个可选参函数,性能上差别不大, 那这种写法的主要作用是让暴露的方法更加清晰易懂.

pipe.Write中,for循环带有once参数,可以保证循环至少来一次, 算是do while的一种实现.

5.总结

不管是PipeReader/PipeWriter,还是pipe,都对Reader/Writer有(部分)实现.

另外还有一些细节没有说道:读写错误和EOF.

反思:本次阅读是先理代码后看文档,才发现关于error部分没有留心到, 后面还是先文档后代码,这样效率会高一点.

到此这篇关于Go语言io pipe源码分析详情的文章就介绍到这了,更多相关Go语言io pipe源码分析内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Go语言io pipe源码分析详情

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Go语言进阶freecache源码分析

这篇文章主要介绍“Go语言进阶freecache源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Go语言进阶freecache源码分析”文章能帮助大家解决问题。00. 什么是 freecach
2023-07-06

go语言构建顺序源码分析

这篇文章主要介绍“go语言构建顺序源码分析”,在日常操作中,相信很多人在go语言构建顺序源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”go语言构建顺序源码分析”的疑惑有所帮助!接下来,请跟着小编一起来
2023-07-05

怎么进行Go语言HTTP Server源码分析

这期内容当中小编将会给大家带来有关怎么进行Go语言HTTP Server源码分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Go语言中HTTP Server:HTTP server,顾名思义,支持ht
2023-06-17

Go语言网络编程与Http源码分析

这篇文章主要介绍“Go语言网络编程与Http源码分析”,在日常操作中,相信很多人在Go语言网络编程与Http源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Go语言网络编程与Http源码分析”的疑惑有所
2023-07-05

go语言字符类型byte与rune源码分析

这篇文章主要介绍“go语言字符类型byte与rune源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“go语言字符类型byte与rune源码分析”文章能帮助大家解决问题。一、byte类型介绍by
2023-07-05

go语言分布式id生成器及分布式锁源码分析

本文小编为大家详细介绍“go语言分布式id生成器及分布式锁源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言分布式id生成器及分布式锁源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。分布式 i
2023-07-05

详解如何在Go语言中调用C源代码

目录开坑说明内嵌形式外置的C代码1. 构建libauth.a静态库2. 对main.go稍加修改3. 编译开坑说明 最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,un
2022-06-07

Go语言中Struct、继承、匿名字段和内嵌结构体源码分析

这篇文章主要介绍“Go语言中Struct、继承、匿名字段和内嵌结构体源码分析”,在日常操作中,相信很多人在Go语言中Struct、继承、匿名字段和内嵌结构体源码分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-07-06

Go语言中内存管理逃逸分析详解

所谓的逃逸分析(Escape analysis)是指由编译器决定内存分配的位置吗不需要程序员指定。本文就来和大家简单分析一下Go语言中内存管理逃逸吧
2023-03-15

从源码到实战:Go语言优秀项目全面解析

Go语言作为一种快速,高效的编程语言,已经在许多项目中得到广泛应用。本文将从源码到实战的角度,全面解析几个Go语言的优秀项目,并附上具体的代码示例,帮助读者更好地理解这些项目的实际应用。1. Gorilla WebSocketGoril
从源码到实战:Go语言优秀项目全面解析
2024-03-05

Go语言基础数据类型实例代码分析

这篇文章主要讲解了“Go语言基础数据类型实例代码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go语言基础数据类型实例代码分析”吧!布尔型布尔型是Go最简单的数据类型,因为布尔型只有两个
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录