2411rust,异步函数
原文
Rust
异步工作组很高兴
地宣布
,在实现在特征
中使用异步 fn
的目标
方面取得了重大进度
.将在下周发布稳定的Rust1.75
版,会包括特征
中支持impl Trait
注解和async fn
.
稳定化
自从RFC#1522
在Rust1.26
中稳定下来以来,Rust
就允许用户按函数的返回类型
(一般叫"RPIT"
)编写impl Trait
.
即该函数
返回"某种实现特征
的类型
".这一般来返回闭包,迭代器
和其他复杂或无法显式编写
的类型.
//给定一个玩家列表,返回在他们的`名字`上的`一个迭代器`.
fn player_names(players: &[Player]
) -> impl Iterator<Item = &String> {players.iter().map(|p| &p.name)
}
从Rust1.75
开始,你可在特征
(RPITIT
)定义和trait impl
中使用返回位置
的impl Trait
.如,你可用它来编写一个返回迭代器
的特征
方法:
trait Container {fn items(&self) -> impl Iterator<Item = Widget>;
}
impl Container for MyContainer {fn items(&self) -> impl Iterator<Item = Widget> {self.items.iter().cloned()}
}
则这一切与异步函数
有什么关系呢?嗯,异步函数
只是返回->impl Future
的函数的"语法糖
".因为在特征
中,现在允许这些,还允许你编写使用async fn
的特征
.
trait HttpService {async fn fetch(&self, url: Url) -> HtmlBody;
//^^^^^^^^变为:
// fn fetch(&self, url: Url) -> impl Future<Output = HtmlBody>;
}
差距在哪?
公开特征中的->impl
特征
仍不建议在公开特征
和API
中普遍使用->impl Trait
,因为用户无法对返回类型
加限制.如,无法对容器
特征通用的编写
此函数:
fn print_in_reverse(container: impl Container) {for item in container.items().rev() {//错误:^^^对`'impl Iterator<Item=Widget>'`未实现`'DoubleEndedIterator'`特征eprintln!("{item}");}
}
尽管某些实现
可能会返回实现DoubleEndedIterator
的迭代器
,但在不定义
另一个特征
时,泛型代码
无法利用它
.
未来,打算
为此添加一个解决方法
.当前,->impl Trait
最适合内部特征
,或当你确信
用户不需要额外
约束时.否则,应该考虑使用关联类型
.
公开特征中的异步函数
因为async fn
解糖为->impl Future
,因此有同样限制
.事实上,如果今天在公开特征
中使用空的异步fn
,则会看到警告.
警告:不建议在公开特征
中使用"async fn"
,因为无法指定自动
特征约束.
异步
用户特别感兴趣
的是,在返回的未来
上的发送
约束.因为用户以后无法添加约束
,因此错误消息
说明你要选择
:是否想你的特征
与多线程
,窃取工作
程序一起使用
?
好的是,现在有个允许在公开特征
中使用异步fn
的方法!建议使用trait_variant::make
过程宏来让你的用户选择
.
该过程
宏是由rustlang
组织发布的traitvariant
包的一部分
.在项目中加上cargo add trait-variant
.使用:
#[trait_variant::make(HttpService: Send)]
pub trait LocalHttpService {async fn fetch(&self, url: Url) -> HtmlBody;
}
这创建两个版本
的特征
:用LocalHttpService
针对单线程
执行器,HttpService
针对多线程工作
窃取执行器
.因为后者更常用
,因此此例中名字更短
.
它有额外的发送
约束:
pub trait HttpService: Send {fn fetch(&self,url: Url,) -> impl Future<Output = HtmlBody> + Send;
}
该宏适合异步
,因为impl Future
很少需要发送
以外的额外约束
,因此可成功为用户
准备好.
动态分发
使用->impl Trait
和asyncfn
的特征
不是对象安全
的,即不支持动态分发
.准备在未来推出的trait-variant
包版本中启用动态分发
.
未来如何改进
未来,希望允许用户添加自己的约束
到impl Trait
返回类型,这样更普遍更有用
.它还支持异步fn
的更高级用法
.语法
可能如下:
trait HttpService = LocalHttpService<fetch(): Send> + Send;
因为这些别名
不需要特征作者
的支持,因此,因此不需要异步特征
的发送
变量.但是,这些变量
仍会方便用户,因此期望大多数包
继续提供它们.
常见问题解答
是否可在特征
中使用->impl Trait
对私有特征
,可自由
使用->impl Trait
.对公开特征
,最好暂时避免使用它们
,除非可预见到用户可能需要的所有约束
(此时,你可用#[trait_variant::make]
,与异步
一样).
期望取消来会此限制.
是否仍应使用#[async_trait]
宏
你可能要继续使用异步特征
的原因
有几个:
1,想支持低于1.75
的Rust
版本.
2,你需要动态分发.
如上,希望在未来版本
中启用动态分发
.
可在特征
中使用async fn
吗?有哪些限制
假设,你不用#[async_trait]
,则完全可以在特征
中使用普通
的异步 fn
.如果想支持多线程运行时
,记住使用#[trait_variant::make]
.
最大限制
是类型
必须总是决定它
实现了特征
的发送
版本还是非发送
版本.它不能在其泛型之一上
有条件地实现发送
版本.
这可在中间件模式
中出现,如,如果T:HttpService
,则为HttpService
的RequestLimitingService<T>
.
为什么我需要#[trait_variant::make]
和Send
约束
简单情况时,发现你的特征
似乎与多线程程序
配合得很好.但是,有些模式
下不管用
.考虑以下
:
fn spawn_task(service: impl HttpService + 'static) {tokio::spawn(async move {let url = Url::from("https://rustlang.org");let _body = service.fetch(url).await;});
}
如果特征
上没有Send
约束,则无法编译
,并显示错误:"不能在线程间安全发送未来"
.用Send
约束创建特征的变量
,可避免发送用户
掉此陷阱
.
注意,如果未公开你的特征
,则不会看到警告
,因为如果有问题,总是可自行
添加发送
约束.
见此博客文章.
我可插件使用async fn
和impl Trait
吗
是的,你可以在特征
和实现
中的async fn
和->implFuture
拼写间自由切换
.即使一个形式
有发送
约束,因此.这样更易使用trait_variant
创建的特征.
trait HttpService: Send {fn fetch(&self, url: Url)-> impl Future<Output = HtmlBody> + Send;
}
impl HttpService for MyService {async fn fetch(&self, url: Url) -> HtmlBody {//只要有`'do_fetch():Send'`就可以了!self.client.do_fetch(url).await.into_body()}
}
为什么这些签名不使用impl Future+'_
对特征中的->impl Trait
,提前用了2024
年的抓规则
.即今天经常看到的+'_
,在特征
中是不必要的,因为已假设中
类型来抓输入生命期
.
在2024
版中,此规则针对所有函数签名
.
为什么在使用->impl Trait
实现特征时收到"细化"
警告
如果你的实现
签名,包含比特征
自身更详细的信息
,你会收到警告
:
pub trait Foo {fn foo(self) -> impl Debug;
}
impl Foo for u32 {fn foo(self) -> String {
//^^^^^^警告:`实现方法签名`中的`impl Trait`与`trait`方法签名不匹配self.to_string()}
}
原因是你可能泄露
了更多实现细节
.如,如果以下代码编译
.
fn main() {//实现者允许使用`'显示'`,还是只允许使用`特征`所说的`'调试'`println!("{}", 32.foo());
}
因为细化了特征
实现,它确实可编译,但编译器会要求你在实现
上使用#[allow(refining_impl_trait)]
,确认你打算细化特征
接口.
注意,只能在可以命名类型
时,才能使用关联类型
.一旦impl_trait_in_assoc_type
稳定下来,才取消此限制
.
这是因为允许知识
从未指定签名
它们的项目中"泄漏
"的auto trait
泄漏.
相关文章:
2411rust,异步函数
原文 Rust异步工作组很高兴地宣布,在实现在特征中使用异步 fn的目标方面取得了重大进度.将在下周发布稳定的Rust1.75版,会包括特征中支持impl Trait注解和async fn. 稳定化 自从RFC#1522在Rust1.26中稳定下来以来,Rust就允许用户按函数的返回类型(一般叫"RPIT")编…...
前端网络性能优化问题
DNS预解析 DNS 解析也是需要时间的,可以通过预解析的⽅式来预先获得域名所对应的 IP。 <link rel"dns-prefetch" href"//abcd.cn"> 缓存 强缓存 在缓存期间不需要请求, state code 为 200 可以通过两种响应头实现&#…...

优选算法——双指针
前言 本篇博客为大家介绍双指针问题,它属于优选算法中的一种,也是一种很经典的算法;算法部分的学习对我们来说至关重要,它可以让我们积累解题思路,同时也可以大大提升我们的编程能力,本文主要是通过一些题…...

【Rabbitmq篇】RabbitMQ⾼级特性----消息确认
目录 前言: 一.消息确认机制 • ⾃动确认 • ⼿动确认 手动确认方法又分为三种: 二. 代码实现(spring环境) 配置相关信息: 1). AcknowledgeMode.NONE 2 )AcknowledgeMode.AUTO 3&…...

开源TTS语音克隆神器GPT-SoVITS_V2版本地整合包部署与远程使用生成音频
文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 本文主要介绍如何在Windows系统电脑使用整合包一键部署开源TTS语音克隆神器GPT-SoVITS,并结合cpolar内网穿透工…...

【idea】更换快捷键
因为个人习惯问题需要把快捷键替换一下。我喜欢用CTRLD删除一下,用CTRLY复制一样。恰好这两个快捷键需要互换一下。 打开file——>setting——>Keymap——>Edit Actions 找到CTRLY并且把它删除 找到CTRLD 并且把它删除 鼠标右键添加CTRLY 同样操作在Delet…...

最小的子数组(leetcode 209)
给定一个正整数数组,找到大于等于s的连续的最小长度的区间。 解法一:暴力解法 两层for循环,一个区间终止位置,一个区间起始位置,找到大于等于s的最小区间长度(超时了) 解法二:双指…...

IDEA-Plugins无法下载插件(网络连接问题-HTTP Proxy Settings)
IDEA-Plugins无法下载插件(网络连接问题) 改成如下配置: 勾选 添这个url即可:https://plugins.jetbrains.com/ 重启插件中心,问题解决。...

AWTK-WIDGET-WEB-VIEW 发布
awtk-widget-web-view 是通过 webview 提供的接口,实现的 AWTK 自定义控件,使得 AWTK 可以方便的显示 web 页面。 项目网址: https://gitee.com/zlgopen/awtk-widget-web-view webview 提供了一个跨平台的 webview 接口,是一个非…...

Mysql每日一题(if函数)
两种写法if()和case if()函数 select *,if(T.xT.y>T.z and T.xT.z>T.y and T.yT.z>T.x,Yes,No) as triangle from Triangle as T; case方法 select *, case when T.xT.y>T.z and T.xT.z>T.y and T.yT.z>T.x then Yes else No end as triangle from Trian…...

Spring Cloud Alibaba [Gateway]网关。
1 简介 网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。而springcloudgateway 作为SpringCloud 官方推出的第二代网关框架,取代了Zuul网关。 1.1 SpringCloudGateway特点: (1)基于Spring5,支持响应…...

【动手学深度学习Pytorch】2. Softmax回归代码
零实现 导入所需要的包: import torch from IPython import display from d2l import torch as d2l定义数据集参数、模型参数: batch_size 256 # 每次随机读取256张图片 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size) # 将展平每个…...
技术周总结 11.11~11.17 周日(Js JVM XML)
文章目录 一、11.11 周一1.1)问题01:js中的prompt弹窗区分出来用户点击的是 确认还是取消进一步示例 1.2)问题02:在 prompt弹窗弹出时默认给弹窗中写入一些内容 二、11.12 周二2.1) 问题02: 详解JVM中的本地方法栈本地方法栈的主要…...

