Skip to content

Rust 语言基础

引言

Rust 是一门现代的系统编程语言,以其内存安全、并发性和性能而闻名。与 Python 不同,Rust 编译成本地代码,提供了接近 C/C++ 的性能,同时提供了更安全的编程模型。对于 LeBot 这样的实时机器人系统,Rust 的低级控制能力和高性能使其成为一个理想的选择。

Rust 的基本概念

为什么使用 Rust?

  1. 内存安全:在编译时检查内存错误,避免运行时崩溃
  2. 无垃圾回收:性能更好,更可预测
  3. 并发安全:防止数据竞争
  4. 零成本抽象:提供高级特性而不牺牲性能
  5. 跨平台:可以编译到多个目标平台,包括 ARM 嵌入式系统

安装 Rust

在 Linux 或 macOS 上安装 Rust:

bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

验证安装:

bash
rustc --version
cargo --version

第一个 Rust 程序

创建一个新的 Rust 项目:

bash
cargo new hello_robot
cd hello_robot

编辑 src/main.rs

rust
fn main() {
    println!("Hello, LeBot!");
}

编译并运行:

bash
cargo run

基本语法

变量和可变性

Rust 中的变量默认是不可变的。

rust
fn main() {
    // 不可变变量
    let x = 5;
    // x = 6;  // 错误:不能修改不可变变量
    
    // 可变变量
    let mut y = 10;
    y = 20;  // 正确
    println!("y = {}", y);
    
    // 常量(必须指定类型)
    const MAX_SPEED: i32 = 1000;
    println!("MAX_SPEED = {}", MAX_SPEED);
    
    // 变量遮蔽(shadowing)
    let x = 5;
    let x = x + 1;  // 创建新变量,遮蔽前一个 x
    let x = x * 2;
    println!("x = {}", x);  // 输出 12
}

数据类型

Rust 是静态类型语言,但通常可以推断类型。

rust
fn main() {
    // 整数类型
    let a: i32 = 5;           // 32 位有符号整数
    let b: u32 = 10;          // 32 位无符号整数
    let c: i64 = 1000i64;     // 64 位整数
    
    // 浮点数
    let x: f32 = 3.14;
    let y: f64 = 2.71828;     // f64 是默认浮点类型
    
    // 布尔值
    let is_moving: bool = true;
    
    // 字符
    let ch: char = 'L';
    
    // 字符串
    let s1: &str = "hello";   // 字符串切片
    let mut s2: String = String::from("hello");
    s2.push_str(" robot");
    
    println!("{}, {}, {}", s1, s2, ch);
}

函数

rust
// 带返回值的函数
fn add(x: i32, y: i32) -> i32 {
    x + y  // 注意:没有分号,这是返回值
}

// 无返回值的函数
fn print_motor_status(motor_id: i32, speed: f32) {
    println!("Motor {} speed: {}", motor_id, speed);
}

// 函数可以作为参数传递
fn apply_operation<F>(x: i32, y: i32, op: F) -> i32 
where
    F: Fn(i32, i32) -> i32
{
    op(x, y)
}

fn main() {
    let result = add(5, 3);
    println!("5 + 3 = {}", result);
    
    print_motor_status(0, 100.5);
    
    // 使用闭包作为函数参数
    let multiply = |x: i32, y: i32| x * y;
    let result = apply_operation(4, 5, multiply);
    println!("4 * 5 = {}", result);
}

控制流

rust
fn main() {
    // if 表达式
    let motor_speed = 500;
    
    if motor_speed > 1000 {
        println!("Speed too high");
    } else if motor_speed > 500 {
        println!("Speed is high");
    } else {
        println!("Speed is normal");
    }
    
    // 作为表达式的 if
    let status = if motor_speed > 0 { "moving" } else { "stopped" };
    println!("Robot is {}", status);
    
    // loop 循环
    let mut count = 0;
    loop {
        count += 1;
        if count == 5 {
            break;
        }
        println!("Count: {}", count);
    }
    
    // while 循环
    let mut n = 1;
    while n <= 5 {
        println!("n = {}", n);
        n += 1;
    }
    
    // for 循环
    for i in 1..=5 {  // 1 到 5 包含 5
        println!("i = {}", i);
    }
    
    // 遍历数组
    let motor_ids = [0, 1, 2, 3];
    for &id in motor_ids.iter() {
        println!("Motor ID: {}", id);
    }
}

所有权系统

所有权是 Rust 最独特的特性。它决定了内存如何管理。

所有权规则

  1. Rust 中的每个值都有一个所有者
  2. 同时只能有一个所有者
  3. 当所有者离开作用域时,值被释放
