当前位置: 首页 > news >正文

2024 Rust现代实用教程 流程控制与函数

文章目录

  • 一、if流程控制与match模式匹配
    • 1.流程控制
    • 2. IF流程控制
    • 3.match 表达式
  • 二、循环与break continue以及与迭代的区别
    • 1.Rust中的循环Loops
    • 2.break && continue
    • 3.迭代
    • 4.循环与迭代的不同
  • 三、函数基础与Copy值参数传递
    • 1.函数的基础知识
    • 2.Copy by value
  • 四、函数值参数的传递、不可变借用参数的传递、可变借用参数的传递
    • 1.函数值参数传递(move)
    • 2.不可变借用(就是C++的引用)
    • 3.可变借用
  • 五、函数返回值与所有权机制
    • 1.返回Copy与Non-Copy
    • 2.返回引用
  • 六、高阶函数:函数作为参数与返回值
    • 1.高阶函数与集合
  • 参考

一、if流程控制与match模式匹配

1.流程控制

Execution Flow(流程)

  • 1.代码执行从上倒下Iine-by-line
  • 2.而我们执行操作时,控制流程可能会改变

主要的流程控制结构
1.顺序结构(Sequential Structure):程序按照代码的顺序一步一步执行,没有跳过或循环。

2.选择结构(Selection Structure):
-根据条件选择不同的路径执行。常见的选择结构有:

  • if语句:根据条件执行不同的代码块。
  • switchi语句(在某些编程语言中):根据不同的条件值执行不同的代码块。

3.循环结构(Iteration Structure):重复执行一段代码,直到满足某个条件为止。常见的循环结构有:

  • for循环:按照指定的次数重复执行一段代码。
  • while循环:在条件为真的情况下重复执行一段代码。
  • do-while循环:类似于while循环,但是保证至少执行一次循环体。

4.跳转结构:控制程序的执行流程跳转到指定的位置。常见的跳转结构有:

  • break语句:终止循环或switch语句的执行。
  • continue语句:跳过当前循环中的剩余代码,进入下一次迭代。
  • goto语句(在某些编程语言中):直接跳转到指定的标签处。

2. IF流程控制

代码一行行执行
执行流程,被If(else)改变
可以嵌套使用,但容易引起可读性问题

在这里插入图片描述

3.match 表达式

match用于模式匹配,允许更复杂的条件和分支。

可以处理多个模式,提高代码的表达力。

·match是表达式,可以返回值。

match value{pattern1 =>/code block executed if value matches pattern1,pattern2 if condition =>/code block executed if value matches pattern2 and condition is true,_=>/code block executed for any other case,
}

IF流程控制与match表达式对比
复杂性:if适用于简单的条件判断,而match更适用于复杂的模式匹配。
表达力:match更灵活,可以处理多个条件和模式,使代码更清晰。
返回值:两者都是表达式,可以返回值,但match通常用于更复杂的场景。

fn main() {let age = 50;if age < 50 {println!("You are young");} else {println!("You are old");}// if 的表达能力很弱let scores = 70;if scores > 90 {println!("Good!!!");} else if scores > 60 {println!("You are OK!");} else {println!("Bad!!!");}// 类似C++ 三元表达式let msg = if age > 50 { "old" } else { "young" };println!("You are {msg}");// matchlet num = 90;match num {80 => println!("80"),90 => println!("90"),_ => println!("Some else"),}match num {25..=50 => println!("25 ... 50"),51..=100 => println!("51 ... 100"),_ => println!("Some else"),}match num {25 | 50 | 75 => print!("25 or 50 or 75"),100 | 200 => println!("100 or 200"),_ => println!("Some else"),}// match 里面使用ifmatch num {x if x < 60 => println!("bad"),x if x == 60 => println!("luck"),_ => println!("Some else"),}let num = 60;let res = match num {x if x < 60 => "bad".to_owned(),x if x == 60 => "luck".to_owned(),_ => "Some else".to_owned(),};println!("res value : {res}");
}

编译及运行

 cargo runCompiling ch11_if_match v0.1.0 (/home/wangji/installer/rust/project/ch11_if_match)Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.55sRunning `target/debug/ch11_if_match`
You are old
You are OK!
You are yong

二、循环与break continue以及与迭代的区别

1.Rust中的循环Loops

Rust提供了几种循环结构,其中最常见的是Ioopwhilefor

  • 1.Ioop循环:
