0%

Rust学习总结报告

Rust是一种注重安全、性能和并发性的系统编程语言。在过去的几周里,我深入学习了Rust语言,对其有了更深入的了解。本报告将总结我所学习的Rust知识点,包括所有权、借用、生命周期、类型系统、模式匹配、错误处理、并发编程等。

1. 所有权

Rust的核心特性之一是所有权(Ownership),它控制了程序中的资源分配和释放。所有权规则包括三条:每个值都有一个变量,称为其所有者;同一时间内只能有一个所有者;当所有者离开作用域时,值将被丢弃。所有权机制有助于避免内存泄漏和数据竞争问题。

2. 借用

借用(Borrowing)允许我们在不转移所有权的情况下访问数据。Rust通过两种借用方式来实现:可变借用(&mut T)和不可变借用(&T)。借用规则包括:同一时间内只能有一个可变借用或多个不可变借用;借用者不能超过所有者的生命周期。

3. 生命周期

生命周期(Lifetimes)是Rust确保引用有效性的关键概念。Rust通过生命周期参数(如’a、’b等)来标注引用的存活时间。生命周期的主要作用是防止悬垂引用和数据竞争。在函数和结构体定义中,我们需要为引用参数和字段指定生命周期参数,以告诉编译器引用之间的关系。

4. 类型系统

Rust的类型系统非常丰富,包括标量类型、复合类型、自定义类型等。标量类型包括整数、浮点数、布尔值和字符;复合类型包括元组、数组、切片和字符串;自定义类型包括结构体、枚举和联合。Rust还提供了类型推导、类型别名、泛型等特性,方便开发者编写灵活、可重用的代码。

5. 模式匹配

模式匹配(Pattern Matching)是Rust中一个强大的控制流和数据处理工具。通过模式匹配,我们可以检查数据类型、解构复合数据、绑定变量等。Rust支持模式匹配的语法包括匹配守卫(match guard)、模式绑定(@)和模式切片等。模式匹配让我们的代码更加简洁、易读和健壮。

6. 错误处理

Rust的错误处理机制主要包括两种:可恢复错误(Result<T, E>)和不可恢复错误(panic!宏)。可恢复错误用于处理可能失败的运算,如文件操作、网络请求等;不可恢复错误用于处理无法恢复的场景,如程序逻辑错误。Rust还提供了?运算符,简化了错误处理的代码编写。

7. 并发编程

Rust提供了丰富的并发编程支持,包括线程、通道、互斥锁等。Rust的线程安全特性得益于所有权和借用机制,使得在多线程环境中共享数据变得简单。通道(Channel)是Rust中的一种并发数据结构,用于线程之间的消息传递。Rust还提供了跨线程共享数据的同步机制,如Arc和Mutex
总之,Rust是一门具有高性能、内存安全和并发性的编程语言。通过学习Rust,我掌握了所有权、借用、生命周期、类型系统、模式匹配、错误处理和并发编程等知识点。这些知识点不仅让我对Rust有了更深入的了解,还提高了我的编程水平。在未来的工作中,我会继续学习和实践Rust,为我国软件产业的发展贡献力量。

Rust一阶段总结

零、个人照片

随便放张生活照吧,很久之前拍的了,呵呵~时间过得真快

一、本次参赛情况概述

本人也是上届训练营参营成员,不过那时候是和一个水友组的队,基本只有我一个人在努力写题。想起上次训练营我啥也不会,也没看过《Rust语言程序设计》,抱着《Rust圣经》+ChatGPT硬啃,勉强过了一阶段的100题,后面由于二阶段实在是有点复杂,迫于学业和项目组项目压力,勉强做了两个就做不下去了。

这次拉了两个工作室成员,都是有一定工程基础的,有一位成员在此之前接触过Rust,所以这次一阶段至少还算轻松,不会了线下相互请教一下,最终也是慢悠悠地过了一阶段。当然这次总结我倒不打算主要讲Rust代码上的东西,哈哈,相比较于程序设计,我倒感觉思想上的收获更多。