rust
fn main() {
    // 字符串所有权转移
    let s1 = String::from("hello");
    let s2 = s1;  // s1 的所有权转移给 s2
    
    // println!("{}", s1);  // 错误:s1 不再拥有这个值
    println!("{}", s2);    // 正确
    
    // 复制(对于简单类型)
    let x = 5;
    let y = x;  // x 被复制给 y,x 仍然可用
    println!("{}, {}", x, y);  // 都正确
}

借用(References)

借用允许你使用一个值而不取得其所有权。

rust
fn get_length(s: &String) -> usize {
    s.len()  // 使用引用,不能修改
}

fn update_string(s: &mut String) {
    s.push_str(" updated");  // 可变引用,可以修改
}

fn main() {
    let mut s = String::from("hello");
    
    // 不可变借用
    let len = get_length(&s);
    println!("Length: {}, String: {}", len, s);
    
    // 可变借用
    update_string(&mut s);
    println!("Updated: {}", s);
    
    // 规则:要么有一个可变引用,要么有多个不可变引用
    let r1 = &s;
    let r2 = &s;
    // let r3 = &mut s;  // 错误:不能同时有可变和不可变引用
    
    println!("{}, {}", r1, r2);
    
    let r3 = &mut s;  // 现在可以了,因为 r1 和 r2 不再被使用
    r3.push_str("!");
}

结构体

结构体允许你创建自定义数据类型。

rust
// 定义结构体
#[derive(Debug, Clone)]  // 派生 Debug 和 Clone trait
struct Motor {
    id: u32,
    max_speed: f32,
    current_speed: f32,
}

impl Motor {
    // 关联函数(类似构造函数)
    fn new(id: u32, max_speed: f32) -> Motor {
        Motor {
            id,
            max_speed,
            current_speed: 0.0,
        }
    }
    
    // 方法
    fn set_speed(&mut self, speed: f32) {
        self.current_speed = speed.max(-self.max_speed).min(self.max_speed);
    }
    
    fn get_speed(&self) -> f32 {
        self.current_speed
    }
    
    fn stop(&mut self) {
        self.current_speed = 0.0;
    }
}

fn main() {
    let mut motor = Motor::new(0, 1000.0);
    
    motor.set_speed(500.0);
    println!("Motor {} speed: {}", motor.id, motor.get_speed());
    
    motor.stop();
    println!("Stopped: {}", motor.get_speed());
    
    // 打印调试信息(使用 Debug trait)
    println!("{:#?}", motor);
}

元组结构体

rust
struct Point(f32, f32, f32);
struct Color(u8, u8, u8);

fn main() {
    let position = Point(1.0, 2.0, 3.0);
    println!("Position: ({}, {}, {})", position.0, position.1, position.2);
    
    let red = Color(255, 0, 0);
    println!("RGB: ({}, {}, {})", red.0, red.1, red.2);
}

枚举

枚举允许你定义一个类型,它可以是几个变体中的一个。

rust
// 定义枚举
enum RobotState {
    Idle,
    Moving,
    Charging,
    Error(String),  // 带关联数据的变体
}

// 定义可能的方向
enum Direction {
    North,
    South,
    East,
    West,
}

impl Direction {
    fn angle(&self) -> f32 {
        match self {
            Direction::North => 90.0,
            Direction::South => 270.0,
            Direction::East => 0.0,
            Direction::West => 180.0,
        }
    }
}

fn main() {
    let mut robot_state = RobotState::Idle;
    
    // 匹配枚举
    match robot_state {
        RobotState::Idle => println!("Robot is idle"),
        RobotState::Moving => println!("Robot is moving"),
        RobotState::Charging => println!("Robot is charging"),
        RobotState::Error(msg) => println!("Error: {}", msg),
    }
    
    // 修改状态
    robot_state = RobotState::Error("Motor malfunction".to_string());
    
    // 使用 if let 处理单个模式
    if let RobotState::Error(msg) = robot_state {
        println!("Error detected: {}", msg);
    }
    
    // 枚举方法
    let direction = Direction::East;
    println!("East angle: {}", direction.angle());
}

Trait

Trait 类似于其他语言中的接口。

rust
// 定义 Trait
trait Actuator {
    fn activate(&mut self);
    fn deactivate(&mut self);
    fn get_status(&self) -> String;
}

// 实现 Trait 的结构体
struct ElectricMotor {
    id: u32,
    active: bool,
}

impl Actuator for ElectricMotor {
    fn activate(&mut self) {
        self.active = true;
        println!("Electric motor {} activated", self.id);
    }
    
    fn deactivate(&mut self) {
        self.active = false;
        println!("Electric motor {} deactivated", self.id);
    }
    
