目录全局变量错误处理unsafeRustmacro宏编程asnyc/await异步编程全局变量全局变量是在整个程序范围内可见的变量。虽然Rust强调模块化和封装,但在某些情况下,全局变量仍然有其用途。定义全局变量//定义全局变量staticCOUNTER:u32
全局变量是在整个程序范围内可见的变量。虽然 Rust 强调模块化和封装,但在某些情况下,全局变量仍然有其用途。
定义全局变量
// 定义全局变量
static COUNTER: u32 = 0;
fn increment_counter() {
    COUNTER += 1;
}
fn main() {
    increment_counter();
    println!("Counter: {}", COUNTER);
}
可变全局变量
在 Rust 中,默认情况下全局变量是不可变的。如果需要可变全局变量,可以使用 static mut 关键字。
// 定义可变全局变量
static mut COUNTER: u32 = 0;
fn increment_counter() {
    unsafe {
        COUNTER += 1;
    }
}
fn main() {
    increment_counter();
    println!("Counter: {}", COUNTER);
}
Rust 提供了多种错误处理机制,包括:
Result 类型是 Rust 中最常用的错误处理类型,它表示一个可能出错的操作。Result 类型有两种变体:Ok(T) 和 Err(E)。
使用 Result
use std::fs::File;
use std::io::{self, Read};
fn read_file(filename: &str) -> io::Result<String> {
    let mut file = File::open(filename)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}
