一、Rust的特性
1、所有权系统。
这是Rust最显著的特性之一,通过所有权系统,Rust可以在编译时跟踪每个值的所有者,并在合适的时候自动释放内存,避免内存泄露和悬挂指针等问题。
2、生命周期
Rust的生命周期系统用于管理引用的有效范围,确保引用不会超出其所指向的对象的生命周期,从而避免悬挂引用和野指针的问题。
3、模式匹配
Rust提供了强大的模式匹配功能,可以用于解构数据结构,匹配不同的情况并执行相应的操作,是编写清晰、简洁代码的重要工具。
4、零成本抽象
在不牺牲性能的情况下实现高级的抽象功能。
二、如何使用VScode准备Rust编程环境?
建议大家安装的时候访问相应的官网并查询文档,这个比较靠谱。比如这个:
https://rust-lang.org/zh-CN/里面有很多的资源可以供大家学习

这个的话是Vscode编写Rust代码的话,可以查看这个
https://code.visualstudio.com/docs/languages/rust

1.安装Rust工具集
记得要挑选相应的Rustup哦!
如果是Linux下面的WIndows子系统用户,
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh


同时还需要下载一个东西,如果可以ctrl+点击连接下载
整个过程比较慢,需要等待一会
2.安装扩展
在VScode里面通过扩展搜索"rust-analyzer"来找到并安装它

安装完成后,我们利用终端确保安装正确
rustc --version
三、基础概念
所有权系统:Rust通过所有权系统管理内存,确保在编译时避免内存泄漏和数据竞争的问题
借用和引用:通过借用和引用机制允许在不用于所有权的情况下访问数据,从而避免了数据多所有权问题
模式匹配:匹配不同的数据结构并执行相应的操作
四、输出hello,world!
Cargo是Rust的官方包管理器,有点像Python中pip
查看它的版本
cargo --version
我们需要在Rust项目中添加外部库时,需要编辑Cargo.html文件
[dependencies]
rand="0.8.4"
我们运行cargo build将会自动下载和编译这些依赖。
Cargo还运行我们在项目中编写和测试,将测试的函数放在src/lib.rs(库)或者src/main.rs(二进制可执行文件)的注释部分内,并以#[test]属性标记,可以使用cargo test运行测试
#[cfg(test)]
mod test {
#[test]
fn it_works() {
assert_eq!(2+2,4);}
}
再写我们hello world之前需要进行环境设置
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
创建新的项目
cargo new hello_world --bin
cd hello_world
我们在当前目录下创建一个名为"hello_world"的二进制文件
我们写入代码并cargo run进行编译
fn main(){
println!("hello,World!");
}
fn main() { }:这是Rust的主函数入口,呈现从这里开始执行
println!:这是一个宏(macro),用于将信息打印到标准输出
五、编程基础
变量和常量
声明变量
let x:i32; //未进行初始化的变量
let y=5; //声明并进行初始化
使用let关键字声明变量,一般情况下,Rust中的变量是不可变的,但可以用mut创建可变变量。
fn main(){
let x=5; //不可变变量
let mut y=10; //可变变量
}
我们声明常量使用const,不可以在程序执行期间更改、
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
同时它还支持变量屏蔽,就是在一个作用域里面多次声明同名的变量
let x=5;
let x=x+1; 变为6了
{
let x=x*2; 变为12了
}
println!("{}",x);
最后的值还是6
数据类型

