Rust笔记【1】

  1. 元组和解构语法
rust 复制代码
let tup : (i32, f64, u8) = (666, 2.0, 1);

let tup = (666, 2.0, 1);
let (x, y, z) = tup;

let x = tup.0;
let y = tup.1;
let z = tup.2;
  1. 数组类型
    数组定义是方括号:[ ]
    元组定义是小圆括号:( )
    结构体定义是大括号:{ },结构体定义和赋值中,成员用逗号,分隔(c++中使用分号分隔)
rust 复制代码
let arr = [1, 2, 3];
let sss = ["mon", "tue", "fri"];

let a: [i32; 5]; # 长度为5的整型数组
let b: [3; 5];	# 5个3

let data = a[0];
  1. 传参、赋值默认都是移动操作。
  2. 引用不移动所有权,默认引用是不可修改的。例如:
rust 复制代码
let s = String::from("hello");

func(&s);

fn func(str: &string) -> ...
  1. 可变引用:
    如果创建了变量的一个可变引用,就不能再创建对改变量的其他引用(包括可变、不可变引用)。
    在一个作用域内不能有多个可变引用,在不同的作用域、不同时创建多个可变引用。
    如果已经创建一个或多个不可变引用,则不能再创建可变引用。
rust 复制代码
let mut s = String::from("hello");

func(&mut s);

fn func(str: &mut String) ->...
  1. 引用的个数:
    在一个作用域内:
    1)有一个或多个不变引用,无可变引用。
    2)只有一个可变引用。

注意:作用域结束不是以大括号结束,是以变量最后一次使用结束变量作用域(是没有显式标志)。

例如:

rust 复制代码
let mut s = String::from("hello");
let r1 = &s; // 没问题
let r2 = &s; // 没问题
println!("{} and {}", r1, r2);
// 此位置之后r1 和r2 不再使用

let r3 = &mut s; // 没问题
println!("{}", r3);
  1. slice是一类引用,引用集合中一段连续的元素序列。
    关键字: 引用,集合,连续片段

字符串slice:

rust 复制代码
let slice_name = target_set[start_index .. end_index]

let s = String::from("hello world");
let h = &s[0..5];
let w = &s[6..11];

# 以下几个等效
let h1 = &s[..5]; 
let w = &s[6..];
let s2 = &s[..];

字符串slice类型声明:&str

rust 复制代码
fn func(s: &String) -> &str { ...

字符串字面值是slice

s类型是&str

rust 复制代码
let s = "hello world";
  1. 结构体
    如果存储引用,则必须指定生命周期。否则编译错误。
rust 复制代码
struct Rectangle {
	width: i32,
	height: i32,
}

# 实例化,不需要new,key: value方式赋值。
let retc = Rectangle {
	width: 10,
	height: 20,
}
  1. 类单元结构体 unit-like struct
    用于在某个类型上实现trait,不存储数据
rust 复制代码
# 不需要大括号定义成员
struct SomeTrait;

# 实例化,不需要括号,没有成员需要赋值
let obj = SomeTrait;
  1. 结构体更新语法
    用一个已有结构体实例为另一个结构体赋值,新结构体只改变部分成员的值
rust 复制代码
struct User {
	a: i32,
	b: i32,
	c: i32,
}

let u1 = User {
	a: 1,
	b: 2,
	c: 3,
};

# ..u1(u1为已有结构体实例)必须放到最后
# 除明确复制的字段(b),其他字段值使用u1实例的
# 结构体更新语法,移动了数据,对于不支持copy trait的类型,更新后,原实例对象不可用。
let u2 = u1 {
	b: 99,
	..u1,
}
  1. 元组结构体
    为元组指定名称,单独的成员不指定名称。有整体名称,无成员变量名称。
    介于元组(无整体名称,无成员变量名称)和结构体(有整体名称,有成员变量名称)之间 。
    适用于区分不同元组类型(便于重用和区分),不需要(或者很容易)区分成员变量。
    成员变量匿名的struct类型定义。
rust 复制代码
struct Color {i32, i32, i32};
struct Point {i32, i32, i32};

let bgColor = {0, 0, 0};
let pointA = {1, 2, 3};
  1. 增加属性,派生Debug trait
    在struct定义前增加:#[derive(Debug)]
    println中使用{:?},不能使用{ }
rust 复制代码
#[derive(Debug)]
struct Rect {
    width: i32,
    height: i32,
}

fn main() {
    let rect = Rect { width: 20, height: 30 };
    println!("retc: {:?}\n", rect);
}
  1. 常用可派生trait
rust 复制代码
Debug
Copy
Clone
Default
Hash
PartialEq, Eq
PartialOrd, Ord
  1. 方法
    定义方式和函数类似,差别:
    1)定义在结构体(枚举、trait)上下文中:impl struct_name { }
    2)第一个参数是self,代表调用方法的实例。
    &selfself: &Self的缩写
    3)方法使用self,可获取所有权、不变借用、可变借用。
    4)impl块可以有多个,会自动合并
rust 复制代码
# 函数示例
struct Rect {
	width: i32,
	height: i32,
}

fn area(rect: &Rect) -> i32 {
	rect.width * rect.height
}

let r = Rect { width: 20, height: 30, };
let a = area(&r); # 调用函数
rust 复制代码
struct Rect {
	width: i32,
	height: i32,
}

# 定义方法,
# 1. 在某个struct类型中:impl Rect { }
# 2. 第一个参数为:&self
# 3. 调用方式,通过实例调用:r.area()
impl Rect {
	fn area(&self) -> i32 {
		self.width * self.height
	}
}