MATLAB 使用教程 —— 矩阵和数组
矩阵和数组MATLAB 中矩阵和数组长什么样?MATLAB 怎么用矩阵计算?创建和操作矩阵矩阵运算示例串联 访问矩阵的元素 矩阵和数组 MATLAB 是“matrix laboratory”的缩写形式。MATLAB 主要用于处理 整个的矩阵和数组,而其他编程语言大多逐个处理…...

React教程第二节之虚拟DOM与Diffing算法理解
1、什么是虚拟DOM 虚拟DOM 是javascript的一个对象,是内存中的一种数据结构,以树的形式存储UI的状态,树中的每个节点都代表着真实的DOM,用来描述我们希望在页面看到的 HTML结构; 现在的MVVM 框架,大多使用…...

C++——类和对象(part2)
前言 本篇博客继续为大家介绍类与对象的知识,承接part1的内容,本篇内容是类与对象的核心内容,稍微有些复杂,如果你对其感兴趣,请继续阅读,下面进入正文部分。 1. 类的默认成员函数 默认成员函数就是用户…...
【FFmpeg系列】:音频处理
前言 在多媒体处理领域,FFmpeg无疑是一个不可或缺的利器。它功能强大且高度灵活,能够轻松应对各种音频和视频处理任务,无论是简单的格式转换,还是复杂的音频编辑,都不在话下。然而,要想真正发挥FFmpeg的潜…...

Python绘制雪花
文章目录 系列目录写在前面技术需求完整代码代码分析1. 代码初始化部分分析2. 雪花绘制核心逻辑分析3. 窗口保持部分分析4. 美学与几何特点总结 写在后面 系列目录 序号直达链接爱心系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4…...

vue3 如何调用第三方npm包内部的 pinia 状态管理库方法
抛砖引玉: 如果在开发vue3项目是, 引用了npm第三方包 ,而且这个包内使用了Pinia 状态管理库,那我们如何去调用 npm内部的 Pinia 状态管理库呢? 实际遇到的问题: 今天在制作npm包时遇到的问题,之前Vue2版本的时候状态管理库用的Vuex ,当时调用npm包内的状态管理库很简单,直接引…...
uni-app快速入门(七)--组件路由跳转和API路由跳转及参数传递
uni-app有两种页面路由跳转模式,即使用navigator组件跳转和调用API跳转,API调转不要理解为调用后台接口的API,而是指脚本函数中使用跳转函数。 一、组件路由跳转 1.1 打开新页面 打开新页面使用组件的open-type"navigate",见下面…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...