第三章 Rust 基础语法

官网:https://www.rust-lang.org/
跟着例子学 Rust:https://tourofrust.com/00_zh-cn.html
Rust 基础入门指南:为 Solana 合约学习铺路 https://learnblockchain.cn/column/113
菜鸟 Rust 教程:https://www.runoob.com/rust/rust-tutorial.html

一、输出到终端

fn main() {
    // 输出小图标 => 
    println!("你好,🦀!"); // 你好,🦀!
    // 占位符输出
    let x = 12;
    println!("x is {}", x); // x is 12
    // 多占位符输出
    println!("x is {},{}", x, x); // x is 12,12
    // 指定index占位符输出
    println!("x is {0},{0}", x); // x is 12,12
    // 输出占位符(转义{})
    println!("{{}}"); // {}
}

二、变量与常量

类型推断

Rust 是强类型语言,但具有自动判断变量类型的能力。变量的定义使用 let

let a = 1; // 等于 let a: i32 = 1

常用数据类型如下:

fn main() {
    // 整数:8位 ~ 128位(8、16、32、64、128)*(有符号i、无符号u)
    // 默认为 i:32
    let a: i128 = -42; // 有符号整数
    let b: u32 = 42; // 无符号整数

    // 浮点数:32位、64位 默认为 f64
    let c = 2.0; // f64
    let d: f32 = 3.0; // f32

    // 布尔数
    let e = true;
    let f: bool = false;

    // 字符类型:4字节(32位)
    // 采用 Unicode 编码,可以存储更广泛的字符,如表情、数学符号
    // 而字符串 String 是多个字符的组合,组成的字符长度可变,每个字符可能占 1-4 字节(UTF-8 编码)
    let g: char = 'A';
    let h: char = '😃';
    let r: char = 'Ω';
    let j: char = '∑';

    // 元组
    // 复合类型,可以将不同类型的多个值组合进一个复合类型
    // 结合函数,返回多个不同类型的返回值,很好用
    let k: (i32, f32, u8) = (100, 6.4, 1);
    // 可以使用 点. 来访问元组的值;也可以用变量接收的方式
    let k1 = k.0;
    let k2 = k.1;
    let (x, y, z) = k;
    println!("y is {}", y);

    // 数组
    // 与元组不同,数组的值必须是同一类型
    let a = [1, 2, 3, 4, 5];
    let b = ["January", "February", "March"];
    let c: [i32; 5] = [1, 2, 3, 4, 5];
    let d = [3; 5]; // 等同于 let d = [3, 3, 3, 3, 3];
    // 数组访问
    let first = a[0];
    let second = a[1];

    a[0] = 123; // 错误:数组 a 不可变,元素不可重新赋值
    let mut a = [1, 2, 3]; // 可变数组
    a[0] = 4; // 正确
}

可变性与类型匹配

fn main() {
    let a = 1; // 默认不可变
    a = 2; // 失败
    let mut b = 10; // mut 修饰为可变变量
    b = 20; // 成功
    b = 20.0; // 失败,类型不匹配
    b = "123"; // 失败,类型不匹配
    println!("Hello, {},{}", a,b)
}

常量

常量的定义使用 const

const A:i32 = 123;

fn main() {
    println!("a is {}", A)
}

三、函数

基本格式:fn <函数名> ( <参数> ) -> 返回类型 <函数体>,如果没有返回,则不需要“-> 返回类型”

fn main() {
    // 函数调用方式
    let return_value = has_return_value(1, 2);
    println!("has_return_value is {}", return_value);
    has_no_return_value(1, 2);
    has_code_block();
    inner_function();
    
    // 函数嵌套
    fn inner_function() {
        println!("inner_function")
    }
}

// 测试返回值,Rust 中定义函数如果需要具备参数必须声明参数名称和类型
fn has_return_value(a: i32, b: i32) -> i32 {
    // 以下三种方式相同
    return a + b;
    // return a + b 不带分号
    // a + b 不带分号
}

// 测试没有返回值
fn has_no_return_value(a: i32, b: i32) {
    println!("has_no_return_value is {}", a + b);
}

// 测试复杂的表达式块
fn has_code_block() {
    let y = {
        let x = 1;
        x + 2 // 表达式块{}中的返回表达式必须不带分号,不可以使用return关键词,函数的任何地方使用了 return 关键词,就表示函数结束
    };

    println!("has_code_block is {}", y);
}

四、流程控制

条件语句

if 语句不仅可以用于条件判断,还可以作为表达式返回值

fn main() {
    let a = 12;
    let b;
    // if 语句不需要小括号,Rust 中的条件表达式必须是 bool 类型
    if a > 0 {
        b = 1;
    } else if a < 0 {
        b = -1;
    } else {
        b = 0;
    }
    println!("b is {}", b);

    // 条件语句赋值
    let x = 3;
    let number = if x > 0 { 1 } else { -1 };
    println!("number 为 {}", number);
}

循环语句

for 语句通常用于遍历集合,并且比 while 更安全(避免数组越界),可以使用 continue 跳过本次迭代,break 终止循环。
while 语句在满足条件时执行循环,但可能会导致索引越界错误
loop 适用于需要手动 break 退出的情况,可以结合 break 作为表达式返回值

fn main() {
    // while 循环
    let mut number = 1;
    while number != 4 {
        println!("{}", number);
        number += 1;
    }

    // for 循环
    let a = [10, 20, 30, 40, 50];
    // 迭代器访问
    for i in a.iter() {
        println!("值为 : {}", i);
    }
    // 索引访问
    for i in 0..5 {
        println!("a[{}] = {}", i, a[i]);
    }

    // loop无限循环
    let s = ['R', 'U', 'N', 'O', 'O', 'B'];
    let mut i = 0;
    loop {
        let ch = s[i];
        if ch == 'O' {
            break;
        }
        println!("\'{}\'", ch);
        i += 1;
    }
    // loop获取返回值
    let location = loop {
        let ch = s[i];
        if ch == 'O' {
            // 返回值
            break i;
        }
        i += 1;
    };
    println!(" \'O\' 的索引为 {}", location);
}

五、模式匹配

match 匹配

match 语句必须覆盖所有可能情况,因此 _ 用于匹配未列出的情况。

fn main() {
    let day = "Monday";
    
    match day {
        "Monday" => println!("新的一周开始了!"),
        "Friday" => println!("周五快乐!"),
        _ => println!("只是普通的一天"),
    }
}

结构体解构匹配

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 5, y: -3 };
    
    match point {
        Point { x: 0, y: 0 } => println!("原点"),
        Point { x, y } if y > 0 => println!("({},{}) 位于上半平面", x, y),
        Point { x, y } => println!("点的坐标: ({},{})", x, y),
    }
}

枚举匹配

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

fn traffic_light_action(light: TrafficLight) {
    match light {
        TrafficLight::Red => println!("请停车!"),
        TrafficLight::Yellow => println!("准备起步!"),
        TrafficLight::Green => println!("可以通行!"),
    }
}

fn main() {
    let light = TrafficLight::Green;
    traffic_light_action(light);
}

if let 简化模式匹配

fn main() {
    let some_value = Some(42);
    
    if let Some(x) = some_value {
        println!("匹配到的值: {}", x);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容