尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Rust Hello World深度实战:环境搭建、编译运行与格式化输出全解析
学 Rust 的朋友第一行代码基本都是从 Hello World 起步的。《通过例子学Rust》Rust by Example这本官方风格的小册子把 Hello World 放在了第 1 章看起来只是打印一句问候语其实里面埋了三个关键问题程序从哪开始执行、println! 为什么带感叹号、Rust 的工具链是怎么把源码变成可执行文件的。这篇文章不打算照抄书里的例子而是把这一章掰开揉碎结合我实际写 Rust 这两年的经验把环境安装、编译方式、格式化输出和最常见的报错一次讲透。准备入坑 rust 语言入门、以后想去折腾 Tauri 桌面应用或者 AI Agent 框架的朋友这篇就是你踩下去的台阶。1. Hello World 背后的两个核心概念1.1 为什么是 fn main程序的入口约定写任何 Rust 程序第一行基本逃不开 fn main()。这个入口约定跟 C 语言一样编译器在链接可执行文件的时候必须找到一个叫 main 的函数然后从它的第一行开始执行。区别在于 Rust 的写法更明确fn 是关键字后面跟函数名小括号表示无参数。你要是写个 hello.rs 却不放 main编译器会直接告诉你 error[E0601]:mainfunction not found in cratehello。新手经常困惑的点是既然是第 1 章为什么框架要用得这么重一个空壳 main 有什么意义我的理解是Rust 是一门需要你在很小的地方就建立正确心锚的语言。main 不写程序连编译都通不过写错了位置编译器也会追着报错。它逼着你从一开始就养成按约定办事的习惯。后面你写库、写测试、写二进制工具入口可能变成 lib.rs、#[tokio::main] 等等但核心思想都一样程序总有一个明确的起点。这里我还想提一个 Rust 和其他语言不太一样的内置习惯main 函数内的代码块是有作用域的最后的表达式不带分号的表达式会被当作返回值。Hello World 阶段暂时用不上但第 2、3 章你会频繁用到这个特性。现在只要记住普通函数在 {} 内部定义语句以分号结尾唯一容易被忽略的是表达式后面没有分号这件事先埋个印象。1.2 println! 为什么带感叹号宏与函数的差别再看 println!(Hello, world!); 这一行新手第一反应是函数调用为什么要加感叹号。这是 Rust 很有辨识度的语法细节带 ! 的调用是宏macro不是普通函数。println! 在被编译的时候会做一些展开工作把你想打印的内容和占位符转换成一套复杂的内部调用最终落到 std::io::stdout() 上。为什么不让它当一个普通函数因为 Rust 的格式化参数是可变的函数签名很难优雅地表达前面是格式字符串后面跟着任意类型的一堆参数。另外宏可以在编译期做类型检查比如 println!({}, 42) 没问题println!({}, vec![1,2,3]) 就会报错因为 Vec 没有实现 Display。这套检查在编译期完成错误早暴露运行时不背锅。与 println! 对应的还有 print!差别只是末尾不换行。如果你连续 print! 两次输出会挤在同一行。这两个宏在 Rust 里属于 std::fmt 这块是使用频率最高的工具之一。以后写测试、写日志库、做 CLI 输出全都要跟 fmt 打交道。所以第 1 章看起来是个你好世界实际是在给你提前铺 fmt 模块的路。2. 从零搭建 Rust 环境安装与工具链2.1 rustup 是官方推荐先把它装明白要跑 Hello World得先把 rust 安装搞定。官方推荐的安装方式是 rustup它不只是装个 rustc 编译器而是负责管理整个 Rust 工具链rustc编译器、cargo包管理器、rustup 自带的文档和组件。Windows 上直接下载 rustup-init.exemacOS 和 Linux 用终端执行安装脚本。装完通常会自动把 ~/.cargo/bin 加进 PATH新开的终端窗口才能用 cargo 和 rustc 命令。装完之后我先建议你跑一句 rustup show看看当前 toolchain 的版本和默认目标。官方默认装的 stable 工具链通常够用如果需要跑 nightly 特性再用 rustup toolchain install nightly 装第二套。初学者别急着追 nightly稳定版就是最好的版本。Windows 上还有一个容易忽略的点如果你要编译原生程序建议把 Microsoft C Build Tools 装上否则链接阶段会报 link.exe not found 之类的错误。这个坑我在第 5 节再展开但安装的时候顺手解决是最舒服的。2.2 编译与运行rustc 直接上还是交给 Cargo装好环境运行 Rust 程序有两种主流方式。最直接的是 rustc hello.rs ./helloWindows 上是 hello.exe编译器会在当前目录生成可执行文件。这种方式适合一两个文件的实验比如《通过例子学Rust》前面几章。另一种更接近日常开发的是 Cargocargo new hello --bin 建项目编辑 src/main.rscargo run 一键编译运行。这两者的差别我列个表对比项rustc 直接编译Cargo 项目上手成本最低只有一个文件需要初始化目录结构依赖管理不支持要手动找库Cargo.toml 声明即可构建缓存每次全量编译增量编译快很多适用场景学习语法、快速验证真实项目、多文件工程我的建议是第 1 章阶段你两种都试一遍眼睛会了之后后面统一用 Cargo。因为从第 2 章起几乎每个例子都可能引入第三方 crate没有 Cargo 你根本玩不转。Cargo 同时承担了 build 和 test runner 的角色cargo test、cargo fmt 都是它管的。顺便说一句Cargo 初始化的目录结构初看很啰嗦src/main.rs、Cargo.toml、target还有 Cargo.lock。但这是 Rust 社区统一的项目骨架学得快的话整个工程布局一开始就在你脑子里有了。后面你用 Tauri 或者写 CLI 工具拿到的第一眼也是这套结构越早习惯越好。2.3 装完先跑几个命令确认环境真的可用环境装完不是等它看起来能用我习惯先跑一段验证链。第一个命令是 rustc --version看到类似 rustc 1.xx.x (xxxxxxx xxxx) 的输出就算通。第二个是 cargo --version。第三个就是我们的重头戏建一个临时目录写 hello.rs编译运行。如果提示 cargo 不是内部或外部命令大概率是 PATH 没生效重开终端或者手动把 %USERPROFILE%.cargo\bin 加进去。如果提示 link.exe not found去装 Build Tools。如果运行起来没有任何输出但也没有报错检查一下是不是用了 print! 而不是 println!或者代码里压根没写 main。这里我想额外提一下验证环境时最容易踩的双工具链坑有的同学电脑上曾经装过 Rust后来卸载不干净导致 rustc 和 cargo 版本对不上甚至出现 rustc 是旧版、cargo 是新版的情况。解决办法简单粗暴卸载后删除 ~/.cargo 和 ~/.rustup再重新安装即可。别担心删坏什么这两个目录只是工具链和缓存删掉重来反而比修补更快。3. 亲手写第一个 Hello World逐行拆解3.1 最小程序文件名、入口、缩进与分号先把最小程序完整贴出来fn main() { println!(Hello, world!); }不用急着看输出先看文件。文件名建议叫 main.rs 或 hello.rsRust 对文件名本身没有强制要求除非你用 Cargo 的默认约定但为了后面方便统一用 main.rs 最省心。代码里第一行 fn main() 是入口第二行是宏调用。缩进风格不是语法要求但社区普遍用 4 空格。分号值得专门说。println!(Hello, world!) 后面有个分号分号表示这是一个语句执行完就完事不产生值。如果把分号去掉这一行就变成了整个 main 函数块的最后一个表达式它的值会被当作函数的返回值然后编译器就报错了。新手阶段分号写错的概率极高我见过有人因为少一个分号排错半小时所以一开始就养成数分号的习惯。还有个细节这里的缩进用的是 4 空格不是 Tab。Rust 社区的 rustfmt 工具会自动格式化但第 1 章你还在手写阶段就按 4 空格来后面跑 cargo fmt 也默认是这个规格。3.2 把 Hello, world! 换成变量let 绑定第 1 章书上还没讲到变量但我建议你直接改一行试试fn main() { let greeting Hello, world!; println!({}, greeting); }let greeting Hello, world!;是定义绑定的写法Rust 里的变量默认不可变翻译成人话就是这个名字绑定了这个值中途不让改。如果你想让值可变得写成 let mut greeting。这个设计跟很多语言反着来默认不可变显式加 mut 才可变。初学者很容易顺手写 greeting other; 然后被编译器教育原因就是没加 mut。println!({}, greeting);里的 {} 是占位符表示把后面位置参数的值插进这里。{} 对应的输出依赖值类型实现了 Display trait字符串、数字都没问题。你要是放一个自定义结构体进去就会触发我在第 4 节要讲的编译错误。这里也顺便解释一下Rust 的字符串字面量是 str 类型不是 String两个类型在使用上差别很大但 Hello World 阶段你只要知道裸字符串基本都长这样就够了。至于为什么这么设计背后是内存所有权和借用的问题第 4 章你会正式接触到。3.3 从 println! 看格式化输出{} 只是一切的开始{} 是最简单的占位符但 std::fmt 提供的远不止这些。往下推进一步你可能会见到这些写法let name Rust; let version 1.84; println!({name} {version:.2}); println!({:10}, name); println!({1} {0}, 42, age);第一行的命名参数能让代码可读性大大提升{name} 会直接找同名变量。{version:.2} 表示浮点数保留 2 位小数。第二行的 {:10} 是把内容右对齐占 10 个字符宽CLI 输出对齐表格时非常有用。第三行的 {1} {0} 是位置参数按顺序取后面参数表达式总数和编号要对应上否则编译期就给你脸色看。这些格式化语法在官方文档里的名字叫 format spec格式规范完整规则包含占位符、位置、填充对齐、类型、精度几个维度。第 1 章不需要全背但你要知道 println! 不是只能打印固定一句话它是一个可以承载结构化输出的工具。后面章节里关于格式化的内容全都基于这里建立的直觉。当你后面写大项目的时候format! 宏会把这段经验延伸出新的用途可以先把格式化后的字符串存到变量里再决定是打印到控制台还是写到文件。println! 其实只是 format! 加一句输出到标准输出的糖。4. 打印的进阶玩法调试输出与常见坑4.1 {:#?} 调试输出结构体一打就现形Hello World 只是起点实际开发里你打印的更多是数组、结构体、HashMap。直接用 {} 会报错这时候就要请出 Debug 派生的 {:#?}#[derive(Debug)] struct Point { x: i32, y: i32, } fn main() { let p Point { x: 10, y: 20 }; println!({:?}, p); println!({:#?}, p); }{:?} 的输出会把结构体完整打出来比如 Point { x: 10, y: 20 }。{:#?} 是 pretty-print 版本多行缩进嵌套结构一展开字段层级一眼就能看清。调试代码的时候我强烈推荐你先上 {:#?}比手写字段拼接省太多时间。再展示一个常见场景let mut score std::collections::HashMap::new(); score.insert(rust, 90); score.insert(python, 80); println!({:#?}, score);HashMap 这种内部顺序不固定的集合用 {:#?} 打印出来是结构化的多行文本调试时能看到每个键值对的 type 和值。Debug 输出虽然不是面向用户的漂亮格式但它是你在性能排查、数据流观察阶段最常用的工具。4.2 Display 未实现报错新手最常见的编译错误新手拿到结构体第一反应就是 println!({}, p);然后编译器甩给你一段非常长的错误开头长这样the traitstd::fmt::Displayis not implemented forPoint。很多人看到 trait 就慌其实这里表达的是println! 想用 {} 打印 Point但 Point 类型没有实现 Displayprintln! 不知道该怎么把它变成人话。解决思路有两条。第一如果只是调试用把 {} 换成 {:?}并在结构体上加上 #[derive(Debug)]这是最快路径。第二如果这个类型真的需要给用户看就得手动实现 Display trait。我几乎每天用第一种写 demo 也习惯性派生 DebugDebug 加上后 {} 打不了还能随时换 {:?} 补救。有时候报错还会伴随提示perhaps two crates are both namedfmt这种是命名冲突通常是你给结构体命名跟 crate 或模块撞了。先按编译器提示改名字多半就好了。4.3 给自定义类型实现 Display 的正确姿势手动实现 Display 也不难格式是固定的use std::fmt; impl fmt::Display for Point { fn fmt(self, f: mut fmt::Formatter_) - fmt::Result { write!(f, Point({}, {}), self.x, self.y) } }写完后 println!({}, p) 就能输出 Point(10, 20)。注意 write! 这里也是宏它返回 fmt::Result正好匹配函数签名。实现 Display 的一个细节是不要在 impl 里直接调用 println!而是用 write! 把内容写进 Formatter这样 println!、format!、eprintln! 都能复用这套实现。到了这一步你已经把 Hello World 玩成了一个小型接口设计练习怎么让一个自定义类型跟标准格式化机制配合。等你以后写库发现用户能用 {} 直接打印你的错误类型体验会好很多。这也是 Rust 比其他语言更强调 trait 的原因之一——打印这种看似微不足道的操作其实也有约定俗成的类型接口。5. Rust 新手的三个典型问题与排查实录5.1 中文输出乱码、注释乱码怎么办很多同学控制台打印中文成了乱码。第一个检查点源文件是不是 UTF-8 编码。Rust 源码默认按 UTF-8 处理如果你用记事本把它存成了其他编码编译器自己都会抱怨更别提输出。第二个检查点终端编码。部分终端默认代码页不一定和 UTF-8 匹配切换到 UTF-8 再运行程序基本能解决。如果你用的是 VS Code 的集成终端把编码设为 UTF-8 即可。乱码问题看着蠢但实际排查过的人都知道有多费时间。我的习惯是项目里所有 .rs 文件一律 UTF-8 无 BOM终端能开 UTF-8 就开 UTF-8一劳永逸。还有源码里写中文注释完全没问题但别在字符串里硬编码需要特殊控制台才能显示的特殊符号能省则省。5.2 main 函数能不能有返回值我见过不少人写 fn main() - i32 { ... } 想模仿 C 语言的退出码。Rust 的稳定版本里main 的返回值其实有讲究可以返回 ()、ResultT, E 或者满足 Termination trait 的类型。Hello World 阶段你写 fn main() - i32 直接编译不通过编译器会提示 main 的返回类型不合法。这不是语言不支持而是要求你想清楚退出状态要从哪来。更实用的场景是 main 返回 Resultfn main() - Result(), Boxdyn std::error::Error { // 文件操作、网络请求等可能失败的逻辑 Ok(()) }对Hello World 阶段用不上但你迟早会遇到。碰到 main 里带 ? 操作符的代码就需要这个返回类型兜底。看到这里不用急着背我提这个是想帮你建立心理准备Rust 的错误处理从第一课就埋在下层不要把 main 的签名当死规矩。5.3 Cargo 构建慢、第一次构建卡住怎么办用 Cargo 项目跑 Hello World其实不需要任何第三方依赖但第一次 cargo run 时它会做初始化某些场景下会比较慢。最直接的建议是先区分是正常等待还是卡死。Cargo 在下载依赖时终端会进进度条等待几秒到几十秒都可能。如果你在项目里 import 了第三方 crate并且依赖树比较复杂构建时间会被拉长和 Hello World 本体无关。另一个常见坑是中途 CtrlC 把 Cargo 进程中断了导致 Cargo 缓存处于半写状态下次构建报莫名其妙的锁错误。解决办法是把 Cargo.lock 和 target 目录删掉重试一般就能恢复。target 目录是构建产物和中间文件的存放处删了不会伤及源码放心删。对了还有个很实用的冷知识Cargo 默认构建是 debug 模式速度较快追求运行性能要用 cargo build --release。第 1 章不需要关心 release但你要知道调试和发布是两条流水线这也是 Cargo 和裸 rustc 之间的另一个隐性差别。6. 下一步从 Hello World 走到真实项目6.1 学完第 1 章的检查清单这本书第 1 章篇幅很小但学完你至少要确认自己这几件事都过关会安装 rustup 并确认 rustc / cargo 可用会用 fn main 写一个最小的可执行程序区分 println! 与 print!理解带 ! 的是宏会用 {} 占位符、命名参数和基本格式规范能把 println! 和 write! 的用法分清遇到 Display 未实现时知道切 {:?} 或实现 Display这六条全部做到Hello World 这一章才算真正通关。不用急着往下一章冲扎实的入口习惯比多刷十个例子都重要。我见过有人第一章跳得飞快结果到写结构体的时候连 fn main 和宏都没分清回头补课反而更慢。6.2 从 Hello World 岔开的几条实战路线第 1 章之外整个 Rust 生态的入口其实很多。有人学 Rust 是为了 Tauri 桌面应用Tauri 用 Rust 做后端壳子配上前端界面打包体积比 Electron 小太多这条路线你需要补的是桌面端能力、文件系统、进程通信。有人是为了命令行工具clap、anyhow 这些库都很成熟用起来和打印 Hello World 一样直白先写一个 hello 命令练手非常合适。还有人被基于 Rust 的 AI Agent 框架吸引最近 Rust 侧的 AI 生态发展很快很多 agent 运行时和推理引擎的底层都是 Rust 写的这条路线前置要求是异步、并发和序列化。更冷门一点的有人在研究复古游戏平台的移植玩法也有工业领域用 Rust 写 OPC UA 协议栈做设备互联的。这些方向听着各不相同但底层都离不开你在这第 1 章打下的几个习惯会建项目、会编译运行、会格式化输出、能读懂编译错误。所以我一直觉得Hello World 不是终点它是一个小小的发令枪把你推向 Cargo、trait、格式化宏、错误处理这些真正组成 Rust 日常的零件。先把手上的程序跑起来再顺着你想去的方向走哪条路都会比想象中顺。我个人折腾 Rust 这么久的体会是Hello World 这一章最值得记住的不是 println! 的输出结果而是它逼你面对三件事入口规矩、宏的存在、编译器的严格。这三样东西在后面的每一章都会被反复强化。你要是今天刚装好环境可以把书里第 1 章的三个例子都跑一遍顺便多加几个中文、数字、结构体的打印实验。跑通之后再打开第 2 章的原生类型去。等你把基础类型刷完回头再看这一章你会惊讶于就那么几行代码原来藏了这么多讲究。
RELATED

