rust语法
# 背景
在做ai-agent项目的时候,公司采用pi-mono + Electron 。 看到一个 pi-rs + Tauri 的项目,运行极低的内存。
顺便将这个项目作为自己的项目来使用,避开公司的内容。
以下就是需要rust语法的过程
# 语法特性
- 很多语法类似于 JavaScript,go
- 他也有 泛型。
- 面向对象: 封装默认私有,用组合优于继承,有特性实现多态
# 注释
// 这是第一种注释方式
/* 这是第二种注释方式 */
/*
* 多行注释
* 多行注释
* 多行注释
*/
/// 文档注释
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 基础数据类型
# 整数型(Integer)
位长度 有符号 无符号 8-bit i8 u8 16-bit i16 u16 32-bit i32 u32 64-bit i64 u64 128-bit i128 u128
# 浮点数型(Floating-Point)
32 位浮点数(f32)和 64 位浮点数(f64)。
默认情况下,64.0 将表示 64 位浮点数
# 布尔型
bool
# 字符型
char
# 字符串
默认utf-8编码,推荐用 String::from("你好") 定义;
# 元组
用一对 ( ) 包括的一组数据,可以包含不同种类的数据。
let tup: (i32, f64, u8) = (500, 6.4, 1); let b = tup.0
# 数组
用一对 [ ] 包括的同类型数据
let a = [1, 2, 3, 4, 5];
# Slice(切片)
go一样的切片,对数据值的部分引用。 可以理解为数组的sub
fn main() {
let s = String::from("broadcast");
let part1 = &s[3..5]; // x..y 表示 [x, y) 的数学含义
let part1 = &s[..5]; // 等价于 0..y
let part1 = &s[3..]; // 等价于位置 3 到数据结束
let part1 = &s[..]; // 等价于位置 0 到结束
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 向量 (Vec)
向量的使用方式类似于列表(List)
let vector: Vec<i32> = Vec::new(); // 创建类型为 i32 的空向量
let vector = vec![1, 2, 4, 8]; // 通过数组创建向量
vector[4] // 会返回错误
vector.get(0) // 会返回 None
1
2
3
4
2
3
4
# 映射表(Map)
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("color", "red");
map.insert("size", "10 m^2");
println!("{}", map.get("color").unwrap());
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 迭代器(Iterator)
- 将数据处理过程与数据本身分离,使代码更清晰、更易读、更易维护。
- 迭代器的设计考虑了安全性、性能和表达力,是 Rust 语言的核心特性之一。通过迭代器,Rust 程序员可以写出既安全又高效的代码。
# 变量
- Rust 是强类型语言,用let声明
- 默认情况下,Rust 中的变量是不可变的
- 使用 mut 关键字声明为可变变量
- 数据类型会自动推断
- 同一变量可以多次声明 (重影):
let a = 123; let a = 456;
# 常量
- const 声明
- 不可多次声明
let a = 123;
let mut a = 456;
const a: i32 = 123;
1
2
3
2
3
# 函数
- fn <函数名> ( <参数> ) <函数体>
- 函数的返回类型通过箭头符号 -> 指定
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
1
2
3
2
3
# 控制流
- if 表达式: if true {}else{}
- loop 无限循环: loop{}
- while 循环: while true {}
- for 循环: for number in 1..4 {}
- 三元条件运算表达式: let number = if a > 0 { 1 } else { -1 };
- match: 类似于 switch 语句。其他情况用 _ 表示
# 结构体 (Structs)
- go也叫结构体,所以得用引用来实现继承。
- 用struct关键词定义
- 单元结构体:无需任何成员。如:
struct UnitStruct;
# 元组结构体
struct Color(u8, u8, u8);
let black = Color(0, 0, 0);
println!("black = ({}, {}, {})", black.0, black.1, black.2);
1
2
3
2
3
# 结构体方法
- 结构体方法的第一个参数必须是 &self,不需声明类型,因为 self 不是一种风格而是关键字。 (类似Python)
- impl 来定义
- 结构体关联函数: 它在 impl 块中却没有 &self 参数。类似于java静态函数。
- 结构体 impl 块可以写几次,效果相当于它们内容的拼接!
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
impl Rectangle {
fn create(width: u32, height: u32) -> Rectangle {
Rectangle { width, height }
}
}
fn main() {
// let rect1 = Rectangle { width: 30, height: 50 };
let rect = Rectangle::create(30, 50);
println!("rect1's area is {}", rect1.area());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 枚举 (Enums) 和 模式匹配 (match)
- 枚举可以是不同数据类型
- match 是 Rust 中强大的控制流工具,类似于 switch 语句。
fn main() {
// 你需要描述两种书的不同属性(纸质书有索书号,电子书只有 URL)
enum Book {
Papery {index: u32},
Electronic {url: String},
}
let book = Book::Papery{index: 1001};
let ebook = Book::Electronic{url: String::from("url...")};
// switch 语句
match book {
Book::Papery { index } => {
println!("Papery book {}", index);
},
Book::Electronic { url } => {
println!("E-book {}", url);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 错误处理
- 特殊的枚举: Result<T, E>
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("Division by zero"))
} else {
Ok(a / b)
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# Option处理
- rust 彻底不允许空值 null 的存在。
- Null 特殊处理
fn get_element(index: usize, vec: &Vec<i32>) -> Option<i32> {
if index < vec.len() {
Some(vec[index]) // 代表有值
} else {
None // 代表null值
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 所有权
# 所有权规则:
- Rust 中的每个值都有一个所有者。
- 每个值在任意时刻只能有一个所有者。
- 当所有者超出作用域时,值会被删除。
# 内存和分配
- 在变量范围结束的时候,Rust 编译器自动添加了调用释放资源函数的步骤。
- 变量的值被当作参数传入函数,就已经释放啦。
# 借用 (borrowing)
- 借用允许引用数据而不获取所有权,通过 & 符号实现。
- 对于c就是指针。
- 可变引用不允许多重引用
- 不可变引用可以多重引用
# 引用 (reference)
生命周期标注用 'a 等来表示,但常见的情况下,编译器会自动推导。
# 组织管理
- Cargo 就是java中的maven。
- 包:一个Cargo.toml工程就是一个包。
- "箱"是二进制程序文件或者库文件,存在于"包"中。
- 模块(Module): mod关键字定义,可以理解为java中的类
- 绝对路径调用 从crate 关键字开始描述:
crate::nation::government::govern(); - 相对路径调用 从 self 或 super 或 直接省略 :
nation::government::govern(); - 私有权限: 默认情况私有,只能 其平级的位置或下级的位置才能访问。
- 公共权限: 需要使用 pub 关键字。
- 每个rs文件: 就是默认就是一个文件名的mod
- use导入:
use crate::nation::govern as nation_govern; let a = nation_govern() - 标准库: https://doc.rust-lang.org/stable/std/all.html
# 错误处理
- 可恢复错误: Result<T, E> 枚举类实现。 作返回值来进行异常表达
- 不可恢复错误: 使用 panic! 宏来处理。 抛异常中断程序
- Result 类提供了两个办法:unwrap() 和 expect(message: &str) 转成 不可恢复错误
- 可恢复的错误的传递: ? 操作符将同类的 Err 直接传递出去
- Result:kind 方法,获得对应类型进行更细化的match分支处理
# 特性
- 接近于 Java 中的接口(Interface)
- 用trait 表示
- impl <特性名> for <所实现的类型名>
- 同一个类可以实现多个特性,每个 impl 块只能实现一个。
- 默认特性: 就是默认实现类的实现方法。
- 特性可做函数的参数。
- 特性作类型表示时如果涉及多个特性,可以用 + 符号表示
- 做返回值: 使用 ‘impl Descriptive’ 标记
trait Descriptive {
fn describe(&self) -> String {
String::from("[Object]")
}
}
struct Person {
name: String,
age: u8
}
impl Descriptive for Person {
fn describe(&self) -> String {
format!("{} {}", self.name, self.age)
}
}
fn main() {
let cali = Person {
name: String::from("Cali"),
age: 24
};
println!("{}", cali.describe());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 宏
- 在编译时生成代码的强大工具,它允许你在编写代码时创建自定义语法扩展。
- 和c语言的宏类似。
# 声明式宏
使用 macro_rules! 关键字进行定义,它们被称为 "macro_rules" 宏。这种宏的定义是基于模式匹配的,可以匹配代码的结构并根据匹配的模式生成相应的代码。这样的宏在不引入新的语法结构的情况下,可以用来简化一些通用的代码模式。
# 过程宏
一种更为灵活和强大的宏,允许在编译时通过自定义代码生成过程来操作抽象语法树(AST)。过程宏在功能上更接近于函数,但是它们在编写和使用上更加复杂。
- 派生宏(Derive Macros):使用 #[derive(Debug)] 声明 用于自动实现trait(比如Copy、Debug)的宏。
- 属性宏(Attribute Macros):用于在声明上附加额外的元数据,如#[derive(Debug)]。
# 闭包
- 能够捕获其定义环境变量的匿名函数。
- JavaScript 的闭包类似。
# 智能指针
- Rust 的智能指针提供了一种安全和自动化的方式来管理内存和共享所有权。
- 他和C++ 的智能指针最为相似。
- 当需要在堆上分配内存时,使用 Box
。 - 当需要多处共享所有权时,使用 Rc
或 Arc 。 - 当需要内部可变性时,使用 RefCell
。 - 当需要线程安全的共享所有权时,使用 Arc
。 - 当需要互斥访问数据时,使用 Mutex
。 - 当需要读取-写入访问数据时,使用 RwLock
。 - 当需要解决循环引用问题时,使用 Weak
。
# 异步编程 async/await
- 类似JavaScript
- Future:Future 是 Rust 中表示异步操作的抽象。
- async 关键字用于定义一个异步函数,它返回一个 Future。
- await 关键字用于暂停当前 Future 的执行,直到它完成。
- rust的 文件与IO (opens new window) : tokio::fs::File 类库
- 并发编程 | 异步通道 (opens new window): tokio::sync::mpsc,允许在异步任务之间传递消息
// 异步任务执行函数
async fn execute_async_task() {
// 调用异步任务,并等待其完成
let result = async_task().await?; // 这里和js语法不一样。 ? 传播错误
// 输出结果
println!("Async task result: {}", result);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 总结常见运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
.. | 范围(不含右端) | 0..5 产生 0 到 4 |
..= | 范围(含右端) | 0..=5 产生 0 到 5 |
as | 类型转换 | 5 as f32 |
? | 错误传播(在 Result 中) | some()?; |
* | 解引用 | *ptr |
& | 取引用 | &x |
ref | 绑定为引用 | let ref y = x; |
# 参考资料
编辑 (opens new window)
上次更新: 2026/04/20, 09:32:44