你還不知道的 Rust10 個小技巧(上)

0x00 開篇

Rust 是一種很棒的編程語言:可靠、快速,但是也相當複雜,學習曲線相對來說比較陡峭。在過去的三年裏,我一直在致力於學習 Rust,並使用 Rust 寫了一些小工具,感覺效果還是蠻不錯的。今天給大家介紹下 Rust 的 10 個小技巧。

0x01 在 VS Code 上使用 Rust Analyzer

VS Code 中有兩款插件,其中一款是 Rust 官方插件,另一款是 matklad 大神的 Rust Analyzer 。其實在使用中很明顯 Rust Analyzer 是優於 Rust 官方插件的(即便官方插件下載量第一)。如果喜歡使用 VS Code 的小夥伴學習 Rust,那我還是強推 Rust Analyzer 。

0x02 使用 Cow 作爲返回類型

有的時候,需要編寫接收字符串切片 (&str) 並有條件地返回其修改的值或原始值的方法。對於上面說的兩種情況,可以使用 Cow ,以便於僅在必要時分配新內存。示例代碼如下:

use std::borrow::Cow;

/// 
/// 將單詞的首字母轉化爲大寫
fn capitalize(name: &str) -> Cow<str> {
    match name.chars().nth(0) {
        Some(first_char) if first_char.is_uppercase() => {
            // 如果首字母已經是大寫,則無需分配內存
            Cow::Borrowed(name)
        }
        Some(first_char) => {
            // 如果首字母非大寫,則需分配新內存
            let new_string: String = first_char.to_uppercase()
              .chain(name.chars().skip(1))
              .collect();
            
            Cow::Owned(new_string)
        },
        None => Cow::Borrowed(name),
    }
}

fn main() {
    println!("{}", capitalize("english"));   // 分配內存
    println!("{}", capitalize("China"));  // 不會分配內存
}

0x03 使用 crossbeam_channel 代替標準庫中的 channel

crossbeam_channel 爲標準庫中的 channel 提供了強大的替代方案,支持 Select 操作、超時等。類似於你在 Golang 和傳統的 Unix Sockets 中開箱即用的東西。示例代碼如下:

use crossbeam_channel::{select, unbounded};
use std::time::Duration;

fn main() {
    let (s1, r1) = unbounded::<i32>();
    let (s2, r2) = unbounded::<i32>();
    s1.send(10).unwrap();

    select! {
        recv(r1) -> msg => println!("r1 > {}", msg.unwrap()),
        recv(r2) -> msg => println!("r2 > {}", msg.unwrap()),
        default(Duration::from_millis(100)) => println!("timed out"),
    }
}

0x04 使用 dbg!() 代替 println!()

如果你是在調試代碼,那麼我推薦你使用 dbg!() 這個宏,它可以用更少的代碼來輸出更多的信息。示例代碼如下:

fn main() {
    let test = 5;

    println!("{}", test); // 輸出: 5
    dbg!(test);// 輸出:[src/main.rs:4] test = 2
}

0x05 類似 Golang 中的 defer 操作

如果你熟悉 Golang,那你肯定知道 defer 用於註冊延遲調用。像在使用原始指針和關閉 Sockets 時釋放內存都會用到。當然在 Rust 中除了 RAII 模式之外,也可以使用 scopeguard crate 來實現 “clean up” 操作。示例代碼如下:

#[macro_use(defer)] extern crate scopeguard;

fn main() {
    println!("start");
    {
        // 將在當前作用域末尾執行
        defer! {
           println!("defer");
        }

        println!("scope end");
    }
    println!("end");
}

程序執行結果:

start
scope end
defer
end

0x06 部分工具地址

Cow 文檔:https://doc.rust-lang.org/std/borrow/enum.Cow.html

Crossbeam Github:https://github.com/crossbeam-rs/crossbeam

scopeguard crate :https://docs.rs/scopeguard/latest/scopeguard/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_bm3RJCvGBn9UOpAM-s-bw