相关推荐

Java仿百度网盘源码实战:分片上传与秒传完整落地

Java仿百度网盘源码实战:分片上传与秒传完整落地

简介:这是一套基于Java技术实现的仿百度网盘项目源码,面向具备一定Java与Web开发基础、希望深入理解云存储系统架构的学习者与开发者。项目围绕文件存储、共享与管理展开,模拟百度网盘的核心功能与界面交互,可用于课程设计、毕业设…

📅 2026/10/9 21:43:34
Android分层架构落地指南:开发工具与工程实践

Android分层架构落地指南:开发工具与工程实践

搞了这么多年Android,有个感悟越来越深:架构分层这件事,从来不是画一张漂亮的分层图就完事了。真正让分层落地到项目里的,是那一整套开发工具和工程实践的配合。你光有MVVM、Data Domain Data的分层意识,没有靠谱的构建…

📅 2026/10/9 21:43:34
深入理解人工智能 AI-RAN Alliance(AI无线接入网联盟)

深入理解人工智能 AI-RAN Alliance(AI无线接入网联盟)

AI-RAN Alliance(AI无线接入网联盟)是一个成立于2024年的全球性产业联盟,旨在推动人工智能(AI)与无线接入网(RAN)的深度融合,构建“AI原生”的下一代网络架构。该联盟发展迅速&#…