    fn get_status(&self) -> String {
        format!("Motor {} is {}", self.id, if self.active { "active" } else { "inactive" })
    }
}

struct ServoMotor {
    id: u32,
    active: bool,
    angle: f32,
}

impl Actuator for ServoMotor {
    fn activate(&mut self) {
        self.active = true;
        println!("Servo motor {} activated", self.id);
    }
    
    fn deactivate(&mut self) {
        self.active = false;
        println!("Servo motor {} deactivated", self.id);
    }
    
    fn get_status(&self) -> String {
        format!("Servo {} is {} at {} degrees", self.id, 
                if self.active { "active" } else { "inactive" }, self.angle)
    }
}

// 使用 Trait 对象进行多态
fn control_actuator(actuator: &mut dyn Actuator) {
    actuator.activate();
    println!("{}", actuator.get_status());
    actuator.deactivate();
}

fn main() {
    let mut electric = ElectricMotor { id: 0, active: false };
    let mut servo = ServoMotor { id: 1, active: false, angle: 0.0 };
    
    control_actuator(&mut electric);
    println!();
    control_actuator(&mut servo);
}

错误处理

Rust 没有异常,而是使用 ResultOption 类型。

rust
use std::fs;
use std::io;

// Result 类型:Ok(T) 或 Err(E)
fn read_motor_config(filename: &str) -> Result<String, io::Error> {
    fs::read_to_string(filename)
}

// Option 类型:Some(T) 或 None
fn find_motor(motors: &[u32], target: u32) -> Option<usize> {
    motors.iter().position(|&m| m == target)
}

fn main() {
    // 处理 Result
    match read_motor_config("config.txt") {
        Ok(content) => println!("Config: {}", content),
        Err(e) => println!("Error reading config: {}", e),
    }
    
    // 使用 ? 操作符(传播错误)
    if let Ok(content) = read_motor_config("config.txt") {
        println!("Successfully read config");
    }
    
    // 处理 Option
    let motors = vec![0, 1, 2, 3];
    match find_motor(&motors, 2) {
        Some(index) => println!("Motor found at index {}", index),
        None => println!("Motor not found"),
    }
    
    // 使用 if let
    if let Some(index) = find_motor(&motors, 2) {
        println!("Motor 2 is at index {}", index);
    }
    
    // 链式操作
    let result = find_motor(&motors, 2)
        .map(|idx| motors[idx])
        .filter(|&m| m > 0);
    
    match result {
        Some(motor_id) => println!("Motor ID: {}", motor_id),
        None => println!("No valid motor found"),
    }
}

泛型编程

泛型允许你编写与数据类型无关的代码。

rust
// 泛型函数
fn find_max<T: PartialOrd>(items: &[T]) -> Option<&T> {
    if items.is_empty() {
        return None;
    }
    
    let mut max = &items[0];
    for item in items.iter().skip(1) {
        if item > max {
            max = item;
        }
    }
    
    Some(max)
}

// 泛型结构体
struct Buffer<T> {
    data: Vec<T>,
    capacity: usize,
}

impl<T: Clone> Buffer<T> {
    fn new(capacity: usize) -> Buffer<T> {
        Buffer {
            data: Vec::new(),
            capacity,
        }
    }
    
    fn push(&mut self, item: T) -> Result<(), &'static str> {
        if self.data.len() >= self.capacity {
            Err("Buffer is full")
        } else {
            self.data.push(item);
            Ok(())
        }
    }
    
    fn pop(&mut self) -> Option<T> {
        self.data.pop()
    }
}

fn main() {
    // 整数最大值
    let numbers = [5, 2, 8, 1, 9, 3];
    if let Some(max) = find_max(&numbers) {
        println!("Max number: {}", max);
    }
    
    // 浮点数最大值
    let floats = [1.5, 3.2, 2.1, 4.0];
    if let Some(max) = find_max(&floats) {
        println!("Max float: {}", max);
    }
    
    // 泛型缓冲区
    let mut sensor_buffer = Buffer::new(5);
    for i in 0..5 {
        sensor_buffer.push(i as f32 * 1.5).unwrap();
    }
    println!("Buffer data: {:?}", sensor_buffer.data);
}

生命周期

生命周期确保引用在使用时有效。

rust
// 函数参数和返回值的生命周期注解
fn get_longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() > s2.len() { s1 } else { s2 }
}

// 结构体中的生命周期
struct Sensor<'a> {
    name: &'a str,
    data: Vec<f32>,
}

