问题的标题可能没有抓住这个问题的本质,我很乐意进行编辑。
我刚刚开始用 Rust 写作,正在编写一个小程序来学习
Rust
和包 Reqwest
。
这是我的小程序。我不明白为什么从
HashMap<&str, &str>
更改为 HashMap<String, String>
可以使其工作,而 cookie 仍然只存在于范围内?我也在代码中评论了我的疑问。
use reqwest::cookie::Jar;
use reqwest::{Client, Url};
use std::sync::Arc;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let jar = Jar::default();
let raw_url = "https://www.google.com";
let url = Url::parse("https://www.google.com").unwrap();
jar.add_cookie_str("session=1", &url);
let jar = Arc::new(jar);
let client_builder = Client::builder();
let client = client_builder
.cookie_provider(Arc::clone(&jar))
.build()?;
let response = client.get(raw_url).send().await?;
let headers: &HeadersMap = response.headers();
let cookies: Impl Iterator<Item=Cookie>+Sized = response.cookies();
// let mut cookie_map = HashMap::<String, String>::new(); // this would work;
let mut cookie_map = HashMap::<&str, &str>::new(); // impl<'a> Cookie<'a>
let mut header_map = HashMap::<&str, &str>::new(); // live as long as the programme
for cookie in cookies { // declared borrowed value here, hence the lifetime kicks in
// Error: cookie does not live long enough
cookie_map.insert(cookie.name(), cookie.value());
// cookie_map.insert(cookie.name().to_string(), cookie.value().to_string());
// with `to_string` we have taken ownership of the value; is this why it's working?
}
// cookie dropped while still borrowed here;
// kv pairs are both borrowed values that have a lifetime `'a` which ends here
// and cookie_map apparently continues to exist, hence the error (this is my guess)
for (k, v) in headers.iter() {
match v.to_str() {
Ok(val) => header_map.insert(k.as_str(), val),
Err(_) => panic!()
};
}
for (hk, kv) in header_map {
println!("header name is {}, header value is {}", hk, kv);
}
Ok(())
}
这是
cargo.toml
:
[package]
name = "tester"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "tester"
test = false
bench = false
[dependencies]
reqwest = { version = "0.11", features = ["blocking", "json", "cookies"] }
tokio = { version = "1", features = ["full"] }
futures = "0.3"
reqwest_cookie_store = "0.7.0"
我已经在节目中评论了我的疑惑。
根据要求,这里提供了
cargo check
错误日志。
error[E0597]: `cookie` does not live long enough
--> src/tools/fetcher.rs:32:32
|
31 | for cookie in cookies {
| ------ binding `cookie` declared here
32 | cookie_map.insert(cookie.name(), cookie.value());
| ---------- ^^^^^^ borrowed value does not live long enough
| |
| borrow later used here
33 | }
| - `cookie` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
error: could not compile `data_fetcher` (bin "data_fetcher") due to 1 previous error
cookie
仅在循环的一次迭代期间存在。 &str
是对字符串的引用,因此引用的值必须至少与引用所在的 HashMap
一样长。但是由于 cookie
在迭代后被销毁,因此该值会丢失。
解决方案是取得
&str
的所有权。这就是您通过将类型更改为 String
所做的事情。