二、语言基础 (一)
1. 输出到控制台
-
两个输出宏:
-
print!("输出内容: {} {} {}", var1, var2, var3)- 与 Java
System.out.print的效果相同
- 与 Java
-
println!("输出内容: {} {} {}", var1, var2, var3)- 与 Java
System.out.println的效果相同
- 与 Java
-
-
具体用法
-
这两个输出宏的语法完全相同
-
如果想输出自定义文字 + 变量,那么与 C, Java 类似
-
示例代码
fn main() { let a= "aa"; let b = "bb"; // 输出指定的变量 println!("这是你想自定义的文字:{},{}", a, b); // 这是你想自定义的文字:aa,bb // 重复输出某个变量 println!("重复两遍变量 a:{0},{0}", a, b); // 重复两遍变量 a:aa,aa println!("重复两遍变量 b:{1},{1}", a, b); // 重复两遍变量 b:bb,bb // 输出左花括号 '{' 或右花括号 '}' println!("输出花括号:{{"); // 输出花括号:{ println!("输出花括号:}}"); // 输出花括号:} println!("输出花括号:{{}}"); // 输出花括号:{} // 输出其他转义字符时,和其他编程语言一样,都是使用反斜杠 '' println!("输出换行符:\n"); // 输出换行符: // 后续还会介绍到另外一种打印变量的快捷方式 }
-
2. 变量定义
-
Rust 是一门强类型语言,但某些情况下可以省略类型注解
- 一个变量的类型可以由类型注解 (参考 Typescript 的说法)确定
- 一个变量的类型也可以由定义时赋值的值类型确定
-
变量定义关键字:
let,const,mut变量类型 关键字 类型注解 可重新赋值 Shadowing特性示例 不可变变量 let非必须 不可 支持 let a= 'a'可变变量 let mut非必须 可 支持 let mut a = 'a'常量 const必须 不可 不支持 const C: i32 = 456 -
重影 (Shadowing) 特性: 用同一个名字重新代表另一个变量实体,其类型、可变属性和值都可以变化
- 这是 Rust 相比于其他语言中比较特殊的一个特性
-
示例代码
fn main() { let a = "abc"; // 定义了一个字符串类型的不可变变量 a let mut b = 123; // 定义了一个整数型的可变变量 b const C: u32 = 456; // 定义了一个无符号32位整型常量 c let a = "efg"; // 允许。a 是不可变变量,利用了 shadowing 特性 let a = b; // 允许。a 是不可变变量,利用了 shadowing 特性 b = c; // 允许。类型匹配,且 b 是可变变量 // 下面是变量赋值的反例 a = "xyz"; // 不允许。a 是不可变变量 b = "123"; // 不允许。类型不匹配 c = 789; // 不允许。c 是常量 // 上一个 a 的作用域到这里就结束了,下面是新 a 的作用域 let mut a = c; // 现在,a 变量的类型变成了无符号32位整型 a = 789; // 允许,类型匹配 a = "abc"; // 不允许,类型不匹配 }
3. 数据类型
3.1 标量类型
-
标量类型:代表一个单独的值
- 类似于 JavaScript 里的字面量
-
Rust 中有四种标量类型:整型、浮点型、布尔类型和字符类型
3.1.1 整型
| 位长度 | 有符号 | 无符号 |
|---|---|---|
| 8位 | i8 | u8 |
| 16位 | i16 | u16 |
| 32位 | i32 | u32 |
| 64位 | i64 | u64 |
| 128位 | i128 | u128 |
| arch | isize | usize |
-
isize 和 usize 是用来衡量数据大小的,它们的位长度取决于所运行的目标平台,主要作为某些集合的索引
-
表述方式
- 十进制:和 C, Java, JavaScript 等编程语言相同
- 十六进制:和 C, Java, JavaScript 等编程语言相同
- 八进制:和 C, Java, JavaScript 等编程语言相同
- 二进制:和 C, Java, JavaScript 等编程语言相同
- 字节 (特有):只能表示无符号8位的整型数字 (即 u8):
b'A'
-
不写类型注解时,整型的类型默认是
i32,因为它通常是最快的,甚至在 64 位系统上也是 -
整型溢出
-
比如:一个
u8的变量,它允许的最大值是 255,如果把它加一-
在 debug 模式编译运行时,会直接 panic
-
在 release 模式编译运行时,会进行二进制补码包装
- 二进制补码包装:255+1 会变成 0,255+2 会变成 1,依次类推
-
-
3.1.2 浮点型
- 32位:
f32 - 64位:
f64 - 不写类型注解时,浮点数的类型默认是
f64,因为在现代 CPU 中,它与f32速度几乎一样,不过精度更高
3.1.3 布尔型
- 类型注解为
bool - 只有
true和false两个值 - 主要的使用场景是条件表达式
3.1.4 字符类型
-
类型注解为
char -
必须包裹在单引号
''中,且其中只能有一个合法字符 (不含转义符)- 和 C 语言的字符类型很像
-
大小为四个字节(four bytes),代表了一个 Unicode 标量值(Unicode Scalar Value)
3.2 复合类型
- 复合类型:可以由多个值组合而来的类型
- Rust 中有两种复合类型:元组,数组
3.2.1 元组
-
用一对小括号
()包裹(value1, value2, ...)
-
元组里的每一个元素可以是不同类型的
-
元组里的元素可以通过
varName.index来调用fn main() { let tup: (i32, f64, u8) = (500, 6.4, 1); println!("{}, {}, {}", tip.0); let (x, y, z) = tup; // 类似 JavaScript 里的解构赋值 } -
类似 Python 里的元组,也类似 Typescript 的元组 (但表现不一样)
3.2.2 数组
-
用一对中括号包裹一组 数据类型相同 的元素
- 和 Java 里的数组概念基本相同
-
仅当数组用
let mut关键字定义时,数组的元素值、数组本身才可变
4. 运算符号
-
和其他编程语言相同的运算符
符号 名称 备注 =赋值运算符 +, -, *, /, %, <<, >>基本数值运算符 这些符号均可与赋值运算符组成组合运算符 `&, , !, ^` 位运算符 只有 &和 `` 可以和赋值运算符组成组合运算符 `&&, , !` 逻辑运算符 <, <=, >, >=, ==, !=条件运算符 ,元素分隔符 .成员访问符 -
相对特殊的运算符
符号 名称 备注 !宏展开运算符 &借用运算符 可以借用类型或变量, 与 C 语言的取地址操作符概念相似 *解引操作符 与 C 语言的指向运算符概念相似 ->返回值类型指定符 用于为函数/方法指定返回值类型 ..范围运算符 在数字范围、数组、元组中用得比较多 -
相比于其他编程语言,Rust 中没有的运算符
-
递增一/递减一 运算符
++/-- -
无符号右移 运算符
>>> -
三元运算符
exp ? exp2 : exp3- 可以通过
let b = if a== exp { exp2 } else { exp3 };来实现相同的效果,但是此时的 exp2 必须和 exp3 是相同类型的才行
- 可以通过
-
5. 注释
-
普通注释
- 单行注释:
// 这是注释内容 - 任意行注释:
/* 这里的内容可以跨越任意行 */
- 单行注释:
-
文档注释
-
方式一:
/// 这是文档注释- 这样的文档注释,可通过
cargo doc命令将项目中的说明注释转换成 HTML 格式的说明文档
- 这样的文档注释,可通过
-
方式二:
/** 这是文档注释 */- 这种文档注释没有试过
-
-
示例代码
fn main() { // 打印一个 bar bar(); /* 除了在上面打印一个 bar 之外 还会在随后打印一个 foo */ foo(); } /** bar 打印一个 bar */ fn bar() { println!("bar"); } /// foo /// 打印一个 foo fn foo() { println!("foo"); }