Rust编程(五)终章:查漏补缺
闭包 & 迭代器
闭包(Closure)通常是指词法闭包,是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量,在函数式编程范式中也被称为自由变量,是指并不是在闭包内定义的变量。将自由变量和自身绑定的函数就是闭包。
闭包的两大特性:
- 延迟执行。返回的闭包只有在需要调用的时候才会执行。
- 捕获环境变量。闭包会获取其定义时所在作用域中的自由变量,以供之后调用时使用。
Rust的闭包语法形式参考了Ruby语言的lambda表达式:
fn main(){let add_op = |a:i32,b:i32| -> i32 {a+b};let c = add_op(1,2);println!("1+2={}",c);
}
闭包的语法都大差不差,rust,ruby,python等都差不多一个样,
rust闭包的具体实现方式可以看Rust编程之道里面有讲解,目前没用到闭包,这里就不做讲解了,看了不用也记不住。
智能指针
智能指针(Box, Rc, Arc, Cell, RefCell, Cow等等),对原始指针进行包装,并添加额外的语义。
Box 是最直接的智能指针——它将数据分配到堆上而非栈上,在栈上只留一个指向堆中数据的指针。Box 没有性能开销,在下面的情况下使用:
- 递归类型,如链表和树,必须使用Box去包装引用自身的字段以保证编译时能确定大小
- 数据太大,希望移动所有权时减少拷贝数据消耗
- 希望持有特定 trait 的值,无关它的实际类型(即不知晓它的大小) 作者:_YKI https://www.bilibili.com/read/cv31741541/ 出处:bilibili
Rc:提供在堆中分配的 T 类型值的共享所有权。在 Rc 上调用克隆方法会生成一个指向堆中相同地址的新指针。当指向给定地址的最后一个 Rc 指针被销毁时,存储在该地址中的值也会被删除。
IO
Rust官方对于IO实现了IO trait,大部分函数看名字就知道作用
pub trait Read {// Required methodfn read(&mut self, buf: &mut [u8]) -> Result<usize>;// Provided methodsfn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> { ... }//is_read_vectored目前还是nightly APIfn is_read_vectored(&self) -> bool { ... }fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { ... }fn read_to_string(&mut self, buf: &mut String) -> Result<usize> { ... }fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { ... }fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { ... }fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<()> { ... }fn by_ref(&mut self) -> &mut Selfwhere Self: Sized { ... }fn bytes(self) -> Bytes<Self> //是指将 Read 按逐字节的方式转换成迭代器。迭代器为Result<u8>,这个Result也是std::io::Result<T>where Self: Sized { ... }fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized { ... }fn take(self, limit: u64) -> Take<Self> where Self: Sized { ... }
}
pub trait Write {// Required methodsfn write(&mut self, buf: &[u8]) -> Result<usize>;fn flush(&mut self) -> Result<()>;// Provided methodsfn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { ... }fn is_write_vectored(&self) -> bool { ... }fn write_all(&mut self, buf: &[u8]) -> Result<()> { ... }fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<()> { ... }fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()> { ... }fn by_ref(&mut self) -> &mut Selfwhere Self: Sized { ... }
}
很多类型实现了标准 IO 特型:File、TcpStream、Vec、&[u8],注意返回类型是std::io::Result,不是std::Result
pub type Result<T> = Result<T, Error>;
使用IO的demo:
use std::io::prelude::*;
use std::fs::File;fn main() -> std::io::Result<()> {let data = b"some bytes";let mut pos = 0;let mut buffer = File::create("foo.txt")?;while pos < data.len() {let bytes_written = buffer.write(&data[pos..])?;pos += bytes_written;}Ok(())
}
安全并发
Rust中的线程管理和线程同步工具相关库为:std::thread模块和std::sync模块。Rust中的线程是本地线程,每个线程都有自己的栈和本地状态。创建一个线程如下:
use std::thread;
fn main(){let mut v = vec![]for id in 0..5 {let child = thread::spawn(move || {println!("in child:{}",id);});//spawn是Rust中线程初始化的函数//直接使用thread::spawn生成的线程,默认没有名称,并且其栈大小默认为2MB。//这里使用move关键字来强行将捕获变量id的所有权转移到闭包中。v.push(child);}println!("in main join before:");for child in v {child.join(); //等待child结束后再接着运行//但是child之间并没有相互等待的关系,输出是乱序的}println!("int main joint after");
}
并发安全是Rust的一个卖点。Rust中内置了两个trait:std::marker::Send和std::marker::Sync,实现了Send的类型可以安全地在线程间传递所有权,即跨线程移动;实现了Sync的类型,可以安全地在线程间传递不可变借用,即跨线程共享。和Send/Sync相反的标记是!Send/!Sync,表示不能在线程间安全传递的类型。智能指针Rc实现了!Send/!Sync,因为Rc内部并不是原子操作,在线程间传递会导致技术不准确。Rust提供了线程安全版的Rc,即Arc,内部使用的是原子操作,可以在线程间安全传递。
这两个标记trait反映了Rust看待线程安全的哲学:多线程共享内存并非线程不安全问题所在,问题在于错误地共享数据。通过Send和Sync将类型贴上“标签”,由编译器来识别这些类型是否可以在多个线程之间移动或共享,从而做到在编译期就能发现线程不安全的问题。
《Rust编程之道》
至于为什么这两个trait就可以实现并发安全,这两个具体怎么用?Rust中的锁怎么写?这部分等到后面用到再仔细分析,目前没有写项目,学了也是纸上谈兵。
宏系统
在 Rust 中宏分为两大类:声明式宏( declarative macros ) macro_rules! 和三种过程宏( procedural macros ):
- #[derive],在之前多次见到的派生宏,可以为目标结构体或枚举派生指定的代码,例如 Debug 特征
- 类属性宏(Attribute-like macro),用于为目标添加自定义的属性
- 类函数宏(Function-like macro),看上去就像是函数调用
声明宏就是与传统的编程语言中的宏的概念是差不多的,但过程宏是使用源代码作为输入参数,基于代码进行一系列操作后,再输出一段全新的代码。有点类似于Python中的装饰器一样。
macro_rules!用来声明一个声明宏,也可以叫生成规则宏,他可以定义代码生成规则,声明式宏允许我们写出类似 match 的代码。match 表达式是一个控制结构,其接收一个表达式,然后将表达式的结果与多个模式进行匹配,一旦匹配了某个模式,则该模式相关联的代码将被执行。语法格式
macro_rules! macro_name{() => { //跟match的语法非常像code;};
}
案例:
#[macro_export] //注释将宏进行了导出,这样其它的包就可以将该宏引入到当前作用域中,然后才能使用。
macro_rules! vec {($($x:expr),*) => ( { //这里的匹配规则有点像正则表达式一样,$x:expr表示可以匹配任何类型,*表示可以重复无数次let mut temp_vec = Vec::new();$(temp_vec.push($x);)*temp_vec} );
}
大部分人都是宏的使用者,很少编写,啥时候用到再学吧。
总结
Rust语言的卖点就是:安全,安全,还是安全。这个安全包括内存安全,并发安全。其实这两点Python都能做到,但是为什么还要推出Rust呢?性能是关键!
Python保证内存安全是使用GC垃圾回收机制,保证并发安全是使用GIL锁。这两个机制都会极大降低Python的运行速度【目前据说GIL锁在新版本的Python中已经可以移除了,但是Python的速度还是没法跟Rust比】。
Rust确保这两点安全的方法是:所有权、声明周期机制以及强大的类型系统。所有权系统和生命周期确保了一份数据在同一时刻只会被一个变量所拥有,有效避免了悬垂指针以及双重释放等内存问题。内存安全的Bug和并发安全的Bug产生的内在原因是相同的,都是因为内存的不正当访问而造成的。同样,利用装载了所有权的强大类型系统,Rust还解决了并发安全的问题。Rust编译器会通过静态检查分析,在编译期就检查出多线程并发代码中所有的数据竞争问题。
类型系统是指编程语言中对于类型的一套规则,并不是真的有个系统,类型系统的主要作用就是类型推导,类型检测,类型转换,Rust是类型安全的,即:在运行时不会出现类型错误。
Rust作为后起之秀,借鉴了很多语言的设计思想,Haskell,C/C++,Python,Ruby等等,像智能指针,模板特化等很多新的技术都有借鉴,这些也一定程度上确保了内存安全。
谈完Rust设计哲学,再谈一谈Rust的编程范式,不用说,基本上所有现代语言都是混合编程范式的,理论上Rust可以支持各种编程范式,但是哪种支持更完备,编程更方便,自然是不一样的。在Rust中,不管哪一种单一编程范式来进行编程都很难受,面向对象,函数式,泛型编程,都是这样的。对于面向对象,Rust中有struct、方法和trait来实现面向对象。对于函数式,Rust中有闭包以及一切皆类型的类型系统。对于泛型编程,Rust有泛型,有模板特化,const模板参数等支持。所以对于Rust项目,比较推荐的编程范式是:轻度面向对象+泛型编程,函数式编程做为边边角角的辅助使用。更多可以看一下这篇文章
至此Rust编程就已经完结了,泛型编程和宏系统的应用,Rust设计模式的实现,异步编程和数据并行编程,unsafe特性,与其他语言相互调用,等等等等,这些特性我建议用到再学,因为学完不用很快就忘了,没必要,有一些概念不清楚的,不要去百度,去看Rust圣经或者直接去看Rust标准库官方文档,写的非常明确。
下一步就是开始从0写操作系统,清华的操作系统训练营还有好几天才开营,先学起来,下一篇打算跟着Rust实战这本书写一个CPU模拟器。
相关文章:

Rust编程(五)终章:查漏补缺
闭包 & 迭代器 闭包(Closure)通常是指词法闭包,是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量,在函数式编程范式中也被称为自由变量,是指并不是在闭包内定义的变量。将自…...

LLM漫谈(五)| 从q star视角解密OpenAI 2027年实现AGI计划
最近,网上疯传OpenAI2027年关于AGI的计划。在本文,我们将针对部分细节以第一人称进行分享。 摘要:OpenAI于2022年8月开始训练一个125万亿参数的多模态模型。第一个阶段是Arrakis,也叫Q*,该模型于2023年12月完成训练&…...
【echart】数据可视化+vue+vite遇到问题
1、vue3使用echars图表报错:"Initialize failed:invalid dom" 原因是因为:Dom没有完成加载时,echarts.init() 就已经开始执行了,获取不到Dom,无法进行操作 解决:加个延时 onMounted(async () …...
mac m1安装和使用nvm的问题
mac m1安装和使用nvm的问题 使用nvm管理多版本node 每个项目可能用的node版本不同,所以需要多个版本node来回切换 但是最近遇到安装v14.19.0时一直安装失败的问题。 首先说明一下,用的电脑是mac M1芯片 Downloading and installing node v14.19.0... …...
git泄露
git泄露 CTFHub技能树-Web-信息泄露-备份文件下载 当前大量开发人员使用git进行版本控制,对站点自动部署。如果配置不当,可能会将.git文件夹直接部署到线上环境。这就引起了git泄露漏洞。 工具GitHack使用:python2 GitHack.py URL地址/.git/ git命令…...

Java项目:78 springboot学生宿舍管理系统的设计与开发
作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统的角色:管理员、宿管、学生 管理员管理宿管员,管理学生,修改密码,维护个人信息。 宿管员…...
ArcGis Pro Python工具箱教程 03 工具箱中工具自定义
ArcGis Pro Python工具箱教程 03 工具箱中工具自定义 用于定义工作工具类的方法 工具方法必选或可选描述__ init __必需项right-aligned 初始化工具类。getParameterInfo可选定义工具的参数。isLicensed可选返回工具是否获得执行许可。updateParameters可选在用户每次在工具对…...

【C++初阶】之类和对象(中)
【C初阶】之类和对象(中) ✍ 类的六个默认成员函数✍ 构造函数🏄 为什么需要构造函数🏄 默认构造函数🏄 为什么编译器能自动调用默认构造函数🏄 自己写的构造函数🏄 构造函数的特性 ✍ 拷贝构造…...

Vue2(十一):脚手架配置代理、github案例、插槽
一、脚手架配置代理 1.回顾常用的ajax发送方式: (1)xhr 比较麻烦,不常用 (2)jQuery 核心是封装dom操作,所以也不常用 (3)axios 优势:体积小、是promis…...

在宝塔面板中,为自己的云服务器安装SSL证书,为所搭建的网站启用https(主要部分攻略)
前提条件 My HTTP website is running Nginx on Debian 10(或者11) 时间:2024-3-28 16:25:52 你的网站部署在Debain 10(或者11)的 Nginx上 安装单域名证书(默认)(非泛域名…...

学习JavaEE的日子 Day32 线程池
Day32 线程池 1.引入 一个线程完成一项任务所需时间为: 创建线程时间 - Time1线程中执行任务的时间 - Time2销毁线程时间 - Time3 2.为什么需要线程池(重要) 线程池技术正是关注如何缩短或调整Time1和Time3的时间,从而提高程序的性能。项目中可以把Time…...
@Transactional 注解使用的注意事项
事务管理 事务管理在系统开发中是不可缺少的一部分,Spring提供了很好的事务管理机制,主要分为编程式事务和声明式事务两种。 编程式事务: 是指在代码中手动的管理事务的提交、回滚等操作,代码侵入比较强。 声明式事务ÿ…...

电商系列之库存
> 插:AI时代,程序员或多或少要了解些人工智能,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 坚持不懈,越努力越幸运,大家…...

Apache HBase(二)
目录 一、Apache HBase 1、HBase Shell操作 1.1、DDL创建修改表格 1、创建命名空间和表格 2、查看表格 3、修改表 4、删除表 1.2、DML写入读取数据 1、写入数据 2、读取数据 3、删除数据 2、大数据软件启动 一、Apache HBase 1、HBase Shell操作 先启动HBase。再…...
【设计模式】原型模式详解
概述 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象 结构 抽象原型类:规定了具体原型对象必须实现的clone()方法具体原型类:实现抽象原型类的clone()方法,它是可以被复制的对象。访问类&…...

企微侧边栏开发(内部应用内嵌H5)
一、背景 公司的业务需要用企业微信和客户进行沟通,而客户的个人信息基本都存储在内部CRM系统中,对于销售来说需要一边看企微,一边去内部CRM系统查询,比较麻烦,希望能在企微增加一个侧边栏展示客户的详细信息…...
如何确定最优的石油管道位置
如何确定最优的石油管道位置 一、前言二、问题概述三、理解问题的几何性质四、转化为数学问题五、寻找最优解六、算法设计6.1伪代码6.2 C代码七算法效率和实际应用7.1时间效率分析7.2 空间效率分析结论一、前言 当我们面对建设大型输油管道的复杂任务时,确保效率和成本效益是…...

FPGA 图像边缘检测(Canny算子)
1 顶层代码 timescale 1ns / 1ps //边缘检测二阶微分算子:canny算子module image_canny_edge_detect (input clk,input reset, //复位高电平有效input [10:0] img_width,input [ 9:0] img_height,input [ 7:0] low_threshold,input [ 7:0] high_threshold,input va…...

2024.3.28学习笔记
今日学习韩顺平java0200_韩顺平Java_对象机制练习_哔哩哔哩_bilibili 今日学习p286-p294 继承 继承可以解决代码复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些…...

33.HarmonyOS App(JAVA)鸿蒙系统app数据库增删改查
33.HarmonyOS App(JAVA)鸿蒙系统app数据库增删改查 关系数据库 关系对象数据库(ORM) 应用偏好数据库 分布式数据库 关系型数据库(Relational Database,RDB)是一种基于关系模型来管理数据的数据库。HarmonyOS关系型…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...