上一篇介绍了Rust 2024年目前的发展情况 , 后边几天也争取把相关Rust的学习笔记和快速入门进行介绍,帮助感兴趣的快速上手Rust,今天先介绍整理的精简核心语法第一波。
Rust精简笔记(一)
-
适用于对Rust语言感兴趣,了解Rust,并想快速学习和掌握Rust开发。
-
通过精简方式来整理核心语法、更方便后续知识点速查、回顾。
-
参考The Rust Programming Language & Rust in Action
一.变量
-
变量声明使用let, 默认为不可变(即只读),声明可变变量 mut (可读写)
let x = 5; //类型可以由编译器自动推断出来
let y: i32 = 6; //或者是在创建变量时,声明类型
let z = 7i32; //数字类型,可以在数字字面量中加入类型注解
二. 基本数据类型
数字类型:
-
分为有符号和无符号整数,浮点数类型、特定平台的整数
-
每一个有符号的变体可以储存包含从 -2n-1 到2n-1-1 在内的数字,这里 n 是变体使用的位数。如:i8 范围(-128-127)
-
无符号的范围为0到 2n-1,如: u8 范围(0-255)(00000000 - 11111111)
类型 | 长度 | 描述 |
i8, i16, i32, i64, i128 | 8,16,32,64,64,128 (bit) | 有符号整数 |
u8, u16, u32, u64, u128 | 8,16,32,64,64,128 (bit) | 无符号整数 |
f32, f64 | 32,64(位) | f32 是单精度浮点数,f64 是双精度浮点数 |
isize, usize | 32或64 | 32 位架构上它们是 32 位的,64 位架构上它们是 64 位的 |
Rust中的整型字面值:
数字字面值 | 描述 |
Decimal (十进制) | 1_100 (使用 _ 做为分隔符以方便读数) |
Hex (十六进制) | 0xff(0x开头) |
Octal (八进制) | 0o77 (0o开头) |
Binary (二进制) | 0b1111_0000(0b开头) |
Byte (单字节字符)(仅限于u8) | b'A'(b开头) |
布尔类型 bool:
fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
复合类型:
-
元组(tuple)和数组(array)
-
Tuple: 将多个其他类型的值组合进一个复合类型,声明后长度固定,索引下标从0开始.
let tup: (i32, f64, u8) = (500, 8.4, 2); //声明类型
let score = ("Team A", 12); //自推断
let five_hundred = tup.0; //取出元组里的500,下标0
-
array: 数组里数据类型必须一致,长度固定
let a = [1, 2, 3, 4, 5]; // 自推断
let b: [i32; 5] = [1, 2, 3, 4, 5]; // 在方括号中包含每个元素的类型,后跟分号,再后跟数组元素的数量。
let c = [3; 5]; //变量名为c的数组将包含 5 个元素,数值都为3,等价与let a = [3, 3, 3, 3, 3]
三. 流程控制
if & if let:
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
// match pattern and assign variable
if let Some(i) = num {
println!("number is: {}", i);
}
// if let 语法让我们以一种不那么冗长的方式结合 if 和 let,来处理只匹配一个模式的值而忽略其他模式的情况
loop:
let mut count = 0;
loop {
count += 1;
if count == 4 {
println!("break");
break;
}
}
Nested loops & labels (循环标签): 如果存在嵌套循环在一个循环上指定一个 循环标签(loop label) 标识为'名字
'outer: loop {
'inner: loop {
break; // This breaks the inner loop
break 'outer; // // This breaks the outer loop
}
}
while & while let:
while n < 101 {
n += 1;
}
let mut optional = Some(0);
while let Some(i) = optional {
print!("{}", i);
}
for 遍历集合:
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
//使用iter()
let array = [(1, 2), (2, 3)];
for (x, y) in array.iter() {
// x, y accessible in loop body only
println!("x={},y={}", x, y);
}
match:
let optional = Some(0);
match optional {
Some(i) => println!("{}", i),
None => println!("No value."),
}
四.所有权&引用&借用
所有权规则:
Rust 中的每一个值都有一个 所有者(owner)
值在任一时刻有且只有一个所有者
当所有者(变量)离开作用域,这个值将被丢弃
借用规则:(引用的行为)
同一作用域内,一个资源要么有一个可变引用,要么存在多个不可变引用
引用总是有效的
String引用:
let s1 = String::from("hello world!");
let s1_ref = s1; // immutable reference
let mut s2 = String::from("hello");
let s2_ref = &mut s2; // mutable reference
s2_ref.push_str(" world!");
-
函数里使用值,但不获取所有权, 使用&,获取变量引用 ,仅读权限
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
-
函数里参数可变引用, 使用&mut ,获取变量可变操作
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
// 对参数声明&mut ,操作写字符
fn change(some_string: &mut String) {
some_string.push_str(", world");
println!("{}", some_string);
}
操作符对应的权限:
x 不可变的值(所有权)
&x x不可变的引用 (只读)
&mut x x的可变引用(读写)
字符串 slice:
-
slice 允许你引用集合中一段连续的元素序列,而不用引用整个集合。slice 是一类引用,它没有所有权
fn main() {
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
}
五. struct
-
普通结构体:struct+一个名字,在大括号中每一部分可以是不同类型,定义每一部分数据的名字和类型,称之为结构体字段
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
-
创建一个实例需要以结构体的名字开头,接着在大括号中使用 key: value 键-值对的形式提供字段
let userinfo = User {
email: String::from("[email protected]"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
元组结构体(tuple structs):
-
元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
类单元结构体(unit-like structs):
-
没有任何字段的结构体
struct AlwaysEqual;
fn main() {
let subject = AlwaysEqual;
}
impl为结构体添加方法:
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
-
&self 实际上是 self: &Self 的缩写。在一个 impl 块中,Self 类型是 impl 块的类型的别名。方法的第一个参数必须有一个名为 self 的Self 类型的参数
impl里的关联函数:
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
-
所有在 impl 块中定义的函数被称为 关联函数(associated functions),因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例
-
多个 impl 块:每个结构体都允许拥有多个 impl 块, 但一个方法只能属于一个impl块。
六.Enum
-
结构体给予将字段和数据聚合在一起的方法,像 Rectangle 结构体有 width 和 height 两个字段。而枚举给予你将一个值成为一个集合之一的方法。
enum IpAddrKind {
V4,
V6,
}
enum IpAddrKind {
V4,
V6,
}
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
route(IpAddrKind::V4);
route(IpAddrKind::V6);
}
fn route(ip_kind: IpAddrKind) {}
枚举可以包含不同的类型:
enum Message {
Quit, // 没有关联任何数据
Move { x: i32, y: i32 }, //类似结构体包含命名字段
Write(String), //包含单独一个 String
ChangeColor(i32, i32, i32), //包含三个 i32
}
-
• 结构体和枚举还有另一个相似点:就像可以使用 impl 来为结构体定义方法那样,也可以在枚举上定义方法。这是一个定义于我们 Message 枚举上的叫做 call 的方法:
fn main() {
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {
// 在这里定义方法体
}
}
let m = Message::Write(String::from("hello"));
m.call();
}
标准库中实用的枚举:Option
enum Option<T> {
None,
Some(T),
}
enum Result<T, E> {
OK(T),
Err(E),
}
第一波先介绍到这里,后边把第二波的整理出来。通过3-4波精简笔记方式,也是我一个个验证过的,能帮助快速掌握rust基础。
PS: 也欢迎大家评论和交流~ 更多文章也可关注微信公号:良技漫谈