写给新手的 Rust 语法:从变量声明到函数定义的 “人话“ 指南

一、Rust 是什么?为什么要学它?
在开始之前,你可能会问:“又一门编程语言?我为什么要学 Rust?” 🤔
简单来说:
- 🚀 快如闪电:运行速度堪比 C/C++
- 🔒 超级安全:编译器会在你写代码时就帮你抓 bug
- 💎 现代化:有包管理器、测试框架、文档工具等完善生态
- 🌟 越来越火:被 Google、Microsoft、Amazon 等大厂广泛使用
好了,废话不多说,让我们正式开始!💪
二、环境搭建(3 分钟速成)
安装 Rust
打开终端(Mac/Linux)或命令提示符(Windows),输入:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安装完成后,验证一下:
rustc --version # 查看 Rust 编译器版本
cargo --version # 查看 Cargo(包管理器)版本
创建第一个项目
cargo new hello_rust
cd hello_rust
cargo run
你会看到:Hello, world! 🎉
恭喜!你的第一个 Rust 程序运行成功了!
三、变量声明:理解 “不可变” 的魔法
3.1 为什么默认不可变?
这是 Rust 最独特的地方!在其他语言里,变量默认都是可以修改的。但 Rust 反其道而行之:默认不可变!
fn main() {
let x = 5;
println!("x 的值是: {}", x);
}
让我们拆解这段代码:
fn main()- 程序的入口函数let x = 5- 声明一个不可变变量 x,值为 5println!- 打印宏(注意有个感叹号!)
3.2 尝试修改会怎样?
fn main() {
let x = 5;
x = 10; // ❌ 编译错误!
}
编译器会告诉你:
error[E0384]: cannot assign twice to immutable variable `x`
为什么要这样设计? 🧐
想象你在写一个大型程序,有 100 个地方用到变量 x。如果默认可变,你在某个角落改了 x,可能会导致其他 99 个地方出 bug!而 Rust 说:“嘿,如果你要改变量,必须明确告诉我!” 这就大大减少了意外错误。
3.3 我真的要改变量怎么办?
用 mut 关键字!
fn main() {
let mut x = 5;
println!("x 是: {}", x); // 5
x = 10; // ✅ 现在可以了!
println!("x 变成: {}", x); // 10
}
人话版理解:let 像是用胶水粘住了变量,let mut 则像是用夹子夹住,可以取下来再换!📌
3.4 常量:永远不变的值
const MAX_LEVEL: u32 = 100;
fn main() {
println!("最大等级: {}", MAX_LEVEL);
}
常量 vs 变量:
| 特性 | let | const |
|---|---|---|
| 可变性 | 可以加 mut | 永远不可变 |
| 类型声明 | 可选 | 必须明确 |
| 命名规范 | 小写_下划线 | 大写_下划线 |
| 作用域 | 函数内 | 全局 |
3.5 变量遮蔽(Shadowing)
这是 Rust 的一个超酷特性!✨
fn main() {
let x = 5;
let x = x + 1; // 创建一个新的 x,"遮蔽" 了旧的 x
let x = x * 2; // 再次遮蔽
println!("x 是: {}", x); // 12
}
与 mut 的区别:
let mut x = 5;
x = x + 1; // 修改同一个变量
// vs
let x = 5;
let x = x + 1; // 创建新变量,遮蔽旧变量
遮蔽的好处:可以改变类型!
let spaces = " "; // 字符串
let spaces = spaces.len(); // ✅ 现在是数字了!
但 mut 不行:
let mut spaces = " ";
spaces = spaces.len(); // ❌ 错误!类型不能变
四、数据类型:Rust 的 “类型动物园”
4.1 整数类型
Rust 的整数类型非常细致:
fn main() {
let a: i8 = -128; // 8 位有符号整数
let b: u8 = 255; // 8 位无符号整数
let c: i32 = -123456; // 32 位有符号整数(默认)
let d: u64 = 999999; // 64 位无符号整数
println!("a={}, b={}, c={}, d={}", a, b, c, d);
}
人话理解:
i= integer(可以是负数)u= unsigned(只能是正数或 0)- 后面的数字 = 位数(8、16、32、64、128)
实用技巧:数字可以加下划线提高可读性!
let big_number = 1_000_000; // 比 1000000 好读多了!
let hex = 0xff; // 十六进制
let binary = 0b1111_0000; // 二进制
4.2 浮点数
fn main() {
let pi: f32 = 3.14; // 单精度
let e = 2.71828; // 默认是 f64(双精度)
println!("π ≈ {}, e ≈ {}", pi, e);
}
4.3 布尔值
fn main() {
let is_raining: bool = true;
let is_sunny = false;
if is_raining {
println!("记得带伞!");
}
}
4.4 字符
Rust 的字符支持 Unicode!🌍
fn main() {
let letter: char = 'A';
let emoji = '🦀';
let chinese = '你';
println!("字符: {}, {}, {}", letter, emoji, chinese);
}
注意:字符用单引号 ',字符串用双引号 "!
4.5 字符串(最容易混淆的部分)
Rust 有两种字符串:
fn main() {
let s1: &str = "Hello"; // 字符串字面量
let s2: String = String::from("World"); // String 类型
println!("{}, {}!", s1, s2);
}
简单记忆法:
&str- 不可变的字符串切片,通常用于只读String- 可增长的字符串,存在堆上
fn main() {
let mut s = String::from("Hello");
s.push_str(", world!"); // ✅ 可以修改
println!("{}", s); // Hello, world!
}
五、复合类型:把数据组合起来
5.1 元组(Tuple)
把不同类型的数据打包在一起:
fn main() {
let person = ("小明", 25, 175.5); // (姓名, 年龄, 身高)
println!("姓名: {}", person.0);
println!("年龄: {}", person.1);
println!("身高: {}cm", person.2);
}
也可以解构:
fn main() {
let (name, age, height) = ("小明", 25, 175.5);
println!("{} 今年 {} 岁,身高 {}cm", name, age, height);
}
5.2 数组(Array)
固定长度,同一类型:
fn main() {
let numbers = [1, 2, 3, 4, 5];
let first = numbers[0];
let second = numbers[1];
println!("第一个: {}, 第二个: {}", first, second);
}
创建重复元素的数组:
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
六、打印输出:让程序"说话"
6.1 基础打印
fn main() {
let name = "小王";
let age = 20;
println!("我叫{}", name);
println!("我今年{}岁", age);
println!("我叫{},今年{}岁", name, age);
}
6.2 位置参数
fn main() {
println!("{0} + {1} = {2}", 1, 2, 3);
println!("{1} - {0} = {2}", 1, 2, 1); // 可以调换顺序
}
6.3 命名参数
fn main() {
println!("{name} 今年 {age} 岁", name="小李", age=22);
}
6.4 调试打印
fn main() {
let numbers = [1, 2, 3];
println!("{:?}", numbers); // [1, 2, 3]
println!("{:#?}", numbers); // 更漂亮的格式
}
6.5 格式化选项
fn main() {
let pi = 3.14159265;
println!("保留 2 位小数: {:.2}", pi); // 3.14
println!("十六进制: {:x}", 255); // ff
println!("二进制: {:b}", 10); // 1010
println!("左对齐: {:<10}", "hi"); // "hi "
println!("右对齐: {:>10}", "hi"); // " hi"
}
七、函数定义:代码的 “积木块”
7.1 最简单的函数
fn say_hello() {
println!("你好!");
}
fn main() {
say_hello();
say_hello();
say_hello();
}
输出:
你好!
你好!
你好!
7.2 带参数的函数
fn greet(name: &str) {
println!("你好,{}!", name);
}
fn main() {
greet("小明");
greet("小红");
}
重点:参数必须声明类型!
多个参数:
fn introduce(name: &str, age: u32, city: &str) {
println!("我叫{},今年{}岁,来自{}", name, age, city);
}
fn main() {
introduce("小王", 25, "北京");
}
7.3 有返回值的函数
这里是 Rust 最特别的地方!🌟
fn add(a: i32, b: i32) -> i32 {
a + b // ← 注意没有分号!
}
fn main() {
let result = add(5, 3);
println!("5 + 3 = {}", result); // 8
}
关键点:
-> i32声明返回类型- 最后一行没有分号,就是返回值!
如果加了分号呢?
fn add(a: i32, b: i32) -> i32 {
a + b; // ❌ 加了分号,这是语句,不返回值!
}
编译器会报错:
error[E0308]: mismatched types
expected `i32`, found `()`
人话解释:
- 没有分号 = 表达式(有值)
- 有分号 = 语句(没有值)
7.4 显式 return
当然,你也可以用 return 关键字:
fn add(a: i32, b: i32) -> i32 {
return a + b; // 显式返回
}
什么时候用 return?通常是提前返回:
fn divide(a: i32, b: i32) -> i32 {
if b == 0 {
return 0; // 提前返回
}
a / b
}
7.5 多返回值(用元组)
fn get_coordinates() -> (i32, i32) {
(100, 200) // 返回元组
}
fn main() {
let (x, y) = get_coordinates();
println!("坐标: ({}, {})", x, y);
}
实用例子:
fn divide_with_remainder(a: i32, b: i32) -> (i32, i32) {
(a / b, a % b) // 返回商和余数
}
fn main() {
let (quotient, remainder) = divide_with_remainder(17, 5);
println!("17 ÷ 5 = {} 余 {}", quotient, remainder);
// 输出:17 ÷ 5 = 3 余 2
}
7.6 无返回值函数
fn print_separator() {
println!("====================");
}
fn main() {
print_separator();
println!("这是内容");
print_separator();
}
实际上,无返回值函数返回的是 ()(单元类型)。
八、控制流:让程序做决定
8.1 if 表达式
fn main() {
let age = 18;
if age >= 18 {
println!("你是成年人");
} else {
println!("你还未成年");
}
}
注意:条件不需要括号!(和 C/Java 不同)
多个条件:
fn main() {
let score = 85;
if score >= 90 {
println!("优秀");
} else if score >= 80 {
println!("良好");
} else if score >= 60 {
println!("及格");
} else {
println!("不及格");
}
}
if 作为表达式:
fn main() {
let number = 5;
let message = if number > 0 {
"正数"
} else if number < 0 {
"负数"
} else {
"零"
};
println!("这是一个{}", message);
}
8.2 循环
loop - 无限循环
fn main() {
let mut count = 0;
loop {
count += 1;
println!("计数: {}", count);
if count == 5 {
break; // 跳出循环
}
}
}
while - 条件循环
fn main() {
let mut number = 3;
while number > 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!🚀");
}
for - 遍历循环
fn main() {
let numbers = [1, 2, 3, 4, 5];
for num in numbers {
println!("数字: {}", num);
}
}
范围循环:
fn main() {
for i in 1..6 { // 1 到 5(不包括 6)
println!("{}", i);
}
for i in 1..=5 { // 1 到 5(包括 5)
println!("{}", i);
}
}
九、常见错误与解决方案
错误 1:忘记声明参数类型 ❌
fn add(x, y) -> i32 { // ❌ 错误!
x + y
}
✅ 正确:
fn add(x: i32, y: i32) -> i32 {
x + y
}
错误 2:混淆表达式和语句 ❌
fn get_number() -> i32 {
let x = 5; // ❌ 语句,没有返回值
}
✅ 正确:
fn get_number() -> i32 {
5 // ✅ 表达式,有返回值
}
错误 3:修改不可变变量 ❌
let x = 5;
x = 10; // ❌ 错误
✅ 正确:
let mut x = 5;
x = 10; // ✅ 正确
十、小结
✅ 变量声明:let、mut、const、变量遮蔽
✅ 数据类型:整数、浮点数、布尔、字符、字符串
✅ 复合类型:元组、数组
✅ 打印输出:println! 和格式化
✅ 函数定义:参数、返回值、表达式 vs 语句
✅ 控制流:if、loop、while、for
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)