Rust 语言基础
引言
Rust 是一门现代的系统编程语言,以其内存安全、并发性和性能而闻名。与 Python 不同,Rust 编译成本地代码,提供了接近 C/C++ 的性能,同时提供了更安全的编程模型。对于 LeBot 这样的实时机器人系统,Rust 的低级控制能力和高性能使其成为一个理想的选择。
Rust 的基本概念
为什么使用 Rust?
- 内存安全:在编译时检查内存错误,避免运行时崩溃
- 无垃圾回收:性能更好,更可预测
- 并发安全:防止数据竞争
- 零成本抽象:提供高级特性而不牺牲性能
- 跨平台:可以编译到多个目标平台,包括 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 最独特的特性。它决定了内存如何管理。
所有权规则
- Rust 中的每个值都有一个所有者
- 同时只能有一个所有者
- 当所有者离开作用域时,值被释放
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 没有异常,而是使用 Result 和 Option 类型。
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 的基础知识包括:
- 所有权系统:内存安全的基础
- 借用机制:允许临时访问值
- 结构体和方法:数据和行为的组织
- Trait:代码的模块化和重用
- 错误处理:使用 Result 和 Option
- 泛型和生命周期:编写灵活、安全的代码
这些概念虽然需要一些学习曲线,但它们使 Rust 能够提供内存安全和性能的完美结合,非常适合 LeBot 这样的系统级应用。
参考资源
- Rust 官方书籍:https://doc.rust-lang.org/book/
- Rust by Example:https://doc.rust-lang.org/rust-by-example/
- Rustlings 练习:https://github.com/rust-lang/rustlings