代码之家  ›  专栏  ›  技术社区  ›  Coldchain9

将unwrap_or/unwrap_or_else与函数型铸造一起使用的惯用方法

  •  0
  • Coldchain9  · 技术社区  · 1 年前

    我有一种情况,我想通过 reqwest::header::HeaderValue

    我使用

    #[tokio::main]
    async fn main() -> Result<(), reqwest::Error> {
        let url = "https://httpbin.org/get";
        let resp = reqwest::Client::new().get(url).send().await?;
    
        // read response headers
        // default if the header does not exist
        let resp_headers: &str = resp
            .headers()
            .get("content-length")
            .unwrap_or(&reqwest::header::HeaderValue::from_str("100").unwrap())
            .to_str()
            .unwrap_or("100");
        println!("{}", resp_headers);
    
        Ok(())
    }
    
    

    这似乎不太习惯,也不会编译。寻找如何处理这样的场景,其中有几个必要的展开来处理并将类型转换为所需的最终结果。

    1 回复  |  直到 1 年前
        1
  •  3
  •   drewtato    1 年前

    您可以使用命名块和let else语句。

    let resp_headers: &str = 'block: {
        let Some(content_length) = resp.headers().get(reqwest::header::CONTENT_LENGTH) else {
            break 'block "100";
        };
        let Ok(content_length) = content_length.to_str() else {
            break 'block "100";
        };
        content_length
    };
    

    或者,如果要保持两个展开值相同,可以使用 Option::and_then .

    let resp_headers: &str = resp
        .headers()
        .get(reqwest::header::CONTENT_LENGTH)
        .and_then(|content_length| content_length.to_str().ok())
        .unwrap_or("100");
    

    或者你可以把它放在一个函数中并使用 ? .

    fn read_content_length(resp: &reqwest::Response) -> Option<&str> {
        resp.headers()
            .get(reqwest::header::CONTENT_LENGTH)?
            .to_str()
            .ok()
    }
    
    let resp_headers: &str = read_content_length(&resp).unwrap_or("100");
    

    但特别针对 content-length 页眉,有 Response::content_length .

    let resp_headers: u64 = resp.content_length().unwrap_or(100);