loop{
///无限循环的代码块
}

Ioop创建一个无限循环,可以通过break语句来中断循环。

  • 2.while循环:
while condition{
//条件为真时执行的代码块
}

while循环在每次迭代之前检查一个条件,只有在条件为真时才执行循环体。

  • 3.for循环:
for item in iterable
{//遍历可迭代对象执行的代码块
}

for循环用于迭代集合或范围,执行代码块来处理每个元素。

2.break && continue

·break关键字用于立即终止循环,并跳出循环体

  • 可以用于跳出指定标签循环

·continue关键字用于立即跳过当前循环中剩余的代码,直接进入下一次循环

3.迭代

Rust的迭代主要通过迭代器(iterators)来实现。迭代器是一个抽象,它提供了一种访问集合元素的统一方式。

从实现上讲在Rust中,迭代器是一种实现了Iterator trait的类型!

简化源码:

pub trait lterator{type Item;fn next (&mut self)->Option<Self:Item>;
}

4.循环与迭代的不同

循环适用于需要明确控制循环流程的情况,而迭代器则提供了一种更抽象的方式来处理集合元素。通常,推荐使用迭代器,因为它们可以提高代码的可读性和表达力。

fo循环是一种语法结构,用于遍历集合中的元素。它依赖于集合类型实现Iterator trait.

  • 在Rust中,迭代器提供了一系列用于遍历集合元素的方法,比如next()、mapO、filter)等,可以让我们的代码更具有表达性。

Example

fn main() {// loop {//     println!("Ctrl+C");//     std::thread::sleep(std::time::Duration::from_secs(1));// }// while循环let mut i = 0;while i < 10 {println!("{}", i);i += 1;}println!("for");// for 循环let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8];for element in arr {println!("{}", element);}// 打印不包括10for i in 0..10 {println!("{}", i);}// 打印包括10for i in 0..=10 {println!("{}", i);}// breaklet arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];for element in arr {if element == 10 {break;}println!("{element}");}let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];for element in arr {if element == 10 {continue;}println!("{element}");}'outer: loop {println!("outer");loop {println!("inner");// break;break 'outer; //直接跳出外部的循环}}// 循环的写法let numbers = [1, 2, 3, 4, 5];let mut for_numbers = Vec::new();for &number in numbers.iter() {let item = number * number;for_numbers.push(item);}println!("for : {:?}", for_numbers);// 迭代的写法,其性能与循环的性能差不多let numbers = [1, 2, 3, 4, 5].to_vec();let iter_number: Vec<_> = numbers.iter().map(|&x| x * x).collect();println!("iter : {:?}", iter_number);
}

编译及测试:

 cargo run Compiling ch12_loop_iter v0.1.0 (/home/wangji/installer/rust/project/ch12_loop_iter)Building [                             ] 0/1: ch12_loop_iter(bin)                                                                                                                                                                                                  Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.99sRunning `target/debug/ch12_loop_iter`
0
1
2
3
4
5
6
7
8
9
for
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
11
outer
inner
for : [1, 4, 9, 16, 25]
iter : [1, 4, 9, 16, 25]

三、函数基础与Copy值参数传递

1.函数的基础知识

1.函数的定义:在Rust中,你可以使用fn关键字声明和定义函数,而main是程序的入口点是一种特殊的函数。
2.参数和返回值
函数可以接受零个或多个参数,每个参数都需要指定类型。
函数可以有返回值,使用->指定返回值类型。如果函数没有返回值,可以使用->()、或省略这部分。
3.调用函数:调用函数时,使用函数名和传递给函数的实际参数。

2.Copy by value

如果数据类型实现Copy特质,则在函数传参时回实现Copy by value操作。

会将实参拷贝为形参,参数改变并不会影响实参。

如果要改变形参,需要加上mut

Struct、枚举、集合等并没有实现copy trait,会实现move操作失去所有权

为数据类型实现copy trait,就可实现copy by value

Example:

fn add(x: i32, y: i32) -> i32 {x + y //直接作为返回值进行返回,如果不加;
}fn change_i32(mut x: i32) {x = x + 4;println!("fn {x}");
}// 修改实参
fn modify_i32(x: &mut i32) {*x += 4;
}#[derive(Copy, Clone)]
struct Point {x: i32,y: i32,
}fn print_point(point: Point) {println!("point x {}", point.x);
}fn main() {let a = 1;let b = 2;let c = add(a, b);println!("c: {c}");let mut x = 1;change_i32(x);println!("x {x}");modify_i32(&mut x); //变成可变引用println!("x {x}");let s = Point { x: 1, y: 2 };print_point(s); // 由于打了标签#[derive(Copy, Clone)],所以可以直接传值println!("{}", s.x);
}

