Rust_CommonConcept
Rust中的变量默认是不可变的, 但是可以添加
mut
关键字使之可变Rust有单次赋值(Single assignment)原则, 尽管Rust变量默认是不可变的, 但是它允许你在声明变量后延迟赋值一次, 只要编译器能确定该变量只会被赋值一次即可.
1
2
3
4
5
6
7// 下面的语句是可以通过编译的
let x;
if cond {
x = 1;
} else {
x = 2;
}常量声明方式:
1
const THREE_HOURS_IN_SENCONDS: u32 = 60 * 60 * 3;
常量不允许使用
mut
关键字来修饰, 也就是说常量是不可改变的.常量存活在程序运行的整个生命周期, 也就是说在常量定义的范围内一直生效
Shadowing: 新变量覆盖了旧变量,导致在特定作用域内旧变量的值不可见
数据类型
整形:
其中,有符号数采用二进制补码存储,
isize
和usize
取决于计算机的架构另外编译的时候,如果使用debug模式, 编译器会检查整形溢出. 但是如果采用release模式, 则不会进行溢出检查, 而是会类型回绕
浮点数: 默认为f64
, 根据IEEE-754标准表示
布尔类型: true
false
字符类型: 一个Rust字符占4字节, 可以表示其他语言, 并且零宽空格也是有效的char值
元组类型: 固定长度, 元组中的元素类型不必相同
1 | let tup: (i32, f64, u8) = (500, 6.4, 1); |
可以通过模式匹配(pattern matching)解构元组值:
1 | let tup = (500, 6.4, 1); |
也可以通过点(.)来获取每个位置的元素
1 | let x: (i32, f64, u8) = (500, 6.4, 1); |
空元组也叫单元(unit), 这个值及对应类型都写作(), 代表空值或者空返回类型.如果表达式没有返回其他任何值, 则隐式返回单元值.
数组类型: 固定长度, 每个元素类型都相同
声明方式:
1 | let months = ["January", "February", "March", "April", "May", "June", "July", |
可以通过中括号声明, eg: months[1], month[2] st.
Statements(语句) 和 Expressions(表达式)
语句是执行某些操作但不返回值的操作
let 绑定
1
let x = 5;
表达式语句
1
2let y = 6;
y + 1; // 这是一个语句, y + 1的结果被丢弃了函数定义
宏调用(作为语句):
println!("Hello, world!");
(虽然println!
是一个宏,但当它用作打印输出时,通常作为不返回值的语句使用)任何以分号结尾的表达式:
表达式是 Rust 中会计算并产生一个值的代码块。它们可以由字面量、变量、运算符、函数调用、宏调用,甚至由花括号包围的代码块组成。可以用于赋值, 并且通常不以分号结尾, 如果以分号结尾,它就会变成一个语句, 其返回值会被丢弃.
1
2
3
4
5let y = {
let x = 3;
x + 1 // 这是一个表达式, 返回4
};
// now y is 4
总结区别
特性 表达式 (Expressions) 语句 (Statements) 返回值 会返回值 不返回值 结尾 通常不以分号结尾(在作为代码块的最后一行时) 通常以分号结尾 目的 计算并产生一个值 执行一个操作 例子 1 + 2
,{ let x = 3; x + 1 }
,if cond { 1 } else { 0 }
let x = 5;
,println!("Hello!");
,x = 10;
函数
声明方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19fn main() {
println!("hello, wworld!");
another_funtion();
}
fn another_funtion(x: i32) { // 必须定义函数形参的类型
prinlin!("Another funtion.");
println!("The value of x is: {x}");
}
fn plus_one(x: i32) {
x + 1
}
fn f(x: i32) -> i32 { // 有返回值的函数
x + 1
// return x + 1; // 显式返回也可以
}Rust不在乎在哪里定义函数(调用前, 调用后), 只要函数被定义在调用者可以看到的作用域中即可.
控制流
条件控制
1
2
3
4
5
6
7
8
9fn main() {
let number = 3;
if number < 5 { // if 后面一定是跟一个bool类型, 如果是其他类型并不会隐式转换为bool类型
println!("condition was true");
} else {
println!("condition was false");
}
}1
2
3
4
5
6
7fn main() {
let condition = true;
let number = if condition { 5 } else { 6 }; // 这里的两个分支都必须是相同的类型, 不然会报错
println!("The value of number is {number}. ");
}因为Rust需要在编译时需要知道变量的类型, 而不是运行时再做推断, 所以如果使用上面的语句来进行赋值的时候, 不同分支返回的都必须是相同的类型.
循环
1
2
3
4
5
6
7
8
9
10
11
12fn main() {
let mut cnt = 0;
let result = loop {
cnt += 1;
if cnt == 10 {
break cnt * 2; // 使用break 中断循环并且返回值
};
}
println!("The result is {result}");
}如果有嵌套循环, 可以通过标签来标注某个特定的循环并且可以
break
掉特的循环:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22fn loopwithlabels() {
let mut cnt = 0;
'counting_up: loop { // 使用单引号来声明一个标签
println!("cnt = {cnt}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break;
}
if cnt == 2 {
break 'counting_up;
}
remaining -= 1;
}
cnt += 1;
}
println!("End cnt = {cnt}");
}while 循环: 与其他语言十分相似
1
2
3
4
5
6
7
8
9
10
11fn main() {
let mut number = 3;
while number != 0 {
println!("{number}");
number -= 1;
}
println!("LIFTOFF!!");
}遍历集合:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/* 通过while循环来遍历 */
fn main() {
let a = [10, 20, 30, 40, 50];
let mut idx = 0;
while idx < 5 {
println!("the value is {}", a[idx]);
idx += 1;
}
}
/* 通过for循环遍历, 推荐 */
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is {element}");
}
}