资讯详情

从Hello World拆解Rust入门:例子驱动学习与工具链实操

📅 2026/10/11 3:47:43 | 华诺云谱 👁 阅读
从Hello World拆解Rust入门:例子驱动学习与工具链实操
很多人一提起 Rust第一反应就是“难、反人类、学习曲线陡”。我自己当年也是从 Hello World 开始碰 Rust 的但后来复盘发现真正劝退大多数人的并不是所有权和生命周期这两个“硬骨头”而是他们在第一天就选错了入手姿势一上来就抱着厚厚的一本语法书硬啃既不写代码也不看输出越看越虚。《通过例子学Rust》这本在线书的好处就是它从头到尾都在“用例子说话”。第一章的 Hello World 也只有三行代码但它并不是那种“随便印个字符串就完事”的简单演示——这一页背后几乎埋着 Rust 工具链、语法习惯和心智模型的全部引子。这篇文章我会把这一章拆开揉碎按我实际学习和跑代码的顺序带你把 Hello World 背后的东西全部榨干。无论你是零基础想入门还是写过别的语言想快速了解 Rust 的风格这一篇都能帮你把地基打牢。1. 为什么我推荐从第一个例子入手而不是先啃语法书1.1 例子驱动的学习方式好在哪我见过太多人学编程语言第一周全在背语法规则结果背到第三周开始写代码时发现自己什么也写不出来。“例子驱动”完全反过来先给你一个能跑、能看结果的完整例子再通过改一改、拆一拆来理解规则。Rust 尤其适合这种方式。它的语法虽然整体是 C 系那一套但细节习惯和传统语言差异不小比如默认不可变变量、表达式返回值、宏和函数的区分等等。这些点如果抽象地讲初学者很容易懵但放到一个具体的 Hello World 里每一处都非常直观——看输出、改代码、看报错多来几个回合语法自然就内化了。《通过例子学Rust》第一章看似简单但它给了你一个完整的“最小闭包”从源码到编译再到运行最后看到输出。这个过程一旦走通后面所有权、生命周期那些概念就有可依托的实验环境不会悬在空中。1.2 为什么第一章值得“慢学”而不是三分钟扫完第一次看到这三行代码时我其实有点不屑觉得这不就是“print 一个字符串”嘛。但后来真正动手折腾了一遍才发现这里面水很深。先看代码fn main() { println!(Hello, world!); }只从“能不能运行”来看这确实是最简单的程序。但从“理解 Rust 世界”来看这个小小程序已经包含了五个关键问题函数怎么声明程序入口到底在哪里println!那一行后面的感叹号是什么意思为什么语句结尾有分号整个程序没有return靠什么退出这些问题在第一章如果只是“看过”而不是“弄懂”后面学函数、宏、表达式时就会出现明显的理解断层。所以我一直建议第一章至少留一个小时别急着往后翻。把这一章的代码敲一遍、跑一遍、故意改坏再修好比看十遍理论都管用。2. 一个 Hello World 背后拆出的三层知识点2.1 第一层那三行代码的字面意思先逐行看。第一行fn main() {fn是 Rust 声明函数的关键字main是函数名也是整个可执行程序的入口一对小括号表示这个函数不接收任何参数花括号则开始一个代码块。第二行println!(Hello, world!);是函数体内的第一条语句。println!是一个宏它做的事情是向标准输出打印一行文本然后换行。双引号里的是字符串字面量分号表示这条语句结束。第三行就是关闭花括号。这里有几个容易忽略但非常重要的点。第一个是缩进Rust 不强制缩进但社区惯例是 4 个空格不用 Tab这种风格问题在后续写多行代码时很容易被编译器报错之外的 linter 提醒。第二个是分号Rust 里分号表示“这条语句到此为止”但 Rust 同时允许“不带分号的表达式”作为最后一行来返回值这个机制在 Hello World 里用不到却是后面写函数时避不开的核心规则。2.2 第二层编译与运行的过程Hello World 不是一个脚本它需要经过编译得到可执行文件。这里我用最原始的方式演示一次rustc main.rs ./mainrustc是 Rust 的编译器main.rs是我的源文件。执行rustc main.rs后目录下多了一个叫mainWindows 上是main.exe的可执行文件再直接运行它就能看到输出。这个过程看起来简单但意义很大Rust 是静态编译语言最终产物是本地机器码不依赖额外的解释器或虚拟机。也就是说编译出来的这个可执行文件可以直接拷贝到另一台配置差不多的机器上运行如果是动态链接可能还需要系统库但 Hello World 这里一般没问题。对比 Python、JavaScript 这类解释型语言你就能体会到“编译型”到底意味着什么所有类型检查、语法检查都在编译阶段完成出错了根本不会给你运行的机会。2.3 第三层函数、宏、入口与返回值的隐藏设定fn加main这两件事其实还可以继续挖。main函数比较特殊的地方在于它是可执行程序启动后的默认入口。默认情况下它不接收命令行参数也不返回任何值这意味着它的返回类型其实是空元组()。这一下就能解释很多常见疑问为什么 Hello World 里没有return 0;因为 Rust 的main默认成功退出就会直接返回()程序进程的退出码由运行时处理正常情况下是 0。如果想手动控制退出码可以用std::process::exit或在后面章节中用带Result返回值的main这些暂时不用深究。至于println!为什么带一个感叹号因为它是“宏”而不是函数。宏可以接收任意数量、任意类型的参数还能在编译期检查格式字符串和参数是否匹配。比如println!({} {}, 1, 2)这种多参数调用普通函数是做不到这么灵活的。把println!当成普通函数去理解后面学自定义宏时会绕不过弯来。3. 从零跑通 Hello World安装、编译、Cargo 全流程记录3.1 安装工具链的细节以及装完之后要检查什么在跑任何代码之前先得有 Rust 工具链。我用的方法是官方提供的rustup它既能管理 Rust 工具链也能方便地切换版本和更新。在 Linux 或 macOS 上官方脚本大体是这样curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh脚本执行完后会在~/.cargo/env写入环境变量需要手动 source 一下或者重新登录终端。Windows 上则是下载rustup-init.exe运行之后按提示选择默认设置即可。安装过程本身不复杂真正需要注意的有两件事。第一安装完成后别急着写代码先检查工具链完整rustc --version cargo --version如果两个命令都能正常输出版本号说明编译器和包管理工具都就绪了。第二如果安装过程中网络不好导致进度很慢可以稍后重试不需要反复卸载重装保持耐心即可。3.2 两种运行方式rustc 直接编译和 Cargo 项目管理第一种方式新建一个main.rs文件写入 Hello World 代码然后执行rustc main.rs并运行生成的可执行文件。这种方式适合理解“编译”本身是怎么回事也适合临时测试单文件的小片段。第二种方式就是用 Cargo 来管理项目。Cargo 是 Rust 官方自带的构建系统和包管理器类似 Python 世界的 pip 加虚拟环境但更偏“项目级”。创建一个新项目cargo new hello_world cd hello_world cargo runCargo 会帮你生成一个完整的项目骨架src/main.rs里已经有一段 Hello World 模板Cargo.toml是项目配置文件Cargo.lock记录依赖版本还会自动用 Git 做版本管理。运行cargo run后你会看到类似下面的流程Compiling hello_world v0.1.0 (/path/to/hello_world) Finished dev profile [unoptimized debuginfo] target(s) in 0.13s Running target/debug/hello_world Hello, world!这里最重要的信息是编译产物在target/debug目录下。默认cargo run是调试模式编译快、没有优化如果想要发布版本用cargo build --release产物在target/release下。直接rustc和用Cargo怎么选我的建议是理解原理用rustc一旦涉及多个文件、第三方依赖或需要长期维护就老老实实用 Cargo。下面这张表可以帮你快速区分两头对比项rustc 直接编译Cargo 项目适用场景单文件、快速验证多文件、依赖管理、正式项目依赖处理不处理需要手动指定路径自动下载和管理构建配置每次写命令行参数统一写在 Cargo.toml 中目录组织源码和产物混在一起源码在 src产物在 target推荐程度学习用可以日常开发强烈推荐3.3 我第一次实操时遇到的两个坑第一个坑是 Windows 下中文输出乱码。Hello World 虽然内容是英文但我想着既然支持 UTF-8试一下println!(你好世界);也无妨。结果在默认命令行窗口里中文变成了乱码。原因很简单Rust 源码按 UTF-8 编码默认命令行窗口却可能是旧编码两边不一致就显示乱码。解决办法是在命令行里执行一次chcp 65001切换代码页或者干脆换用支持 UTF-8 的终端工具。这个问题不是 Rust 本身的问题但确实容易让新人在第一天产生困惑。第二个坑是cargo new时提示failed to execute git。这个发生在我的机器没有配置 Git 的时候——Cargo 想自动初始化 Git 仓库但找不到 Git 命令。它会给你警告但项目本身照样创建只是没有.git目录。遇到这种情况要么先安装并配置好 Git要么直接忽略这个警告它不影响编译运行。4. 把 Hello World 当作试验台顺手消化这些基础语法点4.1 变量绑定与不可变性仅仅改一行代码就能明白很多新手学变量时只记住了“变量可以变”到了 Rust 里却发现默认反而不能改。把 Hello World 稍微扩展一下就能直观地看到这个规则fn main() { let x 5; println!(x {}, x); }这里let用来做“变量绑定”把值 5 绑定到名字 x 上。此时如果我试着在后面加一行x 6;编译器会直接报错大意是“不能对不可变变量二次赋值”。要让它能改得显式加上mutlet mut x 5; x 6;这个设计的逻辑其实非常朴素默认“锁上”比默认“敞开”更安全也更能防止无意间的修改带来的 bug。把变量想象成门锁mut就是那把钥匙谁需要用谁就明确申明这样读代码的人一眼就知道哪些值是允许变化的。这和很多语言里“默认可变、需要额外修饰才能不变”的思路正好相反所以初学阶段一定要刻意适应。4.2 函数与 main 函数Rust 的声明方式和 C/Java 有何不同既然第一章已经出现了fn main()那就可以顺手写一个自定义函数把“函数声明”这个知识点一次性带过fn greet(name: str) { println!(Hello, {}!, name); } fn main() { greet(World); }函数用fn声明参数写在括号里格式是名字: 类型返回值用箭头-加类型标注比如fn add(a: i32, b: i32) - i32。在 Rust 里函数体内最后一个不带分号的表达式会自动作为返回值这和传统语言里必须写return的习惯差异很大。这里出现的str是“字符串引用”类型它表示一个不可变的文本借用。这个例子比 Hello World 稍微超前了一点但好处是能让你提前感知到“引用”这个概念的存在——它会在所有权章节中被反复讨论。现在你只需要把它理解成“我借用了一下这个字符串来读它”不需要继续深挖。4.3 格式化输出从{}到{:?}再到{:#?}println!的第一个参数是格式字符串剩下的参数会按占位符依次填充进去。最常见的写法是{}占位符println!(x {}, x)。但{}不是万能的。普通显示用{}调试显示用{:?}它会把结构体的字段名和值都打印出来想要更漂亮的调试输出用{:#?}它会带缩进和换行。后面你调试复杂结构时这两个格式会让你省很多事。另外还有两个兄弟宏值得知道print!不换行eprintln!输出到标准错误而不是标准输出。实际项目中经常用它打印错误日志方便把正常输出和错误信息分流。下面是这几个宏的简单对照宏输出目标换行典型用途println!标准输出是常规日志、展示结果print!标准输出否需要连续拼接的提示eprintln!标准错误是错误信息、警告format!返回字符串否构造并复用格式化文本5. 学完第一章后值得动手尝试的几个变体实验5.1 把 Hello World 改成自己的版本从“抄”到“造”学任何东西最快的内化方式都是把例子改一改改成自己的东西。比如原版是打印Hello, world!你可以试试fn main() { println!(Hello, Rust!); println!(你好世界); println!({} 年我开始了 Rust 学习之旅, 2025); }这个过程中你一定会用到“在格式字符串里放占位符、再传入不同变量或字面量”的套路也会顺手验证字符串编码相关的问题。这种“改一点、立刻看输出”的反馈循环是纯看书完全给不了的。每改一次你对这段代码的掌控感就强一点。5.2 故意制造编译错误体会 Rust 编译器的“咬文嚼字”我强烈建议新手做一件看起来有点“犯贱”的事把代码故意改成有问题的版本然后认真读一遍编译错误。比如把分号去掉、把println!写成println、把main拼成mian看编译器分别怎么回应。去掉println!后面的分号编译器会提示你期望一个分号把println!写成printlnRust 会告诉你“这里期望的是函数却找到了宏”意思是你要调用的东西其实是个宏需要加上感叹号把main拼成mian编译器会提示找不到主函数。这些报错信息设计得非常讲究很多时候会直接告诉你“要不要试试这样改”。与其怕报错不如把报错当成老师和学习材料。每读懂一条编译错误你就对 Rust 的语法规则多了一层理解。5.3 从 Hello World 延伸到命令行参数Hello World 的main没有参数但如果你想做一个稍微有用的小工具通常都要读取用户输入这就涉及命令行参数。最简单的方式是用标准库里的std::env::argsfn main() { let args: VecString std::env::args().collect(); for arg in args { println!({}, arg); } }这个例子稍微超前里面出现了Vec和for循环但它能让你理解一个重要概念程序入口main虽然没有参数但运行时环境可以把信息传进来。等学到更后面的章节你会发现很多命令行工具都是从这个点开始扩展起来的。如果你愿意甚至可以给这个程序加一个判断如果没有输入参数打印Hello, world!如果有就打印Hello, 参数内容!。这样你的第一个 Rust 程序就已经具备“输入—处理—输出”的完整结构了。6. 给新手的几个学习习惯建议基于这本例子的实际反馈6.1 先跑通再深挖先看现象再查原理《通过例子学Rust》这类书的最大价值是给你一条“能跑”的最小路径。很多人学 Rust 容易陷入“一个点没吃透就不往下走”的完美主义比如非要彻底搞懂println!宏底层是怎么展开的才肯写第二行代码。这样做效率很低。正确的节奏应该是把例子跑起来看到输出然后“大概知道”这一步在干什么就继续往下走。很多深层的原理比如所有权的细节、宏的展开机制会在后面的章节反复露面到时候再回头补理解会深刻得多。先保证自己一直在“写能跑的代码”保持成就感兴趣才不会断。6.2 把书里的例子“抄”一遍不是一个字一个字抄手打代码和复制粘贴的体验完全不同。复制粘贴很快就忘了手打则会强迫你把每一个字符都过一遍连中文引号和英文引号这种细节都会格外敏感。我自己的经验是每学一个新例子先关掉书凭记忆写出来再对一下原版。写不出来的地方就是你还没真正掌握的地方。6.3 建立自己的“报错笔记”从 Hello World 开始你就会不断遇到编译错误。建议你准备一个笔记记录三样东西错误信息的前几行、出错代码的上下文、你最终怎么修的。不要小看这个习惯后面大量“踩坑—查资料—解决”的循环都会依赖你的这套记录。很多问题看起来当时记住了过两个月就会忘但笔记不会。接触 Rust 到一定阶段你就会发现它真正难的不是语法而是思维方式。Hello World 虽然简单但这第一关走扎实了后续的学习曲线会顺很多。如果你现在刚装好工具链不妨就照着上面几个变体实验多折腾一会儿等你把“打印输出”玩顺手了再翻开第二章那种感觉会完全不一样。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