📅 2026/10/9 21:43:34
MORE NEWS

更多资讯

📰

适合办公的Agent工具:TRAE Work如何提升日常办公效率

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

矿山机器人现状与落地挑战:从巡检到数字孪生的技术解读

简介:围绕矿山机器人的现状、问题与发展的PPT学习教案,适合矿业工程、机器人技术及安全工程等相关专业的教学与自学场景。内容系统梳理了矿山机器人对煤矿安全和应急救援的重要性,对比美国、英国、德国、澳大利亚、日本及我国在救援机器人领域…

📰

FastGPT + OneAPI 构建知识库:把 endpoint 改到 TaoToken 的完整配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

变电站异物检测:168张VOC数据集的实战加载与模型适配

简介:本资源是面向电力系统智能化运维与计算机视觉算法研发者的专业图像数据集,聚焦变电站及输电线路场景下的异物识别任务,为安全巡检类目标检测模型的训练与验证提供高质量标注基础。数据集包含168张真实场景JPG图像及配套VOC格式XML标注文…

📰

微信小程序旅游服务平台源码解析:从项目结构到二次开发实战

1. 从一份“超全”标题说起:这类旅游小程序项目到底交付了什么我经常在技术社区里看到类似"【超全】基于微信小程序的旅游服务平台【包括源码文档调试】"这样的标题,说实话,第一反应是警惕,第二反应是好奇。警惕是因为&…

📰

相变材料工程落地指南:选型、封装与系统集成实战

1. 从实验室到货架:相变材料到底解决了什么问题第一次接触相变材料是在一个储能项目里,当时团队想给一个户外设备做恒温保护,试过加热片、保温棉、甚至半导体制冷,效果都不理想——要么耗电太狠,要么温度波动压不住。后…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