变量与可变性

Rust变量是默认不可变的。一旦它被绑定到了某个值上面,这个值就无法再被改变。

要想变量可变,需要在声明的变量的时候在变量前面添加mut关键字来实现。

对于重型数据结构,适当使用可变性去修改一个实例,要比赋值或者重新返回一个新实例要更有效率,对于轻量的数据结构,通过函数式编程创建新变量来赋值,代码更容易理解。

变量与常量的不同

虽然Rust中变量默认是不可变的,但是它与常量仍然是不同的。

  1. 常量不能使用mut修饰
  2. 常量使用const修饰,并且声明时要显示标注类型
  3. 常量可以被声明在任何作用域上。
  4. 常量只能绑定到常量表达式上,编译期就能够确定值。

Rust确定使用下划线分割的全大写字母来命名一个常量。

隐藏

我们知道在C/C++中是不可以重复声明变量的,但是Rust中可以。 重复使用let关键字配以相同的名称,那么在接下来的生命周期中,发挥作用的就是新的变量,旧的变量就好像被隐藏(shadow) 一样。

隐藏机制实际上是创建了一个新的变量,可以修改可变性和变量的类型

常见的使用实例就是:从控制台读取的输入都是字符串类型,但是通常需要转换成我们需要的类型,使用隐藏就可以方便实现这一点而不用引入新的命名。

隐藏机制可以在保持不可变性的情况下对变量进行变换。

数据类型

Rust是一种静态类型语言,需要在编译程序的过程中就需要知道所有变量的具体类型。

大部分情况下,编译器可以根据如何绑定、使用变量的值来自动推导出类型,对于不能推导出的,需要显示标注类型。

标量类型

标量类型是单个值的类型的统称。Rust中内建了4种基本的标量类型:整数、浮点数、布尔值及字符

整数类型

整数是指没有小数部分的数字。

长度有符号无符号
8位i8u8
16位i16u16
32位i32u32
64位i64u64
archisizeusize

isizeusize比较特殊,它们的长度是与平台架构相关的,64位架构就是64位、32位架构就是32位。

整数字面量如下:

整数字面量示例
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte(u8)b’A’

Rust默认整数字面量的推导类型为i32,它在大部分情况下都是运行最快的,64位系统也是如此

usizeisize通常用作某些集合的索引。

整数溢出

在debug模式下,程序中包含整数溢出的运行时检测代码,检测到溢出会触发panic。 在release模式下,整数溢出不会触发panic

浮点数类型

浮点数就是带小数的数字。只有两种类型f32f64,分别占用32位和64位。

默认的浮点数字字面量会推导为f64,精度更高并且运行效率相差不大。

数值运算

数值类型都支持常见的数学运算:加、间、乘、除、取余。

布尔类型

布尔类型只有两个值:truefalse,占用一个字节空间。

字符类型

Rust中使用char描述单个字符,使用单引号指定。

char类型占用4字节,一个Unicode标量值。甚至emoji表情就是一个有效的char类型。

复合类型

复合类型可以将多个不同类型的值组合成为一个类型。Rust有两种内置的基础复合类型:元组(tuple)和数组(array)

元组类型

元组可以将多个不同类型的值组合在一起,并且在元组声明结束后长度就固定了,无法增加或者减少。 示例:

fn main() {
	// 声明一个元素
	let tup = (500, 6.4, 1);
	// 使用模式匹配解构元素
	let (x,y,z) = tup;
 
	println!("The value of y is {}", y)
}

使用.和索引来访问元组的元素,例如:

let tup = (500, 6.4, 1);
let num1 = tup.0
let num2 = tup.2

数组类型

数组中的每个元素必须是相同的类型,Rust数组与其它语言的不同,Rust中的数组一旦声明,大小固定不可改变。对于需要改变大小的数组,Rust提供了动态数组vector,这在后续介绍。

示例:

// 创建一个类型为i32,长度为5的数组
let a:[i32; 5] = [1,2,3,4,5];
// 创建一个数组为[3,3,3,3,3]
let b = [3;5]
 
// 访问数组元素
a[0];
a[1]

