Rust 详细教程
Rust 是一种系统编程语言,专注于安全、并发和性能。以下是 Rust 的全面教程:
1. Rust 简介
主要特点
- 内存安全:所有权系统保证内存安全
- 零成本抽象:高级特性不带来运行时开销
- 并发安全:借用检查器防止数据竞争
- 高性能:与 C/C++ 相当的性能
- 跨平台:支持多种操作系统和架构
- 现代工具链:内置包管理器和构建工具
适用场景
- 系统编程
- 网络服务
- 嵌入式开发
- WebAssembly
- 命令行工具
- 高性能应用
2. Rust 安装
安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
更新 Rust
rustup update
验证安装
rustc --version
cargo --version
卸载 Rust
rustup self uninstall
3. 开发工具
1. Cargo (Rust 构建系统和包管理器)
cargo new project_name # 创建新项目
cargo build # 构建项目
cargo run # 运行项目
cargo test # 运行测试
cargo doc # 生成文档
cargo update # 更新依赖
2. 推荐 IDE/编辑器
- VS Code + Rust Analyzer 插件
- IntelliJ IDEA + Rust 插件
- CLion + Rust 插件
4. 基本语法
Hello World
fn main() {
println!("Hello, world!");
}
变量绑定
let x = 5; // 不可变绑定
let mut y = 10; // 可变绑定
const PI: f64 = 3.14159; // 常量
数据类型
// 标量类型
let a: i32 = -42; // 32位有符号整数
let b: u64 = 100; // 64位无符号整数
let c: f64 = 3.14; // 64位浮点数
let d: bool = true; // 布尔值
let e: char = 'R'; // Unicode字符
// 复合类型
let tup: (i32, f64, char) = (500, 6.4, 'J'); // 元组
let arr: [i32; 5] = [1, 2, 3, 4, 5]; // 数组
控制流
// if 表达式
let number = 6;
if number % 4 == 0 {
println!("divisible by 4");
} else if number % 3 == 0 {
println!("divisible by 3");
} else {
println!("not divisible by 4 or 3");
}
// 在 let 语句中使用 if
let condition = true;
let x = if condition { 5 } else { 6 };
// 循环
loop {
println!("again!");
break;
}
let mut count = 0;
while count < 5 {
println!("count: {}", count);
count += 1;
}
for element in [10, 20, 30].iter() {
println!("value: {}", element);
}
for number in 1..4 { // 范围
println!("{}", number);
}
5. 所有权系统
所有权规则
- Rust 中每个值都有一个所有者
- 一次只能有一个所有者
- 当所有者离开作用域,值将被丢弃
移动语义
let s1 = String::from("hello");
let s2 = s1; // s1 被移动到 s2
// println!("{}", s1); // 错误!s1 不再有效
克隆
let s1 = String::from("hello");
let s2 = s1.clone(); // 深度拷贝
println!("s1 = {}, s2 = {}", s1, s2); // 都有效
函数与所有权
fn takes_ownership(s: String) {
println!("{}", s);
} // s 离开作用域并被丢弃
let s = String::from("hello");
takes_ownership(s);
// println!("{}", s); // 错误!s 已被移动
引用与借用
fn calculate_length(s: &String) -> usize {
s.len()
} // s 离开作用域但不会丢弃它指向的数据
let s = String::from("hello");
let len = calculate_length(&s);
println!("Length of '{}' is {}.", s, len); // s 仍然有效
可变引用
fn change(s: &mut String) {
s.push_str(", world");
}
let mut s = String::from("hello");
change(&mut s);
引用规则
- 任意时刻,只能有一个可变引用或多个不可变引用
- 引用必须总是有效的
6. 结构体
定义与实例化
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
let user1 = User {
email: String::from("user@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
let mut user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
active: false,
sign_in_count: 0,
};
user2.sign_in_count = 1;
元组结构体
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);
方法语法
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
// 关联函数
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}
7. 枚举与模式匹配
枚举
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
Option 枚举
enum Option<T> {
Some(T),
None,
}
let some_number = Some(5);
let absent_number: Option<i32> = None;
match 控制流
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => {
println!("Lucky penny!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
}
}
}
if let 简洁控制流
let some_u8_value = Some(3u8);
if let Some(3) = some_u8_value {
println!("three");
}
8. 模块系统
模块定义
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
文件系统模块
src/
lib.rs
front_of_house/
hosting.rs
// src/lib.rs
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
// src/front_of_house/hosting.rs
pub fn add_to_waitlist() {}
9. 常见集合
Vector
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
let third: &i32 = &v[2];
let third: Option<&i32> = v.get(2);
for i in &v {
println!("{}", i);
}
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
String
let mut s = String::new();
let data = "initial contents";
let s = data.to_string();
let s = String::from("initial contents");
let mut s = String::from("foo");
s.push_str("bar");
s.push('!');
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // 注意 s1 被移动了
let s = format!("{}-{}-{}", "tic", "tac", "toe");
let hello = "Здравствуйте";
let s = &hello[0..4]; // 每个 Unicode 标量值占 2 字节
HashMap
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
let score = scores.get(&String::from("Blue"));
for (key, value) in &scores {
println!("{}: {}", key, value);
}
scores.entry(String::from("Blue")).or_insert(50);
10. 错误处理
panic!
panic!("crash and burn");
Result
use std::fs::File;
use std::io::ErrorKind;
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error)
}
},
};
// 更简洁的写法
let f = File::open("hello.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("hello.txt").unwrap_or_else(|error| {
panic!("Problem creating the file: {:?}", error);
})
} else {
panic!("Problem opening the file: {:?}", error);
}
});
// unwrap 和 expect
let f = File::open("hello.txt").unwrap();
let f = File::open("hello.txt").expect("Failed to open hello.txt");
传播错误
use std::io;
use std::io::Read;
use std::fs::File;
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
// 更简洁的写法
fn read_username_from_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
// 最简洁的写法
use std::fs;
fn read_username_from_file() -> Result<String, io::Error> {
fs::read_to_string("hello.txt")
}
11. 泛型、Trait 和生命周期
泛型
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
let mut largest = list[0];
for &item in list.iter() {
if item > largest {
largest = item;
}
}
largest
}
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
Trait
pub trait Summary {
fn summarize(&self) -> String {
String::from("(Read more...)")
}
}
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
// Trait 作为参数
pub fn notify(item: impl Summary) {
println!("Breaking news! {}", item.summarize());
}
// Trait Bound 语法
pub fn notify<T: Summary>(item: T) {
println!("Breaking news! {}", item.summarize());
}
// 多个 Trait Bound
pub fn notify(item: impl Summary + Display) {}
pub fn notify<T: Summary + Display>(item: T) {}
// where 子句
fn some_function<T, U>(t: T, u: U) -> i32
where T: Display + Clone,
U: Clone + Debug
{}
// 返回实现了 Trait 的类型
fn returns_summarizable() -> impl Summary {
NewsArticle {
headline: String::from("Penguins win the Stanley Cup Championship!"),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from("The Pittsburgh Penguins once again are the best hockey team in the NHL."),
}
}
生命周期
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 {
3
}
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("Attention please: {}", announcement);
self.part
}
}
12. 测试
单元测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
fn larger_can_hold_smaller() {
let larger = Rectangle { width: 8, height: 7 };
let smaller = Rectangle { width: 5, height: 1 };
assert!(larger.can_hold(&smaller));
}
#[test]
#[should_panic(expected = "Guess value must be between 1 and 100")]
fn greater_than_100() {
Guess::new(200);
}
#[test]
fn it_works() -> Result<(), String> {
if 2 + 2 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
}
集成测试
tests/
integration_test.rs
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
13. 并发编程
线程
use std::thread;
use std::time::Duration;
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap();
消息传递
use std::sync::mpsc;
use std::thread;
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
共享状态
use std::sync::{Mutex, Arc};
use std::thread;
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
14. 面向对象编程
结构体与方法
pub struct AveragedCollection {
list: Vec<i32>,
average: f64,
}
impl AveragedCollection {
pub fn add(&mut self, value: i32) {
self.list.push(value);
self.update_average();
}
pub fn remove(&mut self) -> Option<i32> {
let result = self.list.pop();
match result {
Some(value) => {
self.update_average();
Some(value)
}
None => None,
}
}
pub fn average(&self) -> f64 {
self.average
}
fn update_average(&mut self) {
let total: i32 = self.list.iter().sum();
self.average = total as f64 / self.list.len() as f64;
}
}
Trait 对象
pub trait Draw {
fn draw(&self);
}
pub struct Screen {
pub components: Vec<Box<dyn Draw>>,
}
impl Screen {
pub fn run(&self) {
for component in self.components.iter() {
component.draw();
}
}
}
15. 高级特性
不安全 Rust
unsafe fn dangerous() {}
unsafe {
dangerous();
}
// 解引用裸指针
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("r1 is: {}", *r1);
*r2 = 10;
}
// 调用不安全函数
extern "C" {
fn abs(input: i32) -> i32;
}
unsafe {
println!("Absolute value of -3 according to C: {}", abs(-3));
}
高级 Trait
use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
trait Pilot {
fn fly(&self);
}
trait Wizard {
fn fly(&self);
}
struct Human;
impl Pilot for Human {
fn fly(&self) {
println!("This is your captain speaking.");
}
}
impl Wizard for Human {
fn fly(&self) {
println!("Up!");
}
}
impl Human {
fn fly(&self) {
println!("*waving arms furiously*");
}
}
let person = Human;
Pilot::fly(&person);
Wizard::fly(&person);
person.fly();
高级类型
type Kilometers = i32;
let x: i32 = 5;
let y: Kilometers = 5;
println!("x + y = {}", x + y);
// Never 类型 (!)
fn bar() -> ! {
loop {
println!("forever");
}
}
宏
// 声明宏
#[macro_export]
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
// 使用宏
let v: Vec<u32> = vec![1, 2, 3];
// 过程宏
use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;
#[derive(HelloMacro)]
struct Pancakes;
fn main() {
Pancakes::hello_macro();
}
16. 实战项目
1. 命令行工具
use std::env;
use std::process;
fn main() {
let args: Vec<String> = env::args().collect();
let config = Config::new(&args).unwrap_or_else(|err| {
println!("Problem parsing arguments: {}", err);
process::exit(1);
});
if let Err(e) = minigrep::run(config) {
println!("Application error: {}", e);
process::exit(1);
}
}
2. Web 服务器
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
for stream in listener.incoming() {
let stream = stream.unwrap();
handle_connection(stream);
}
}
fn handle_connection(mut stream: TcpStream) {
let mut buffer = [0; 1024];
stream.read(&mut buffer).unwrap();
let get = b"GET / HTTP/1.1\r\n";
let (status_line, contents) = if buffer.starts_with(get) {
("HTTP/1.1 200 OK", "Hello, World!")
} else {
("HTTP/1.1 404 NOT FOUND", "404 Not Found")
};
let response = format!(
"{}\r\nContent-Length: {}\r\n\r\n{}",
status_line,
contents.len(),
contents
);
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
3. 多线程 Web 服务器
use std::thread;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
type Job = Box<dyn FnOnce() + Send + 'static>;
struct Worker {
id: usize,
thread: Option<thread::JoinHandle<()>>,
}
impl Worker {
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
let thread = thread::spawn(move || loop {
let job = receiver.lock().unwrap().recv().unwrap();
println!("Worker {} got a job; executing.", id);
job();
});
Worker {
id,
thread: Some(thread),
}
}
}
pub struct ThreadPool {
workers: Vec<Worker>,
sender: mpsc::Sender<Job>,
}
impl ThreadPool {
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let (sender, receiver) = mpsc::channel();
let receiver = Arc::new(Mutex::new(receiver));
let mut workers = Vec::with_capacity(size);
for id in 0..size {
workers.push(Worker::new(id, Arc::clone(&receiver)));
}
ThreadPool { workers, sender }
}
pub fn execute<F>(&self, f: F)
where
F: FnOnce() + Send + 'static,
{
let job = Box::new(f);
self.sender.send(job).unwrap();
}
}
Rust 是一门强大而复杂的语言,本教程涵盖了 Rust 的主要特性和概念。要精通 Rust 需要大量实践,建议通过实际项目来巩固所学知识。