任何一种语言都有自身独特的语法,要想上手编程,还是得先掌握其语法,本文介绍 rust 常见的语法特性,帮助你快速上手 rust 编程。
变量和常量
在 rust 中,变量使用 let
关键字声明,默认是不可变的,如果需要改变变量的值,需要使用 mut
关键字声明可变变量。
let site = "https://kelen.cc";site = "https://www.kelen.cc" // 报错:error: cannot assign twice to immutable variablelet mut site2 = "https://kelen.cc";site2 = "https://www.kelen.cc"; // 正确
常量使用 const
关键字声明,必须指定类型,常量定义的值不能改变。
const MAX_POINTS: u32 = 100_000;const PI: f64 = 3.1415926;
数据类型
rust 有两类数据类型:标量类型和复合类型。
标量类型
标量类型有整数,浮点数,布尔值,字符类型。
- 整数有四种基本类型:
位数 | 有符号 | 无符号 |
---|---|---|
8 位 | i8 | u8 |
16 位 | i16 | u16 |
32 位 | i32 | u32 |
64 位 | i64 | u64 |
128 位 | i128 | u128 |
arch | isize | usize |
其中
isize
和usize
是针对当前机器位数的,比如 64 位机器,isize
和usize
都是i64
和u64
。
浮点数有两种基本类型:
f32
和f64
。布尔值有两种值:
true
和false
。字符类型是单引号括起来的字符,
char
类型。
let x: i32 = 42;let x1 = 42; // 默认是 i32 类型let y: f64 = 3.14;let z: char = '😻'let t: bool = true;
复合类型
复合类型有元组和数组。
- 元组是将多个不同类型的值组合在一起。
- 数组是将多个相同类型的值组合在一起。
let tup: (i32, f64, u8) = (500, 6.4, 1); // 元组let (x, y, z) = tup; // 解构元组let x: i32 = tup.0;let y: f64 = tup.1;let z: u8 = tup.2;let a: [i32; 5] = [1, 2, 3, 4, 5]; // 数组let b = [3; 5]; // [3, 3, 3, 3, 3]let first = a[0];let second = a[1];let third = a[2];let non_exist = a[10]; // 编译报错:error: index out of bounds: the len is 5 but the index is 10
数据结构
- 结构体
结构体是用户自定义的数据类型,可以包含多个字段,每个字段可以有不同的数据类型。
struct Site { name: String, url: String,}// 创建结构体实例let site1 = Site { name: String::from("kelen"), url: String::from("https://www.kelen.cc"),};// 访问结构体字段println!("{}", site1.name);println!("{}", site1.url);
- 元组结构体
元组结构体是另一种自定义数据类型,它将多个不同类型的值组合在一起,类似于元组。
struct Color(i32, i32, i32);let black = Color(0, 0, 0);println!("{}", black.0);
- 单元结构体
单元结构体没有字段,只有一个名字。类似于其他编程语言中的空类或空元组。单元结构体可以用来定义一个类型,但不与任何数据关联。
单元结构体的一个实际应用是当需要一个类型来表示某个特定的状态或概念,而不需要携带任何额外的数据时。
例如,可以使用单元结构体来实现枚举类型的变体。
enum IpAddrKind { V4, // 单元结构体变体 V6, // 单元结构体变体}fn main() { let four = IpAddrKind::V4; let six = IpAddrKind::V6; route(four); route(six);}fn route(ip_kind: IpAddrKind) { match ip_kind { IpAddrKind::V4 => println!("处理 IPv4 路由"), IpAddrKind::V6 => println!("处理 IPv6 路由"), }}
- 枚举
枚举用 enum
关键字定义,每个枚举变体可以有不同的数据类型。
// 定义一个名为 `Drink` 的枚举,它有四个变体,每个变体关联一个中文字符串。enum Drink { Tea(String), Coffee(String), Juice(String), Water(String),}// 为枚举实现一个方法,用于打印出饮品种类和描述。impl Drink { fn print_description(&self) { match self { Drink::Tea(desc) => println!("饮品: 茶 - {}", desc), Drink::Coffee(desc) => println!("饮品: 咖啡 - {}", desc), Drink::Juice(desc) => println!("饮品: 果汁 - {}", desc), Drink::Water(desc) => println!("饮品: 水 - {}", desc), } }}fn main() { // 创建 `Drink` 枚举的不同实例,每个实例携带不同的中文描述。 let tea = Drink::Tea(String::from("清香四溢的绿茶")); let coffee = Drink::Coffee(String::from("浓郁香醇的黑咖啡")); let juice = Drink::Juice(String::from("新鲜榨取的橙汁")); let water = Drink::Water(String::from("纯净的矿泉水")); // 调用每个实例的方法,打印描述。 tea.print_description(); coffee.print_description(); juice.print_description(); water.print_description();}
函数
函数使用 fn
关键字声明,参数类型必须指定,返回值类型可以省略,rust 会根据函数体最后一行的表达式推断返回值类型。
fn add(x: i32, y: i32) -> i32 { x + y}// orfn printSum(x: i32, y: i32) { println!("x + y = {}", x + y);}
控制流
rust 控制流有:if 表达式,loop 循环,while 循环,for 循环,match 表达式,if let 语句,
// if 表达式let number = 3;if number < 5 { println!("值小于 5");} else { println!("值大于等于 5");}// loop 循环let mut counter = 0;loop { counter += 1; if counter == 10 { break; }}// while 循环let mut number = 3;while number != 0 { println!("{}!", number); number -= 1;}
match 表达式是 Rust 中的强大的模式匹配工具,可以用来匹配不同的模式,类似于 switch 语法;
let number = 3;match number { 1 => println!("One"), 2 => println!("Two"), 3 => println!("Three"), _ => println!("Other"),}// 匹配函数返回的值或者错误fn divide(x: i32, y: i32) -> Result<i32, &'static str> { if y == 0 { return Err("分母不能为 0"); } Ok(x / y)}let result = divide(10, 2);match result { Ok(value) => println!("结果是:{}", value), Err(err) => println!("错误:{}", err),}
if let
语句是 if 的语法糖,可以简化匹配表达式的写法,只匹配一个模式。
let some_value = Some(3);if let Some(value) = some_value { println!("value is {}", value);}
总结
rust 的语法特性很多,这里只介绍一些常用的语法特性,希望对大家有所帮助。如果你想深入了解 rust,可以查看官方文档,或者阅读《Rust 编程之道》这本书,这本书是我学习 rust 时的参考书籍,非常推荐。