编译及运行:

 cargo runCompiling ch13_fn v0.1.0 (/home/wangji/installer/rust/project/ch13_fn)
warning: field `y` is never read--> src/main.rs:18:5|
16 | struct Point {|        ----- field in this struct
17 |     x: i32,
18 |     y: i32,|     ^|= note: `Point` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis= note: `#[warn(dead_code)]` on by defaultwarning: `ch13_fn` (bin "ch13_fn") generated 1 warningFinished `dev` profile [unoptimized + debuginfo] target(s) in 0.56sRunning `target/debug/ch13_fn`
c: 3
fn 5
x 1
x 5
point x 1
1

四、函数值参数的传递、不可变借用参数的传递、可变借用参数的传递

1.函数值参数传递(move)

函数的代码本身通常是存储在可执行文件的代码段,而在调用时函数会在栈,开辟一个新的stack frame(栈空间),用于存储函数的局部变量、参数和返回地址等信息,而当函数结束后会释放该空间。

而当传入non-Copy value(Vec、String等)传入函数时,实参会转移value的所有权给形参,实参会失去value的所有权而在函数结束时,value的所有权会释放。

2.不可变借用(就是C++的引用)

如果你不想失去value的所有权,你又没有修改value的需求,你可以使用不可变借用

在Rust中,你可以将不可变引用作为函数的参数,从而在函数内部访问参数值但不能修改它。这有助于确保数据的安全性,防止在多处同时对数据进行写操作,从而避免数据竞争。

如何应用不可变借用

  • Use*to deference,去获取其的值

3.可变借用

如果你有修改值的需求你可以使用可变借用,以允许在函数内部修改参数的值。这允许函数对参数进行写操作,但在同一时间内只能有一个可变引用。

需要在形参前加&mut

如何应用可变借用

  • 同样使用Use*to deference,去获取其的值

Example:

// p1有默认拷贝
// p2没有默认拷贝,所以是move
fn move_func(p1: i32, p2: String) {println!("p1 is {}", p1);println!("p2 is {}", p2);
}// borrow引用,但是在这里没意义,对于&i32这种类型而言
fn print_value(value: &i32) {println!("{}", value);
}fn string_func_borrow(s: &String) {println!("{}-{}", (*s).to_uppercase(), s.to_uppercase());
}#[derive(Debug)]
struct Point {x: i32,y: i32,
}fn modify_point(point: &mut Point) {(*point).x += 2;point.y += 2; //等价于(*point).y += 2
}fn main() {let n = 12;let s = String::from("oo");move_func(n, s);println!("n is {}", n);// println!("s is {}", s);let s = String::from("oo");print_value(&n);print_value(&n);string_func_borrow(&s);println!("s is {}", s);let mut p = Point { x: 0, y: 0 };println!("{:?}", p); //就是调用#[derive(Debug)]特质modify_point(&mut p);println!("{:?}", p);
}

编译及测试:

 cargo runCompiling ch14_fn_move_borrow_mut v0.1.0 (/home/wangji/installer/rust/project/ch14_fn_move_borrow_mut)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28sRunning `target/debug/ch14_fn_move_borrow_mut`
p1 is 12
p2 is oo
n is 12
12
12
OO-OO
s is oo
Point { x: 0, y: 0 }
Point { x: 2, y: 2 }

五、函数返回值与所有权机制

1.返回Copy与Non-Copy

都可以返回,但是要注意Non-Copy是在堆上的。

性能:

  • 在一般情况下,返回Copy类型的值通常具有更好的性能。这是因为Copy类型的值是通过复制进行返回的,而不涉及堆上内存的分配和释放,通常是在栈上分配。这样的操作比涉及堆上内存额分配和释放更为高效。

2.返回引用

在只有传入一个引用参数,只有一个返回引用时,生命周期不需要声明

其他情况下需要声明引用的生命周期

慎用‘static

Example:

fn func_copy_back() -> i32 {let n = 42;n
}fn func_non_copy_back() -> String {let s = String::from("hello");s
}fn get_mess(mark: i32) -> &'static str {if mark == 0 {"😊😀"} else {"≧ ﹏ ≦😫"}
}fn main() {let i = func_copy_back();println!("{}", i);let s = func_non_copy_back();println!("{}", s);println!("{}", get_mess(i));
}

