Rust 基本知识

更多是从一个前端开发者的角度，来比较一下两门语言的区别，以助于更方便的入门。

基本类型（DataType）

多数情况下，基本类型直接代表了最底层的语言实现。

JavaScript 是弱类型，基本数据类型有以下 7 种：

String

Number

BigInt

Boolean

Symbol (ECMAScript 2016 新增)

null

undefined

Rust 是 静态类型 ( statically typed ) 语言，也就是说在编译时就必须知道所有变量的类型。每一个值都属于某一个 数据类型 ( data type )，这告诉 Rust 它被指定为何种数据，以便明确数据处理方式。基本都属于两类数据类型子集：标量（scalar）和复合（compound）。

Integer （整数类型）

位长度 | 有符号 | 无符号
8-bit | i8 | u8
16-bit | i16 | u16
32-bit | i32 | u32
64-bit | i64 | u64
128-bit | i128 | u128
arch | isize | usize

每一个有符号的变体可以储存包含从 $-(2^{n-1})$ 到 $2^{n-1}-1$ 在内的数字，这里 $n$ 是变体使用的位数。所以 i8可以储存从 $-(2^7)$ 到 $2^7-1$ 在内的数字，也就是从 $-128$ 到 $127$ 。无符号的变体可以储存从 $0$ 到 $2^n-1$ 的数字，所以 u8 可以储存从 $0$ 到 $2^8-1$ 的数字，也就是从 $0$ 到 $255$。

注意：可以使用以下表格的任何一种形式编写数字字面值。请注意可以是多种数字类型的数字字面值允许使用类型后缀，例如 57u8 来指定类型，同时也允许使用 _ 做为分隔符以方便读数，例如1_000，它的值与你指定的 1000 相同。

Integer 的表述方法

进制 | 案例
十进制 | 98_222
十六进制 | 0xff
八进制 | 0o77
二进制 | 0b1111_0000
字节（只表示 u8 型） | b'A'

Floating-Point Number （浮点数字类型）

浮点数就是带小数点的数字。Rust 的浮点数类型是 f32和 f64，分别占 32 位和 64 位。默认类型是 f64，因为在现代 CPU 中，它与 f32 速度几乎一样，不过精度更高。所有的浮点型都是有符号的。

Bool （布尔型）

标识：bool

true

false

Char（字符类型）

单引号标识字符类型 (char)，双引号声明字符串 (str)。

Rust 的 char 类型的大小为四个字节 (four bytes)，并代表了一个 Unicode 标量值（Unicode Scalar Value），这意味着它可以比 ASCII 表示更多内容。在 Rust 中，拼音字母（Accented letters），中文、日文、韩文等字符，emoji（绘文字）以及零长度的空白字符都是有效的 char 值。Unicode 标量值包从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF 在内的值。不过，「字符」 并不是一个 Unicode 中的概念，所以人直觉上的「字符」 可能与 Rust 中的 char 并不符合。

Compound types（复合类型）

Rust 有两个原生的复合类型：元组（tuple）和数组（array）。

元组是一个将多个其他类型的值组合进一个复合类型的主要方式。

元组长度固定：一旦声明，其长度不会增大或缩小。

数组中的每个元素的类型必须相同。

Rust 中的数组长度是固定的。

其他

Vector（Vec<T>）

可变长数组

Vector 允许我们在一个单独的数据结构中储存多于一个的值，它在内存中彼此相邻地排列所有的值

String

字符串就是作为字节的集合外加一些方法实现的。

称作 String 的类型是由标准库提供的，而没有写进核心语言部分，它是可增长的、可变的、有所有权的、UTF-8 编码的字符串类型。

Map（HashMap<K, V>）

它通过一个 哈希函数（hashing function）来实现映射，决定如何将键和值放入内存中。很多编程语言支持这种数据结构，不过通常有不同的名字：哈希、map、对象、哈希表或者关联数组等等

哈希 map 可以用于需要任何类型作为键来寻找数据的情况，而不是像 vector 那样需要通过索引。

变量（Variables）

Copy
var code = 123; // 在老版本的规范里面，只需要通过 var 关键字来声明
let firstName = "kaby"; // ES6 之后，let 表示变量，允许修改
const lastName = "Zhao"; // ES6 之后，const 表示是常量，不允许修改

firstName = "bike"; // 正常
lastName = "Hu"; // 报错 - Uncaught TypeError: Assignment to constant variable

Copy
// Rust 所有的变量默认都是不允许修改的，如
let code = 123;
println!("The value of code is: {code}"); // 正常
code = 456; // 抛出错误 - cannot assign twice to immutable variable `code`

// 声明一个允许改变的变量
let mut name = "lulu";
println!("The name is: {name}"); // 输出 lulu
name = "jack";
println!("The name is: {name}"); // 输出 jack

// 同样可以声明常量的关键词
// 不允许对常量使用 mut
// 常量不光默认不能变，它总是不能变
const WAIT_SEC:u32 = 30;

// 变量隐藏
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
// 12
println!("The value of x in the inner scope is: {x}");
}
// 6
println!("The value of x is: {x}");
}

函数 & 逻辑

Copy
// 方法的声明
function getName() {
return "jack";
}

// 通过变量的方式
let getInfo = function() {
return {
"age": 18
}
}

// 上面也可以使用箭头表示
let getInfo = () => ({ "age": 18 })

// 逻辑
// 判断 if / switch
if (getName() == "jack") {
return "lose";
} else if (getName() == "lose") {
return "moth";
} else {
return "";
}

// 循环 for...in / for...of / while
let arr = [1, 2, 3];
for(let i = 0; i < arr.length; i++) {
console.info(i);
}

// 可以看出来，JavaScript 因为是弱类型语言，会自动对变量类型进行推导和转化
// 所以对于一些比较和判断来说比较简单，直接通过 == 就可以
// 但是也会出现一些意外的情况，比如
// "5" == 5 的结果是 true，这边要多注意，可以通过 "5" === 5 解决。
// 也可以直接判断字符串是否相等
// "abc" == "cde"

Copy
// 方法
fn main() {
println!("hello world");

another_function();

// print_labeled_measurement
print_labeled_measurement(5, 'h');

// plus_one
let po = plus_one(8);
// po == 9
println!("计算结果是 {}", po);

// do logic_info function
logic_info("abc", 12);

// loop
loop_info();
}

// another_function
fn another_function() {
println!("another_function");
}

// 带参数的方法
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {value}{unit_label}");
}

// 如果这个方法有返回值的话，还需要定义返回值的类型
fn plus_one(x: i32) -> i32 {
return x + 1;
}

// 逻辑判断
fn logic_info(name: &str, age: i32) {
println!("{} 的年龄是 {} ", name, age);

// 对于数字类型，可以直接使用 if 比较
if age > 12 {
println!("大于 12 岁，需要购买车票");
} else if age < 12 {
println!("免费乘车");
} else {
println!("12 岁，需要购买车票");
}

// 字符串的比较
if name == "lulu" {
println!("你好, {}", name);
} else {
println!("名字不匹配");
}
}

// 循环
fn loop_info() {
// while 循环
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("LIFTOFF!!!");

// for 循环
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}

// loop 循环
// 注意，loop 循环不会自动终止，需要手动 break
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("loop 循环结果是： {result}");
}

// 可以在这里查看具体的代码
// https://play.rust-lang.org/?gist=e87ef95f861dbc22bf8f23722e40aa34

—EOF—