# 多个impl块
impl Rect {
	fn isSquare(&self) -> bool {
		self.width == self.height
	}
}

let r = Rect { width: 20, height: 30, };
let x = r.area(); # 调用方法
let y = r.isSquare();
  1. 关联函数(像类的静态方法,和实例无关)
    定义在impl块中,没有self参数,通常用于定义new函数,创建关联结构体的实例。
    1)定义在imple中
    2)没有self参数
    3)返回Self类型(关联结构体类型)
    4)使用结构体类型名调用,不用实例调用:Rect::new()
rust 复制代码
struct Rect {
	w: i32,
	h: i32,
}

impl Rect {
	fn new (a: i32, b: i32) -> Self {
		Self {
			w: a,
			h: b,
		}
	} // fn new
} // impl

let r = Rect::new(20, 30);
  1. 枚举类型
rust 复制代码
enum IpAddrKind {
	V4,
	V6,
}
rust 复制代码
// 可以替代enum + struct
// 枚举成员可以是各种类型值,不同成员可以是不同类型。
// 枚举类型成员名字,也是一个构建枚举类型实例的函数。
enum IpAddrKind {
	V4 (u8, u8, u8, u8),
	V6 (String),
}

let four = IpAddrKind::V4;

struct Ipv4Addr { 
	//...
}
struct Ipv6Addr { 
	//...
}
// enum成员是struct类型
enum IpAddr {
	V4(Ipv4Addr),
	V6(Ipv6Addr),
}

// 成员多种不同类型
enum Message {
	Quit,
	Move {x: i32, y:i32, },
	Write (String),
	ChangeColor(i32, i32, i32),
}

// 在impl块中增加方法定义
impl Message {
	fn call(&self) {
	// ...
	}
}

let m = Message::Write(String::from("hello"));
m.call();
  1. option
    Rust中没有空值(NULL)。
    Option是一个枚举类型。
    包含在preclude中,不需要显示引入作用域。
    使用Option就必须处理空值,其他不是Option类型的就一定不为空值。
rust 复制代码
enum Option<T> {
	None,
	Some(T),
}

let num = Some(5);
let empty: Option<i32> = None;
  1. match运算符
rust 复制代码
enum Week {
	Mon,
	Tue,
	Sat,
	Sun,
}

fn query(day: Week) -> i32 {
	match day {
		Week::Mon => 1,
		Week::Tue => {
			println!("...");
			2
		// }后面的,是可选的
		},
		Week::Sat => 6,
		Week::Sun => 7,
	}
}
  1. 绑定值模式
rust 复制代码
struct Ipv4Addr { 
	//...
}
struct Ipv6Addr { 
	//...
}
// enum成员是struct类型
enum IpAddr {
	V4(Ipv4Addr),
	V6(Ipv6Addr),
}

// 在match匹配过程中,把值绑定到变量
fn process(data: IpAddr) {
	match data {
	
		IpAddr::V4 (addr4) => {
			// consume addr4
		},
		IpAddr::V6 (addr6) => {
			// consume addr6
		},
	}
}
  1. 匹配 Option 和 if let
    1)if let工作方式和match相同,是match的一个语法糖
    2)if let后面是:模式 = 表达式
    3)if let匹配match的一个分支,忽略其他值,也可以通过else分支处理。
rust 复制代码
fn func(x: Option<i32>) -> Option<i32> {
	match x {
		None => None,
		Some(i) => Some(i+1),
	}
}

let num = Some(12);
let res2 = func(num);
let res3 = func(None);

// 和上面match等价
if let Some(i) = num {
	Some(i+1)
} else {
	None
}
  1. 通配模式和 ""占位符
    Rust中match匹配必须是穷尽的。
    1)为所有情况单独处理每个分支,例如enum类型。
    2)使用通配模式,用到匹配的值。
    3)使用占位符"
    ",和通配模式类似,匹配的值不用,抛弃。
    4)通配符或占位符只能在最后一个分支,否则其后面的分支不会被执行。
rust 复制代码
let result: i32 = func();
match result {
	6 => "lucky",
	8 => "money",
	other => println!("the result: {}", other),
}

match result {
	6 => "lucky",
	8 => "money",
	_ => "ok",
	// 或者完全忽略
	_ => (),
}
相关推荐
LKID体13 分钟前
Python操作neo4j库py2neo使用之py2neo 删除及事务相关操作(三)
开发语言·python·neo4j
小屁孩大帅-杨一凡14 分钟前
Python-flet实现个人视频播放器
开发语言·python·音视频
算家云17 分钟前
快速识别模型:simple_ocr,部署教程
开发语言·人工智能·python·ocr·数字识别·检测模型·英文符号识别
Thomas_Cai28 分钟前
Python后端flask框架接收zip压缩包方法
开发语言·python·flask
霍先生的虚拟宇宙网络30 分钟前
webp 网页如何录屏?
开发语言·前端·javascript
澜世32 分钟前
2024小迪安全基础入门第三课
网络·笔记·安全·网络安全
温吞-ing32 分钟前
第十章JavaScript的应用
开发语言·javascript·ecmascript
Bald Baby33 分钟前
JWT的使用
java·笔记·学习·servlet
魔道不误砍柴功38 分钟前
实际开发中的协变与逆变案例:数据处理流水线
java·开发语言
鲤籽鲲1 小时前
C# MethodTimer.Fody 使用详解
开发语言·c#·mfc