编译及运行

 cargo runCompiling ch15_fn_back v0.1.0 (/home/wangji/installer/rust/project/ch15_fn_back)Finished `dev` profile [unoptimized + debuginfo] target(s) in 10.05sRunning `target/debug/ch15_fn_back`
42
hello
≧ ﹏ ≦😫

六、高阶函数:函数作为参数与返回值

高阶函数(Higher-Order Functions):Rust 允许使用高阶函数,即函数可以作为参数传递给其他函数,或者函数可以返回其他函数。

高阶函数也是函数式编程的重要特性。

1.高阶函数与集合

1、map函数:map函数可以用于对一个集合中的每个元素应用一个函数,并返回包含结果的新集合。

2、filter函数:filter函数用于过滤集合中的元素,根据一个谓词函数的返回值。

3、fold:fold函数(有时也称为reduce^)可以用于迭代集合的每个元素,并将它们累积到一个单一的结果中。

Example:

fn func_twice(f: fn(i32) -> i32, x: i32) -> i32 {f(f(x))
}fn mul(x: i32) -> i32 {x * x
}fn add(x: i32) -> i32 {x + 10
}fn main() {let result = func_twice(mul, 4);println!("{result}");let res = func_twice(add, 10);println!("{res}");// 数学计算let numbers = vec![1, 2, 3, 4, 5, 6, 7];let res: Vec<_> = numbers.iter().map(|&x| x + x).collect();println!("{:?}", res);// filterlet numbers = vec![1, 2, 3, 4, 5, 6, 7];// ref ref_mut movelet evens = numbers.into_iter().filter(|&x| x % 2 == 0).collect::<Vec<_>>(); //等价于let evens: Vec<_>println!("{:?}", evens);let numbers = vec![1, 2, 3, 4, 5, 6, 7]; //构造一个vectorlet sum = numbers.iter().fold(0, |acc, &x| acc + x);println!("Sum: {}", sum);
}

编译及测试

 cargo runCompiling ch16_higher_func v0.1.0 (/home/wangji/installer/rust/project/ch16_higher_func)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29sRunning `target/debug/ch16_higher_func`
256
30
[2, 4, 6, 8, 10, 12, 14]
[2, 4, 6]

参考

  • 2024 Rust现代实用教程

http://www.mrgr.cn/news/63356.html

相关文章:

  • 视频文件损坏无法播放怎么办?有什么办法可以修复视频吗?
  • 信息论与熵information and entropy
  • 使用语言模型进行文本摘要的五个级别(llm)
  • 亿级排行榜设计
  • 浏览器相关题集
  • Python 实现斐波那契数列的方法
  • 递归到分治
  • 显示器不亮?解决“显示器不支持当前的输入时序,请将输入时序更改为 1920x1080, 60Hz”的终极指南
  • 别再盲目选购随身WiFi了!一文教你精准挑选最适合自己的随身WiFi!随身wifi哪个牌子的最好用?
  • o1驾驶无人机后空翻,OpenAI开发者日惊掉下巴!2分钟爆改代码写App
  • Vite学习之模式
  • AI实践-PyTorch-CNN-手写数字识别
  • 多线程在打包工具中的运用
  • 5分钟搞定:Spring AI支持SpringBoot快速构建人工智能AI应用_springai_springboot_AI应用
  • jlink识别不到gd32@
  • 连续11年领跑行业 凯迪仕智能锁双11再次稳居全渠道销量第一
  • 鸿蒙HarmonyOS应用开发者(基础+高级)认证
  • jmeter结合ansible分布式压测--准备工作
  • 青少年编程与数学 02-003 Go语言网络编程 03课题、网络编程协议
  • 通义灵码上新功能:用代码画流程图
  • 仓库物品带下拉提示搜索与开单自定义数量和备注带提交反馈单页功能
  • 充电宝哪一款最实用?2024年推荐五款性价比最高选择,附选购攻略
  • R语言贝叶斯
  • LeetCode 热题 100之二叉树
  • 语音IC方案,在交通信号灯语音提示器的应用解析,NV040D
  • T10打卡—数据增强