Rust后端开发者必读:为何拥抱TypeScript是你的下一个超能力

从JS的混沌到TypeScript的禅定:一个Rust后端程序员的顿悟 哥们,让我猜猜。 你是不是一个后端程序员?每天和 Java 的 Spring、Rust 的 Axum 或者 Python 的 Django 亲密无间,享受着强类型、严谨架构带来的那种“一切尽在掌握”的快感? 然后,你瞥了一眼隔壁前端同事屏幕上花花绿綠的 JavaScript 代码,嘴角是不是划过一丝不屑? “切,这玩意儿也叫编程?” 如果被我说中了,别紧张。因为,我曾经也和你一模一样。 我热爱 JavaScript,从它还野得像个没人管的疯孩子时,我就在它身边了。不是因为它有多优雅,也不是因为它逻辑多清晰,而是因为它拥有其他语言无法企及的一样东西: 那就是在浏览器里、在每一个屏幕上呼风唤雨的、最原始的统治力! 今天,很多人看着被 TypeScript、React 全副武装的现代 JavaScript,点点头说:“嗯,现在总算能用了。” 但我,早在它“从良”之前,就看到了它的价值。 这篇文章不是一篇教程。这是一个后端老兵从**“鄙视”到“真香”**的心路历程。如果你也是一个还在对 JS 持有偏见的后端开发者,我只想对你说一句话: 别再抗拒 Web 的浪潮了,你应该去驾驭它! 想当年,JavaScript 就是个狂野的西部世界 在那个遥远的 2010 年代,写 JS 简直就像蒙着眼睛走钢丝。 全局变量满天飞,一不小心就污染了整个世界。 == 和 === 的爱恨情仇,能让你在调试时怀疑人生。 没有模块,没有类型,更别提什么代码检查工具了。 IE、Chrome、Firefox 三国鼎立,一段代码,三种死法。 那时候,你不是在写应用,你是在雷区里跳舞。 比如下面这段远古代码,现在看简直是“犯罪现场”: // 蛮荒时代的JS代码 function doStuff(a, b) { if (a == b) { // 天知道这里会发生什么隐式转换 alert("它们匹配了"); } } 但即便如此,我还是爱死了那种感觉。那就像是在“黑入”现实世界。我用最原始的 DOM 操作,写出了表单、动画、幻灯片。虽然代码丑得不忍直视,但它能跑,而且跑在每个人的电脑上! 黎明前的曙光:jQuery、ES6 和理智的回归 然后,变革的浪潮来了。 jQuery 横空出世,这位“带善人”让操作 DOM 变得不再那么反人类。 JSON 成了 API 的通用语,前后端总算有了共同的沟通方式。 ES6 带着天神下凡,let/const、箭头函数、Promise……它让 JS 看起来终于像一门“正经”语言了。 Node.js 炸开了后端的大门,JS 第一次走出了浏览器,开始在服务器端搅动风云。 突然之间,JS 不再只是个浏览器里的“小丑脚本”,它成了一门真正的语言。 ...

July 30, 2025 · 2 min · 279 words · 梦兽编程

5个常见的Rust生命周期错误及其修复方案

