简体   繁体   中英

How to return struct in Rust without 'use of moved value' error?

I think the problem I'm running into with this code is that the struct I'm trying to return has variables that are strings. Currently I am querying an InfluxDB database and storing the result in the result variable. The print line towards the bottom of my function confirms that the index it correctly and is printing

IotData { time: 2021-12-27T14:01:34.404593Z, device_id: "1000", transaction_date: "27-12-2021", transaction_time: "14:01:34", usage: 8 }

How do I return this struct? I added the Clone attribute to the struct and return the clone since I encountered the has not attribute 'Copy' error, but now I am receiving the error, use of moved value: 'result' . I am new to Rust and don't quite understand ownership. My next guess is that I need to add lifetimes to my function and return the reference instead, but am not sure where to go from here.

Code Dump:

use influxdb::{ Client, ReadQuery};
use chrono::{ Utc };
extern crate serde;
extern crate serde_json;
use serde_derive::{ Serialize, Deserialize };

#[derive(Serialize, Deserialize, Debug, Clone)]
struct IotData {
    time: chrono::DateTime<Utc>,
    device_id: String,      
    transaction_date: String,
    transaction_time: String,
    usage: i64,
}

pub async fn pull(last_time: u64) -> IotData {
    let client = Client::new("http://localhost:8086", "PuPPY");
    let query_text = format!("
        SELECT * 
        FROM device_data 
        WHERE time > {} 
        ORDER BY time 
        LIMIT 1", last_time);
    let read_query = ReadQuery::new(query_text);
    let result = client
        .json_query(read_query)
        .await
        .and_then(|mut db_result| db_result.deserialize_next::<IotData>()); 
    println!("{:?}", result.unwrap().series[0].values[0]); 
    return result.unwrap().series[0].values[0].clone();
}

Minimized example yielding the essentially same error:

pub fn pull<T: std::fmt::Debug>(opt: Option<T>) -> T {
    println!("{:?}", opt.unwrap());
    opt.unwrap()
}

Playground
The error is this:

error[E0382]: use of moved value: `opt`
   --> src/lib.rs:3:5
    |
1   | pub fn pull<T: std::fmt::Debug>(opt: Option<T>) -> T {
    |                                 --- move occurs because `opt` has type `Option<T>`, which does not implement the `Copy` trait
2   |     println!("{:?}", opt.unwrap());
    |                          -------- `opt` moved due to this method call
3   |     opt.unwrap()
    |     ^^^ value used here after move
    |
note: this function takes ownership of the receiver `self`, which moves `opt`
help: consider calling `.as_ref()` to borrow the type's contents
    |
2   |     println!("{:?}", opt.as_ref().unwrap());
    |                          +++++++++

(By the way, if you're reading your errors from IDE, you might not see most of this. That's the general advice: confusing compiler errors in IDE are usually more clear in console, where they are not trimmed)

Here, it's easy to see the issue: Option::unwrap consumes self , since that's the only way for it to yield the owned value. So, then we unwrap the incoming Option to print its contents, we destroy it for good - there's nothing more to return.

To fix it, we can do one of the following:

  • Just follow the compiler suggestion and add as_ref before first unwrap . In this case, we will consume not the Option<T> , but only the shared reference to it, which can be freely used without touching the value.
  • Remove the println! , since it seems to be purely debugging information anyway.
  • Unwrap the Option once, and then use the unwrapped value twice:
pub async fn pull(last_time: u64) -> IotData {
    // --snip--
    let value = result.unwrap().series[0].values[0];
    println!("{:?}", value); 
    return value;
}

Note also that you don't really need clone in any case - again, Option::unwrap returns an owned value, so you don't have to clone it explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM