Skip to content

Rust

Rust 作为未来 C++ 的替代者,可以在编译期保证内存安全。

Hello World

rust
fn main() { // main 函数是 rust 程序入口
    println!("hello world");
}

注释

rust
// 单行注释

/* 单行注释 */

/*
 * 多行注释
 * 多行注释
 * 多行注释
 */

/// 文档注释

表达式与语句

rust
fn main() {
    let y = {
        let x = 3;
        x + 1
    };
    println!("The value of y is: {y}");
}

常量与变量

rust
fn main() {
    const MY_CONST: i32 = 0; // 常量,类型必须显式指定,值必须在编译期确定
    let my_var: i32 = 1; // 不可变变量
    let mut my_mut_var: i32 = 2; // 可变变量
    my_mut_var = 3; // 修改可变变量
    println!("{} {} {}", MY_CONST, my_var, my_mut_var);
}

所有权

  • Rust 中的每一个值都有一个变量作为所有者。
  • 值在任一时刻有且只有一个所有者。
  • 当所有者离开作用域,这个值将被丢弃。
rust
fn main() {
    let s = String::from("hello"); // s 拥有 hello 的所有权
    println!("{}", s); // 打印 s
    // s 被丢弃,String 类型实现了 Drop 特性,这里会隐式调用其 drop 方法,释放堆内存
}

所有权转移

rust
fn main() {
    let s1 = String::from("hello");
    {
        let s2 = s1; // String 类型没有实现 Copy 特征,将 hello 的所有权转移至 s2
        println!("{}", s2); // 打印s2
        // s2 被丢弃
    }
    // s1 丧失所有权
}

引用

rust
fn main() {
    let mut s = String::from("hello");
    {
        let r1 = &s; // s 被不可变引用为 r1,hello 的所有权依然属于 s
        println!("{}", r1); // 打印 r1,这里会自动解引用
    }
    {
        let r2 = &mut s; // s 被可变借用为 r2,可变借用具有独占性
        r2.push_str(" world"); // 调用方法,这里会自动解引用
        println!("{}", r2);
    }
    // s 被丢弃
}

再引用

rust
fn main() {
    let mut i: i32 = 0;
    let r1 = &mut i;
    let r2: &mut i32 = r1;
    *r2 = 1;
    println!("{}", r2);
    *r1 = 2;
    println!("{}", r1);
    i = 3;
    println!("{}", i);
}

流程控制

if

rust
fn main() {
    let n = 1;
    if n > 0 {
        println!("n > 0");
    } else if n < 0 {
        println!("n < 0");
    } else {
        println!("n = 0");
    }

    // 当具有 else 时,if 表达式是有值的,可以和 let 结合使用
    let r = if n >= 0 {
        n
    } else {
        -n
    };
    println!("{}", r);
}

loop

rust
fn main() {
    let mut count = 0;
    loop {
        count += 1;
        println!("count: {}", count);
        if count >= 7 {
            break;
        }
    }

    // loop 表达式是有值的
    let r = loop {
        if count < 3 {
            break count;
        }
        count -= 3;
    }
    println!("leave {}", r);
}

while

rust
fn main() {
    let mut i = 3;
    while i > 0 {
        println!("{}", i);
        i -= 1;
    }
}

for

rust
fn main() {
    let a = [1, 2, 3, 4, 5];
    for e in a { // 目标必须实现 Iterator 或者 IntoIterator
        println!("{}", e);
    }
}

panic!

rust
fn main() {
    // 程序终止运行
    panic!("crash and burn");
}

基本类型

rust
fn main() {
    // 整型
    // 无符号 u8, u16, u32, u64, u128, usize
    // 有符号 i8, i16, i32, i64, i128, isize
    // 默认为 i32
    let mut my_int: i32;
    my_int= 99;
    my_int = 0b11;
    my_int = 0o77;
    my_int = 0xff;
    my_int = 123_456;
    my_int = 1_i32

    // 浮点型 f32, f64
    // 默认为 f64
    let mut my_float: f64;
    my_float = 3.0;

    // 布尔型(8bit) bool
    let mut my_bool: bool;
    my_bool = true;
    my_bool = false;

    // 字符型(32bit) char
    let mut my_char: char;
    my_char = 'a';
    my_char = '中';
}

元组

rust
fn main() {
    let t: (i32, bool) = (0, false);
    println!("{} {}", t.0, t.1);
}

数组

rust
fn main() {
    let arr: [i32; 3] = [1, 2, 3];
    println!("{} {} {}", arr[0], arr[1], arr[2]);
}

函数

rust
fn largest(a: i32, b: i32) -> i32 {
    if a > b {
        a
    } else {
        b
    }
}

largest 的类型是 fn(i32, i32) -> i32 ,代表一个函数指针

结构体

rust
struct User {
    username: String,
    email: String,
}