二、rustlings任务完成心得

这次任务,我将之前的(多)线程、外部导入函数、裸指针、所有权与借用以及模式匹配更层次地理解了一遍。想起我上次都是靠GPT撑过来的,属实确实有点搞笑了,这里我总结一下如何跟着这个Rust训练营的学习方法:

2.1看官方文档

这里的官方有多个含义。

首先是训练营官方给出的环境搭建文档,跑软件不可避免要进行环境搭建,最简单也得学会用docker,学会了搭建最基础的环境,才能整式开始学习之旅。

然后是看《Rust程序设计》这本mdbook,一阶段很多知识点,其实可以从这本书找到答案,换句话说,这本书相当于rustlings的提示手册了,仔细钻研这本书,还是可以学到很多东西的,如果直接去看《Rust圣经》 对没有基础的同学来说还是容易劝退

最后就是看Rust语言的官方文档了,有中英双语版本,可以看到每个函数的具体解释,这里我推荐使用zeal这个软件安装Rust的文档进行查看,不需要联网,支持全局查找,还是很不错的

2.2看他人博客

虽然很多文档都有,但是大部分都是英文的,可惜我们一组3个成员英语都不太好,只能硬啃文档。另一种好的方法是去找别人学习源码的笔记,一遍写得好的笔记也是能传递很多知识的,我在仔细翻阅他们的笔记之后,加深了对所有权和一些陷阱的理解

2.3多动手实验

当然,理工科的东西还是以动手为主。我们由于本身有工程基础,于是乎就开始拉几台服务器自己装下环境,在ubuntu装,在windows装,在WSL装,在classroom装,都装一遍,写好通用的执行流程和坑点,加深对Rust的理解。

不过说实话,如果操作系统训练营要成为一门面向大众的训练营,以目前的文档详细程度来说,其实在文档上面下的功夫依旧不够,代入一个新手的视角来看,配置gitHub秘钥是陌生的,github进在线classroom运行时陌生的,git是陌生的,如果仅仅只有LInux基础还是很容易劝退,这就必须要个人有一点自主学习,热爱钻研的能力才能坚持下去,很多工程新手要完成这个阶段也得两三天。就我个人刚入门工程项目的时候,我自学git就很容易犯低级错误,或者进行不规范的操作,我觉得训练营至少要给出一遍基础操作,这样就能带动更广泛的学生参与进来。只要过了环境配置,后面通过一阶段那就只是坚持下去就能完成的事情了。

三、完成rustlings过程中遇到的困难

3.1语法不熟悉

其实环顾rustlings和《Rust语言程序设计》,这两者都没有重点讲Option是什么,Result是什么,unwarp()是什么,都需要自己去找额外的文档进行理解,很多需要的函数,不如trip(),insert(),get_mut(),as_mut(),as_ref()这些奇怪的函数,但是其实这些挺基础的,如果不会这些,不知道某些函数的返回值是什么类型,OPtion有什么用,其实是很难写下去的。鉴于以往学C++的经验,我自己重新学习了一下Rust的基本数据结构,以及基本数据结构的内置方法,还有一些通用方法和获取指针的方法,这些都是比较重要的。

3.2STL不会用

这次新增了一些算法题,颇有种使用C构建数据结构写算法的感觉,不过还好是填空的模式,对于没有掌握全部数据结构的我来说,还是能勉强接受的。致辞的算法题都是基于基本的容器进行操作的,比如bfs就是基于queue,算法里面使用deque,还有后面使用vec充当邻接表,还用到了hashMap当做node进行映射,不会使用容器做这些还是稍微有些困难的,当然,稍微学学容器方法还是可以写出来的

四、本次一阶段的收获

这次一阶段,我个人和另外的成员承担的项目任务更轻松了一点,拉了两个人来一起学习,还是蛮不错的

掌握了更多的学习途径和方法,从“正确的方向”巩固了Rust的语言基础,我现在感觉Rust+cargo越来越好用了,中途踩了几个小坑,每犯一次错误都能学到东西,嘿嘿~

