| name | rust-fundamentals |
| description | Rust 语言基础技能,覆盖 Tauri 开发中常用的 Rust 核心概念。
触发场景:
- 遇到 Rust 编译错误(所有权/借用/生命周期)
- 需要理解 Rust 语法和概念
- 需要编写 Rust 数据结构和函数
- 需要使用 Rust 异步编程
触发词: Rust、所有权、借用、生命周期、编译错误、borrow、move、lifetime、async、trait
|
Rust 基础(Tauri 开发必备)
核心概念速查
所有权规则
let s1 = String::from("hello");
let s2 = s1;
let s1 = String::from("hello");
let s2 = s1.clone();
println!("{} {}", s1, s2);
let x = 5;
let y = x;
println!("{} {}", x, y);
引用与借用
fn print_length(s: &str) {
println!("长度: {}", s.len());
}
fn append(s: &mut String) {
s.push_str(" world");
}
let mut s = String::from("hello");
print_length(&s);
append(&mut s);
在 Tauri Command 中的应用
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
#[tauri::command]
fn create_greeting(name: String) -> String {
format!("Hello, {}!", name)
}
常用类型
Option 和 Result
fn find_user(id: u32) -> Option<User> {
if id == 1 { Some(User { name: "Alice".into() }) }
else { None }
}
match find_user(1) {
Some(user) => println!("{}", user.name),
None => println!("未找到"),
}
let name = find_user(1).map(|u| u.name).unwrap_or("未知".into());
fn parse_number(s: &str) -> Result<i32, String> {
s.parse::<i32>().map_err(|e| e.to_string())
}
fn process(input: &str) -> Result<i32, String> {
let num = parse_number(input)?;
Ok(num * 2)
}
结构体和枚举
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
id: u32,
name: String,
email: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum Status {
Active,
Inactive,
Pending,
}
impl User {
fn new(id: u32, name: String) -> Self {
Self { id, name, email: None }
}
fn display_name(&self) -> &str {
&self.name
}
}
异步编程
async fn fetch_data(url: &str) -> Result<String, String> {
reqwest::get(url)
.await
.map_err(|e| e.to_string())?
.text()
.await
.map_err(|e| e.to_string())
}
#[tauri::command]
async fn async_operation() -> Result<String, String> {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok("完成".into())
}
#[tauri::command]
async fn parallel_fetch() -> Result<Vec<String>, String> {
let (r1, r2) = tokio::join!(
fetch_data("https://api1.example.com"),
fetch_data("https://api2.example.com"),
);
Ok(vec![r1?, r2?])
}
线程安全与 Mutex
use std::sync::Mutex;
struct AppState {
counter: Mutex<u32>,
items: Mutex<Vec<String>>,
}
#[tauri::command]
fn increment(state: tauri::State<'_, AppState>) -> Result<u32, String> {
let mut counter = state.counter.lock().map_err(|e| e.to_string())?;
*counter += 1;
Ok(*counter)
}
常见编译错误速查
| 错误信息 | 原因 | 解决方法 |
|---|
value moved here | 所有权已转移 | 使用 clone() 或引用 & |
cannot borrow as mutable | 不可变引用存在时不能可变借用 | 调整借用顺序 |
lifetime may not live long enough | 引用的生命周期不足 | 添加生命周期标注或 clone |
the trait bound is not satisfied | 类型未实现所需 trait | 添加 derive 宏或手动实现 |
cannot move out of borrowed content | 试图从引用中移出所有权 | 使用 .clone() 或 .to_owned() |
常见错误
| 错误做法 | 正确做法 |
|---|
到处 clone() 解决编译错误 | 先理解所有权,必要时才 clone |
unwrap() 处理 Result | 使用 ? 或 map_err |
| 不用 Mutex 包裹共享状态 | Tauri State 中的可变数据必须 Mutex |
| 忽略 Rust 编译器建议 | 编译器建议通常是正确的 |