当前位置: 首页 > news >正文

go数据处理之textproto.Pipeline

Pipeline类的奇妙效果

发现一个很有意思的类textproto.Pipeline, 这个类可以让我们定义函数执行的顺序。
比如,我定义了一个testPrintln函数,功能是向控制台打印,当我输入了:

testPrintln("3")
testPrintln("1")
testPrintln("2")
testPrintln("0")
testPrintln("4")

但是结果却是:

0
1
2
3
4

Pipeline类的简介

  • 在 Go 语言的 net/textproto 包中,Pipeline 是一个用于协调并发读写文本协议的同步工具,主要解决多个 goroutine 并发发送请求时,响应与请求的顺序匹配问题。它常用于基于文本的协议(如 HTTP、SMTP、FTP 等)的客户端实现中。

  • 当多个 goroutine 同时通过同一个连接发送请求时,可能出现 “请求乱序” 或 “响应与请求不匹配” 的问题(例如,goroutine A 发送的请求,其响应可能被 goroutine B 错误接收)。Pipeline 通过内部同步机制,确保:

  1. 响应的接收顺序与请求的发送顺序严格一致;
  2. 每个请求的响应能被对应的 goroutine 正确接收。

核心方法

  • Pipeline 结构体仅暴露两个核心方法,用于标记请求的生命周期:
  1. StartRequest()
    • 无参数、无返回值。
    • 调用时机:在发送请求前调用,标记一个新请求的开始。
    • 内部逻辑:通过互斥锁增加内部计数器,记录当前活跃请求的数量。
  2. EndRequest()
    1. 无参数、无返回值。
    2. 调用时机:在请求处理完成(通常是收到响应后)调用,标记请求的结束。
    3. 内部逻辑:减少内部计数器,并唤醒等待的读取操作,确保下一个响应能被正确处理。

工作原理

Pipeline 内部通过计数器等待队列实现同步:

  1. 维护一个计数器 n,记录当前未完成的请求数量(StartRequest 增 1,EndRequest 减 1)。
  2. 当读取响应时,Pipeline 会检查计数器,确保只有前序请求都已完成(n 递减到对应值),当前响应才能被读取。
  3. 这种机制强制响应按 “请求发送顺序” 被接收,即使多个 goroutine 并发操作,也不会出现响应错乱。

示例代码

package mainimport ("fmt""net/textproto""time"
)func testRequest(id uint, pipeline *textproto.Pipeline) {pipeline.StartRequest(id)fmt.Println("request: ", id)defer pipeline.EndRequest(id)
}func testResponse(id uint, pipeline *textproto.Pipeline) {pipeline.StartResponse(id)fmt.Println("response: ", id)defer pipeline.EndResponse(id)
}
func main() {pipeline := textproto.Pipeline{}go testRequest(3, &pipeline)go testRequest(1, &pipeline)go testRequest(2, &pipeline)go testRequest(0, &pipeline)go testRequest(4, &pipeline)time.Sleep(5 * time.Second)go testResponse(3, &pipeline)go testResponse(1, &pipeline)go testResponse(2, &pipeline)go testResponse(0, &pipeline)go testResponse(4, &pipeline)time.Sleep(5 * time.Second)
}
http://www.lryc.cn/news/615243.html

相关文章:

  • CamX-骁龙相机修改
  • python学智能算法(三十六)|SVM-拉格朗日函数求解(中)-软边界
  • 【Mac】MLX:Lora微调工作流
  • 学习Java的Day28
  • windows10 ubuntu 24.04 双系统 安装教程
  • ✨ 基于 JsonSerialize 实现接口返回数据的智能枚举转换(优雅告别前端硬编码!)
  • 【ref、toRef、toRefs、reactive】ai
  • 矩阵的条件数 向量的条件数
  • Ubuntu22.04 安装vitis2023.2 卡在“Generating installed device list“.
  • Day 36: 复习
  • 什么情况下需要JVM调优?
  • 如何更改win11自带录音机所录制文件的存储路径
  • 进阶向:Python编写网页爬虫抓取数据
  • synchronized和RentrantLock用哪个?
  • leetcode 49. 字母异位词分组 - java
  • 视图是什么?有什么用?什么时候用?MySQL中的视图
  • 深入理解强化学习:近端策略优化(PPO)算法详解
  • 阿里云 ECS 怎么用 nginx 部署80端口多个网站
  • 组件通信的方式
  • Docker容器部署Tomcat线上商城
  • Leetcode——556. 下一个更大元素 III
  • 八、《DaaS(设备即服务):企业轻资产化新路径》--从97.4%首期投入削减到AI算力高效迭代的范式革命
  • Spring 框架中提供Aware接口,实现感知容器对象
  • spring.config.import 不存在
  • “高大上“的SpringCloud?(微服务体系入门)
  • ELK常见的问题
  • 智能机票助手-接入Ollama本地模型-Spring-AI-Alibaba
  • 在ubuntu服务器下安装cuda和cudnn(笔记)
  • 揭秘MyBatis核心类MappedStatement
  • 多模态RAG赛题实战--Datawhale AI夏令营