0%

2024春开源操作系统训练营第一阶段总结报告-Wislist

基本数据类型-原生类型

image-20240410195209385

  • 元组(tuple)

​ 允许各个元素类型不相同

1
2
3
fn main(){
let tup: (i32,f64,u8) = (500,6.4,1);
}
  • 字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// quiz2.rs
//
// This is a quiz for the following sections:
// - Strings
// - Vecs
// - Move semantics
// - Modules
// - Enums
//
// Let's build a little machine in the form of a function. As input, we're going
// to give a list of strings and commands. These commands determine what action
// is going to be applied to the string. It can either be:
// - Uppercase the string
// - Trim the string
// - Append "bar" to the string a specified amount of times
// The exact form of this will be:
// - The input is going to be a Vector of a 2-length tuple,
// the first element is the string, the second one is the command.
// - The output element is going to be a Vector of strings.
//
// No hints this time!

// I AM NOT DONE

pub enum Command {
Uppercase,
Trim,
Append(usize),
}

mod my_module {
use super::Command;

// TODO: Complete the function signature!
pub fn transformer(input: Vec<(String,Command)>) -> Vec<String> {
// TODO: Complete the output declaration!
let mut output: Vec<String> = vec![];
for (string, command) in input.iter() {
// TODO: Complete the function body. You can do it!
match command{
Command::Uppercase => output.push(string.to_uppercase()),
Command::Trim => output.push(string.trim().to_string()),
Command::Append(n) => {
let mut append_stirng = string.clone();
for _ in 0..*n {
append_stirng += "bar";
}
output.push(append_stirng);
}
}

}
output
}
}

#[cfg(test)]
mod tests {
// TODO: What do we need to import to have `transformer` in scope?
use super::my_module::transformer;
use super::Command;

#[test]
fn it_works() {
let output = transformer(vec![
("hello".into(), Command::Uppercase),
(" all roads lead to rome! ".into(), Command::Trim),
("foo".into(), Command::Append(1)),
("bar".into(), Command::Append(5)),
]);
assert_eq!(output[0], "HELLO");
assert_eq!(output[1], "all roads lead to rome!");
assert_eq!(output[2], "foobar");
assert_eq!(output[3], "barbarbarbarbarbar");
}
}
  • String

image-20240414142656028

  • "rust is fun!".to_owned() 是一个字符串字面量(string literal),.to_owned() 是一个字符串切片(&str)的方法,用于将字符串切片转换为一个拥有所有权的 String 类型的对象。这个方法的作用是创建一个新的 String 对象,其中包含了字符串切片的内容,同时拥有了自己的内存空间,与原始的字符串切片无关。

  • "nice weather".into() 是 Rust 中的一个特殊的语法,它实际上是调用了 From trait 中的实现,将一个类型转换为另一个类型。在这种情况下,"nice weather".into() 将一个字符串字面量(&str 类型)转换为 String 类型。这种转换是通过实现了 From<&str> for String 的 trait 来完成的,它会将给定的字符串切片(&str)复制到一个新的 String 对象中,并返回这个新对象。这种转换通常被称为”类型推导”,因为编译器会根据上下文自动推导出需要转换的目标类型。

  • Option

    和match配合

    image-20240417114555485

  • 通配符

image-20240417114753525

  • if let 简介控制流

相当于二元控制流

  • 泛型

image-20240417120202658

  • Trait(interface)

image-20240417120533444

(1) trait作为参数

image-20240417230445201

小计:

.fold()

1
2
3
4
5
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum = numbers.iter().fold(0, |acc, &x| acc + x);
println!("The sum is: {}", sum); // 输出:The sum is: 15
}

.fold()迭代器方法

1
2
3
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,

这里的参数含义是:

  • init 是初始值,它是要合并的类型的默认值或起始状态。
  • f 是一个闭包函数,它接受两个参数:累积值(accumulator)和当前迭代的元素,并返回一个新的累积值。

.fold() 方法会迭代迭代器的每个元素,并在每次迭代中调用闭包函数 f,将当前累积值和当前元素作为参数传递给闭包函数,然后将闭包函数的返回值作为新的累积值。最终,.fold() 方法返回的值是所有元素被合并后得到的单个值。

智能指针

通常用结构体来实现,不同之处在于实现了DerefDrop traitDereftrait 允许智能指针结构体示例表现的像引用一样,Drop trait允许我们自定义当智能指针离开作用域时运行的代码

  • Box

box允许将值直接放到到堆上

递归类型

cons list

每一项都包含两个元素:当前的值和下一项。其最后一项

  • 计算非递归类型的大小

image-20240421090726614

Rust知道为Message分配多少空间时,他会检查每一个成员,并发现quit并不需要任何空间,Move需要两个i32空间,依此类推

Deref

实现Deref允许我们重载解引用运算符* 我们无法直接使用指针所指向的数据,需要通过解引用运算符

Drop

制定在值离开作用域时应该执行Droptrait。一般是自动进行。

当我们想手动执行,就可以使用公用的drop

image-20240421092345178

Rc< T >智能指针

引用计数

  • Rc< T >来共享数据

image-20240421092803615

  • 可以用来计数

image-20240421092829590

会打印出引用计数,可以调用strong_count函数获得

但是,虽然可以共享数据,其还是没有违反借用和所有权的定义,只是使别的变量具有a变量的可读性

RefCell < T >和内部可变性

  • RefCell 大量使用unsafe代码来模糊rust规则,要手动检查是否符合规则

结合Rc < T >和 RefCell < T > 来拥有多个可变数据所有者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#[derive(Debug)]
enum List {
Cons(Rc<RefCell<i32>>, Rc<List>),
Nil,
}

use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
let value = Rc::new(RefCell::new(5));

let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));

let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));

*value.borrow_mut() += 10;

println!("a after = {:?}", a);
println!("b after = {:?}", b);
println!("c after = {:?}", c);
}

可以拥有一个表面上不可变的List,不过可以使用RefCell< T>中提供内部可变性的方法来再需要时修改

多线程

spawn创建多线程

image-20240421094452825

线程间传送数据

提供了信道(channel)来实现。信道分为发送者和接收者

image-20240421103518959

可以允许多个发送者 但是只能有一个接收者
类比java

信道与所有权转移

send函数会获取其参数的所有权并移动这个值归接收者所有。

image-20240421104012845

不想所有权转移:

互斥器Mutex< T >

image-20240421104351246

同步和异步async和多线程

异步返回的都是future

.await异步机制的实现 更像

Macro)指的是 Rust 中一系列的功能:使用 macro_rules!声明Declarative)宏,和三种 过程Procedural)宏:

  • 自定义 #[derive] 宏在结构体和枚举上指定通过 derive 属性添加的代码
  • 类属性(Attribute-like)宏定义可用于任意项的自定义属性
  • 类函数宏看起来像函数不过作用于作为参数传递的 token

为什么已经有了函数还需要宏呢?

宏是一种代码生成器,允许在编译时对代码进行操作和生成,可以在更大的范围内改变代码结构和行为。在某些情况下,使用宏可以提高代码的灵活性和效率,但同时也会增加代码的复杂性和难以理解性。

总结

怀着java的心来学rust,在很多情况下,rust所有权问题总是是一个大坑,rust是对底层深入的语言,相比于java非常多的工具链,rust给我最大的感觉就是如同汽车修理工那样,一个零件一个零件的卸下和装配。说实话,时间太短了,很多概念是第一次接受,并没有特别深入的了解,之后会尽力去做的。