impl<'a> Sensor<'a> {
    fn new(name: &'a str) -> Sensor<'a> {
        Sensor {
            name,
            data: Vec::new(),
        }
    }
    
    fn add_reading(&mut self, value: f32) {
        self.data.push(value);
    }
}

fn main() {
    let s1 = "hello";
    let s2 = "world";
    let longer = get_longer(s1, s2);
    println!("Longer string: {}", longer);
    
    let sensor_name = "IMU";
    let mut sensor = Sensor::new(sensor_name);
    sensor.add_reading(9.8);
    sensor.add_reading(0.1);
    println!("Sensor: {}, readings: {:?}", sensor.name, sensor.data);
}

标准库常用组件

集合

rust
fn main() {
    // 向量(动态数组)
    let mut numbers = vec![1, 2, 3, 4, 5];
    numbers.push(6);
    
    for num in &numbers {
        println!("Number: {}", num);
    }
    
    // 哈希表
    use std::collections::HashMap;
    
    let mut motor_speeds = HashMap::new();
    motor_speeds.insert(0, 100.0);
    motor_speeds.insert(1, 200.0);
    motor_speeds.insert(2, 150.0);
    
    for (id, speed) in &motor_speeds {
        println!("Motor {} speed: {}", id, speed);
    }
    
    // 获取值
    if let Some(speed) = motor_speeds.get(&0) {
        println!("Motor 0 speed: {}", speed);
    }
    
    // 哈希集合
    use std::collections::HashSet;
    
    let mut active_motors = HashSet::new();
    active_motors.insert(0);
    active_motors.insert(1);
    active_motors.insert(3);
    
    if active_motors.contains(&0) {
        println!("Motor 0 is active");
    }
}

迭代器

rust
fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    
    // 基础迭代
    for num in &numbers {
        println!("{}", num);
    }
    
    // 映射
    let doubled: Vec<i32> = numbers.iter()
        .map(|x| x * 2)
        .collect();
    println!("Doubled: {:?}", doubled);
    
    // 筛选
    let evens: Vec<i32> = numbers.iter()
        .filter(|&x| x % 2 == 0)
        .copied()
        .collect();
    println!("Evens: {:?}", evens);
    
    // 求和
    let sum: i32 = numbers.iter().sum();
    println!("Sum: {}", sum);
    
    // 链式操作
    let result: Vec<i32> = numbers.iter()
        .filter(|&x| x > 2)
        .map(|x| x * 10)
        .collect();
    println!("Filtered and mapped: {:?}", result);
}

字符串处理

rust
fn main() {
    // 字符串字面量
    let s1 = "hello";  // &str
    
    // 字符串对象
    let mut s2 = String::from("hello");
    s2.push_str(" robot");
    
    // 字符串分割
    let parts: Vec<&str> = s2.split(' ').collect();
    println!("Parts: {:?}", parts);
    
    // 字符串替换
    let replaced = s2.replace("robot", "LeBot");
    println!("Replaced: {}", replaced);
    
    // 大小写转换
    println!("Uppercase: {}", s2.to_uppercase());
    println!("Lowercase: {}", s2.to_lowercase());
    
    // 格式化字符串
    let motor_id = 1;
    let speed = 500.5;
    let formatted = format!("Motor {} speed: {}", motor_id, speed);
    println!("{}", formatted);
}

模块系统

rust
// 定义模块
mod motor_control {
    pub struct Motor {
        pub id: u32,
        speed: f32,
    }
    
    impl Motor {
        pub fn new(id: u32) -> Motor {
            Motor { id, speed: 0.0 }
        }
        
        pub fn set_speed(&mut self, s: f32) {
            self.speed = s;
        }
        
        pub fn get_speed(&self) -> f32 {
            self.speed
        }
    }
}

mod sensor_reading {
    pub fn read_imu() -> (f32, f32, f32) {
        (0.1, 0.2, 9.8)
    }
}

fn main() {
    let mut motor = motor_control::Motor::new(0);
    motor.set_speed(500.0);
    println!("Motor speed: {}", motor.get_speed());
    
    let (ax, ay, az) = sensor_reading::read_imu();
    println!("IMU: ax={}, ay={}, az={}", ax, ay, az);
}

总结

Rust 的基础知识包括:

  1. 所有权系统:内存安全的基础
  2. 借用机制:允许临时访问值
  3. 结构体和方法:数据和行为的组织
  4. Trait:代码的模块化和重用
  5. 错误处理:使用 Result 和 Option
  6. 泛型和生命周期:编写灵活、安全的代码

这些概念虽然需要一些学习曲线,但它们使 Rust 能够提供内存安全和性能的完美结合,非常适合 LeBot 这样的系统级应用。


参考资源

由 LeBot 开发团队编写