014 Rust 非同步程式設計,遞迴

linghuyichong發表於2020-07-15

在內部,async fn建立一個狀態機型別,其中包含每個正在等待的子Future。那麼,當涉及到遞迴的時候怎麼辦呢?

示例1

  • 原始碼
use futures;

async fn first() {}
async fn second() {}

async fn foo() {
    first().await;
    second().await;
}

fn main() {
    futures::executor::block_on(foo());
}
  • 配置

    [dependencies]
    futures = "0.3"
  • 說明

編譯器會async塊生成對應的結構體,上面的例子生成的結構體如下:

enum Foo {
    First(first),
    Second(second),
}

示例2

那麼,當對應到遞迴會是什麼樣的呢?

  • 原始碼
use futures;

fn re() {
    re().await;
    re().await;
}

fn main() {
    futures::executor::block_on(re());
}
  • 說明

執行該程式報錯。編譯器對應的展開可能如下:

enum Re {
    First(Re),
    Second(Re),
}

顯然,這樣創造了一個無限尺寸大小的型別,因此報錯。

解決辦法

那麼我們要使用遞迴怎麼辦?只需要使用Box就可以了,不過對應的限制是需要變成同步函式。

  • 原始碼
use futures::future::{BoxFuture, FutureExt};

fn re() -> BoxFuture<'static, ()> {
    async move {
        re().await;
        re().await;
    }.boxed()
}

fn main() {
    re();
}
  • 配置
    [dependencies]
    futures = "0.3"

執行ok。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章