五、自己找的学习资源汇总

权当分享啦~

5.1Rust 程序设计语言 - Rust 程序设计语言 中文版 (rustwiki.org)

5.2std - Rust (rustwiki.org)

5.3Rust 中文文档 | Rust 文档网 (rustwiki.org)

5.4关于本书 - Rust语言圣经(Rust Course)

5.5Rust入门第一课 - Rust入门秘籍 (junmajinlong.com)

5.6介绍 - Rust精选 (rustmagazine.github.io)

5.7简介 - 通过例子学 Rust 中文版 (rustwiki.org)

呼~ 第一阶段就这样结束了呀!

自打去年从群友们那里了解到这个训练营之后就一直在关注了,
因为我对操作系统本身就很感兴趣,
加上又是使用 Rust 语言还能有一群小伙伴一起努力何尝不是一个很好的学习机会。
其实去年秋季也有报名过一次,惭愧的是因为各种原因第一阶段都没写完 uwu

对于 Rust 这么个频繁被推荐的语言,难免是有些好奇的,
常常是拿出 《Rust 权威指南》然后翻过前几章与别的语言相差不大的那些部分后打算狠狠一顿学习,
但又是惭愧的是每次品鉴 “生命周期”、“所有权”、“动态分配 Trait” 等几个词语后便急忙把书塞回它该在的地方了。
可恶!怎么这么点字就是看不懂了 ——

于是今年刚报名完春季的训练营后便暗自地赌气:我要一晚上做完第一阶段

(是的,真的第一天晚上就做完了,鉴定为太能熬夜了)

除了 Rustlings 外今年还添加了一部分数据结构和算法的内容,包括常见的队列、链表、二叉树和排序等,
而且比较有意思的是因为 Rust 对安全性要求很严苛,找出一种写法不使用 unsafe 也是一种很不错的挑战。

三分时间写七分时间对付编译器那种(雾)

后续的三周就比较空闲了,我终于找到了一个机会和理由把《Rust 权威指南》看完了,
后来还发现一本《Effective Rust》类似是《Effective Java》或是 C/C++ 版本一样,通过一些案例说明什么写法是好的什么写法不太完美。
期间留下一些小笔记:https://blog.hanbings.io/posts/effective-rust/

总的来说,还是很感谢社区以一个这样的形式提供了一个这么好的学习机会,希望后续的学习还能够坚持下去吧!
那么… 第二阶段见!

春季训练营只写了第一阶段的 blog,再来参加的时候得补了呜呜
其实经历了什么忘得差不多了(小声)

ch3:
clock 数据被覆盖,高 32 位全是 0,是在 TaskManager 中使用 get_clock 出现的错误,且仅在 Intel CPU(13500h 13900h) 中会出现,而 AMD (7860hs 6800hs)并不会。
排错的方式是从 get_clock 调用一路往上进行 log,直到我把 get_clock 调用从 TaskManager 移出来后错误消失,
到最后我也没弄明白原因,如果是写法问题就不应该出现某些处理器能跑的情况,
个人感觉问题会出在 qemu 或 sbi 上,所以也许会遇到这样的问题换个机器试一试?

ch4: 没认真看文档,问题出现在了几个标志位上 😭😭😭

ch5: 这个章节个人认为是没有 ch4 难的(是确实没有什么印象了 uwu)简单点说就是在 tcb 里放一个优先级字段,然后在切换任务的地方遍历 tcb 根据优先级选择就可以了

ch6: 使用了一个 Hash Map,在 syscall 那一层就索引这个表取链接了,到这里只要注意没有压到别的内存好像就没有什么很特别的内容了?只是 Hash Map 的实现会比较麻烦(好吧,后来我才发现 core 里也有一个 Map)

果然这类日志类的文字,还是要在解决问题的时候就马上记录下来
嗯… 真的很潦草…

前言