函数
我们使用fn关键字来定义一个新的函数,函数参赛需要指定类型,并函数可以返回值。
Rust 中的大多数时候不需要使用 return 关键字来返回值,因为 Rust 支持表达式
fn add(x:i32,y:i32) -> i32 {
x+y
}
fn greet(name &str) {
println!("Hello,{}!",name);
}
这里的i32是有符号位整数
注释分为单行注释//和多行注释/*, 还有一种文档注释,它们使用 /// 或 /*! ... */ 来表示,这个注释就跟C一样。
if ... else条件语句
fn main(){
let number =3;
if number <5 {
println!("数字小于5!");}
else{
println!("数字大于5!");}
}
使用Rust的if ...else条件语句时需要注意这几点:
每个条件必须是布尔类型;
不要在条件中使用赋值运算符=,而应该使用相等运算符==;
Rust中没有三元运算符,必须使用if ...else结构或match表达式
循环
loop是创建一个无限循环,直到break语句来退出它
fn main(){
let mut count =0;
loop{
count +=1;
println!("count is:{}",count);
if count==5;
{
break;}
}
}
while创建一个带有条件的循环,只有条件为真,循环就会继续执行。
fn main(){
let mut a=0;
let mut b=1;
while b <100{
let temp =a;
a =b;
b = temp +b;}
println!("The last Fibonacci number under 100 is:{}",a);
}
for用于遍历集合(数组,向量和范围)中的元素
fn main(){
let numbers =[1,2,3,4,5];
for num in numbers.iter()
{
println!("The number is:{}",num);
}
}
number.iter()方法返回一个迭代器,它允许我们遍历数组中的每个元素,然后我们使用for循环来打印出每个元素。
break用于立即退出循环和continue语句用于跳过当前迭代并继续下一次迭代。
标签循环
Rust中还支持使用标签来标识循环,还可以在嵌套的循环中精确地指定要退出或跳过哪个循环。
fn main(){
'outer:loop {
for x in 0..10{
if x% 2==0{
continue;}
}
else if x==9{
break 'outer;
}
println!("x is: {}",x);
}
}
}
'outer标签来标识外部循环,当x是偶数时,continue语句会跳过当前迭代并继续下一次迭代;当x等于9时,break 'outer;语句会退出外部循环。
迭代器
迭代器模式提供一个方法,可以顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示
Rust中的迭代器是一个实现Iterator trait的类型,这个trait要求实现者提供一种方法、
pub trait Iterator{
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
Item是一个关联类型,它代表了迭代器返回的元素的类型,当我们调用next方法时,如果集合中还有更多的元素,迭代器就会返回这个元素包裹在some中,如果没有更多的元素,它会返回None
创建一个简单的计数器迭代器,这个迭代器将从0开始,并在每次调用next方法时返回下一个整数。
struct CountIterator{
count:usize,
}
impl Iterator for CountIterator{
type Item =usize;
fn next(&mut self) -> Option<Self::Item>
{
let result =self.count;
self.cont += 1;
Some(result)
}
}
Rust的标准库为迭代器提供了许多有用锋办法,这些方法可以帮助我们高效地处理数据流,其中一些常见的方法包括:
map:将闭包应用于每个元素,并返回一个新的迭代器
filter:保留满足特定条件的元素,并返回一个新的迭代器
collect:将迭代器转换为集合(如向量或哈希映射)
闭包
闭包是一种可以在定义它们的作用域内捕获环境中变量的函数。闭包可以访问和操控其作用域内的变量,即使这些变量在定义闭包之后仍然存在。
fn函数类型:接收参数并返回值
带有输入但没有返回值的闭包,使用||定义,通过在=后面写表达式来指定闭包
只带有一个参数并将其作为返回值的闭包:当闭包的主体是单个表达式可以省略花括号和关键字,Rust会自动推断返回值的类型。
let add_one =|x:i32| -> i32 {x+1};
//定义一个闭包i32并返回i32的闭包
let print_message =|| println! ("Hello,world!");
//带有输入但没有返回值的闭包
let double = |x| x * 2;
//只带有一个参数并且将其作为返回值的闭包
Rust中的闭包可以通过以下三种方式捕获其作用域内的变量:
FnOne:闭包只能被调用一次,因为它可以获取并消耗变量
FnMut:闭包可以多次修改同一个变量
Fn:闭包只读取变量,不会修改或消耗变量
fn apply<F>(f: F, x:i32) -> 32
where
F: Fn(i32) ->32,
{
f(x)
}
fn make_closure(y: i32) -> impl Fn(i32) ->i32 {
move |x| x+y
}