Rust 教程
Rust教程
简介
Rust 是一门静态类型、系统级编程语言,支持零成本抽象和内存安全。Rust 由 Mozilla 开发,致力于创造一种快速、可靠和安全的语言,适用于编写操作系统、Web 服务、游戏等高性能应用。
Rust 的主要特点包括:
- 零成本抽象,不会对程序性能造成影响
- 内存安全,防止悬空指针和内存泄漏
- 并发编程,支持线程和异步函数,避免竞态条件
- 高效编译,快速构建出运行代码
安装
-
执行安装程序,安装过程会提示是否将
cargo
(Rust 的包管理工具)加入环境变量中 -
验证安装是否成功,执行以下命令:
$ rustc --version rustc 1.55.0 (c8dfcfe04 2021-09-06) $ cargo --version cargo 1.55.0 (32da73ab1 2021-11-04)
基础概念
变量和数据类型
Rust 中的变量默认是不可变的,如果需要可变变量,需要使用 mut
关键字。如:
let x = 10;
let mut y = 20;
y = 30;
Rust 的数据类型有以下几种:
- 基本类型:
u8
、u16
、u32
、u64
、i8
、i16
、i32
、i64
、f32
、f64
、bool
、char
- 复合类型:元组(tuple)、数组(array)、结构体(struct)
函数
Rust 中的函数使用 fn
关键字定义,如:
fn main() {
println!("Hello, world!");
hello();
}
fn hello() {
println!("Hello, Rust!");
}
Rust 函数的参数和返回值都需要指定数据类型,如:
fn add(a: i32, b: i32) -> i32 {
a + b
}
let sum = add(10, 20);
控制流
Rust 中的控制流语句包括:
if/else
:条件语句,可以使用if/else if/else
实现多分支条件判断while
:循环语句,与其他语言类似for
:循环语句,用于遍历数组等数据结构match
:模式匹配语句,类似switch
语句,但更加强大
let n = 5;
if n < 0 {
println!("{} < 0", n);
} else if n > 0 {
println!("{} > 0", n);
} else {
println!("{} = 0", n);
}
let mut i = 0;
while i < 5 {
println!("{}", i);
i += 1;
}
let numbers = [1, 2, 3, 4, 5];
for num in numbers.iter() {
println!("{}", num);
}
let result = match n {
1 => "one",
2 => "two",
_ => "other",
};
println!("{}", result);
模块和包
Rust 中模块是代码组织的基本单元,包含变量、函数、结构体等代码。在 Rust 中,一个文件就是一个模块。通过 mod
关键字可以声明一个新的模块,如:
mod my_module {
fn hello() {
println!("Hello, module!");
}
}
在调用模块中的函数时,需要使用 crate
关键字指明模块所在的包,如:
mod my_module {
pub fn hello() {
println!("Hello, module!");
}
}
fn main() {
my_module::hello();
}
进阶特性
所有权和生命周期
Rust 的一个重要特性是使用所有权(ownership)系统管理内存。每个值都有一个所有者,当所有者离开作用域时,该值将被释放。
Rust 中还有生命周期(lifetime)的概念,它是一种用于指定值的作用域的注释,防止出现悬空指针等内存安全问题。
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权被转移给 s2,s1 无法再使用
println!("{}", s2); // 输出:"hello"
}
为了避免因所有权转移而导致的问题,Rust 提供了引用(reference)的概念,通过引用可以访问值而不获取其所有权。
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // s1 的引用传递给 calculate_length 函数
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // 接收 String 类型的引用
s.len() // 返回 s 的长度
}
面向对象编程
Rust 中并没有类的概念,但可以通过结构体和 trait 实现面向对象编程。结构体类似于 C 语言中的结构体,可以用于封装数据和函数,trait 则类似于接口,用于定义一组共同的行为。
struct Person {
name: String,
age: u8,
}
impl Person {
fn new(name: &str, age: u8) -> Person { // 表示 Person 的构造函数
Person {
name: String::from(name),
age,
}
}
fn say_hello(&self) { // 表示 Person 的成员函数
println!("Hello, my name is {}, and I'm {} years old.", self.name, self.age);
}
}
trait Speak { // 定义 Speak trait,表示具备说话能力
fn speak(&self);
}
impl Speak for Person { // 表示 Person 实现了 Speak trait
fn speak(&self) {
self.say_hello();
}
}
fn main() {
let p = Person::new("Tom", 20);
p.speak(); // 输出:"Hello, my name is Tom, and I'm 20 years old."
}
并发编程
Rust 通过线程和异步函数支持并发编程,避免了常见的竞态条件等问题。线程可以使用标准库中的 thread
模块创建,异步函数可以通过 async/await
语法实现。
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| { // 创建一个新线程
for i in 1..=5 {
println!("Thread {}: {}", thread::current().name().unwrap(), i);
thread::sleep(Duration::from_millis(500));
}
});
for i in 1..=5 {
println!("Main thread: {}", i);
thread::sleep(Duration::from_millis(500));
}
handle.join().unwrap(); // 等待新线程执行结束
}
异步函数可以使用 async/await
语法实现,需要配合 tokio
库使用,示例代码如下:
async fn print_numbers() {
for i in 1..=5 {
println!("{}: {}", thread::current().name().unwrap(), i);
tokio::time::sleep(Duration::from_millis(500)).await; // 异步等待 500ms
}
}
#[tokio::main]
async fn main() {
tokio::spawn(print_numbers()); // 创建异步任务
print_numbers().await; // 执行另一个异步任务
}
结语
Rust 作为一门现代化的编程语言,拥有丰富的特性和功能,并且不会对性能造成影响。它的底层表现力使其成为编写高性能应用的首选语言。同时,所有权和生命周期系统使得 Rust 具备了很高的内存安全性。