用微信小程序怎么做网站,网页设计计费,推广方式单一的原因,云端视差wordpress企业主题破解版通用编程概念
变量和可变性
默认情况下变量是不可变的#xff08;immutable#xff09;,不过你也可以选择让变量是可变的#xff08;mutable#xff09;.
变量的遮蔽
你可以声明和前面变量具有相同名称的新变量,说这个是第一个变量被第二个变量遮蔽#xff08;shadowimmutable,不过你也可以选择让变量是可变的mutable.
变量的遮蔽
你可以声明和前面变量具有相同名称的新变量,说这个是第一个变量被第二个变量遮蔽shadow这意味着当我们使用变量时我们看到的会是第二个变量的值。我们可以通过使用相同的变量名并重复使用 let 关键字来遮蔽变量如下程序并不会报错:
let x 5;
let x x1;
{let x x*3;
}
let x String::new();遮蔽和将变量标记为 mut 的方式不同因为除非我们再次使用 let 关键字否则若是我们不小心尝试重新赋值给这个变量我们将得到一个编译错误。通过使用 let我们可以对一个值进行一些转换但在这些转换完成后变量将是不可变的。
mut 和遮蔽之间的另一个区别是因为我们在再次使用 let 关键字时有效地创建了一个新的变量所以我们可以改变值的类型但重复使用相同的名称。
常量
与不可变变量类似常量constant是绑定到一个常量名且不允许更改的值但是常量和变量之间存在一些差异。
首先常量不允许使用 mut。常量不仅仅默认不可变而且自始至终不可变。常量使用 const 关键字而不是 let 关键字来声明并且值的类型必须注明。
最后一个不同点是常量只能设置为常量表达式或能在运行时计算得到的值。而不能是函数调用的结果.
Rust 常量的命名约定是全部字母都使用大写并使用下划线分隔单词。
将整个程序中用到的硬编码hardcode值命名为常量对于将该值的含义传达给代码的未来维护者很有用。如果将来需要更改硬编码的值则只需要在代码中改动一处就可以了。
数据类型
Rust 的每个值都有确切的数据类型data type该类型告诉 Rust 数据是被指定成哪类数据从而让 Rust 知道如何使用该数据。
请记住 Rust 是一种静态类型statically typed的语言这意味着它必须在编译期知道所有变量的类型。编译器通常可以根据值和使用方式推导出我们想要使用的类型。
标量类型
标量scalar类型表示单个值。Rust 有 4 个基本的标量类型整型、浮点型、布尔型和字符。
整数
整数integer是没有小数部分的数字
举个例子u32 类型。此类型声明表明它关联的值应该是占用 32 位空间的无符号整型有符号整型以 i 开始i 是英文单词 integer 的首字母与之相反的是 u代表无符号 unsigned 类型
长度有符号类型无符号类型8 位i8u816 位i16u1632 位i32u3264 位i64u64128 位i128u128archisizeusize
有符号数字以二进制补码形式存储
此外isize 和 usize 类型取决于程序运行的计算机体系结构在表中表示为“arch”若使用 64 位架构系统则为 64 位若使用 32 位架构系统则为 32 位。
数字字面量示例十进制98_222十六进制0xff八进制0o77二进制0b1111_0000字节 (仅限于 u8)bA
整型溢出
比方说有一个 u8 它可以存放从 0 到 255 的值。那么当你将其修改为范围之外的值比如 256则会发生整型溢出integer overflow这会导致两种行为的其中一种。当在调试debug模式编译时Rust 会检查整型溢出若存在这些问题则使程序在编译时 panic.Rust 使用 panic 这个术语来表明程序因错误而退出。
在当使用 --release 参数进行发布release模式构建时Rust 不检测会导致 panic 的整型溢出。相反当检测到整型溢出时Rust 会进行一种被称为二进制补码包裹two’s complement wrapping的操作。简而言之大于该类型最大值的数值会被“包裹”成该类型能够支持的对应数字的最小值。比如在 u8 的情况下256 变成 0257 变成 1依此类推。程序不会 panic但是该变量的值可能不是你期望的值。依赖整型溢出包裹的行为不是一种正确的做法。
要显式处理溢出的可能性可以使用标准库针对原始数字类型提供的以下一系列方法
使用 wrapping_* 方法在所有模式下进行包裹例如 wrapping_add如果使用 checked_* 方法时发生溢出则返回 None 值使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值使用 saturating_* 方法使值达到最小值或最大值
浮点型
浮点数floating-point number是带有小数点的数字在 Rust 中浮点类型简称浮点型数字也有两种基本类型。Rust 的浮点型是 f32 和 f64它们的大小分别为 32 位和 64 位。默认浮点类型是 f64因为在现代的 CPU 中它的速度与 f32 的几乎相同但精度更高。所有浮点型都是有符号的。f32 类型是单精度浮点型f64 为双精度浮点型。
数字运算
Rust 的所有数字类型都支持基本数学运算加法、减法、乘法、除法和取模运算。整数除法会向下取整。
布尔型
和大多数编程语言一样Rust 中的布尔类型也有两个可能的值true 和 false。布尔值的大小为 1 个字节.
字符类型
Rust 的 char字符类型是该语言最基本的字符类型
注意我们声明的 char 字面量采用单引号括起来这与字符串字面量不同字符串字面量是用双引号括起来。Rust 的字符类型大小为 4 个字节表示的是一个 Unicode 标量值这意味着它可以表示的远远不止是 ASCII。标音字母中文/日文/韩文的文字emoji还有零宽空格(zero width space)在 Rust 中都是合法的字符类型。Unicode 值的范围为 U0000 ~ UD7FF 和 UE000~U10FFFF。不过“字符”并不是 Unicode 中的一个概念所以人在直觉上对“字符”的理解和 Rust 的字符概念并不一致。
补充一下计算机基础知识
一个字节byte由 8 位bit 组成。这是计算机科学中标准的定义
位bit是计算机中最小的数据单位它可以表示两种状态之一通常用 0 或 1 表示
字节byte是计算机存储数据的基本单位。一个字节由 8 个位组成可以表示 2的8次方256 种不同的值从 0 到 255。
1 字节 (Byte) 8 位 (bit) 1 千字节 (KB) 1024 字节 (B) 1 兆字节 (MB) 1024 千字节 (KB) 1 吉字节 (GB) 1024 兆字节 (MB)
复合类型
复合类型compound type可以将多个值组合成一个类型。Rust 有两种基本的复合类型元组tuple和数组array。
元组
元组是将多种类型的多个值组合到一个复合类型中的一种基本方式。元组的长度是固定的声明后它们就无法增长或缩小。
我们通过在小括号内写入以逗号分隔的值列表来创建一个元组。元组中的每个位置都有一个类型并且元组中不同值的类型不要求是相同的。
let tup: (i32, f64, u8) (500, 6.4, 1);变量 tup 绑定到整个元组因为元组被认作是单个复合元素。 想从元组中获取个别值我们可以使用模式匹配来解构destructure元组的一个值
let tup (500, 6.4, 1);
let (x, y, z) tup;该程序首先创建一个元组并将其绑定到变量 tup 上。 然后它借助 let 来使用一个模式匹配 tup并将它分解成三个单独的变量 x、y 和 z。 这过程称为解构destructuring
除了通过模式匹配进行解构外我们还可以使用一个句点.连上要访问的值的索引来直接访问元组元素
let x: (i32, f64, u8) (500, 6.4, 1);
let five_hundred x.0;
let six_point_four x.1;
let one x.2;该程序创建一个元组 x然后通过使用它们的索引为每个元素创建新的变量。和大多数编程语言一样元组中的第一个索引为 0。
没有任何值的元组 () 是一种特殊的类型只有一个值也写成 ()。该类型被称为单元类型unit type该值被称为单元值unit value。如果表达式不返回任何其他值就隐式地返回单元值。
数组类型
将多个值组合在一起的另一种方式就是使用数组array。与元组不同数组的每个元素必须具有相同的类型。与某些其他语言中的数组不同Rust 中的数组具有固定长度。
我们在方括号内以逗号分隔的列表形式将值写到数组中:
let a [1, 2, 3, 4, 5];
// 数组的另一种声明方式 i32 是每个元素的类型。分号之后数字 5 表明该数组包含 5 个元素。
let a: [i32; 5] [1, 2, 3, 4, 5];
// 指定初始值,和个数的数组
let a [3; 5];访问数组元素
数组是可以在栈上分配的已知固定大小的单个内存块。可以使用索引访问数组的元素
let a [1, 2, 3, 4, 5];
let first a[0];
let second a[1];在这个例子中名为 first 的变量将获得值 1因为它是数组中索引 [0] 处的值。名为 second 的变量将从数组中的索引 [1] 中获取得 2。
当你尝试使用索引访问元素时Rust 将检查你指定的索引是否小于数组长度。如果索引大于或等于数组长度Rust 会出现 panic。这种检查必须在运行时进行尤其是在这种情况下因为编译器可能无法知道用户之后运行代码时将输入什么值。
函数
Rust 代码中的函数和变量名使用下划线命名法snake case直译为蛇形命名法规范风格。在下划线命名法中所有字母都是小写并使用下划线分隔单词。
Rust 中的函数定义以 fn 开始后跟着函数名和一对圆括号。大括号告诉编译器函数体在哪里开始和结束。
可以使用函数名后跟圆括号来调用我们定义过的任意函数。函数的定义位置无关紧要,不用非要像c语言那样一定要在面之前或者在面之前需要一个定义.Rust 不关心函数定义于何处只要定义了就行。
参数
函数也可以被定义为拥有参数parameter参数是特殊变量是函数签名的一部分。当函数拥有参数形参时可以为这些参数提供具体的值实参。技术上讲这些具体值被称为实参argument但是在日常交流中人们倾向于不区分使用 parameter 和 argument 来表示函数定义中的变量或调用函数时传入的具体值。
在函数签名中必须声明每个参数的类型。这是一个 Rust 设计中经过慎重考虑的决定要求在函数定义中提供类型标注意味着编译器几乎从不需要你在代码的其他地方注明类型来指出你的意图。
语句和表达式
Rust 是一门基于表达式expression-based的语言.
语句statement是执行一些操作但不返回值的指令。表达式expression计算并产生一个值
{let x 3;x 1
}这是一个表达式,注意x 1 行的末尾没有分号这与你目前见过的大部分代码行不同。表达式的结尾没有分号。如果在表达式的末尾加上分号那么它就转换为语句而语句不会返回值。在接下来探讨函数返回值和表达式时请记住这一点。
记住代码块的值是其最后一个表达式的值而数字本身就是一个表达式
带有返回值的函数
函数可以向调用它的代码返回值。我们并不对返回值命名但要在箭头-后声明它的类型。在 Rust 中函数的返回值等同于函数体最后一个表达式的值。使用 return 关键字和指定值可以从函数中提前返回但大部分函数隐式返回最后一个表达式。这是一个有返回值函数的例子
fn five() - i32 {5
}fn main() {let x five();println!(The value of x is: {}, x);
}在 five 函数中没有函数调用、宏甚至没有 let 语句——只有数字 5 本身。这在 Rust 中是一个完全有效的函数。注意函数返回值的类型也被指定好即 - i32。
注释
// 单行注释/*多行注释
*//// 文档注释
/// 说明函数功能等/**
* 文档注释
* 用于说明函数功能等
*/
控制流
if表达式
if number 5 {println!(condition was true);
} else {println!(condition was false);
}if 表达式中与条件关联的代码块有时被叫做分支arm和 match 表达式中的分支一样.
另外值得注意的是代码中的条件必须是 bool 值。如果条件不是 bool 值我们将得到一个错误
else if if number % 4 0 {println!(number is divisible by 4);} else if number % 3 0 {println!(number is divisible by 3);} else if number % 2 0 {println!(number is divisible by 2);} else {println!(number is not divisible by 4, 3, or 2);}在let语句中使用if
因为 if 是一个表达式我们可以在 let 语句的右侧使用它来将结果赋值给一个变量 let condition true;let number if condition { 5 } else { 6 };使用循环重复执行
loop
loop 关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。 loop {println!(again!);}Rust 也提供了一种从代码中跳出循环的方法。可以使用 break 关键字来告诉程序何时停止循环,循环中的 continue 关键字告诉程序跳过这个循环迭代中的任何剩余代码并转到下一个迭代。
如果存在嵌套循环break 和 continue 应用于此时最内层的循环。你可以选择在一个循环上指定一个循环标签loop label然后将标签与 break 或 continue 一起使用使这些关键字应用于已标记的循环而不是最内层的循环。下面是一个包含两个嵌套循环的示例
fn main() {let mut count 0;counting_up: loop {println!(count {}, count);let mut remaining 10;loop {println!(remaining {}, remaining);if remaining 9 {break;}if count 2 {break counting_up;}remaining - 1;}count 1;}println!(End count {}, count);
}从循环返回
loop 的一个用例是重试可能会失败的操作比如检查线程是否完成了任务。然而你可能会需要将操作的结果从循环中传递给其它的代码。为此你可以在用于停止循环的 break 表达式添加你想要返回的值该值将从循环中返回以便您可以使用它如下所示
fn main() {let mut counter 0;let result loop {counter 1;if counter 10 {break counter * 2;}};println!(The result is {}, result);
}while 条件循环
fn main() {let mut number 3;while number ! 0 {println!({}!, number);number - 1;}println!(LIFTOFF!!!);
}使用for遍历集合
fn main() {let a [10, 20, 30, 40, 50];for element in a {println!(the value is: {}, element);}
}fn main() {for number in (1..4).rev() {println!({}!, number);}println!(LIFTOFF!!!);
}