Rust结构化编程
Rust结构化编程
条件判断
| 条件判断语句 | 说明 | 
|---|---|
| if 语句 | if 语句用于模拟现实生活中的 如果…就… | 
| if...else 语句 | if...else 语句用于模拟 如果…就…否则… | 
| else...if 和嵌套if 语句 | 嵌套if 语句用于模拟 如果…就…如果…就… | 
| match 语句 | match 语句用于模拟现实生活中的 老师点名 或 银行叫 | 
if 语句
if 条件表达式 {
    // 条件表达式为true时要执行的逻辑
}示例
let total:f32 = 666.00;
if total > 500.00 {
   println!("打8折,{}",total*0.8)
}
// 输出 打8折,532.8if …else 语句
if 条件表达式 {
   // 如果 条件表达式 为真则执行这里的代码
} else {
   // 如果 条件表达式 为假则执行这里的代码
}示例
let total:f32 = 166.00;
if total > 500.00 {
   println!("打8折,{}", total*0.8)
} else {
   println!("无折扣优惠,{}", total)
}
输出 无折扣优惠,166if…else if… else 语句
if 条件表达式1 {
   // 当 条件表达式1 为 true 时要执行的语句
} else if 条件表达式2 {
   // 当 条件表达式2 为 true 时要执行的语句
} else {
   // 如果 条件表达式1 和 条件表达式2 都为 false 时要执行的语句
}示例
let total:f32 = 366.00;
if total > 200.00 && total < 500.00 {
    println!("打9折,{}",total*0.9)
} else if total > 500.00 {
    println!("打8折,{}",total*0.9)
} else {
    println!("无折扣优惠,{}",total)
}
// 输出 打9折,329.4可以作为表达式赋值 (三元运算符)
if 语句是表达式而非语句
用 if 来赋值时,要保证每个分支返回的类型一样,如果返回类型不一致就会报错
if condition == true {
    // A...
} else {
    // B...
}match 语句
Rust 中的 match 语句有返回值,它把 匹配值 后执行的最后一条语句的结果当作返回值。
语法
match variable_expression {
   constant_expr1 => {
      // 语句;
   },
   constant_expr2 => {
      // 语句;
   },
   _ => {
      // 默认
      // 其它语句
   }
};示例
let code = "10010";
let choose = match code {
   "10010" => "联通",
   "10086" => "移动",
   _ => "Unknown"
};
println!("选择 {}", choose);  // 输出 选择 联通
let code = "80010";
let choose = match code {
   "10010" => "联通",
   "10086" => "移动",
   _ => "Unknown"
};
println!("选择 {}", choose);  // 输出 选择 Unknown循环
现实中的循环很多,比如我们在学校操场里跑步,一圈一圈的跑。在计算机中,循环 其实就是一种重复,在满足指定的条件下,重复的做某些事情。
Rust 语言中也有三种表示 循环 的语句:
- loop 语句。一种重复执行且永远不会结束的循环。
 - while 语句。一种在某些条件为真的情况下就会永远执行下去的循环。
 - for in 语句。一种有确定次数的循环。
 
for in 循环
for 临时变量 in 集合 { // 常见用法:用 `左区间..右区间` 来构建一个序列集合
   // 执行业务逻辑
}左区间..右区间,这是一个左闭右开的区间,1..5,那就只包含 1,2,3,4
for num in 1..5 {
   println!("num is {}", num);
}
// 输出
num is 1
num is 2
num is 3
num is 4可以使用 a..=b 表示两端都包含在内的范围。
for num in 1..=5 {
   println!("num is {}", num);
}
// 输出
num is 1
num is 2
num is 3
num is 4
num is 5for in 与迭代器
2021版本后不用 .iter() 也行,但本质上还是因为隐式地转换成迭代器
iter (集合不变)
在每次迭代中借用集合中的一个元素。这样集合本身不会被改变,循环之后仍可以使用。
let studyList = vec![
     "《Go语言极简一本通》",
     "Go语言微服务架构核心22讲",
     "从0到Go语言微服务架构师",
];
for name in studyList.iter() {
    match name {
        &"从0到Go语言微服务架构师" => println!("恭喜你进阶到第三阶段-{}!", name),
        _ => println!("学习: {}", name),
    }
}
// 输出
学习: 《Go语言极简一本通》
学习: Go语言微服务架构核心22讲
恭喜你进阶到第三阶段-从0到Go语言微服务架构师!可以简化不写 .iter()
使用 for 时我们往往使用集合的引用形式,除非你不想在后面的代码中继续使用该集合(比如我们这里使用了 container 的引用)。如果不使用引用的话,所有权会被转移(move)到 for 语句块中,后面就无法再使用这个集合了)
for item in &container {
  // ...
}into_iter (消耗集合)
会消耗集合。在每次迭代中,集合中的数据本身会被提供。一旦集合被消耗了,之后就无法再使用了,因为它已经在循环中被 “移除”(move)了。
let studyList2 = vec![
    "《Go语言极简一本通》",
    "Go语言微服务架构核心22讲",
    "从0到Go语言微服务架构师",
];
for name in studyList2.into_iter() {
    match name {
        "从0到Go语言微服务架构师" => println!("恭喜你进阶到第三阶段-{}!", name),
        _ => println!("学习: {}", name),
    }
}
// 输出
学习: 《Go语言极简一本通》
学习: Go语言微服务架构核心22讲
恭喜你进阶到第三阶段-从0到Go语言微服务架构师!iter_mut (集合可改)
可变地(mutably)借用集合中的每个元素,从而允许集合被就地修改。
 就是停止本次执行剩下的语句,直接进入下一个循环。
