fnmain(){let x =5u32;let y ={let x_squared = x * x;let x_cube = x_squared * x;// 将此表达式赋给 `y`
x_cube + x_squared + x
};let z ={// 分号结束了这个表达式,于是将 `()` 赋给 `z`2* x;};println!("x is {:?}", x);println!("y is {:?}", y);println!("z is {:?}", z);}
流程控制
Rust中的if、for等循环等。
if/else循环
if、else循环不需要和let一样使用";"结尾,但是如果遇到let绑定的就必须遵守let的规则
fnmain(){let n =5;if n <0{print!("{} is negative", n);}elseif n >0{print!("{} is positive", n);}else{print!("{} is zero", n);}let big_n =if n <10&& n >-10{println!(", and is a small number, increase ten-fold");// 这个表达式返回一个 `i32` 类型。10* n
}else{println!(", and is a big number, half the number");// 这个表达式也必须返回一个 `i32` 类型。
n /2// 试一试 ^ 试着加上一个分号来结束这条表达式。};// ^ 不要忘记在这里加上一个分号!所有的 `let` 绑定都需要它。println!("{} -> {}", n, big_n);}
#![allow(unreachable_code)]fnmain(){'outer:loop{println!("Entered the outer loop");'inner:loop{println!("Entered the inner loop");// 这只是中断内部的循环//break;// 这会中断外层循环break'outer;}println!("This point will never be reached");}println!("Exited the outer loop");}
fnmain(){// 计数器变量letmut n =1;// 当 `n` 小于 101 时循环while n <101{if n %15==0{println!("fizzbuzz");}elseif n %3==0{println!("fizz");}elseif n %5==0{println!("buzz");}else{println!("{}", n);}// 计数器值加 1
n +=1;}}
for 循环
for和区间:基本方法是使用for in 结构:
for in 结构可以遍历一个 Iterator(迭代器)。创建迭代器的一个最简单的方法是使用区间标记 a..b。这会生成从 a(包含此值) 到 b(不含此值)的,步长为 1 的一系列值。
有两种方法:
for n in 1..101
for n in 1..=100 这两种表达式的结果相同,都是使用
[
1
,
100
]
[1,100]
[1,100]的闭区间,但是写法不同。
for和迭代器
iter()
iter_mut()
into_iter()
&T
&mut T
T
iter提供迭代
iter_mut可以改变原值
使用过后就不能再使用了
iter:在每次迭代中借用集合中的一个元素。这样集合本身不会被改变,循环之后仍可以使用。
fnmain(){let names =vec!["Bob","Frank","Ferris"];for name in names.iter(){match name {&"Ferris"=>println!("There is a rustacean among us!"),
_ =>println!("Hello {}", name),}}}
fnmain(){let names =vec!["Bob","Frank","Ferris"];for name in names.into_iter(){match name {"Ferris"=>println!("There is a rustacean among us!"),
_ =>println!("Hello {}", name),}}}
iter_mut : 可变地(mutably)借用集合中的每个元素,从而允许集合被就地修改
fnmain(){letmut names =vec!["Bob","Frank","Ferris"];for name in names.iter_mut(){*name =match name {&mut"Ferris"=>"There is a rustacean among us!",
_ =>"Hello",}}println!("names: {:?}", names);}
这个是它的输出:
names:["Hello","Hello","There is a rustacean among us!"]
match 匹配
类似switch,但是所有符合的值必须均被列出来进行匹配,常用的是_匹配。
match是一个表达式
fnmain(){let number =13;// 试一试 ^ 将不同的值赋给 `number`println!("Tell me about {}", number);match number {// 匹配单个值1=>println!("One!"),// 匹配多个值2|3|5|7|11=>println!("This is a prime"),// 试一试 ^ 将 13 添加到质数列表中// 匹配一个闭区间范围13..=19=>println!("A teen"),// 处理其他情况
_ =>println!("Ain't special"),// 试一试 ^ 注释掉这个总括性的分支}let boolean =true;// match 也是一个表达式let binary =match boolean {// match 分支必须覆盖所有可能的值false=>0,true=>1,// 试一试 ^ 将其中一条分支注释掉};println!("{} -> {}", boolean, binary);}
match可以用来解构
元组
枚举
指针和引用
结构体
match解构元组
fnmain(){let triple =(0,-2,3);// 试一试 ^ 将不同的值赋给 `triple`println!("Tell me about {:?}", triple);// match 可以解构一个元组match triple {// 解构出第二个和第三个元素(0, y, z)=>println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),(1,..)=>println!("First is `1` and the rest doesn't matter"),// `..` 可用来忽略元组的其余部分
_ =>println!("It doesn't matter what they are"),// `_` 表示不将值绑定到变量}}
match解构枚举
// 需要 `allow` 来消除警告,因为只使用了枚举类型的一种取值。#[allow(dead_code)]enumColor{// 这三个取值仅由它们的名字(而非类型)来指定。Red,Blue,Green,// 这些则把 `u32` 元组赋予不同的名字,以色彩模型命名。RGB(u32,u32,u32),HSV(u32,u32,u32),HSL(u32,u32,u32),CMY(u32,u32,u32),CMYK(u32,u32,u32,u32),}fnmain(){let color =Color::RGB(122,17,40);// 试一试 ^ 将不同的值赋给 `color`println!("What color is it?");// 可以使用 `match` 来解构 `enum`。match color {Color::Red=>println!("The color is Red!"),Color::Blue=>println!("The color is Blue!"),Color::Green=>println!("The color is Green!"),Color::RGB(r, g, b)=>println!("Red: {}, green: {}, and blue: {}!", r, g, b),Color::HSV(h, s, v)=>println!("Hue: {}, saturation: {}, value: {}!", h, s, v),Color::HSL(h, s, l)=>println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),Color::CMY(c, m, y)=>println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),Color::CMYK(c, m, y, k)=>println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
c, m, y, k),// 不需要其它分支,因为所有的情形都已覆盖}}
match解构指针
解引用使用*
解构使用&、ref、ref mut
ref用来创建一个引用,可以使用解引用来对其进行解引用。
fnmain(){// 获得一个 `i32` 类型的引用。`&` 表示取引用。let reference =&4;match reference {// 如果用 `&val` 这个模式去匹配 `reference`,就相当于做这样的比较:// `&i32`(译注:即 `reference` 的类型)// `&val`(译注:即用于匹配的模式)// ^ 我们看到,如果去掉匹配的 `&`,`i32` 应当赋给 `val`。// 译注:因此可用 `val` 表示被 `reference` 引用的值 4。&val =>println!("Got a value via destructuring: {:?}", val),}// 如果不想用 `&`,需要在匹配前解引用。match*reference {
val =>println!("Got a value via dereferencing: {:?}", val),}// 如果一开始就不用引用,会怎样? `reference` 是一个 `&` 类型,因为赋值语句// 的右边已经是一个引用。但下面这个不是引用,因为右边不是。let _not_a_reference =3;// Rust 对这种情况提供了 `ref`。它更改了赋值行为,从而可以对具体值创建引用。// 下面这行将得到一个引用。letref _is_a_reference =3;// 相应地,定义两个非引用的变量,通过 `ref` 和 `ref mut` 仍可取得其引用。let value =5;letmut mut_value =6;// 使用 `ref` 关键字来创建引用。// 译注:下面的 r 是 `&i32` 类型,它像 `i32` 一样可以直接打印,因此用法上// 似乎看不出什么区别。但读者可以把 `println!` 中的 `r` 改成 `*r`,仍然能// 正常运行。前面例子中的 `println!` 里就不能是 `*val`,因为不能对整数解// 引用。match value {ref r =>println!("Got a reference to a value: {:?}", r),}// 类似地使用 `ref mut`。match mut_value {refmut m =>{// 已经获得了 `mut_value` 的引用,先要解引用,才能改变它的值。*m +=10;println!("We added 10. `mut_value`: {:?}", m);},}}
解构结构体
fnmain(){structFoo{ x:(u32,u32), y:u32}// 解构结构体的成员let foo =Foo{ x:(1,2), y:3};letFoo{ x:(a, b), y }= foo;println!("a = {}, b = {}, y = {} ", a, b, y);// 可以解构结构体并重命名变量,成员顺序并不重要letFoo{ y: i, x: j }= foo;println!("i = {:?}, j = {:?}", i, j);// 也可以忽略某些变量letFoo{ y,..}= foo;println!("y = {}", y);// 这将得到一个错误:模式中没有提及 `x` 字段// let Foo { y } = foo;}
卫语句
可以在其中添加卫语句进行过滤,如if之类
fnmain(){let pair =(2,-2);// 试一试 ^ 将不同的值赋给 `pair`println!("Tell me about {:?}", pair);match pair {(x, y)if x == y =>println!("These are twins"),// ^ `if` 条件部分是一个卫语句(x, y)if x + y ==0=>println!("Antimatter, kaboom!"),(x, _)if x %2==1=>println!("The first one is odd"),
_ =>println!("No correlation..."),}}
绑定
// `age` 函数,返回一个 `u32` 值。fnage()->u32{15}fnmain(){println!("Tell me what type of person you are");matchage(){0=>println!("I haven't celebrated my first birthday yet"),// 可以直接匹配(`match`) 1 ..= 12,但那样的话孩子会是几岁?// 相反,在 1 ..= 12 分支中绑定匹配值到 `n` 。现在年龄就可以读取了。
n @1..=12=>println!("I'm a child of age {:?}", n),
n @13..=19=>println!("I'm a teen of age {:?}", n),// 不符合上面的范围。返回结果。
n =>println!("I'm an old person of age {:?}", n),}}