「深挖Rust」Rust 异步编程 - 1

574 阅读2分钟

「这是我参与2022首次更文挑战的第 25 天,活动详情查看:2022首次更文挑战」。


与其等到我们对异步编程很迷惑的时候,不如主动出击有意地由浅入深研究一下。

我们先创建一个新项目:

$ cargo new waytoodeep
     Created binary (application) `waytoodeep` package

然后安装 cargo-edit ,有利于我们使用 cargo add 为项目添加依赖。

$ cargo install cargo-edit

然后我们选择一个异步运行时,因为 futures 不会自己 poll......这里我选择tokio,原因其实是:过去几个月我一直在用这个。

$ cargo add tokio@1.9.0 --features full

然后我们改变我们的 main(),让它使用一个默认的tokio执行器(crate创建的时候默认就会生一个 main(), 但是这里不符合本篇文章探究的异步范畴)。

// in `src/main.rs`

#[tokio::main]
async fn main() {
    println!("Hello from a (so far completely unnecessary) async runtime");
}
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/waytoodeep`
Hello from a (so far completely unnecessary) async runtime

很好!然后让我们添加一些我在其他项目中喜欢的lib。

首先,在错误处理方面 → 我们正在编写一个应用程序,我们将从不同的库中得到一堆不同的类型,如果我们能有一个类型来统一它们,那就太好了。

eyre 为我们提供了这样的功能(类似:anyhow)!因为我喜欢终端里面显示漂亮的颜色,所以我将使用 color-eyre :

$ cargo add color-eyre@0.5.11
		Updating '<https://github.com/rust-lang/crates.io-index>' index
	     Adding color-eyre v0.5.11 to dependencies

现在 color-eyre 作为默认的 panic handler,我还偷偷地修改了一些环境变量,这样我们就可以默认获得 backtrace

use color_eyre::Report;

#[tokio::main]
async fn main() -> Result<(), Report> {
    setup()?;

    println!("Hello from a (so far completely unnecessary) async runtime");

    Ok(())
}

fn setup() -> Result<(), Report> {
    if std::env::var("RUST_LIB_BACKTRACE").is_err() {
        std::env::set_var("RUST_LIB_BACKTRACE", "1")
    }
    color_eyre::install()?;

    Ok(())
}

很好! 如果现在我们有一个地方出错,我们会看到完整的堆栈跟踪,像下面这样:

image.png

最后,因为我喜欢我的日志呈现结构化,让我们添加 tracing 并在终端用漂亮的颜色打印它们。所以添加这个crate → tracing-subscriber

$ cargo add tracing@0.1.26 tracing-subscriber@0.2.19
    Updating '<https://github.com/rust-lang/crates.io-index>' index
      Adding tracing v0.1.26 to dependencies
      Adding tracing-subscriber v0.2.19 to dependencies

我们已经有了一个 setup(),所以我们只需在那里给整个应用程序安装 tracing-subscriber。并且我们要把使用 println! 的地方改为 info!。另外,再次对环境变量进行一些操作,这样如果没有设置 RUST_LOG ,我们就将所有crate的日志级别默认设置为 info

use color_eyre::Report;
use tracing::info;
use tracing_subscriber::EnvFilter;

#[tokio::main]
async fn main() -> Result<(), Report> {
    setup()?;

    info!("Hello from a comfy nest we've made for ourselves");

    Ok(())
}

fn setup() -> Result<(), Report> {
    if std::env::var("RUST_LIB_BACKTRACE").is_err() {
        std::env::set_var("RUST_LIB_BACKTRACE", "1")
    }
    color_eyre::install()?;

    if std::env::var("RUST_LOG").is_err() {
        std::env::set_var("RUST_LOG", "info")
    }
    tracing_subscriber::fmt::fmt()
        .with_env_filter(EnvFilter::from_default_env())
        .init();

    Ok(())
}

好了,前置环境已经配置好了!下面我们要做一些有意思的尝试!