fn main() {
    match read_file("example.txt") {
        Ok(contents) => println!("File contents: {}", contents),
        Err(e) => eprintln!("Error reading file: {}", e),
    }
}
使用 ? 操作符
? 操作符用于将 Result 类型的错误向上抛出。
use std::fs::File;
use std::io::{self, Read};
fn read_file(filename: &str) -> io::Result<String> {
    let mut file = File::open(filename)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    Ok(contents)
}
fn main() {
    match read_file("example.txt") {
        Ok(contents) => println!("File contents: {}", contents),
        Err(e) => eprintln!("Error reading file: {}", e),
    }
}
Option 类型用于表示可能不存在的值,它有两种变体:Some(T) 和 None。
使用 Option
rust
fn find_value(values: &[i32], target: i32) -> Option<i32> {
    for &value in values.iter() {
        if value == target {
            return Some(value);
        }
    }
    None
}
fn main() {
    let numbers = [1, 2, 3, 4, 5];
    match find_value(&numbers, 3) {
        Some(value) => println!("Found value: {}", value),
        None => println!("Value not found"),
    }
}
使用 if let 和 match
fn find_value(values: &[i32], target: i32) -> Option<i32> {
    for &value in values.iter() {
        if value == target {
            return Some(value);
        }
    }
    None
}
fn main() {
    let numbers = [1, 2, 3, 4, 5];
    if let Some(value) = find_value(&numbers, 3) {
        println!("Found value: {}", value);
    } else {
        println!("Value not found");
    }
}
panic! 宏用于处理不可恢复的错误。当程序遇到不可恢复的错误时,会触发一个 panic,导致程序崩溃。
使用 panic!
fn divide(x: i32, y: i32) {
    if y == 0 {
        panic!("Division by zero");
    }
    println!("Result: {}", x / y);
}
fn main() {
    divide(10, 0);  // 触发 panic!
}
Unsafe Rust 是 Rust 中的一个重要概念,用于处理那些无法通过 Rust 的类型系统和所有权模型自动验证的操作。常见的 unsafe 操作包括指针操作、内存访问等。
// 定义 unsafe 函数
unsafe fn dangerous_operation() {
    // 危险操作
    let mut x = 5;
    let y = &mut x as *mut i32;
    *y = 10;
}
fn safe_function() {
    // 安全函数调用 unsafe 函数
    unsafe {
        dangerous_operation();
    }
}
fn main() {
    safe_function();
}
// 定义 unsafe 指针操作
fn pointer_operations() {
    let mut x = 5;
    let y = &mut x as *mut i32;
    unsafe {
        *y = 10;
    }
    println!("x: {}", x);
}
fn main() {
    pointer_operations();
}
// 不安全的类型转换
fn type_casts() {
    let mut x = 5;
    let y: *const i32 = &x;
    unsafe {
        let z: *mut i32 = y as *mut i32;
        *z = 10;
    }
    println!("x: {}", x);
}
fn main() {
    type_casts();
}
宏是 Rust 中一种强大的元编程工具,用于在编译时生成代码。宏分为两种类型:声明式宏 (macro_rules!) 和过程宏 (proc_macro 和 proc_macro_derive).
macro_rules! my_macro {
    ($val:expr) => {
        println!("Value: {}", $val);
    };
}
fn main() {
    my_macro!(42);
}
过程式宏分为两种:属性宏 (proc_macro_attribute) 和派生宏 (proc_macro_derive)。
属性宏
// 属性宏定义
#[proc_macro_attribute]
pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
    // 处理输入
    let args_str = args.to_string();
    let input_str = input.to_string();
    format!("{} [{}] {}", args_str, input_str, "processed").parse().unwrap()
}
// 属性宏使用
#[my_attribute]
struct MyStruct {
    field: i32,
}
fn main() {
    let s = MyStruct { field: 42 };
    println!("MyStruct: {:?}", s);
}
派生宏
// 派生宏定义
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: TokenStream) -> TokenStream {
    // 处理输入
    let input_str = input.to_string();
    format!("{} [derived] {}", input_str, "processed").parse().unwrap()
}
// 派生宏使用
#[derive(MyDerive)]
struct MyStruct {
    field: i32,
}
fn main() {
    let s = MyStruct { field: 42 };
    println!("MyStruct: {:?}", s);
}
全局变量示例
// 定义全局变量
static COUNTER: u32 = 0;
fn increment_counter() {
    unsafe {
        COUNTER += 1;
    }
}
fn main() {
    increment_counter();
    println!("Counter: {}", COUNTER);
}
Unsafe 指针操作示例
// 定义 unsafe 指针操作
fn pointer_operations() {
    let mut x = 5;
    let y = &mut x as *mut i32;
    unsafe {
        *y = 10;
    }
    println!("x: {}", x);
}
fn main() {
    pointer_operations();
}
声明式宏示例
macro_rules! my_macro {
    ($val:expr) => {
        println!("Value: {}", $val);
    };
}
fn main() {
    my_macro!(42);
}
属性宏示例
// 属性宏定义
#[proc_macro_attribute]
pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
    // 处理输入
    let args_str = args.to_string();
    let input_str = input.to_string();
    format!("{} [{}] {}", args_str, input_str, "processed").parse().unwrap()
}
// 属性宏使用
#[my_attribute]
struct MyStruct {
    field: i32,
}
fn main() {
    let s = MyStruct { field: 42 };
    println!("MyStruct: {:?}", s);
}
派生宏示例
// 派生宏定义
#[proc_macro_derive(MyDerive)]
pub fn my_derive(input: TokenStream) -> TokenStream {
    // 处理输入
    let input_str = input.to_string();
    format!("{} [derived] {}", input_str, "processed").parse().unwrap()
}
// 派生宏使用
#[derive(MyDerive)]
struct MyStruct {
    field: i32,
}
fn main() {
    let s = MyStruct { field: 42 };
    println!("MyStruct: {:?}", s);
}
异步编程的概念 异步编程允许程序在等待某些操作完成(如网络请求、文件读取)时执行其他任务。这可以显著提高应用程序的响应性和性能。
async/await 语法
use std::time::Duration;
use tokio::time::sleep;
async fn async_function() {
    println!("Starting async function...");
    sleep(Duration::from_secs(1)).await; // 模拟耗时操作
    println!("Async function completed!");
}
#[tokio::main]
async fn main() {
    async_function().await; // 调用异步函数
}
Future 接口 所有异步操作最终都实现了 Future 接口。
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
struct MyFuture;
impl Future for MyFuture {
    type Output = ();
    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 实现具体的逻辑
        Poll::Ready(())
    }
}
任务调度
通过调用 .poll() 方法来手动推进 Future 的执行,直到它完成或准备好继续执行。
use std::pin::Pin;
use std::task::{Context, Poll};
use std::future::Future;
struct MyFuture;
impl Future for MyFuture {
    type Output = ();
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
        // 假设这是一个异步操作
        if /* 条件 */ {
            Poll::Ready(())
        } else {
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}
事件循环
事件循环负责调度任务,通常由库如 tokio 或 async-std 提供。
#[tokio::main]
async fn main() {
    let future = async {
        println!("Hello, world!");
    };
    tokio::spawn(future); // 将任务放入事件循环
}
Pin 概念 使数据结构固定在内存中,防止它们被移动,这对于异步代码特别重要。
use std::pin::Pin;
use std::sync::Arc;
struct MyPinnedStruct;
impl Unpin for MyPinnedStruct {} // 标记为可移动
let pinned_struct: Pin<Box<MyPinnedStruct>> = Pin::new(Box::new(MyPinnedStruct));
Unpin 概念 允许对象在内存中自由移动。
struct MyUnpinnedStruct;
impl Unpin for MyUnpinnedStruct {}
Stream 概念 可以产生一系列值的数据源。
use futures::stream::StreamExt;
let stream = futures::stream::iter(vec![1, 2, 3]);
while let Some(item) = stream.next().await {
    println!("Received item: {}", item);
}
结合使用 异步函数可以消费或产生流,使得处理大量数据更加高效。
use futures::stream::StreamExt;
async fn process_stream(stream: impl Stream<Item = i32>) {
    while let Some(item) = stream.next().await {
        println!("Processing item: {}", item);
    }
}
等待多个 Future 同时完成。
use tokio::task::JoinHandle;
#[tokio::main]
async fn main() {
    let handle1 = tokio::spawn(async {
        println!("Task 1 started");
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
        println!("Task 1 finished");
    });
    let handle2 = tokio::spawn(async {
        println!("Task 2 started");
        tokio::time::sleep(std::time::Duration::from_secs(2)).await;
        println!("Task 2 finished");
    });
    let (res1, res2) = tokio::try_join!(handle1, handle2).unwrap();
}
从多个可能完成的 Future 中选择第一个完成的。
use tokio::select;
#[tokio::main]
async fn main() {
    let handle1 = tokio::spawn(async {
        println!("Task 1 started");
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
        println!("Task 1 finished");
    });
    let handle2 = tokio::spawn(async {
        println!("Task 2 started");
        tokio::time::sleep(std::time::Duration::from_secs(2)).await;
        println!("Task 2 finished");
    });
    select! {
        _ = handle1 => println!("Task 1 completed first"),
        _ = handle2 => println!("Task 2 completed first"),
    }
}
生命周期管理 确保引用不会超出其被引用的数据的生命周期。
use std::pin::Pin;
use std::sync::Arc;
struct MyData {
    value: Arc<i32>,
}
impl MyData {
    fn new(value: i32) -> Self {
        MyData { value: Arc::new(value) }
    }
    fn get_value(&self) -> &i32 {
        &*self.value
    }
}
fn main() {
    let data = MyData::new(42);
    let ref_value = data.get_value(); // 安全的引用
}
错误处理 正确处理异步操作中的错误,避免程序崩溃。
use std::error::Error;
use std::fmt;
#[derive(Debug)]
struct MyError(String);
impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "My custom error: {}", self.0)
    }
}
impl Error for MyError {}
async fn async_function() -> Result<(), MyError> {
    println!("Starting async function...");
    if /* 条件 */ {
        Err(MyError("An error occurred".to_string()))
    } else {
        Ok(())
    }
}
#[tokio::main]
async fn main() {
    match async_function().await {
        Ok(_) => println!("Async function completed successfully"),
        Err(e) => eprintln!("Error: {}", e),
    }
}
设置环境 安装必要的依赖库。
cargo new my_async_web_server
cd my_async_web_server
cargo add hyper
cargo add tokio
编写服务端代码 创建 HTTP 服务器并处理请求。
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
use std::convert::Infallible;
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
    let addr = ([127, 0, 0, 1], 3000).into();
    let listener = TcpListener::bind(&addr).await.unwrap();
    println!("Listening on http://{}", addr);
    let server = Server::from_tcp(listener)
        .expect("Failed to bind TCP listener")
        .serve(make_service_fn(|_| async {
            Ok::<_, Infallible>(service_fn(|req| async move {
                match req.uri().path() {
                    "/" => {
                        let body = "Hello, World!";
                        Ok(Response::new(Body::from(body)))
                    }
                    _ => {
                        let body = "Not Found";
                        Ok(Response::builder()
                            .status(404)
                            .body(Body::from(body))
                            .unwrap())
                    }
                }
            }))
        }));
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}                        如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!