还在死磕 Rust 生命周期?搞懂 ‘a’ 的真正含义,悄悄卷赢所有同事 关注梦兽编程微信公众号,幽默学习Rust。 欢迎来到 Rust 的世界,勇敢的开发者!在这里,你将遇到一位严厉但慈爱的守护神——借用检查器 (Borrow Checker)。它赋予了 Rust 无与伦比的内存安全,但也带来了一个让无数新手闻风丧胆的神秘符号:'a。 这个小小的撇号,看起来像是古代符文,充满了神秘感。它到底是什么?是时间?是魔法? 别慌,让我为你揭开它的神秘面纱。生命周期(Lifetime)无关乎时间,而关乎“作用域”。它就像一份“契约”,你用它来向那位守护神(借用检查器)承诺,你借用的东西在被使用期间,绝对是活着的、有效的。 今天,我们就来盘点一下新手最常踩的几个“生命周期天坑”,并告诉你如何像个老手一样优雅地爬出来。 1. 结构体生命周期:修复 missing lifetime specifier 错误 很多新手想当然地以为,在结构体里放个引用,就像放个普通变量一样简单。 你以为这样可行: struct User { name: &str, // 致命错误! } 守护神的低语(编译器报错): error[E0106]: missing lifetime specifier (“喂,你借了东西,却没告诉我能借多久,我可不答应!”) 💡 神之改造:签下生命周期契约 struct User<'a> { name: &'a str, } 看,我们加上了 <'a>。这就像一份契约,你在向 Rust 郑重承诺:“嘿,这个 User 结构体,以及它里面的 name 引用,它们的寿命都不能超过一个叫做 'a 的生命周期。” 这样一来,守护神就放心了,它知道你借用的 name 不会提前“溜走”。 2. 函数返回引用:解决生命周期不匹配问题 这可能是最常见的错误。你写了一个函数,想从两个引用里返回一个,比如返回更长的那个字符串。 你天真地写下: fn longest(a: &str, b: &str) -> &str { if a.len() > b.len() { a } else { b } } 守护神的低语: "Function returns a reference that may not live long enough." (“你要还我一个引用,可这个引用的‘出身’我不清楚。万一它来自一个短命的家伙,我怎么保证安全?”) ...

July 24, 2025 · 2 min · 283 words · 梦兽编程
Rust Traits和Generics常见陷阱指南

Rust内卷终极指南:5个让同事高攀不起的Trait与泛型骚操作

Rust内卷终极指南:5个让同事"高攀不起"的Trait与泛型骚操作 关注梦兽编程微信公众号,幽默学习Rust 你好,勇敢的Rustacean(Rust开发者)! 你是否曾被Rust的编译器"按在地上摩擦"?面对着一屏幕天书般的错误信息,怀疑自己是不是选错了编程语言?别怕,你不是一个人在战斗。 Rust最强大的武器,莫过于它的"零成本抽象"能力。而这套武功的核心秘籍,就是Traits(特性)、Generics(泛型)和Where(约束)。用好了,你的代码会像诗一样优雅,像F1赛车一样迅猛。 但……如果用错了呢?它们会瞬间变成一锅让你头皮发麻的"意大利面",编译错误能绕地球三圈,足以把任何一个编程新手吓得连夜卸载Rust。 今天我将为你揭示并填平那些最常见的Trait与泛型"天坑"。坐稳了,发车! 天坑一:屠龙刀用来切菜 —— 不必要的泛型滥用 想象一下,你拥有了一把削铁如泥的屠龙宝刀,但你每天都用它来切土豆丝。是不是有点大材小用了? 你可能正在犯的错: // 看起来没毛病,对吧? fn print_value<T: std::fmt::Debug>(value: T) { println!("{:?}", value); } 技术上讲,这代码能跑。但问题是,如果你在整个项目中,调用这个函数时传进去的永远都只是一个i32类型,那你为什么要用泛型? 你为了一个根本不存在的"灵活性",凭空增加了代码的复杂度。编译器需要为每个具体类型进行"单态化"(Monomorphization),生成额外的代码。这就像你为了偶尔可能要招待一位国王,把家里所有房间都按五星级总统套房装修了一遍,结果来的永远是邻居老王。 更明智的做法: // 朴实无华,但高效 fn print_value(value: i32) { println!("{:?}", value); } 我的神之箴言: 记住,泛型是你的超能力,但别过早地炫耀肌肉。只有当你真正需要处理多种类型时,再去召唤泛型这条"神龙",否则,从具体类型开始,永远是最高效、最清晰的选择。 天坑二:代码界的"意面"—— 杂乱无章的Trait约束 当你的函数需要不止一个泛型参数,并且每个参数都带着一堆约束时,你的函数签名很快就会变成一碗看不懂的"意大利面条"。 你可能正在犯的错: // 一个参数还行,两个试试? fn log_json<T: serde::Serialize + std::fmt::Debug + Clone>(item: T) { // ... } 当约束条件越来越多,尖括号 <> 里的内容会变得越来越长,可读性直线下降,维护起来简直是噩梦。 更明智的做法:让where子句来拯救你! where子句就像一个专业的图书管理员,它会把所有乱七八糟的约束条件整齐地收纳起来,让你的函数签名清爽得像夏天的风。 // 使用 where,代码瞬间清爽 fn log_json<T>(item: T) where T: serde::Serialize + std::fmt::Debug + Clone, { // ... } // 多个参数?小菜一碟! fn process_data<T, U>(a: T, b: U) where T: Clone + std::fmt::Debug, U: Default + std::fmt::Debug, { // ... } 我的神之箴言: 把约束条件从尖括号里解放出来,交给where子句去管理。这不仅是风格问题,更是代码可读性和可维护性的生命线。 ...

January 27, 2025 · 2 min · 294 words · 梦兽编程

Rust错误处理指南:精通Result、Option与unwrap/expect

还在用 unwrap()?同事们都偷偷在学这套 Rust 错误处理"组合拳",再不看就晚了! 你好,未来的 Rust 大神。我知道你为何而来。你听说 Rust 是一头性能猛兽,安全可靠,于是满怀激情地跳了进来。然后,你遇到了它的第一个下马威——错误处理。 和那些用 try-catch 给你铺好柔软安全网的语言不同,Rust 直接塞给你一把利剑和一个盾牌——Result 和 Option。它对你说:“上吧,勇士!命运掌握在你自己手中。” 很多新手没走两步,就掉进了各种陷阱。但你不同,因为你正在阅读这篇文章。今天,我就带你拆解 Rust 错误处理的五大“天坑”,并传授你一套能让同事们惊呼“优雅”的武林秘籍。 目录 第一式:戒掉心魔 unwrap() 第二式:正视编译器的"唠叨" 第三式:告别"金字塔",用 ? 变身优雅魔术师 第四式:不在公共场所"引爆炸弹" 第五式:分清 Option 和 Result 总结:你的"封神"之路 第一式:戒掉心魔 unwrap(),别让你的程序"自爆" 每个 Rust 新手都曾对 .unwrap() 爱不释手。它就像恶魔的低语,在你耳边说:“别担心,这里肯定有值,直接拆开用吧!” 于是,你写下了这样的“YOLO 代码”: fn main() { let input = "hello"; // 砰!你的程序在这里灰飞烟灭 let num: i32 = input.parse().unwrap(); } 这可不是什么可以被捕获的“异常”,这是程序的“猝死”,是 panic!,是拉响手雷与代码同归于尽。在生产环境里这么干,你的同事会顺着网线来揍你。 大神操作: 真正的勇士,敢于直面可能发生的“错误”。 用 match 来做一次精密的“外科手术”: fn main() { let input = "hello"; match input.parse::<i32>() { Ok(num) => println!("转换成功: {num}"), Err(e) => println!("出错了,凡人: {e}"), } } 或者,给它一个“备胎”,如果失败了就用默认值: ...

December 19, 2024 · 3 min · 439 words · 梦兽编程
Rust异步编程:7个导致性能瓶颈和崩溃的常见错误

Rust异步编程:7个导致性能瓶颈和崩溃的常见错误

你的Rust异步代码为什么又慢又容易崩溃?本文揭示了7个致命陷阱,从被遗忘的Future到错误的锁机制,并提供详细解决方案,助你编写高效、健壮的异步程序。

July 31, 2024 · 2 min · 397 words · 梦兽编程
Rust 惰性迭代器常见陷阱解析

Rust 迭代器懒惰陷阱:代码不执行的 3 大常见原因

“见鬼!我的代码怎么不执行?”—— Rust 迭代器常见“懒惰”陷阱大揭秘" 关注梦兽编程微信公众号,轻松入门Rust。 你是否也曾对着一段自认为天衣无缝的 Rust 代码,抓耳挠腮,百思不得其解? “我明明让它打印数字了,怎么控制台空空如也,连个鬼影都没有?” 你反复检查,逻辑清晰,语法正确,甚至开始怀疑人生,是不是自己的电脑中了什么邪。 别慌,我的朋友。你没有疯,电脑也没坏。你只是不小心掉进了 Rust 迭代器最著名、也最迷人的陷阱里——它,实在是太“懒”了! Rust 的迭代器就像一位天赋异禀但极其懒散的绝世高手。你把一本武功秘籍(比如 .map())交给他,他只是拿在手里翻了翻,记下了招式,但压根就没打算开始练。除非你冲他大吼一声:“开打!”(比如使用 .collect() 或 for 循环),否则他能保持那个姿势直到天荒地老。 今天,我就以“文案之神”的名义,带你彻底揭开这位“懒惰大师”的神秘面纱,让你从此告别“代码不翼而飞”的灵异事件。 陷阱一:皇帝不急太监急——光说不练的 map 这是最经典的“灵异事件”现场。你满怀期待地写下: ❌ 错误的“意念驱动”代码: fn main() { let nums = vec![1, 2, 3, 4, 5]; // 期望它能打印 1, 2, 3, 4, 5 nums.iter().map(|x| println!("{}", x)); } 结果呢? 一片寂静,啥也没发生。 这究竟是为什么? 记住我的比喻:.map() 只是给了迭代器一张“改造计划书”。它告诉迭代器:“喂,伙计,你的任务是把每个路过的数字都打印出来。” 但迭代器这位懒汉,仅仅是收下了计划书,点了点头,然后……就没然后了。他根本没动身!因为你没有给他一个“执行”的命令。 ✅ 正确的“强制执行”姿势: 想让它动起来?你得在链条的最后,给它一个明确的“收尾动作”(我们称之为“消费”)。 最简单粗暴的方法是使用 for_each,它的存在就是为了执行这类“有副作用但不需要结果”的操作。 fn main() { let nums = vec![1, 2, 3, 4, 5]; // 方法一:使用 for_each 来消费 nums.iter().map(|x| println!("{}", x)).for_each(|_| ()); // for_each 里的闭包 `|_| ()` 是个空操作,像是在说:“干活就行,不用汇报!” } 当然,更符合直觉、更地道的方式是直接用 for 循环,这本身就是一种消费行为。 ...

July 26, 2024 · 2 min · 291 words · 梦兽编程

Rust借用检查器详解:所有权、借用与生命周期入门指南

别再怕Rust的借用检查器了!本文把它比作你最忠诚的保镖,用有趣的方式带你彻底搞懂所有权、借用和生命周期,让你轻松写出安全高效的Rust代码。

July 26, 2024 · 1 min · 133 words · 梦兽编程

Bun (Elysia) vs Rust (Actix) 性能实测:新贵与老炮的极限对决

我拿 Bun 和 Rust 干了一架,结果 Bun 的血条直接被打没了… 哥们儿,我跟你讲,在咱们程序员这圈儿里,总有那么几个话题能吵翻天。比如 “PHP是不是最好的语言?”,再比如,今天的主角:JavaScript的新贵Bun,和性能界的老炮儿Rust,到底谁更快? 光说不练假把式。很多人都觉得,这还用问?肯定是Rust啊! 没错,但我就特别好奇,这个“快”,到底是快一点点,还是快到离谱?所以,我搭了个擂台,让它俩正儿八经地干了一架。 结果嘛……这么说吧,场面一度非常“残忍”。 先介绍下两位选手 红方选手:Bun (配Elysia框架) 你可以把它想象成JS圈儿里现在最火的“小鲜肉”,人长得帅(开发体验好),功夫还很全(自带一堆工具),号称速度超快,拳打Node.js,脚踢Deno,是无数前端和全栈开发者的“新宠”。 蓝方选手:Rust (配Actix框架) 这位就不是小鲜肉了,这是性能界硬核得不能再硬核的“重量级拳王”。没啥花里胡哨的,主打一个稳、准、狠。它的字典里就没有“内存泄漏”和“性能妥协”这几个字,是系统级、底层开发领域的绝对霸主。 擂台规则:不服跑个分! 为了公平,我给它俩安排了同一个任务:做一个URL短链服务。这活儿特能考验一个后端框架的真实水平,因为请求量一上来,谁在“裸泳”就一清二楚了。 测试环境是我的M4 MacBook Air,数据库用的是PostgreSQL。 我让10个、50个、甚至100个虚拟用户同时对着它俩疯狂发请求,看看谁先撑不住。 战况揭晓:这哪是比赛,这是单方面吊打啊! 第一项,比“出拳速度”(吞吐量RPS) 简单说,就是一秒钟能处理多少个请求。 我跟你说,当100个用户一起上的时候,我看到数据都惊了: Bun/Elysia:14,295 RPS Rust/Actix:143,514 RPS 你没看错,小数点也没点错。Rust的出拳速度,是Bun的整整10倍! Bun同学在旁边累得呼哧带喘,Rust大哥在那儿跟没事人一样,甚至还想点根烟。这血条,基本上算是被打空了。 第二项,比“反应速度”(延迟Latency) 这项更要命,它决定了你的用户体验顺不顺滑。 就好比,你点个按钮,Rust那边“唰”一下就响应了,P99延迟才11.97毫秒,你根本感觉不到。 Bun呢?在高压下就有点“反应迟钝”了,P99延迟干到了111.95毫秒。这个延迟,用户是能明显感觉到的,就像网突然卡了一下。对于追求丝滑体验的应用来说,这挺致命的。 所以呢?咱是不是以后就不用Bun了? 别急着下结论!技术这东西,从来不是非黑即白。 Rust是快,快到变态。但这玩意儿的学习曲线也一样“变态”,想写好它,得掉不少头发。 这就好比你出门,去楼下便利店买瓶水,你肯定不会开一辆F1赛车去吧?虽然F1贼快,但你光是启动、热车、停车就得折腾半天,人家骑共享单车的哥们儿早都买完水回家打游戏了。 这次对决,真正告诉我们的是“看菜下饭”: 啥时候用Bun? 当你需要快速把产品做出来的时候!搞个创业项目、做个MVP、快速迭代功能,Bun和它背后的整个JS生态,能让你爽到飞起。开发效率高,社区庞大,遇到问题分分钟就能找到解决方案。在绝大多数场景下,它的性能都绰绰有余。 啥时候必须上Rust? 当你的项目是那种“公司命脉”级的核心业务时!比如交易系统、支付网关、或者任何预见到未来会有毁天灭地般流量的场景。这时候,你牺牲一点开发速度,换来的是极致的性能、铁一般的稳定性和晚上能睡得踏实的安心感。 总之一句话: 用Bun,图的是今天爽;用Rust,为的是明天稳。 想看更多这种用大白话聊技术的干货?来我这儿坐坐。 关注梦兽编程微信公众号,解锁更多黑科技。 原文参考:URL shortener service benchmarking: Bun (Elysia) vs Rust (Actix)

July 22, 2024 · 1 min · 61 words · 梦兽编程
Rust智能指针三大神器:Box、Rc、RefCell

Rust智能指针详解:Box、Rc与RefCell的实用指南

Rust所有权:别再死记硬背了!把智能指针当“玩具”玩,三巨头(Box, Rc, RefCell)让你秒懂内存管理 嘿,朋友!还在被 Rust 的所有权系统搞得头昏脑胀吗?什么借用、生命周期的,是不是感觉像在考一本永远也搞不懂的法律条文? 别怕,今天咱们不讲那些大道理。咱们把代码世界想象成一个游乐场,把数据想象成心爱的玩具,看看 Rust 是怎么通过几个“智能”的“玩具箱”(也就是智能指针),让内存管理变得既安全又有趣的。 一号玩具箱:Box<T> —— “这玩具太大了,我家放不下!” 想象一下,你买了个超酷的乐高千年隼号,但它太大了,你的小房间(栈 Stack)根本放不下。怎么办? 你老妈(编译器)说:“傻孩子,放不下就租个外面的储物柜(堆 Heap)嘛!” Box<T> 就是那个帮你租储物柜、再把玩具放进去的“万能箱子”。 它很简单,就干一件事:把你的数据从栈上,搬到堆上。而你手里呢?只用拿着一张指向储物柜的“钥匙”(也就是指针)。这张“钥匙”本身很小,你的房间(栈)肯定放得下。 // 房间(栈)里放不下 100 万个整数 // let a = [0; 1000000]; // 这可能会让程序崩溃 // 用 Box 把它放到外面的储物柜(堆)里 let b = Box::new([0; 1000000]); // 轻松搞定! 最关键的是,这个“储物柜”的钥匙,同一时间只能有一个主人。你把钥匙给了你的朋友,你就不能再用了。这,就是Box<T>的单一所有权。当“你”(持有Box的变量)离开游乐场(作用域)时,Rust 会自动帮你把储物柜退掉,里面的玩具也销毁了,干干净净,绝不健忘。 什么时候用它? 当你的“玩具”太大,栈上放不下时。 当你需要一个“玩具”清单,但清单里每个玩具的大小都不一样时(特征对象 Box<dyn Trait>)。 当你创造了一个会“自己生自己”的递归玩具时(比如链表)。 二号玩具箱:Rc<T> —— “我的玩具,大家可以一起看!” 现在,你有一个绝版的漫画书(一份数据),你的好几个朋友(代码的不同部分)都想看。 如果用Box,你把漫画书(所有权)给了朋友A,朋友B和C就没得看了。这显然不行,友谊的小船说翻就翻。 于是,Rc<T>(Reference Counting,引用计数)闪亮登场!它像一个“图书管理员”。 Rc<T>会把你的漫画书放在一个公共阅览室(还是在堆上),然后给每个想看的朋友发一张“借书卡”(克隆一个Rc指针)。它内部有一个计数器,记录着现在有多少张“借书卡”被发出去了。 use std::rc::Rc; // 把漫画书《Rust从入门到放弃》用 Rc 管理起来 let book = Rc::new(String::from("Rust从入门到放弃")); println!("当前借阅人数: {}", Rc::strong_count(&book)); // 输出 1,只有你自己 // 朋友A借走了 let friend_a = Rc::clone(&book); println!("当前借阅人数: {}", Rc::strong_count(&book)); // 输出 2 // 朋友B也借走了 let friend_b = Rc::clone(&book); println!("当前借阅人数: {}", Rc::strong_count(&book)); // 输出 3 当一个朋友看完,把“借书卡”销毁时(变量离开作用域),计数器就减一。当计数器归零,说明没人再看这本漫画书了,图书管理员Rc就会把书处理掉,回收内存。 ...

January 15, 2024 · 1 min · 172 words · 梦兽编程

Rust Async内幕:让代码学会摸鱼,效率还能翻倍的秘密!

Rust Async内幕:让代码学会"摸鱼",效率还能翻倍的秘密! 关注梦兽编程微信公众号,幽默学习Rust。 你好,未来的Rust大师!今天我们来聊一个神奇的话题:异步编程(Async)。 你可能在JavaScript或Python里和它打过照面,觉得它就像个幕后英雄,默默处理着一切。但在Rust里,这位“英雄”的行事风格可完全不一样。它不玩“魔法”,一切都摆在明面上,既明确又高效,而且编译后几乎是“零成本”的! 准备好脑洞大开了吗?我们这就发车! 第一站:async 关键字,一个“稍后处理”的承诺 想象一下,你让一个机器人帮你倒水。你对它说:“去倒杯水。” 在普通的同步世界里,这个机器人会立刻放下手头所有事,跑到厨房,找到杯子,打开水龙头,等水满,然后端回来给你。在这整个过程中,它(以及你)都在原地“阻塞”着,啥也干不了。 但如果这是一个 async 机器人呢? async fn pour_water() { println!("💧 好的,马上去倒水!"); } 当你调用 pour_water() 时,最奇妙的事情发生了:它什么都没做! 没错,它没有去倒水。它只是给了你一张“欠条”,专业点说,这叫 Future(未来)。这张欠条上写着:“我承诺,未来会去倒一杯水。” 这个 async 关键字,就像是在给任务打上一个“稍后处理”的标签。它本身不执行任何操作,只是打包了一个“未来会发生的事”。在Rust里,所有的 Future 都是天生的“懒虫”,你不催它,它绝不动弹。 第二站:Future,一张需要兑现的“未来”欠条 所以,这个 Future 到底是个啥? 你可以把它想象成一张详细的菜谱。比如一个计算 21 + 21 的 async 函数: async fn compute() -> u32 { 21 + 21 } 调用 compute() 得到的 Future,就是一张写着“把21和21加起来”的菜谱。菜谱本身并不能填饱肚子,它只是一个待完成的计算。 在编译器眼中,这个 Future 其实是一个实现了特定 trait(可以理解为接口或能力)的复杂结构体。它内部有一个核心方法叫 poll,像个不知疲倦的检查员,不断地问:“喂,菜做好了吗?能上菜了吗?” 不过别担心,你暂时不需要亲手去写这么底层的代码,Rust已经帮你把这一切都漂亮地隐藏在 async/await 语法糖之下了。 第三站:.await,兑现承诺的“催收电话” 既然 Future 这么懒,我们怎么才能让它动起来,真正地去“倒水”或“计算”呢? 答案就是拨打一个“催收电话”——使用 .await 关键字。 但是,光有催收员还不行,我们还需要一个“项目经理”来统筹全局。在Rust的世界里,这个项目经理就是 Runtime(运行时)。Rust标准库本身不带这玩意儿,你需要从社区“聘请”一个,其中最著名的就是 tokio。 use tokio; #[tokio::main] async fn main() { println!("我想要杯水..."); pour_water().await; // 喂,是倒水机器人吗?我现在就要水! println!("啊,水来了,真好!"); } 看到那个 #[tokio::main] 了吗?它就像是给你的 main 函数配备了一个全能的 tokio 项目经理。 ...

January 15, 2024 · 1 min · 185 words · 梦兽编程