2022年在和同事聊天的时候了解到了Rust,在他的推荐下“投资未来”,学习了Rust这门语言。前期确实困难重重,Rust的
学习曲线确实比较陡峭,在三本Rust著作(《Rust权威指南》,《Rust实战》,《Rust程序设计》)和极客时间《陈天 · Rust编程第一课》的帮助下算是成功入门。

2023年参加了“第三界中国Rust开发者大会”,收益破丰,也是在这里第一次了解到“操作系统训练营”,今年在公众号“Rust语言中文社区”
了解到2024训练营要开办了,果断报名。

希望通过训练营的学习与实践能进一步夯实Rust语言功底,掌握操作系统知识,拓展知识面。

第一阶段总结

第一阶段主要是Rust的基础学习部分,110道题目巩固了不少基础语法知识。让我感觉最有收获的是后面的
10道算法题,之前有用Rust刷过一些LeetCode,但用Rust来实现栈,堆,队列等经典数据结构却是从没做过的,这一次有了了解。
除了实现数据结构外,这次做题也第一次编写“有意义的”unsafe代码,它终于不再那么神秘莫测了。

RISC-V

参加训练营是第一次接触RISC-V,目前正在学习《RISC-V-Reader》。RISC-V有一个很鲜明的特点是模块化,这似乎是技术发展的未来趋势,各种现代编程语言都
在使自己模块化,如Java,生活中常用的设备也在模块化,如笔记本电脑,手机,甚至我这个月刚买的小米鱼缸,RISC-V走在了ISA模块化的前沿。

下一步

目前打算在第二阶段开始前看完《RISC-V-Reader》,之后再补充一些操作系统的知识,为第二阶段的学习做好准备。

开端

从同学听到有关这个开源夏令营的事情,一方面对rust这种新兴语言颇为感兴趣,另一方面也正巧学习计算机系统知识,认识到计算机系统的精妙,也希望借此机会提高自己对计算机系统的理解,获得一定的开源经验。

链接

主要的笔记都记录在notion中,主要包含我rustlings过程中的思考和体会,记录比较精简。
https://ash-chair-1e2.notion.site/193e1434faf44e5587e71865fc9614af?v=6e2890c3bd084a77b864410b009d9706&pvs=4

第一阶段总结

这一阶段主要是熟悉rust语法以及相关知识。在我的学习中看来,rust主要有以下几个难点:

  1. 控制权转换。
    • rust中,move是默认语义,而浅拷贝(在rust中被称为引用)成为了次要语义,这使得程序需要不断地考虑生命周期
  2. 引用的简写
    • rust中让我最不能够理解的是引用的自动解引用功能,我认为一个强类型语言可以用更加明了的方式进行引用和非引用的区分。当然这只是我的浅薄观点,因为引用和非引用的自动转换实在让我伤透脑筋。
  3. 生命周期
    • 实际上rust中存在对生命周期非常精准的控制,然而受限于我的学习速度,还没有对生命周期参数和控制有更深的了解。
  4. 大量的现代特性
    • 在学习rust的过程中,我体会到了很多“旧语言”没有的特性,例如函数式编程、模板约束、宏的元编程等特性。这不禁让我想起了学习现代C++的某些特性(但是根本没有实际使用过)

第二阶段

接下来,主要就是学习riscv指令集,同时准备把更多时间花在系统课程上,配合CSAPP学习一个操作系统的基础实现。

学习Rust有一段时间了,做rustlings中途没有写blog,正好总结一下作为初学者对Rust的一些关注点和总结。

没写完,就先这样吧(逃)

todo!();

Rust基本语法

变量

Rust变量声明使用let,类型放在变量名后面。例如:

1
let x: i32 = 114514;

Rust也能自动推断类型:

1
2
let i = 114514;
let s = "string".to_string();

i被自动推断为i32s被自动推断为String

有些情况Rust也不能自动推断类型,比如:

1
let v = vec![];

报错信息如下:

1
2
3
4
5
6
7
8
9
10
error[E0282]: type annotations needed for `Vec<_>`
--> exercises/variables/variables1.rs:10:9
|
10 | let v = vec![];
| ^ ------ type must be known at this point
|
help: consider giving `v` an explicit type, where the placeholders `_` are specified
|
10 | let v: Vec<_> = vec![];
| ++++++++

这是因为Rust是一门静态类型语言在编译期必须得知变量类型的大小。

函数声明

声明方式大致如下。

1
2
3
fn func(a: i32, b: i32) -> i32 {
a + b
}

…很多内容在其他语言都有类似的概念,只是语法稍有不同,因为懒惰不再赘述

Rust的特色

作为一门年轻的语言,Rust整合了许多其他语言的优势,比如C/C++的底层系统编程能力、Ruby 的包管理器Bundler (cargo)等等。而除了严格的编译期检查、所有权和生命周期机制实现的内存安全,Rust也有许多其他大大小小的特色和亮点,比如:

组合优于继承

表达式

模式匹配

闭包

使用Option来表达可能为空的值

使用Result来处理异常

各种智能指针

使用RefCell实现内部可变性

Rust与数据结构和算法

学Rust当然要从链表写起!
==学Rust千万不要从链表写起!==

Rust如何实现链表?

按照C/C++的一贯做法,我们可能会写出:

1
2
3
4
struct node {
val: i32,
next: Box<node>,
}

然而实际用起来,会发现你用不起来

1
2
3
4
5
6
let n = node {
val: 114514,
next: Box::new(node {

})
}

问题就在于Box里必须要有东西,即它任何时候必须指向一个有效的元素!别说链表末尾节点如何实现,我们甚至无法完成头节点(任何节点)这样一个递归定义的形式。

于是我们想到使用Option来表示可能为空的值,从而能够定义单个节点。

1
2
3
4
struct node {
val: i32,
next: Option<Box<node>>,
}

面向rCore的Rust

为了完成rCore,还需要深入了解Rust的哪些?

unsafe

外部接口

Rust编译和链接

Rust项目结构

另外推荐:《Rust死灵书》

始于rust

在参加训练营之前,我学rust有大概一年的时间了。rust是一门让我惊叹的语言,同时我也学到了很多。第一次完整阅读一本英文书正是官方的the book,它极大的提高我对英语的兴趣以及阅读能力。在rust之前,我学过c、c++、java、python以及go,但是毫无疑问我现在是rustacean,因为rust的设计哲学简直太赞了,其中特别是rust对option和错误的优雅处理。
学完rust后我就经常逛rust中文网,刚好了解到开源操作系统训练营,由此开始了我的开源操作系统之旅。

第一阶段总结

前100题主要是熟悉rust语法,其实这次我是第二次参加了,因此前100题对我来说没什么压力。后十题是算法题,涉及链表、二叉树、图等。学过rust的同学知道,在rust中处理自引用的数据结构相对其它语言会难上许多,不过真正了解过Box、NonNull等之后会感觉还好。这次二刷rustlings我又深入看了下标准库的Box、NonNull等结构,收获颇丰!

avetar

第一阶段 Rustling心得

Rustlings对于rust的上手帮助很大,不过它的难度比较松弛,而额外添加的10道算法题又弥补了这一部分。尽管如此,我在完成rustlings过程中还是遇到了很多问题和疑惑,解决这些问题让我对rust的理解提高了很多

24 vecs2

1
2
3
4
5
fn vec_map(v: &Vec<i32>) -> Vec<i32> {
v.iter().map(|element| {
element*2
}).collect()
}

在这里出现了map和collect方法。map和collect的搭配是rust非常常用的元素处理方法,代表对迭代器中的每一个元素都进行传入的闭包的操作,并最后collect进一个集合中,collect可以指定集合的类型,如collect::<Vec<i32>>(),非常的好用

39 strings4

