samber/lo 库的使用方法: 处理 channel
samber/lo 库的使用方法: 处理 channel
samber/lo 是一个 Go 语言库,提供了一些常用的集合操作函数,如 Filter、Map 和 FilterMap。汇总目录页面
这个库函数太多,因此我决定按照功能分别介绍,本文介绍的是 samber/lo 库中channel相关的函数。
ChannelDispatcher
将信息从输入通道消息分发到 N 个子通道中。当输入通道关闭时,这个关闭事件会被传播到所有的子通道,也就是说,所有的子通道也会被关闭。这些通道可以有一个固定的缓冲容量,或者当 cap(容量)为 0 时,它们是无缓冲的。
// 创建了一个带有 42 个缓冲区的整数通道 ch,并向其中发送 0 到 10 的整数。
ch := make(chan int, 42)
for i := 0; i <= 10; i++ {ch <- i
}// 使用 lo.ChannelDispatcher 函数创建了 5 个子通道,每个通道的缓冲区大小为 10。
// 这个函数会将 ch 中的数据按照轮询策略分发到这些子通道中。
children := lo.ChannelDispatcher(ch, 5, 10, DispatchingStrategyRoundRobin[int])
// []<-chan int{...}// 定义了一个 consumer 函数,这个函数会从给定的通道中读取数据,直到通道关闭。
// 如果通道已经关闭,ok 会为 false,我们就打印 "closed" 并退出循环。
consumer := func(c <-chan int) {for {msg, ok := <-cif !ok {println("closed")break}println(msg)}
}// 为每个子通道启动一个 consumer goroutine。
// 这样,我们就创建了 5 个并发的消费者,它们会并行地从 ch 中读取数据。
for i := range children {go consumer(children[i])
}
有很多分发策略可用:
- lo.DispatchingStrategyRoundRobin: 使用轮询策略将消息分发到子通道中。
- lo.DispatchingStrategyRandom: 使用随机策略将消息分发到子通道中。
- lo.DispatchingStrategyWeightedRandom: 使用加权随机策略将消息分发到子通道中。
- lo.DispatchingStrategyFirst: 分发消息到第一个非满的子通道中。
- lo.DispatchingStrategyLeast: 分发消息到最空的子通道中。
- lo.DispatchingStrategyMost: 分发消息到最满的子通道中。
其中一些策略会带有回退机制,以便优先考虑非阻塞行为。请参阅实现。
对于自定义策略,只需实现 lo.DispatchingStrategy
原型即可:
type DispatchingStrategy[T any] func(message T, messageIndex uint64, channels []<-chan T) int
-
DispatchingStrategy 是一个函数,它接受三个参数:
-
message T:这是要分发的消息,其类型为泛型 T。
-
messageIndex uint64:这是消息的索引,通常用于确定将消息分发到哪个通道。
-
channels []<-chan T:这是一个通道切片,消息将被分发到这些通道中的一个。
-
这个函数返回一个 int,表示消息应该被分发到 channels 切片中的哪个通道。
Eg:
type Message struct {TenantID uuid.UUID
}func hash(id uuid.UUID) int {h := fnv.New32a()h.Write([]byte(id.String()))return int(h.Sum32())
}// Routes messages per TenantID.
customStrategy := func(message string, messageIndex uint64, channels []<-chan string) int {destination := hash(message) % len(channels)// check if channel is fullif len(channels[destination]) < cap(channels[destination]) {return destination}// fallback when child channel is fullreturn utils.DispatchingStrategyRoundRobin(message, uint64(destination), channels)
}children := lo.ChannelDispatcher(ch, 5, 10, customStrategy)
...
SliceToChannel
返回一个只读的通道,其中包含了集合中的元素。当最后一个元素被读取后,通道会被关闭。第一个参数是通道的容量,第二个参数是集合。
list := []int{1, 2, 3, 4, 5}for v := range lo.SliceToChannel(2, list) {println(v)
}
// prints 1, then 2, then 3, then 4, then 5
ChannelToSlice
返回一个由通道中的元素构建的切片。阻塞直到通道关闭。
list := []int{1, 2, 3, 4, 5}
ch := lo.SliceToChannel(2, list)items := ChannelToSlice(ch)
// []int{1, 2, 3, 4, 5}
Generator
实现了生成器设计模式。通道在最后一个元素被读取后会被关闭。通道的容量可以被定制。 Generator的第一个参数是通道的容量,第二个参数是生成器函数, 返回一个通道。 其中,生成器函数的参数是一个函数,这个函数用于向通道中发送元素。
generator := func(yield func(int)) {yield(1)yield(2)yield(3)
}for v := range lo.Generator(2, generator) {println(v)
}
// prints 1, then 2, then 3
Buffer
创建一个包含 n 个元素的切片,这些元素来自通道。返回切片、切片长度、读取时间和通道状态(打开/关闭)。第一个参数是通道,第二个参数是切片的长度。
ch := lo.SliceToChannel(2, []int{1, 2, 3, 4, 5})items1, length1, duration1, ok1 := lo.Buffer(ch, 3)
// []int{1, 2, 3}, 3, 0s, true
items2, length2, duration2, ok2 := lo.Buffer(ch, 3)
// []int{4, 5}, 2, 0s, false
示例:RabbitMQ 消费者
ch := readFromQueue()for {// read 1k itemsitems, length, _, ok := lo.Buffer(ch, 1000)// do batching stuffif !ok {break}
}
BufferWithTimeout
和Buffer函数类似, 但是增加了一个超时参数, 如果超时,返回已经读取的元素。
generator := func(yield func(int)) {for i := 0; i < 5; i++ {yield(i)time.Sleep(35*time.Millisecond)}
}ch := lo.Generator(0, generator)items1, length1, duration1, ok1 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)
// []int{1, 2}, 2, 100ms, true
items2, length2, duration2, ok2 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)
// []int{3, 4, 5}, 3, 75ms, true
items3, length3, duration2, ok3 := lo.BufferWithTimeout(ch, 3, 100*time.Millisecond)
// []int{}, 0, 10ms, false
示例:RabbitMQ 消费者
ch := readFromQueue()for {// read 1k items// wait up to 1 seconditems, length, _, ok := lo.BufferWithTimeout(ch, 1000, 1*time.Second)// do batching stuffif !ok {break}
}
示例:多线程的 RabbitMQ 消费者
ch := readFromQueue()// 5 workers
// prefetch 1k messages per worker
children := lo.ChannelDispatcher(ch, 5, 1000, lo.DispatchingStrategyFirst[int])consumer := func(c <-chan int) {for {// read 1k items// wait up to 1 seconditems, length, _, ok := lo.BufferWithTimeout(ch, 1000, 1*time.Second)// do batching stuffif !ok {break}}
}for i := range children {go consumer(children[i])
}
FanIn
合并多个输入通道的消息到一个缓冲通道中。输出消息没有优先级。当所有的上游通道到达 EOF 时,下游通道关闭。
stream1 := make(chan int, 42)
stream2 := make(chan int, 42)
stream3 := make(chan int, 42)all := lo.FanIn(100, stream1, stream2, stream3)
// <-chan int
FanOut
广播所有上游消息到多个下游通道。当上游通道到达 EOF 时,下游通道关闭。如果任何下游通道已满,广播将暂停。
stream := make(chan int, 42)all := lo.FanOut(5, 100, stream)
// [5]<-chan int
相关文章:
samber/lo 库的使用方法: 处理 channel
samber/lo 库的使用方法: 处理 channel samber/lo 是一个 Go 语言库,提供了一些常用的集合操作函数,如 Filter、Map 和 FilterMap。汇总目录页面 这个库函数太多,因此我决定按照功能分别介绍,本文介绍的是 samber/lo…...

铌酸锂芯片与精密划片机:科技突破引领半导体制造新潮流
在当今快速发展的半导体行业中,一种结合了铌酸锂芯片与精密划片机的创新技术正在崭露头角。这种技术不仅引领着半导体制造领域的进步,更为其他产业带来了前所未有的变革。 铌酸锂芯片是一种新型的微电子芯片,它使用铌酸锂作为基底材料&#x…...

大数据计算技术秘史(上篇)
在之前的文章《2024 年,一个大数据从业者决定……》《存储技术背后的那些事儿》中,我们粗略地回顾了大数据领域的存储技术。在解决了「数据怎么存」之后,下一步就是解决「数据怎么用」的问题。 其实在大数据技术兴起之前,对于用户…...

论文精读--word2vec
word2vec从大量文本语料中以无监督方式学习语义知识,是用来生成词向量的工具 把文本分散嵌入到另一个离散空间,称作分布式表示,又称为词嵌入(word embedding)或词向量 Abstract We propose two novel model architec…...

Android13 针对low memory killer内存调优
引入概念 在旧版本的安卓系统中,当触发lmk(low memory killer)的时候一般认为就是内存不足导致,但是随着安卓版本的增加lmk的判断标准已经不仅仅是内存剩余大小,io,cpu同样会做评判,从而保证设备…...

【深入理解设计模式】 工厂设计模式
工厂设计模式 工厂设计模式是一种创建型设计模式,它提供了一种在不指定具体类的情况下创建对象的接口。在工厂设计模式中,我们定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 工厂设计模式的目…...

Windows下搭建EFK实例
资源下载 elasticSearch :下载最新版本的就行 kibana filebeat:注意选择压缩包下载 更新elasticsearch.yml,默认端口9200: # Elasticsearch Configuration # # NOTE: Elasticsearch comes with reasonable defaults for most …...

工厂方法模式Factory Method
1.模式定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实例化延迟到子类 2.使用场景 1.当你不知道改使用对象的确切类型的时候 2.当你希望为库或框架提供扩展其内部组件的方法时 主要优点: 1.将具体产品和创建…...

Vue的个人笔记
Vue学习小tips ctrl s ----> 运行 alt b <scrip> 链接 <script src"https://cdn.jsdelivr.net/npm/vue2.7.16/dist/vue.js"></script> 插值表达式 指令...

linux platform架构下I2C接口驱动开发
目录 概述 1 认识I2C协议 1.1 初识I2C 1.2 I2C物理层 1.3 I2C协议分析 1.3.1 Start、Stop、ACK 信号 1.3.2 I2C协议的操作流程 1.3.3 操作I2C注意的问题 2 linux platform驱动开发 2.1 更新设备树 2.1.1 添加驱动节点 2.1.2 编译.dts 2.1.3 更新板卡中的.dtb 2.2 …...

基于机器学习的青藏高原高寒沼泽湿地蒸散发插补研究_王秀英_2022
基于机器学习的青藏高原高寒沼泽湿地蒸散发插补研究_王秀英_2022 摘要关键词 1 材料和方法1.1 研究区概况与数据来源1.2 研究方法 2 结果和分析2.1 蒸散发通量观测数据缺省状况2.2 蒸散发与气象因子的相关性分析2.3 不同气象因子输入组合下各模型算法精度对比2.4 随机森林回归模…...
Failed at the node-sass@4.14.1 postinstall script.
问题描述 安装sass # "node-sass": "^4.9.0" npm i node-sass报错如下 npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! node-sass4.14.1 postinstall: node scripts/build.js npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the node-sass4…...

【鸿蒙系统学习笔记】网络请求
一、介绍 资料来自官网:文档中心 网络管理模块主要提供以下功能: HTTP数据请求:通过HTTP发起一个数据请求。WebSocket连接:使用WebSocket建立服务器与客户端的双向连接。Socket连接:通过Socket进行数据传输。 日常…...

LabVIEW风力机智能叶片控制系统
LabVIEW风力机智能叶片控制系统 介绍了一种风力机智能叶片控制系统的开发。通过利用LabVIEW软件与CDS技术,该系统能够实时监测并调整风力机叶片的角度,优化风能转换效率。此项技术不仅提高了风力发电的稳定性和效率,而且为风力机的智能化管…...
HarmonyOS Stage模型 权限申请
配置声明权限 在module.json5配置文件中声明权限。不论是system_grant还是user_grant类型都需要声明权限,否则应用将无法获得授权。 {"module" : {// ..."requestPermissions":[{"name": "ohos.permission.DISCOVER_BLUETOOTH…...
标题:从预编译到链接:探索C/C++程序的翻译环境全貌
引言 在软件开发的世界里,我们通常会遇到两种不同的环境——翻译环境与运行环境。今天,我们将聚焦于前者,深入剖析C/C程序生命周期中至关重要的“翻译环境”,即从源代码到可执行文件这一过程中涉及的四个关键阶段:预编…...

深入理解单端模拟多路复用器DG406DW-E3 应用于高速数据采集、ATE系统和航空电子设备解决方案
DG406DW-E3是一款16通道单端模拟多路复用器设计用于将16个输入中的一个连接到公共端口由4位二进制地址确定的输出。应用包括高速数据采集、音频信号切换和路由、ATE系统和航空电子设备。高性能低功耗损耗使其成为电池供电和电池供电的理想选择远程仪器应用。采用44V硅栅CMOS工艺…...

Redis篇----第六篇
系列文章目录 文章目录 系列文章目录前言一、Redis 的持久化机制是什么?各自的优缺点?二、Redis 常见性能问题和解决方案:三、redis 过期键的删除策略?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章…...
【LeetCode】509. 斐波那契数(简单)——代码随想录算法训练营Day38
题目链接:509. 斐波那契数 题目描述 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n -…...
[OpenGL教程05 ] glAccum() 函数对累积缓存设置
Accumulation Buffer:累积缓存 一、说明 openGL编程之所以困难,是因为它是三维图表示;简简单单加入一个Z轴,却使得几何遮挡、光线过度、运动随影等搞得尤其复杂。它的核心处理环节是像素缓存,本篇的积累缓存就是其一个…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
机器学习的数学基础:线性模型
线性模型 线性模型的基本形式为: f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法,得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...