Rust async 函数:会 “暂停” 的魔法函数,返回的是 “未来” 的承诺
async 函数:会 “暂停” 的魔法函数,返回的是 “未来” 的承诺
先从 “点咖啡” 理解什么是 async 函数
你去咖啡店点了一杯拿铁,店员说 “稍等,做好了叫你”,然后你就站在旁边刷手机 —— 这时候你没有傻等着,还能做别的事。这个 “点咖啡” 的过程,就像调用一个 async 函数:
- 普通函数是 “点完咖啡必须站在吧台前死等,啥也干不了”,直到拿到咖啡才走(同步执行);
- async 函数是 “点完就拿到一个‘取餐号’(Future),可以去干别的,咖啡好了再回来取”(异步执行)。
所谓async函数,就是能 “暂停工作” 的函数。它不会像普通函数那样一口气跑完,而是在遇到await关键字时 “打个盹”,把控制权交出去,让其他任务先执行。等await的事情办完了,它再从暂停的地方接着干。
啥是 Future?就是 “还没做好,但迟早给你” 的东西
当你调用async函数时,它不会立刻返回结果,而是返回一个Future(中文叫 “未来”)。这东西就像你点咖啡时拿到的取餐号 —— 它不是咖啡本身,但拿着它,你知道 “咖啡正在做,做好了会通知你”。
比如你写了个async fn make_coffee() -> String,调用它的时候不会立刻得到 “热拿铁”,而是得到一个Future对象。这个对象有两个状态:
- 没准备好(Pending):咖啡还在做;
- 准备好了(Ready):咖啡做好了,可以拿结果了。
就像取餐号不会自己把咖啡送过来,Future也不会自己 “跑起来”,得靠 “执行者”(Executor)来驱动 —— 比如咖啡店的厨师就是执行者,负责把 “取餐号” 对应的咖啡做出来。
暂停点(await):async 函数的 “休息站”
async函数里的await关键字,就是 “暂停点”。它像个休息站,告诉函数:“我现在要等个东西(比如网络请求、文件读取),你先暂停,让别人用用 CPU,等我完事了再叫你继续。”
举个例子:你用async函数写一个 “早晨流程”,包括 “煮咖啡” 和 “烤面包”,这两件事可以同时做:
rust
// 模拟煮咖啡(需要2秒)
async fn brew_coffee() -> String {
println!("开始煮咖啡...");
// 暂停2秒(实际中可能是等待咖啡机完成)
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
"香喷喷的咖啡".to_string()
}
// 模拟烤面包(需要1秒)
async fn toast_bread() -> String {
println!("开始烤面包...");
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
"酥脆的面包".to_string()
}
// 早晨流程(async函数)
async fn morning_routine() {
// 同时启动两个任务,而不是等咖啡煮完再烤面包
let coffee_future = brew_coffee();
let bread_future = toast_bread();
// 等待两个任务都完成(这里的.await就是暂停点)
let coffee = coffee_future.await;
let bread = bread_future.await;
println!("早餐好了:{} + {}", coffee, bread);
}
这个例子里,brew_coffee和toast_bread都是async函数,它们内部的sleep().await就是暂停点 —— 函数会在这儿 “休息”,让 CPU 去处理别的事(比如同时烤面包)。如果用普通函数,得先等 2 秒煮完咖啡,再花 1 秒烤面包,总共 3 秒;但用async/await,两件事同时做,总共只花 2 秒(等最慢的那个完成)。
为什么需要 async 函数?解决 “等不起” 的麻烦
想象你在网上买东西,付款时需要:
- 检查余额(调用银行 API,耗时 1 秒);
- 扣钱(调用支付接口,耗时 1.5 秒);
- 发送订单确认短信(调用短信接口,耗时 0.5 秒)。
如果用普通函数,这三件事得串行执行,总共花 3 秒,期间你的程序啥也干不了,就像 “卡住” 了一样。
但用async函数,你可以让这三个操作 “重叠” 进行:发起查余额请求后,不等结果回来就发起扣钱请求,再发起发短信请求。最后只等最久的那个操作(1.5 秒)完成就行,大大节省时间。
这就像快递员送三件货:普通函数是送完一件再取下一件;async函数是一次性把三件货的地址都输入导航,顺路依次送达,效率高多了。
给新手的 3 个实用建议
- 别把 async/await 当 “万能加速剂”:如果任务本身不需要 “等”(比如纯计算),用 async 函数反而会增加开销,就像买瓶矿泉水没必要用 “外卖跑腿”,自己下楼买更快。
- await 只能用在 async 函数里:就像 “休息站” 只能建在高速公路上,普通函数里不能用 await,强行用会报错。
- Future 要 “驱动” 才会跑:拿到 Future 后,如果不调用.await或者交给执行者(比如 tokio),它就永远是 “没准备好” 的状态,就像取餐号丢了,咖啡做好了也没人去拿。
两个标题
- async 函数:会 “暂停” 的魔法函数,返回的是 “未来” 的承诺
- 从点咖啡到写代码:聊聊 async 函数的 “暂停” 与 “未来”
简介
本文用 “点咖啡”“烤面包” 等生活场景,通俗解释了 async 函数的核心逻辑:它能通过 await 暂停执行,返回的 Future 就像 “取餐号”,代表 “未来会完成的任务”。结合具体案例对比同步与异步的区别,说明 async 函数如何提高程序效率,并给出新手避坑建议,帮你轻松理解这一异步编程利器。
#async 函数 #Future #暂停点 #异步编程 #await