1
2
3
4
5
6
7
8
9
10
string_slice("blue");
string("red".to_string());
string(String::from("hi"));
string("rust is fun!".to_owned());
string("nice weather".into());
string(format!("Interpolation {}", "Station"));
string_slice(&String::from("abc")[0..1]);
string_slice(" hello there ".trim());
string("Happy Monday!".to_string().replace("Mon", "Tues"));
string("mY sHiFt KeY iS sTiCkY".to_lowercase());

string主题的练习中,&str和string类型的互相转换是一个重点,但是需要额外注意的不仅是各类函数的适用对象,还有其返回值所有权的不同,如to_lowercase()方法返回的是一个全新的string类型变量,而不是发生了所有权的转移。

51 errors2

1
2
3
4
5
6
7
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;
let qty = item_quantity.parse::<i32>()?;

Ok(qty * cost_per_item + processing_fee)
}

在这里解析item_quantity时,如果使用unwrap方法,解析错误会导致程序崩溃,而使用?运算符简化之后,如果发生解析错误,? 运算符会自动将 Err 值返回给调用方,从而避免了使用 unwrap 方法导致的潜在崩溃。

72 iterators2

rust的迭代器非常强大,也具有非常多的特性,这里进行整理:

  1. 创建迭代器:你可以通过调用集合的 .iter()、.iter_mut() 或 .into_iter() 方法来创建迭代器,具体取决于你需要对集合进行何种操作(只读、可变或所有权转移)。
    1
    2
    3
    4
    let numbers = vec![1, 2, 3, 4, 5];
    let iter = numbers.iter(); // 创建只读迭代器
    let iter_mut = numbers.iter_mut(); // 创建可变迭代器
    let into_iter = numbers.into_iter();// 创建所有权转移迭代器
  2. 迭代元素:使用 for 循环来遍历迭代器中的元素。在每次迭代中,迭代器会返回一个元素,并将其绑定到指定的变量上。
    1
    2
    3
    4
    let numbers = vec![1, 2, 3, 4, 5];
    for num in numbers.iter() {
    println!("Number: {}", num);
    }
  3. 使用迭代器逐个处理元素:你可以使用迭代器的方法链来对元素进行各种操作。例如,你可以使用 .map() 方法对每个元素进行映射,使用 .filter() 方法进行过滤,使用 .fold() 方法进行累积等等。
1
2
3
4
5
let numbers = vec![1, 2, 3, 4, 5];
let doubled_numbers: Vec<i32> = numbers.iter()
.map(|&num| num * 2)
.collect();
println!("{:?}", doubled_numbers); // 输出: [2, 4, 6, 8, 10]
  1. 惰性求值与及早求值:Rust 的迭代器是惰性求值的,意味着它们只在需要时才会产生元素。这使得你可以在迭代器链中组合多个操作,而不会立即执行它们。只有在需要结果时(例如调用 .collect() 方法)才会触发迭代器链的执行。
    1
    2
    3
    4
    5
    6
    let numbers = vec![1, 2, 3, 4, 5];
    let sum: i32 = numbers.iter()
    .filter(|&num| num % 2 == 0)
    .map(|&num| num * 2)
    .sum();
    println!("Sum: {}", sum); // 输出: 12

104 algorithm4

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
fn insert(&mut self, value: T) {
if self.root.is_none() {
self.root = Some(Box::new(TreeNode::new(value)));
return;
}
let mut root = self.root.as_mut().unwrap();
loop {
if value > root.value {
if root.right.is_none() {
root.right = Some(Box::new(TreeNode::new(value)));
break;
} else {
root = root.right.as_mut().unwrap();
}
} else if value < root.value {
if root.left.is_none() {
root.left = Some(Box::new(TreeNode::new(value)));
break;
} else {
root = root.left.as_mut().unwrap();
}
}
else { break; }
}
}

在算法题中涉及了好几次获取可变引用和unwrap,这里要注意的点是unwrap会导致所有权的转移,所以需要首先调用as_mut获取可变引用,再进行unwrap,防止出现所有权问题。

第二阶段:

第二阶段的总结发布在我的个人博客上:笔记-rCoreLab实验笔记

