Golang Channel 使用详解、注意事项与死锁分析
#作者:西门吹雪
文章目录
- 一、引言:Channel 在 Go 并发编程中的关键地位
- 二、Channel 基础概念深度剖析
- 2.1 独特特性
- 2.2 类型与分类细解
- 三、Channel 基本使用实操指南
- 3.1 声明与初始化
- 3.3 单向 Channel 的运用
- 四、Channel 典型使用场景实战案例
- 4.1 协程间数据传输
- 4.2 同步控制
- 4.3 超时控制
- 五、Channel 使用中的注意事项与死锁分析
- 5.1 未初始化 Channel 的陷阱
- 5.2 阻塞操作引发的死锁风险
- 5.3 关闭 Channel 的注意要点
- 5.4 Range 遍历的注意事项
- 六、死锁规避策略全面解析
- 6.1 配对原则
- 6.2 超时机制
- 6.3 缓冲区规划
- 6.4 明确关闭
- 七、总结与展望
一、引言:Channel 在 Go 并发编程中的关键地位
在 Go 语言的并发编程领域,Channel 堪称基石级的核心数据结构,它搭建起了协程(goroutine)之间通信的桥梁。在高并发的复杂场景下,不同协程需要交换数据、协调执行顺序,Channel 的存在让这些操作变得高效且安全,成为编写健壮并发程序不可或缺的要素。
二、Channel 基础概念深度剖析
2.1 独特特性
- 线程安全保障:Channel 内部精巧地实现了同步锁机制,在多协程并发访问的场景下,能够有效防止数据竞争问题。这意味着多个协程可以安全地对 Channel 进行读写操作,无需额外的复杂同步逻辑,极大地简化了并发编程的难度。
- FIFO 有序传输:数据在 Channel 中严格按照发送顺序传递,这一特性保证了通信的有序性。无论是在简单的双协程通信,还是复杂的多协程协作场景中,接收方总能按照发送顺序获取数据,避免了数据乱序带来的逻辑错误。
- 类型严格约束:每个 Channel 在创建时都声明了特定的数据类型,它只能传输该类型的值。这种强类型约束在编译阶段就能发现类型不匹配的错误,提前避免运行时的异常,增强了程序的稳定性。
2.2 类型与分类细解
2.2.1 按方向性划分
- 只读 Channel(<-chan T):如同一个单向管道,数据只能从这个 Channel 中读取,常用于专注于数据接收的协程。例如,在数据处理流程中,负责数据处理的协程可以通过只读 Channel 接收上游协程发送的数据,而无需担心数据被误写入。
- 只写 Channel(chan<- T):与只读 Channel 相反,它仅允许向 Channel 中写入数据,适用于数据的发送端。比如在数据采集的场景中,负责采集数据的协程可以通过只写 Channel 将采集到的数据发送给下游处理协程。
- 双向 Channel(chan T):兼具读写功能,在很多通用场景中被广泛应用。它就像一个双向管道,允许数据在两个方向上流动,为协程之间的复杂通信提供了便利。
2.2.2 按缓冲区划分 - 无缓冲 Channel:这种 Channel 实现的是同步通信,要求发送方和接收方必须同时就绪。当发送方尝试发送数据时,如果没有接收方准备好接收,发送操作就会被阻塞,直到有接收方出现;反之,接收方尝试接收数据时,若没有数据发送过来,接收操作也会被阻塞。这种同步机制保证了数据的即时传输和处理。
- 有缓冲 Channel:提供了异步通信能力。当缓冲区未满时,发送方可以直接将数据写入缓冲区而不会阻塞;当缓冲区不为空时,接收方也能顺利读取数据。然而,一旦缓冲区满了,继续写入会导致发送方阻塞;缓冲区空了,继续读取则会使接收方阻塞。合理设置缓冲区大小可以平衡通信效率和资源占用。
三、Channel 基本使用实操指南
3.1 声明与初始化
var ch1 chan int // 声明一个未初始化(nil)的Channel,此时它不能用于通信,对其操作会导致阻塞或错误
ch2 := make(chan int) // 使用make函数创建一个无缓冲的Channel,立即可以用于同步通信
ch3 := make(chan string, 5) // 创建一个缓冲大小为5的Channel,可暂存5个string类型的数据,实现异步通信
3.2 核心操作// 写入操作,将data发送到Channel ch中,若Channel已满(有缓冲情况)或无接收方(无缓冲情况),会阻塞
ch <- data
// 读取操作,从Channel ch中接收数据并赋值给data,若Channel为空(有缓冲情况)或无发送方(无缓冲情况),会阻塞
data := <-ch
// 关闭Channel,释放相关资源,关闭后不能再写入数据,读取操作会返回零值(需配合ok检测)
close(ch)
// 非阻塞检测,尝试从Channel ch中读取数据,若成功读取,val为读取到的值,ok为true;若Channel已关闭且无数据,val为零值,ok为false
val, ok := <-ch
3.3 单向 Channel 的运用
func producer(ch chan<- int) { // 生产者函数,只负责向Channel写入数据ch <- 1
}
func consumer(ch <-chan int) { // 消费者函数,只从Channel读取数据fmt.Println(<-ch)
}
通过这种方式,明确了每个协程对 Channel 的操作权限,提高了代码的可读性和安全性。
四、Channel 典型使用场景实战案例
4.1 协程间数据传输
func main() {ch := make(chan int)go func() { ch <- 42 }() // 启动一个协程,向Channel发送数据42fmt.Println(<-ch) // 主线程从Channel读取数据并打印,输出: 42
}
在这个简单的例子中,通过 Channel 实现了主线程与子协程之间的数据传递。
4.2 同步控制
func worker(done chan bool) {// 模拟执行任务time.Sleep(time.Second)done <- true // 任务完成后,向Channel发送完成信号
}
func main() {done := make(chan bool)go worker(done)<-done // 主线程阻塞等待,直到接收到任务完成信号fmt.Println("Worker task completed")
}
利用 Channel 实现了主线程对子协程任务完成情况的同步等待,确保程序逻辑的正确性。
4.3 超时控制
func main() {ch := make(chan int)go func() {time.Sleep(5 * time.Second)ch <- 100 // 5秒后发送数据}()select {case res := <-ch:fmt.Println("Received:", res)case <-time.After(3 * time.Second):fmt.Println("Timeout!") // 3秒内未收到数据,触发超时}
}
通过select语句结合time.After函数,实现了对数据接收的超时控制,避免程序无限期阻塞。
五、Channel 使用中的注意事项与死锁分析
5.1 未初始化 Channel 的陷阱
- 读 / 写风险:对未初始化(值为 nil)的 Channel 进行读或写操作,会导致协程永久阻塞,进而可能引发整个程序的死锁。因为 nil 的 Channel 没有实际的通信能力,任何操作都无法完成,操作会一直处于等待状态。
- 关闭错误:尝试关闭一个未初始化的 Channel 会触发 panic,因为关闭操作需要对 Channel 的内部状态进行管理,而 nil 的 Channel 没有有效的内部状态,无法进行关闭操作。
5.2 阻塞操作引发的死锁风险
5.2.1 无缓冲 Channel
- 发送无接收死锁:当发送方尝试向无缓冲 Channel 发送数据,而此时没有接收方准备好接收时,发送操作会一直阻塞,导致死锁。这是因为无缓冲 Channel 要求发送和接收必须同时进行,否则就会陷入等待。
- 接收无发送死锁:同理,当接收方尝试从无缓冲 Channel 接收数据,而没有发送方发送数据时,接收操作也会一直阻塞,最终导致死锁。
5.2.2 有缓冲 Channel
- 写满后继续写死锁:当有缓冲 Channel 的缓冲区已满,发送方继续写入数据,会导致发送方阻塞。如果在复杂的多协程场景中,这种阻塞形成循环等待,就会引发死锁。
- 读空后继续读死锁:当缓冲区为空,接收方继续读取数据,同样会导致接收方阻塞。若处理不当,也可能引发死锁。
示例:
func main() {ch := make(chan int)ch <- 1 // 主线程尝试向无缓冲Channel发送数据,但无接收者,导致死锁go func() { <-ch }()
}
在这个例子中,主线程发送数据时没有接收者,而接收协程在主线程之后启动,来不及接收数据,从而引发死锁。
5.3 关闭 Channel 的注意要点
- 重复关闭风险:对一个已经关闭的 Channel 再次执行关闭操作,会触发 panic。因为 Channel 的关闭状态是一次性的,重复关闭会破坏其内部状态,导致不可预测的错误。
- 向已关闭 Channel 写数据错误:尝试向已关闭的 Channel 写入数据,也会触发 panic。已关闭的 Channel 不再接受新的数据写入,以保证数据的一致性和安全性。
- 读取已关闭 Channel 的正确方式:从已关闭的 Channel 读取数据,会返回该 Channel 类型的零值。为了准确检测 Channel 是否已关闭,需要配合ok进行检测,如val, ok := <-ch,当ok为false时,表示 Channel 已关闭。
5.4 Range 遍历的注意事项
- 未关闭 Channel 的死锁隐患:在使用range遍历 Channel 时,如果 Channel 未关闭,range会一直等待 Channel 有新的数据到来,导致协程阻塞,可能引发死锁。
- 正确用法:通常由发送方在完成数据发送后关闭 Channel,接收方使用range安全遍历。这样当 Channel 关闭时,range会自动结束,避免死锁。
func main() {ch := make(chan int)go func() {for i := 0; i < 5; i++ {ch <- i}close(ch) // 发送方完成数据发送后,关闭Channel}()for val := range ch {fmt.Println(val)}
}
六、死锁规避策略全面解析
6.1 配对原则
在设计并发程序时,要确保每个发送操作都有对应的接收操作,避免出现发送或接收的孤立操作。仔细规划数据的流向和通信逻辑,从根本上防止死锁的发生。例如,在一个多协程的数据处理流程中,要明确每个协程发送数据的时机和接收数据的来源。
6.2 超时机制
使用select语句结合time.After函数,为数据接收等操作设置超时时间。在等待数据接收时,若超过一定时间仍未收到数据,则执行超时处理逻辑,避免程序因永久阻塞而导致死锁。
select {
case res := <-ch:// 处理接收到的数据
case <-time.After(5 * time.Second):// 处理超时情况
}
6.3 缓冲区规划
根据实际的业务需求和数据流量,合理设置 Channel 的缓冲大小。在数据流量较大的场景中,适当增大缓冲区可以避免因缓冲区满或空导致的阻塞和死锁;而在资源有限的情况下,要避免设置过大的缓冲区造成资源浪费。
6.4 明确关闭
明确由发送方关闭 Channel,当发送方完成数据发送后,及时关闭 Channel,以此通知接收方数据传输结束。接收方可以据此安全退出相关操作,避免因等待数据而导致死锁。
七、总结与展望
Channel 作为 Go 语言并发模型的核心组件,在构建高效、可靠的并发程序中起着关键作用。正确使用 Channel,需要牢记以下要点:
- 初始化先行:务必避免对未初始化的 Channel 进行操作,在使用前进行正确的初始化,为后续的通信操作奠定基础。
- 方向精准控制:合理运用单向 Channel,通过限制其方向性,增强程序的可读性和安全性,使代码逻辑更加清晰。
- 生命周期妥善管理:及时关闭 Channel,并在读取时准确检测其状态,确保 Channel 在整个生命周期内的正常运行。
- 死锁有效预防:遵循配对原则、设置超时机制、合理规划缓冲区和明确关闭等设计模式,有效避免死锁的发生。
掌握这些要点,开发者就能在 Go 语言的并发编程中如鱼得水,充分发挥 Channel 的强大功能,构建出健壮、高性能的并发程序,应对各种复杂的业务场景。随着 Go 语言的不断发展和应用场景的日益广泛,深入理解和熟练运用 Channel 将成为开发者的必备技能。
相关文章:
Golang Channel 使用详解、注意事项与死锁分析
#作者:西门吹雪 文章目录 一、引言:Channel 在 Go 并发编程中的关键地位二、Channel 基础概念深度剖析2.1 独特特性2.2 类型与分类细解 三、Channel 基本使用实操指南3.1 声明与初始化3.3 单向 Channel 的运用 四、Channel 典型使用场景实战案例4.1 协程…...
CSS 入门指南(一):基本概念 选择器 常用元素属性
一、初识 CSS 1, CSS 定义 层叠样式表(Cascading Style Sheets,缩写为 CSS),是一种 样式表 语言,用来描述 HTML 文档的呈现(美化内容) CSS 能够对网页中元素位置的排版进行 像素级 精确控制,实现美化页面…...
c_cpp_properties.json等三个文件解释
不建议太小白的人看啊 在 Visual Studio Code 中使用 C 语言进行编程时,通常会看到一些特定的配置文件。这些文件是用来帮助你配置开发环境、调试程序等 就是这三个文件 首先是c_cpp_properties.json: 这是 Visual Studio Code 配置 C/C 开发环境的文件。…...
G-Star 公益行起航,挥动开源技术点亮公益!
公益组织,一直是社会温暖的传递者,但在数字化浪潮中,也面临着诸多比大众想象中复杂的挑战:项目管理如何更高效?志愿者管理又该如何创新?宣传推广怎么才能更有影响力?内部管理和技术支持又该如何…...
Jetson Xavier NX安装CUDA加速的OpenCV
我们使用SDKManager刷机完成后,使用jtop查看,发现OpenCV 是不带CUDA加速的,因此,我们需要安装CUDA加速的OpenCV,这样后续在使用的时候速度会快很多。 首先我们先卸载默认OpenCV sudo apt purge libopencv* -y sudo …...
用android studio模拟器,模拟安卓手机访问网页,使用Chrome 开发者工具查看控制台信息
web 网页项目在安卓手机打开时出现问题,想要查看控制台调试信息。记录一下使用android studio 模拟器访问的方式。 步骤如下: 1.安装android studio,新增虚拟设备(VDM- virtual device manager) 点击Virtual Device Manager后会…...
基于Transformer的医学文本分类:从BERT到BioBERT
随着自然语言处理(NLP)技术的快速发展,Transformer模型在文本分类、情感分析、机器翻译等任务中取得了显著成果。在医学领域,文本数据(如电子病历、医学文献、临床报告)具有高度的专业性和复杂性,传统的NLP方法往往难以处理。Transformer模型,尤其是BERT及其变体,通过…...
【Python】Django 中的算法应用与实现
Django 中的算法应用与实现 在 Django 开发中,算法的应用可以极大地扩展 Web 应用的功能和性能。从简单的数据处理到复杂的机器学习模型,Django 都可以作为一个强大的后端框架来支持这些算法的实现。本文将介绍几种常见的算法及其在 Django 中的使用方法…...
vs code配置 c/C++
1、下载VSCode Visual Studio Code - Code Editing. Redefined 安装目录可改 勾选创建桌面快捷方式 安装即可 2、汉化VSCode 点击确定 下载MinGW 由于vsCode 只是一个编辑器,他没有自带编译器,所以需要下载一个编译器"MinGW". https://…...
YOLO11 环境安装
1.安装Anaconda/Miniconda 在Ubuntu中安装Miniconda Anaconda/Miniconda pip 配置清华镜像源 Anaconda/Miniconda 基本操作命令 2.创建python虚拟环境 # 创建 conda create -n yolo11_env python3.12# 激活 conda activate yolo11_env 3.安装pytorch # Pytorch https://…...
BLEU评估指标
一、介绍 用于评估模型生成的句子和实际句子差异的指标,取值在[0,1],匹配度高就距离1近,反之距离0近。这个指标计算代价小,容易理解,与语言无关,与人类评价结果高度相关。 BLEU主要基于n-gram匹配&#x…...
学习路之TP6 --重写vendor目录下的文件(新建命令)
[TOC](学习路之TP6 --重写vendor目录下的文件(新建命令)) 一、新建命令文件 php think make:command CustomWorker二、修改 复制vendor\topthink\think-worker\src\command\Server.php 内容到app\command\CustomWorker.php 修改继承类:class CustomWorker exten…...
[Linux] 3588开发准备工作
背景需求 在3588上开发软件系统,用于视频流读取,处理,推流等操作。一般来说,会先买对应型号的开发板进行开发测试。同步制作硬件,等到硬件回来之后,可将代码进行烧录到嵌入式板端,能够执行相应…...
小程序网络大文件缓存方案
分享一个小程序网络大图加载慢的解决方案 用到的相关api getSavedFileList 获取已保存的文件列表;getStorageSync 获取本地缓存;downloadFile 下载网络图片;saveFile 保存文件到本地;setStorage 将数据储存到小程序本地缓存&…...
在 Windows 上快速部署 OpenManus:从安装到运行
在当今快速发展的 AI 领域,OpenManus 作为一个强大的开源工具,为开发者提供了便捷的 AI 应用开发体验。本文将详细介绍如何在 Windows 系统上安装并运行 OpenManus,帮助你快速搭建一个本地的 AI 开发环境。 一、安装 Anaconda Anaconda 是一…...
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
前言 在将 Spring Boot 项目升级至 3.3.4 版本后,遇到 Logback 配置的兼容性问题。本文将详细描述该问题的错误信息、原因分析,并提供调整日志回滚策略的解决方案。 错误描述 这是SpringBoot 3.3.3版本之前的回滚策略的配置 <!-- 日志记录器的滚动…...
快速集成1688商品API:10分钟实现跨境选品数据自动化
要快速集成 1688 商品 API 以实现跨境选品数据自动化,可参考以下步骤: 注册并申请 API 权限:注册账号创建应用并申请所需的 API 权限,如商品搜索、筛选、获取详情等相关权限。获取 API Key 和 Secret:在应用管理页面获…...
21天 - 说说 TCP 的四次挥手?TCP 的粘包和拆包能说说吗?说说 TCP 拥塞控制的步骤?
说说 TCP 的四次挥手? TCP 协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,它通过著名的 “三次握手” 来建立连接。相对地,TCP 协议通过四次挥手来断开连接。以下是四次挥手的详细过程: 第一次挥手(Clien…...
LeetCode:93. 复原 IP 地址(DFS Java)
目录 93. 复原 IP 地址 题目描述: 实现代码与解析: DFS 原理思路: 93. 复原 IP 地址 题目描述: 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0)…...
Flutter_学习记录_device_info_plus 插件获取设备信息
引入三方库device_info_plus导入头文件 import package:device_info_plus/device_info_plus.dart;获取设备信息的主要代码 DeviceInfoPlugin deviceInfoPlugin DeviceInfoPlugin(); BaseDeviceInfo deviceInfo await deviceInfoPlugin.deviceInfo;完整案例 import package…...
详解CISC与RISC及其区别
CISC(Complex Instruction Set Computing,复杂指令集计算机)和RISC(Reduced Instruction Set Computing,精简指令集计算机)是两种不同的计算机架构理念,主要区别在于指令集的设计和处理方式&…...
偶然发现了 setTimeout 的隐藏彩蛋
最近在看《JavaScript高级程序设计(第4版)》,运行书中的一个代码示例时,偶然发现了 setTimeout 的一些之前没注意到的特性,觉得挺有意思的,就来记录一下。 书中代码如下: for (var i 0; i &l…...
zerotier搭建免费moon服务器
🌟 前言 ZeroTier是一种基于P2P的虚拟组网工具,通过搭建Moon服务器可大幅提升跨运营商/跨国节点的连接质量。本文使用云服务演示部署流程。 📋 准备工作 注册三丰云账号 创建CentOS 8.5实例 (这里选择centos8以上&a…...
Unity Timeline 扩展
这里认为大家已经会timeline的基本使用了,只介绍怎么自定义扩展。 第一步.自定义Track 首先要自定义一条轨道。剪辑是要在轨道里跑的,系统自带的轨道我们加不了自定义剪辑,得新建自己用的。这个很简单。 [TrackClipType(typeof(TransformTw…...
HarmonyOS第21天:解锁分布式技术,开启跨设备协同新体验
一、HarmonyOS 分布式技术:开启万物互联新时代 在物联网蓬勃发展的今天,设备之间的互联互通不再是遥不可及的梦想,而是真切融入日常生活的现实。从智能家居设备的联动控制,到智能办公场景中的高效协作,再到智能出行中的…...
BUUCTF Pwn [ZJCTF 2019]EasyHeap unlink+freehook做法
checksec exeinfo : IDA64打开: delete_heap函数已经将指针清零 无UAF edit_heap允许自己输入读取字节 存在堆溢出 同时 存储的指针位于bss段 那接下来就想到unlink方法: 图示: 后续修改0x6020E0的位置为freehook 再修改一次 让其…...
【解决方案】RAGFlow部分问题清单及解决方案备忘1
一、长时间显示:Task is queued 多半是因为模型确实在队列中排队的原因,要么是内存一直在被占用中,要么是CPU或GPU一直在被占用中,可以首先检查硬件利用率: 如果是内存导致的队列缓慢,可以将.env文件中的M…...
Linux笔记---文件系统硬件部分
1. 文件系统 文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构,即在存储设备上组织文件的方法。 1.1 基本组成 索引节点(inode)ÿ…...
低成本抗衡DeepSeek-R1!QwQ-32B本地部署教程:消费级硬件可部署
QwQ-32B是阿里通义千问团队在3月6日发布的开源大模型,这款仅有320亿参数的模型,在数学、代码、通用能力等核心场景里,几乎跟满血版DeepSeek-R1(6710亿参数)不相上下。可以说实现了开源领域的降维打击。 参数规模与性能…...
二叉树中堆的实现
1 堆的声明和定义 typedef int HPDateType; typedef struct Heap {HPDateType* arr;int size;int capcity; }HP; 与顺序表相似,我们需要一个数组,有效空间大小,有效元素个数 2 堆的初始化 void HPInit(HP*php) {assert(php);php->arr …...
概率论的基本知识
逆概率还不懂,改天再想想。 联合概率 联合概率(Joint Probability) 是概率论中的一个重要概念,用于描述多个随机变量同时取某些值的概率。联合概率可以帮助我们理解多个变量之间的关系。...
LVDS(Low Voltage Differential Signaling)电平详解
一、LVDS的定义与核心特性 LVDS(低压差分信号)是一种 低功耗、高速、抗干扰 的差分信号传输技术,通过一对互补的电压信号(正负端差值)传递数据。其核心特性包括: 电气特性 电压摆幅:差分电压约…...
2024年第十五届蓝桥杯软件C/C++大学A组——五子棋对弈
蓝桥杯原题: 题目描述: “在五子棋的对弈中,友谊的小船说翻就翻? ” 不!对小蓝和小桥来说,五子棋不仅是棋盘上的较量,更是心与心之间的沟通。这两位挚友秉承着 “ 友谊第一,比赛第二…...
OpenRewrite配方之import语句的顺序——org.openrewrite.java.OrderImports
org.openrewrite.java.OrderImports 是 OpenRewrite 工具库中的一个重要规则(Recipe),专为 Java 项目设计,用于自动化调整 import 语句的顺序,使其符合预定义的代码规范。从而提高代码的一致性和可读性。 核心功能 排序规则: 静态导入优先:默认将静态导入(import stati…...
数字电子技术基础(二十八)——TTL门电路的静态功耗和动态功耗
1 静态功耗 门电路的工作需要直流电压源的支持,无论在模拟电路还是在数字电路中,只有在外加直流电源的作用下,半导体二极管具有单向导电性,晶体管的放大能力以及开关特性才能体现出来芯片的电源端正负级。芯片的电源端正负极如果…...
RISC-V汇编学习(四)—— RISCV QEMU平台搭建(基于芯来平台)
RISCV汇编学习系列: RISC-V汇编学习(一)—— 基础认识 RISC-V汇编学习(二)—— 汇编语法 RISC-V汇编学习(三)—— RV指令集 RISC-V汇编学习(四)—— RISCV QEMU平台搭建…...
链表的定义、节点结构、基本操作(C++)
1. 链表的基本概念 链表是一种动态数据结构,它的元素(节点)在内存中不一定是连续存储的。每个节点通过指针连接到下一个节点,形成一个链式结构。链表分为单向链表、双向链表和循环链表等,这里主要介绍单向链表。 2. …...
deepseek使用记录21——脑图记录
我们有比前人更先进的工具,为何不利用起来呢? 工作的时候,问问自己,这个问题是理论问题?还是实践问题?如何在系统中劈开一条可实践路径?系统中的缝,系统中的力量(人先进…...
[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现
标题:[多线程]基于阻塞队列(Blocking Queue)的生产消费者模型的实现 水墨不写bug 文章目录 一、生产者消费者模型特点:二、实现2.1详细解释1. 成员变量2. 构造函数3. Isfull 和 Isempty4. Push 函数5. Pop 函数6. 析构函数7. GetSize 函数 三、总结与多线…...
【时时三省】(C语言基础)输入输出的概念
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 有关数据输入输出的概念 从前面的程序中可以看到:几乎每一个C程序都包含输入输出。因为要进行运算,就必须给出数据,而运算的结果当然需要输出,…...
基于ragflow中deepdoc对pdf文档的rag系统
基于ragflow中deepdoc对pdf文档的rag系统 一、安装 conda环境安装到指定的路径 conda create 包名/环境的名字 rag就是包的名字,ragflow就是环境名; 怎样激活环境?–我是在百度飞桨上面跑的 conda activate /home/aistudio/rag/ragflow …...
基于WebRTC技术的EasyRTC嵌入式音视频SDK:多平台兼容与性能优化
在当今数字化、智能化的时代背景下,实时音视频通信技术已成为众多领域不可或缺的关键技术。基于WebRTC技术的EasyRTC嵌入式音视频SDK,凭借其在ARM、Linux、Windows、安卓、iOS等多平台上的兼容性,为开发者提供了强大的工具,推动了…...
Linux驱动开发实战(四):设备树点RGB灯
Linux驱动开发实战(四):设备树点RGB灯 文章目录 Linux驱动开发实战(四):设备树点RGB灯前言一、驱动实现1.1 驱动设计思路1.2 关键数据结构1.3 字符设备操作函数1.4 平台驱动探测函数1.5 匹配表和平台驱动结…...
大模型架构记录5-向量数据库
一 倒排索引、KNN、PQ 1.1 基础版本 query -> requery 对问题做处理,处理上下文 对query 做 refined query 1.2 向量数据库 二 搜索逻辑 2.1 knn 2.2 近似KNN 先和N个空间的均值比较再和空间内部的所有点比较,计算最近值。 优化一: …...
【 Fail2ban 使用教程】
Fail2ban 使用教程 1. 安装 Fail2ban2. 配置 Fail2ban2.1 创建 jail.local 文件2.2 基本配置参数说明2.3 配置具体服务的监控规则2.3.1 SSH 服务2.3.2 Apache 服务 3. 启动和管理 Fail2ban3.1 启动 Fail2ban 服务3.2 设置 Fail2ban 开机自启3.3 检查 Fail2ban 服务状态3.4 重新…...
Django系列教程(8)——函数视图及通用类视图
目录 什么是视图(View)及其工作原理 接近现实的函数视图 更复杂的案例: 视图处理用户提交的数据 基于函数的视图和基于类的视图 Django通用类视图 a. ListView b. DetailView c. CreateView d. UpdateView e. FormView f. DeleteView 小结 Django的视图(view)是处理…...
【C#学习笔记04】C语言格式化输出
引言 printf()函数不仅可以将数据输出到控制台,还可以通过格式化字符串灵活地控制输出的格式。printf()函数的使用规则,包括标志说明、字段宽度、转换精度、长度修饰、转换说明、转义字符。 1. printf()函数概述 printf…...
九点标定和十二点标定的区别
九点标定和十二点标定是机器视觉中常用的两种手眼标定方法,用于建立图像坐标系与机械坐标系之间的映射关系。它们的核心区别在于标定点的数量、变换模型和适用场景。以下是详细对比: 1. 九点标定 特点 标定点数量:9 个点,通常排…...
qt+opengl 播放yuv视频
一、实现效果 二、pro文件 Qt widgets opengl 三、主要代码 #include "glwidget.h"GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent) {connect(&m_timer, &QTimer::timeout, this,[&](){this->update();});m_timer.start(1000/33); }v…...
【揭秘测绘艺术】从基础到法律,绘制地球的智慧蓝图
在人类探索与塑造世界的征途中,有一门古老而又现代的科学默默发挥着基石作用——测绘。它不仅仅是地图的绘制,更是对地球空间信息的精准捕捉与智慧应用。今天,让我们一起走进测绘的世界,解码“测绘”与“基础测绘”的内涵…...