一般对于长度固定的数据,例如月份,会使用数组类型。其它情况使用动态数组。

使用非法索引访问数组,Rust将会触发panic。

函数

Rust函数的格式如下:

fn 函数名(参数列表) -> 返回类型{
	//函数体
}
  • 使用fn关键字来声明一个函数
  • Rust使用蛇形命名法来规范函数和变量的风格,就是使用全小写和下划线分割单词的格式命名。
  • 参数列表中的参数使用逗号分割,每个参数必须显示标注类型
  • Rust函数可以使用元组包含多个值来实现多个返回值的。

语句和表达式

Rust是基于表达式的语言。将语句表达式分为两个概念。

  • 语句:执行操作但不返回值的指令。
  • 表达式:进行计算并产生一个值作为结果的指令。

例如,let创建变量绑定值就是一条语句,因为没有值产生,所以无法将let语句赋值给一个变量

// 发生错误
let x = (let y = 6)

所以在Rust中无法实现其它语言一样的x = y = 6这样的语句。

能够返回值的就是表达式,无论是字面量还是数值运算,例如

let x = 5;
let y = {
	let x = 3;
	x + 1
}

在Rust中,绝大部分代码都是表达式,例如5 + 6,而表达式也常作为语句的一部分,例如上面的字面量5,函数调用也是表达式,创建新作用于的花括号也是表达式

代码块中的最后一条表达式的值就是代码块的返回值,注意上面的x + 1后面没有分号,计算的结果是4,代码块的返回结果也是4,最后绑定到变量y上的值也是4。

函数返回值

在Rust中,函数的返回值等同于函数体最后一个表达式的值。这其实与上面说所的一致,因为函数体也是在代码块当中的。

不过也可以使用return关键字指定一个值提前从返回中返回。

Note

Rust中的函数和代码块的最后一条指令如果是语句,因为语句没有值,而代码块实际上是一个有返回值的表达式,所以Rust中函数或代码块默认会返回()空元组

注释

Rust中的注释以双斜杠//开始,一直到本行结束

// Hello, World

控制流

主要就是if表达式和循环表达式。

if表达式

满足条件则执行这代码,不满足则跳过。

fn main() {
	let number = 2;
	if number < 5 {
		println!("condition was true");
	} else {
		println!("condition was false");
	}
}

Note

条件表达式必须产生一个bool类型的值,而不像C语言一样能够将非0值作为true,0值作为false

可以使用else if来实现多重条件判断。

从本节标题就可以看出来,if表达式既然是表达式,那么是可以产生值的,也就是说我们可以将if表达式的值绑定到变量上。

fn main() {
	let condition = true;
	let number = if condition {
		5
	} else {
		6
	};
	println!("The value of number is {}", number);
}

if表达式的值取决于哪个分支得到了执行,也就是说,每个分支可能的返回值类型是同一类型

循环表达式

Rust有三种循环:loopwhilefor。与if一样,作为表达式是同样会产生值的。

三种循环是可以相互转换的。

loop循环

loop循环反复执行一块代码,直到显示声明退出。

fn main() {
	loop {
		println!("again!");
	}
}

loop可以使用break退出循环,还可以在break后面添加表达式作为循环的返回值

fn main() {
	let mut counter = 0;
	loop {
		counter += 1;
		if counter == 10 {
			break counter * 2;
		}
	}
}

while循环

while循环每次执行循环体之前都判断一次条件。条件为真再执行。

fn main() {
	let mut number = 3;
	while number != 0 {
		println!("{}!", number);
		number = number - 1;
	}
}

for循环

for循环通常用来遍历集合,不需要像loop或者while循环一样关注索引,避免不正确的索引导致错误出现。

fn main() {
	let a = [10, 20, 30, 40, 50];
	for element in a.iter() {
		println!("The value is {}!", element);
	}
}

for循环是最常用的循环结构,通常与Range配置来实现特定次数的任务:

fn main() {
	for number in (1..4) {
		println!("{}!", number);
	}
}

Range就是上面的(1..4)的写法,用来生成从一个数字开始到另一个数字结束之前的所有数字序列。


tags: Rust数据类型 Rust基本语法