第三阶段:

第三阶段主要的时间在进行系统能力大赛的内核开发,有关比赛内核开发的日志发布在我的个人博客上:【开发日志】chaos开发日志

在完成宏内核方向的作业时,我也遇到了一些值得记录的错误。按照作业要求中修改代码之后并没有按照预期发生panic,mmap syscall的执行完全正常。为了出现预期的错误,我们将map flag修改为MAP_FIXED,经过修改,mmap syscall出现错误,返回了-1,但是仍然不会出现panic。通过阅读mmap的完整实现源码后我发现,StarryOS的处理没有任何问题,问题的根本来自于我错误认识了MAP_ANONYMOUS的意思,将其用MAP_FIXED替换,正确的做法应该是同时加上二者。

到这里,整个开源操作系统训练营彻底结束了,在这两个月时间里我对操作系统的理解从一问三不知到一知半解,再到现在有能力逐步开发内核,训练营的引导功不可没。训练营提供的绝好平台让我和许许多多高手可以一同凭借自己的爱好和热情学习操作系统,这会是我操作系统方向研究的开始,也会是我一辈子都不会忘记的经历。感谢训练营为我提供的机会,也要感谢我对操作系统的热爱。

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

前言

了解到这个训练营源自一次机缘巧合,刚学完操作系统的鄙人在b站刷课时无意刷到了前训练营的导学部分,并在评论区看到了up主留下的链接,点进去一看正好都是我很感兴趣的方向,而且学习资源和github页面都整理得很完善,于是果断加入了

Rust编程基础

初探

第一阶段的的主要任务是学习Rust语言,刚接触这门语言时候的第一感觉就是概念十分的多,有些概念甚至看起来匪夷所思,如生命周期标注,我十分不理解为什么Rust要这么设计,但是秉持着能跑就行的原则,还是硬着头皮和编译器作斗争

初窥门径

带着以上这些问题,我找到了斯坦福大学CS110L这门课,这门课并不是教学生如何进行Rust编程,而是希望通过Rust的视角反映出当今两种主流内存分配机制——手动管理(malloc&free)和垃圾回收(GC)——的不足,在其三节课就主要讨论了它们所会遇到的问题:

  • 手动管理(C/C++)

    C/C++的类型系统对内存所有权的表达能力是十分有限的,以至于工程师在设计函数接口时会显得十分臃肿,还必须附上大量的注释来告知调用者去担负起管理内存的责任,也就是说内存的管理取决于程序员的自觉性,这就导致程序员经常会忘记之前申请过释放内存,而且随着工程的不断壮大,这种错误会不可避免地发生

  • 垃圾回收(Java)

    Java通过某种类似于引用计数的方式来自动回收内存,但这种设计会带来性能上的损耗(回收机制过于复杂)

而Rust便带来了属于它的第三种方案,那就是所有权机制,在这种机制下,内存管理会变得高效且安全,这得益于它强大的静态检测机制,能够在编译时期就规避掉很多内存泄露的隐患

但这也是有代价的,既然要求在编译时期就能发现错误,那么Rust编译器就会要求程序员在编码时附带足够多的信息供它推断,也就出现了类似于生命周期标注这些语法

牛刀小试

在初步过完几轮Rust基础并完成了rustlings之后,便开始着手用Rust复刻了一些之前写过的小项目(当然,还有那令Rust新手望而生畏的链表),在这段过程中越发能感受到Rust的一些设计理念在影响着我的编码习惯,也引起了我对与内存安全的思考

总结

在经历了这一阶段的学习后,虽然我到现在也不认为我是一个Rust程序员,但是也多多少少能用Rust去进行一些有效编码了

十分感谢第一阶段中为我答疑解惑的老师和同学,同时更要感谢开源操作系统训练营提供了这么一个平台把大家聚集在了一起,我十分喜欢这里的学习氛围,大家一起交流着学习上的疑惑并提出自己的见解,这开源的理念也使我收益颇丰