【问题标题】:How can I extend the lifetime of a struct so that I can call tokio::run with it?如何延长结构的生命周期,以便可以使用它调用 tokio::run?
【发布时间】:2018-10-30 11:06:21
【问题描述】:

我有一个有效的功能:

extern crate tokio;

use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::Interval;

fn run(label: String) -> impl Future<Item = (), Error = ()> {
    Interval::new(Instant::now(), Duration::from_millis(1000))
        .for_each(move |instant| {
            println!("fire; instant={:?}, label={:?}", instant, label);
            Ok(())
        })
        .map_err(|e| panic!("interval errored; err={:?}", e))
}

fn main() {
    tokio::run(run("Hello".to_string()));
}

playground

我想创建一个结构,在这种情况下使用一个方法 run 来保存一些参数 (label),该方法将利用这些参数:

extern crate tokio;

use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::Interval;

struct Ir {
    label: String,
}

impl Ir {
    fn new(label: String) -> Ir {
        Ir { label }
    }

    fn run(&self) -> impl Future<Item = (), Error = ()> + '_ {
        Interval::new(Instant::now(), Duration::from_millis(1000))
            .for_each(move |instant| {
                println!("fire; instant={:?}, label={:?}", instant, self.label);
                Ok(())
            })
            .map_err(|e| panic!("interval errored; err={:?}", e))
    }
}

fn main() {
    let ir = Ir::new("Hello".to_string());
    tokio::run(ir.run());
}

playground

我得到的是:

error[E0597]: `ir` does not live long enough
  --> src/main.rs:28:16
   |
28 |     tokio::run(ir.run());
   |                ^^ borrowed value does not live long enough
29 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

我已阅读“Rust by Example”中的“Advanced Lifetimes”和“Validating References with Lifetimes”,但我仍然不明白如何修复它。
为什么ir 的寿命不够长?
我已经在我试图调用ir.run() 的同一范围内创建了它,所以我认为它会一直存在。

【问题讨论】:

  • 从 tokio 运行要求生命周期是静态的,tokio-rs.github.io/tokio/tokio/runtime/fn.run.html
  • 所以签名应该是fn run(&amp;self) -&gt; impl Future&lt;Item = (), Error = ()&gt; + 'static { ?
  • 我想但是我显然不够熟练,那次运行必须消耗self而不是作为参考。
  • @Stargateur 你是对的,消费self 解决了问题!

标签: rust


【解决方案1】:

如果你重写:

tokio::run(ir.run());

作为:

tokio::run(Ir::run(&ir))

错误变得更清楚了:

error[E0597]: `ir` does not live long enough
  --> src/main.rs:28:24
   |
28 |    tokio::run(Ir::run(&ir));
   |                        ^^ borrowed value does not live long enough
29 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

因为tokio::run 需要'static 的未来生命周期:

pub fn run<F>(future: F) 
where
    F: Future<Item = (), Error = ()> + Send + 'static, 

为避免生命周期问题,请考虑使用 Ir 值:

fn run(self) -> impl Future<Item = (), Error = ()>  {
    Interval::new(Instant::now(), Duration::from_millis(1000))
        .for_each(move |instant| {
            println!("fire; instant={:?}, label={:?}", instant, self.label);
            Ok(())
        })
        .map_err(|e| panic!("interval errored; err={:?}", e))
}

【讨论】:

  • 是的,它成功了,更重要的是我现在明白了为什么它需要这样!
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多