英文:
use of moved value: `response` value used here after move for types not implementing the Copy trait
问题
以下是翻译好的部分:
我有这段代码,它抛出以下错误:use of moved value: response value used here after move
。
错误来自于 response_body
变量使用了 response
变量并占用了它的所有权。我想要克隆 response
,或者将提取键(execution_id)的操作封装在一个函数中,并传递 response
的引用,但都没有成功。
我应该实现 Clone 或 Copy 特性,但无法为未在 crate 中定义的结构体实现它们。所以我不知道如何处理这种情况。
如何消除这个错误?谢谢。
英文:
I have this code which is throwing the following error: use of moved value: response value used here after move
.
use std::collections::HashMap;
use reqwest::Response;
use serde_json::json;
async fn error_example() -> (Response, String) {
let execute_url = "https://jsonplaceholder.typicode.com/todos/1";
let client = reqwest::Client::new();
let response = client.post(execute_url).send().await.unwrap();
let response_body = response.text().await.unwrap();
let response_body: HashMap<String, String> = serde_json::from_str(&response_body).unwrap();
let execution_id = response_body.get("userId").unwrap();
return (response, execution_id.clone()); // use of moved value: `response` value used here after move
}
The error come from the response_body variable using the response variable and taking ownership of it. I wanted to clone the response, or wrap the extraction of the key (execution_id) in a function and passing a ref of the response
but none worked.
I should have the Clone or Copy trait implemented but I can't implement it for struct not defined within the crate. So I don't know how to handle this case.
How can I get rid of the error ? Thanks
答案1
得分: 2
Reqwest的Response
类型实际上并不包含响应体。它基本上是一个开放的网络套接字,加上接受数据所需的状态。当你调用text
时,它直接从套接字构建一个String
。如果你想再次调用text
,你需要重新发送请求,因为Response
和套接字都不存储这些数据。
所以如果你想返回整个请求体,你可以返回刚刚创建的字符串。
let response_body = response.text().await.unwrap();
let response_map: HashMap<String, String> = serde_json::from_str(&response_body).unwrap();
let execution_id = response_map.get("userId").unwrap().clone();
(response_body, execution_id)
或者你可以返回头部、状态码或任何其他你需要的内容。Reqwest没有一种类型来表示已使用的响应,但你可以自己创建一个。
另一件事是,不必反序列化整个响应。你可以为只需要的字段创建一个结构体,这意味着你只需要分配一个String
,而且不需要克隆它。
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct OnlyUserId {
user_id: String
}
let only_user_id: OnlyUserId = serde_json::from_str(&response_body).unwrap();
let execution_id = only_user_id.user_id;
(response_body, execution_id)
英文:
Reqwest's Response
type does not really contain the response body. It's basically an open network socket plus the state needed to accept the data. When you call text
, it builds a String
straight from the socket. If you wanted to call text
again, you'd need to resend the request, since neither Response
nor the socket store this data.
So if you want to return the whole request body, you can return the string that was just created.
let response_body = response.text().await.unwrap();
let response_map: HashMap<String, String> = serde_json::from_str(&response_body).unwrap();
let execution_id = response_map.get("userId").unwrap().clone();
(response_body, execution_id)
Or you could return the headers, or status code, or whatever else you need. Reqwest doesn't have a type to represent a spent response, but you could make your own.
Another thing is that deserializing the entire response is not necessary. You can make a struct for just the field you need, which means you only need to allocate one String
, and you don't need to clone it.
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct OnlyUserId {
user_id: String
}
let only_user_id: OnlyUserId = serde_json::from_str(&response_body).unwrap();
let execution_id = only_user_id.user_id;
(response_body, execution_id)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论