「这是我参与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(())
}
很好! 如果现在我们有一个地方出错,我们会看到完整的堆栈跟踪,像下面这样:
最后,因为我喜欢我的日志呈现结构化,让我们添加 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(())
}
好了,前置环境已经配置好了!下面我们要做一些有意思的尝试!