环境
- windows 10 64bit
变量
Rust
中的变量默认是不可变的,这点跟目前市面上主流编程语言中的变量是不同的。不过,可以通过在变量名前面添加关键字 mut
,来让变量可变。
let total = 100;
total = 200;
可以看到提示 cannot assign twice to immutable variable
,意思就是不可变变量无法被赋值2次,这时候,我们在变量名前面加上 mut
就不会有问题了,total
变量可以被重新多次赋值。
let mut total = 100;
total = 200;
这里需要注意一点,常量不能够使用 mut
关键字,而且声明常量用的是 const
关键字,最后还必须显式的指明数据的类型,如
// 无符号32位数
const MAX_NUMBER: u32 = 100;
Rust
还有个重要的特性,就是隐藏 shadow
,一个新声明的变量可以覆盖掉原来的同名变量
let total = 100;
let total = total + 1;
代码中的第二个 total
会隐藏掉第一个 total
,后面使用的 total
变量都指的是第二个 total
变量
数据类型
在 Rust
中,每一个值都有其对应的数据类型,这里将数据类型分为两大类,标量类型(scalar
) 和复合类型(compound
)。标量类型包括了整数类型、浮点数类型、布尔类型、字符类型;而复合类型包含了元祖(tuple
)和数组(array
)。
整数类型
分为有符号数(以字母 i
开头)和无符号数(以字母 u
开头)
对于一个位数为 n
的有符号整数类型,它可以存储从负的2的 n-1
次方到2的 n-1
次方减1范围内的所有整数。比如对于 i8
来讲,它可以存储从-128到127之间的所有整数。而对于无符号整数类型而言,则可以存储从0到2的 n
次方减1范围内的所有整数。以 u8
为例,它可以存从0到255之间的所有整数。
注意到上表中,还有 isize
和 usize
两种特殊的整数类型,它们的长度取决于程序运行的目标平台。在64位架构上,它们就是64位的,而在32位架构上,它们就是32位的。
let total:i8 = 200;
给变量赋值超过了它的范围,编译器就会报错
浮点数类型
浮点数就是带小数的数字,占用32位的 f32
和占用64位的 f64
,默认情况下,使用的是 f64
let x = 100.0;
let y: f32 = 100.0;
布尔类型
Rust
中的布尔类型占据单个字节空间,它只有2个可能的值,一个是 true
,另一个是 false
,类型名称是 bool
let isFlag: bool = true;
let isFlag = false;
字符类型
Rust
中,用 char
来表示字符类型,是单个字符,用单引号表示,而字符串用双引号表示
let c: char = 'A';
元组类型
将多个不同类型的值组合起来就是元组,元组在声明后无法增加或减少其中的元素数量。
let tup: (char, u32, f64) = ('a', 100, 49.9);
// 通过.操作符来访问元组中的元素,元组的索引从0开始
println!("{}", tup.0);
数组类型
除了元组类型,数组类型同样可以将多种数据类型组合在一起,不过,与元组不同的是,数组要求每一个元素都必须是相同的类型,而且数组一旦声明后,就不能随意更改大小。
let arr = [4, 3, 2, 1];
// 通过索引来访问数组中的元素,索引从0开始
println!("{}", arr[0]);
函数
前面已经接触过了函数,那就是 main
函数,它是程序的入口。
fn main() {
println!("Hello, world!");
}
其中,fn
是关键字,表明这是一个函数,main
是函数名, 大括号 {}
内的内容是函数体,它是函数逻辑实现的地方。main
函数中并没有参数,来看下面这个例子。
fn add(x: i32, y: i32) {
println!("x={}", x);
println!("y={}", y);
}
这里的小括号中有2个参数,2个参数都是 i32
数据类型。
在 Rust
中,有2个容易混淆的概念,语句(statement
)和表达式(expression
)。语句指那些执行操作但不返回值的指令,而表达式则是指会进行计算并产生一个值作为结果的指令。
比如,使用 let
声明一个变量就是一条语句
let total: u32 = 100;
表达式就更常见了,如上面的字面量100、数值计算、函数调用、println!
宏调用等都是表达式
接着,看一下函数的返回值,在函数参数后面加上 --> 返回值类型
fn add(x: i32, y: i32) -> i32 {
println!("x={}", x);
println!("y={}", y);
}
最后看一个完整的例子
fn add(x: i32, y: i32) -> i32 {
println!("x={}", x);
println!("y={}", y);
return x + y;
}
fn main() {
println!("Hello, world!");
// 函数调用是表达式,将表达式的值赋给num变量
let num = add(5, 4);
// main函数的返回值是隐藏了,其实就是最后一个表达式的值,本例中是宏调用
println!("number={}", num);
}
控制流
Rust
中通过 if
和 else
将逻辑进行分流,这和绝大多数编程语言是一样的
let num = 99;
if(num > 100) {
println!("big than 100.\n")
} else {
println!("small than 100.\n")
}
需要注意的是,这里的条件表达式期待的是一个 bool
类型,而 Rust
不会自动尝试将非布尔类型的值转换为布尔类型,我们必须显式地在 if
表达式中提供一个布尔类型作为条件,这一点与某些编程语言是不一样的。
通过 else if
语句,可以实现多重的条件判断
let num = 100;
if(num > 100) {
println!("big than 100.\n")
} else if(num == 100) {
println!("equal to 100.\n")
} else {
println!("small than 100.\n")
}
除了条件语句,Rust
为我们提供了3种循环,分别是 loop
、while
和 for
。
在需要循环执行的代码块前面加上 loop
关键字,就能让代码块无限循环的执行下去
loop {
println!("Hello Rust.");
}
要想退出循环,可以使用 break
关键字
let mut counter = 0;
loop {
println!("Hell Rust.");
counter = counter + 1;
if(counter > 20) {
break;
}
}
while
循环是在每次执行循环体之前都去判断一次条件,如果条件为真则执行代码片段。这种模式可以通过 loop
、if
、else
及 break
关键字的组合使用来实现。
let mut counter = 100;
while (counter > 0) {
println!("counter={}", counter);
counter = counter - 1;
}
for
循环也是使用频率非常的一种,它通常被用来遍历集合中的元素。
let scores = [90, 93, 95, 97, 99, 100];
for score in scores {
println!("score={}", score);
}
注释
在 Rust
中,使用 //
来表名注释,写在语句或者表达式的前面,多行注释使用 /**/
。
let score = 100;
// let sc = 0;
/*
let a = 1;
let b = 2;
let c = 3;
*/
为了让自己的代码更加的通俗易懂,建议大家多写注释。编译器在编译的过程中会忽略掉注释,注释不会影响到程序的性能。