impl User {
    fn new(username: String) -> User {
        let mut email = username.clone();
        email.push_str("@google.com");
        User { username, email }
    }
    fn print(&self) {
        println!("{}: {}", self.username, self.email);
    }
    fn set(&mut self, username: String) {
        let mut email = username.clone();
        email.push_str("@google.com");
        self.username = username;
        self.email = email;
    }
    fn get(self) -> String {
        self.username
    }
}

struct Color(u32, u32, u32);

fn main() {
    let u1 = User {
        username: String::from("foo"),
        email: String::from("foo@google.com"),
    };
    u1.print();

    let User { username: username, email: email } = u1;
    // 可简化为 let User { username, email } = u1;
    println!("{}: {}", username, email);

    let username = String::from("foo");
    let u2 = User {
        username,
        email: String::from("foo@google.com"),
    };
    u2.print();

    let u3 = User {
        username: String::from("foofoo"),
        ..u2
    };
    u3.print();

    let mut u4 = User::new(String::from("foo"));
    u4.set(String::from("foofoo"));
    u4.print();
    // TODO partial move and borrow

    let black = Color(0, 0, 0);
    println!("{} {} {}", black.0, black.1, black.2);
    let Color(c1, c2, c3) = black;
    println!("{} {} {}", c1, c2, c3);
}

枚举

rust
enum Shape {
    Dot,
    Circle(u32),
    Rectangle { width: u32, height: u32 },
}

fn main() {
    let s = Shape::Rectangle {
        width: 2,
        height: 4,
    };

    match s {
        Shape::Dot => println!("dot"),
        Shape::Circle(r) => println!("circle with {}", r),
        Shape::Rectangle { width, height } => println!("rectangle with {} {}", width, height),
    }
}

if let & while let 处理枚举

rust
fn main() {
    let mut o: Option<i32> = Some(1);
    while let Some(i) = o {
        println!("{}", i);
        if i == 3 {
            o = None;
        } else {
            o = Some(i + 1);
        }
    }
    println!("end")
}

泛型

fn my_fn<T>(arg: T) {
    // ...
}

struct MyStruct<T> {
    // ...
}

enum MyEnum<T> {
    // ...
}

impl<T> ... {
    // ...
}

特征

rust
trait Summary {
    type Author;

    fn summarize_author(&self, author: Author) -> String;

    fn summarize(&self) -> String {
        format!("(Read more from {}...)", self.summarize_author())
    }
}

struct Tweet;

impl Summary for Tweet {
    type Author = String;

    fn summarize_author(&self, author: Self::Author) -> String {
        format!("@{}", author)
    }
}

pub fn notify<T: Summary>(item: T) { // fn notify(item: impl Summary) {
    println!("Breaking news! {}", item.summarize());
}

fn main() {
    notify(Tweet { username: String::from("foo") });
}

生命周期

引用变量的生命周期不应该超过被引用变量的生命周期,因此生命周期约束是很有必要的。

rust
fn largest<'a, 'b, 'c>(a: &'a i32, b: &'b i32) -> &'c i32
where
    'a: 'c,
    'b: 'c,
{
    if a > b {
        a
    } else {
        b
    }
}

fn main() {
    let a = 1;
    let ar = &a;
    {
        let b = 2;
        let br = &b;
        let cr = largest(ar, br);
        println!("{}", cr);
    }
}

类型别名

rust
type MyResult<T> = Result<T, u32>;

动态类型

Rust 中有的类型不能在编译器确定其内存大小,需要使用胖指针包装成内存大小确定的类型。

切片

rust
fn main() {
    let l1 = [1, 2, 3];
    let mut r: &[i32] = &l1;
    println!("{}", r.len());
    let l2 = [1, 2, 3, 4];
    r = &l2;
    println!("{}", r.len());
}

特征对象

rust
trait Animal {
    fn print_name(&self);
}

struct Cat;
impl Animal for Cat {
    fn print_name(&self) {
        println!("Cat");
    }
}

struct Dog;
impl Animal for Dog {
    fn print_name(&self) {
        println!("Dog");
    }
}

fn main() {
    let mut v: Vec<Box<dyn Animal>> = Vec::new();
    v.push(Box::new(Cat {}));
    v.push(Box::new(Dog {}));
    for a in v {
        a.print_name();
    }
}

不是所有的特征都支持特征对象,必须遵守一系列的规则才行。这些规则被称为对象安全规则。

模块

rust
mod internal_mod {
    // pub 表示可以被模块外部代码访问
    // pub 可以修饰模块、函数、结构体、枚举、字段、方法等
    pub fn print_hello() {
        do_print_hello();
    }

    // 默认都是不能被模块外部代码访问
    fn do_print_hello() {
        println!("hello");
    }
}

mod external_mod;
/* external_mod.rs 或者 external_mod/mod.rs
pub fn print_hello() {
    do_print_hello();
}
fn do_print_hello() {
    println!("hello");
}
*/

use internal_mod::print_hello;

fn main() {
    internal_mod::print_hello();
    external_mod::print_hello();

    print_hello(); // this is internal!
}