Rust学习通过例子学习Rust(1)
1. 例子
1.1 注释
fn main() {
//这是一个行注释
/*
* 这是一个块注释
*/
let x = 5 + /* r = 10*/ 5;
println!("{}", x); //10
}
1.2 格式化输出
debug: trait fmt::Debug
display: std::fmt;
write!()
format!()
2.原生类型
2.1 运算符
和C 一样
2.2元组
fn main() {
let a = (1, true, 'a');
println!("{:?}", a);
println!("{:?}", a.0); //1
}
2.3 数组和切片
let x = [1; 3];
println!("{:?}", x[0]);
3 自定义结构体
3.1 struct
struct x {
a:i32,
b:u32
}
3.2 enum
num
3.3
const / 'static
4 变量
具体参见书本
5类型系统
5.1 类型转换
let decimal = 54.5;
let character = decimal as u32;
println!("{}", character);//54
5.2 字面量
let x = 1u8;
let y = 1;
println!("{}", std::mem::size_of_val(&x)); //1
println!("{}", std::mem::size_of_val(&y)); //4
5.3 类型判断
let elem = 5;
let mut vc = Vec::new();
vc.push(elem);//确认集合类型
println!("{:?}", vc);//[5]
5.4 别名
as
6 类型转换
From 和 Into 两个 trait
6.1 from and into
Into trait 就是把 From trait 倒过来而已。也就是说,如果你为你的类型实现了 From,那么同时你也就免费获得了 Into。
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T
where
U: From<T>,
{
/// Calls `U::from(self)`.
///
/// That is, this conversion is whatever the implementation of
/// <code>[From]<T> for U</code> chooses to do.
#[inline]
fn into(self) -> U {
U::from(self)
}
}
6.2 TryFrom and TryInto
类似于 From 和 Into,TryFrom 和 TryInto 是类型转换的通用 trait。不同于 From/Into 的是,
TryFrom 和 TryInto trait 用于易出错的转换,也正因如此,其返回值是 Result 型。
//TryFrom trait
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
#[stable(feature = "try_from", since = "1.34.0")]
type Error;
/// Performs the conversion.
#[stable(feature = "try_from", since = "1.34.0")]
fn try_from(value: T) -> Result<Self, Self::Error>;
}
use std::convert::TryFrom;
#[derive(Debug, PartialEq)]
struct EvenNumber(i32);
impl TryFrom<i32> for EvenNumber {
type Error = ();
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value % 2 == 0 {
Ok(EvenNumber(value))
} else {
Err(())
}
}
}
fn main() {
//TryFrom
assert_eq!(EvenNumber::try_from(2), Ok(EvenNumber(2)));
assert_eq!(EvenNumber::try_from(3), Err(()));
//TryInto
let result: Result<EvenNumber, ()> = 2i32.try_into();
assert_eq!(result, Ok(EvenNumber(2)));
let result: Result<EvenNumber, ()> = 3i32.try_into();
assert_eq!(result, Err(()));
}
6.3 ToString and FromStr
要把任何类型转换成 String,只需要实现那个类型的 ToString trait。然而不要直接这么做,
您应该实现fmt::Display trait,它会自动提供 ToString
use std::fmt;
struct Circle {
r: i32,
}
impl fmt::Display for Circle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Circle with radius {}", self.r)
}
}
fn main() {
let circle = Circle { r: 10 };
println!("{}", circle);
}
6.4 解析字符串 FromStr trait
fn main() {
let parsed: i32 = "5".parse().unwrap();
let turbo_parsed = "5".parse::<i32>().unwrap();
let sum = parsed + turbo_parsed;
println!("{}", sum); //10
}
7 表达式
Rust 程序(大部分)由一系列语句构成:
fn main() {
//语句
}
代码块也是表达式,所以它们可以用作赋值中的值。代码块中的最后一个表达式将赋给适当的表达式,例如局部变量。但是,如果代码块的最后一个表达式结尾处有分号,则返回值为 ()
(译注:代码块中的最后一个语句是代码块中实际执行的最后一个语句,而不一定是代码块中最后一行的语句)。
fn main() {
let x = 3;
let y = {
// 分号结束了这个表达式,于是将 `()` 赋给 `z`
2 * x;
};
println!("{:?}", y);//()
}
8 控制流
8.1 if/else 表达式
let parent = 10;
if parent > 5 {
println!("parent is greater than 5");
} else {
println!("parent is less than 5");
}
8.2 loop 循环
let mut count = 1;
loop {
loop {
count += 1;
if count == 15 {
println!("count is equal to 15");
continue;
}
if count == 20 {
println!("count is equal to 20");
break;
}
}
println!("count is equal to {}", count);
break;
}
8.3 while 循环
let mut counter = 0;
while counter < 10 {
counter += 1;
println!("counter is equal to {}", counter);
}
8.4 for 循环
for i in 1..3{
println!("i is equal to {}", i);
}
8.5 match 匹配
match number {
1 => println!("one"),
10 => println!("10"),
_ => println!("other"),
}
解构元组
let triple = (0,2,-3);
match triple {
(0,x,y)=>println!("x is {} and y is {}", x, y),
_=>println!("other")
}
解构枚举
#[allow(dead_code)]
enum Color {
Red,
Green,
RGB(u32, u32, u32),
}
let color = Color::RGB(1, 2, 3);
match color {
Color::Green => println!("{}", "Green"),
Color::RGB(r, g, b) => println!("r is {} and g is {} and b is {}", r, g, b),
_ => println!("other"),
}
指针和引用
解引用使用 *
解构使用 &、ref、和 ref mut
结构体
struct Foo {
x: (i32, i32),
y: i32,
};
let foo = Foo { x: (1, 2), y: 3 };
let Foo { x: (a, b), y } = foo;
println!("a is {} and b is {}", a, b);
let Foo { x: (a, b), .. } = foo;
println!("a is {} and b is {}", a, b);
let Foo { y, .. } = foo;
println!("y is {}", y);
绑定
在 match 中,若间接地访问一个变量,则不经过重新绑定就无法在分支中再使用它。match 提供了 @ 符号来绑定变量到名称:
// `age` 函数,返回一个 `u32` 值。
fn age() -> u32 {
15
}
fn main() {
println!("Tell me what type of person you are");
match age() {
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),
}
}
if let
fn main() {
// 全部都是 `Option<i32>` 类型
let number = Some(7);
let letter: Option<i32> = None;
let emoticon: Option<i32> = None;
// `if let` 结构读作:若 `let` 将 `number` 解构成 `Some(i)`,则执行
// 语句块(`{}`)
if let Some(i) = number {
println!("Matched {:?}!", i);
}
// 如果要指明失败情形,就使用 else:
if let Some(i) = letter {
println!("Matched {:?}!", i);
} else {
// 解构失败。切换到失败情形。
println!("Didn't match a number. Let's go with a letter!");
};
// 提供另一种失败情况下的条件。
let i_like_letters = false;
if let Some(i) = emoticon {
println!("Matched {:?}!", i);
// 解构失败。使用 `else if` 来判断是否满足上面提供的条件。
} else if i_like_letters {
println!("Didn't match a number. Let's go with a letter!");
} else {
// 条件的值为 false。于是以下是默认的分支:
println!("I don't like letters. Let's go with an emoticon :)!");
};
}
while let
fn main() {
// 将 `optional` 设为 `Option<i32>` 类型
let mut optional = Some(0);
// 这读作:当 `let` 将 `optional` 解构成 `Some(i)` 时,就
// 执行语句块(`{}`)。否则就 `break`。
while let Some(i) = optional {
if i > 9 {
println!("Greater than 9, quit!");
optional = None;
} else {
println!("`i` is `{:?}`. Try again.", i);
optional = Some(i + 1);
}
// ^ 使用的缩进更少,并且不用显式地处理失败情况。
}
// ^ `if let` 有可选的 `else`/`else if` 分句,
// 而 `while let` 没有。
}