let mut studyList3 = vec![
    "《Go语言极简一本通》",
    "Go语言微服务架构核心22讲",
    "从0到Go语言微服务架构师",
];
for name in studyList3.iter_mut() {
    *name = match name {
        &mut "从0到Go语言微服务架构师" => {
            "恭喜你进阶到第三阶段---从0到Go语言微服务架构师"
        }
        _ => *name,
    }
}
println!("studyList3: {:?}", studyList3);
// 输出
studyList3: ["《Go语言极简一本通》", "Go语言微服务架构核心22讲", "恭喜你进阶到第三阶段---从0到Go语言微服务架构师"]可以简化不写 .iter_mut()
for item in &mut collection {
  // ...
}总结,比较各种循环方式
总结如下:
| 使用方法 | 等价使用方式 | 所有权 | 
|---|---|---|
for item in collection | for item in IntoIterator::into_iter(collection) | 转移所有权 | 
for item in &collection | for item in collection.iter() | 不可变借用 | 
for item in &mut collection | for item in collection.iter_mut() | 可变借用 | 
如果想在循环中获取元素的索引:
fn main() {
    let a = [4, 3, 2, 1];
    // `.iter()` 方法把 `a` 数组变成一个迭代器
    for (i, v) in a.iter().enumerate() {
        println!("第{}个元素是{}", i + 1, v);
    }
}两种循环方式优劣对比
以下代码,使用了两种循环方式:
// 第一种
let collection = [1, 2, 3, 4, 5];
for i in 0..collection.len() {
  let item = collection[i];
  // ...
}
// 第二种
for item in collection {
}第一种方式是循环索引,然后通过索引下标去访问集合,第二种方式是直接循环集合中的元素,优劣如下:
- 性能: 
- 第一种使用方式中 
collection[index]的索引访问,会因为边界检查(Bounds Checking)导致运行时的性能损耗 —— Rust 会检查并确认index是否落在集合内 - 但是第二种直接迭代的方式就不会触发这种检查,因为编译器会在编译时就完成分析并证明这种访问是合法的
 
 - 第一种使用方式中 
 - 安全: 
- 第一种方式里对 
collection的索引访问是非连续的,存在一定可能性在两次访问之间,collection发生了变化,导致脏数据产生。 - 而第二种直接迭代的方式是连续访问,因此不存在这种风险( 由于所有权限制,在访问过程中,数据并不会发生变化)。
 
 - 第一种方式里对 
 
由于 for 循环无需任何条件限制,也不需要通过索引来访问,因此是最安全也是最常用的
小技巧:省略i
有同学可能会想到,如果我们想用 for 循环控制某个过程执行 10 次,但是又不想单独声明一个变量来控制这个流程,该怎么写?
可以用 _ 来替代 i 用于 for 循环中,在 Rust 中 _ 的含义是忽略该值或者类型的意思,如果不使用 _,那么编译器会给你一个 变量未使用的 的警告。
for _ in 0..10 {
  // ...
}while 循环
while ( 条件表达式 ) {
    // 执行业务逻辑
}上面的条件表达式为真,就会执行 while 循环。
let mut num = 1;
while num < 20 {
    println!("num is {}",num);
    num= num*2;
}
// 输出
num is 1
num is 2
num is 4
num is 8
num is 16loop 循环+break
loop {
    // 执行业务逻辑
}
break; 中断的意思,就是跳出loop循环示例
let mut num = 1;
loop {
   if num > 20{
      break;
   }
   println!("num is {}",num);
   num = num*3;
}
// 输出
num is 1
num is 3
num is 9continue与break
略