You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
14 KiB
Markdown

2 years ago
# 特别策划|学习锦囊(二):听听课代表们怎么说
你好我是Rust课程的编辑叶芊。今天是特邀课代表分享个人学习经验的第二辑。
一直有新同学困惑到底怎么学才能更丝滑地上手为什么我看了前6讲越看越懵到底需要什么知识背景才能学Rust才能学这个专栏希望能提供专栏的食用手册或者做相关背景知识整理之类的需求……
为了帮助你在新的一年更好地学习我特地邀请了几位课代表来分享一下他们学习专栏、学习Rust语言的个人经验和方法希望能给你一些参考和启发。学习愉快。
* * *
## @Marvichov
你好我是Marvichov是一名工龄5年的软件工程师。目前的工作领域是分布式机器学习主力语言是Python。之前也有Cpp的工作经验搞过两年半搜索引擎也做过一年半[开源项目](https://github.com/apple/turicreate/pull/2210)。平时也使用Java和Go进行个人项目开发和学习。
和大多数人一样立了flag要好好学完这门课程结果止步于aysnc。
学习一门语言先要明白为什么要学。世界上的语言千千万万学习英语不也挺香对我来说学Rust的理由很简单Rust的安全模型很有意思确实能解决很多C/CPP的痛点。对于底层开发来说安全越来越重要有着比性能更高的优先级。
分享个同事的例子自从项目从C转到Rust之后他晚上能安心睡觉了。不会因为突如其来的Segfault半夜被叫醒。某些多线程bugdebug一个月是常态。现在他可以安心merge新人的PR了因为有compiler去阻断有安全隐患的代码。
**不出意外的话未来Rust会制霸底层。如果要搞底层开发的话还是绕不开这座大山**。
最开始学的时候,我先去读了官方[the book](https://doc.rust-lang.org/book/)算是对Rust有了一些初步、直观认识。然而The book写得比较浅各种知识点都是点到为止。尤其是最重要的lifetime和borrow checkthe book没有讲得很深入我看完还是不知道compiler是怎么计算lifetime的。更深入学习的话还是要求助于[死灵书](https://doc.rust-lang.org/nomicon/lifetimes.html)和官方[reference](https://doc.rust-lang.org/stable/reference)。
后来遇到了Non-Lexical Lifetime ([NLL](http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction))深入到了compiler的实现细节我愈加发现自己力不从心钻语法的牛角尖。花了大量的时间钻研语言本身而非积累实战项目经验。
这和我之前学习CPP的经历很相似纠结各种语法特性浪费了很多时间在死记硬背实战用不到的语法上。到头来CPP还是靠不断在工作中做项目熟练掌握的。况且大部分语法实战中根本不会用。花了大量时间纸上谈兵。到头来不是在学习而是在感动自己。
因此,**学习一门语言,我还是倾向于快速上手,直接撸项目。很多大神学习新语言的方法就是用新语言把自己熟悉的项目重新写一遍**。
我记得耗子叔就在《听风》专栏讲过,他学语言就是看这个几个主要方面:内存管理、错误处理、类型系统等等,然后花一两天写个小项目就把一门语言掌握了。各个语言都是大同小异的,学习多了之后就能很快触类旁通。然而,我并没有什么端到端的项目经历,这种方法对我来说还是挺有难度的。
不过对于大多数人包括我来说熟悉语言还有一种快速上手的方法就是刷题把那些之前写过的算法用Rust写一遍。
Leetcode对Rust的支持很一般发生错误之后也没有stack trace。**我个人就选择用**[exercism](https://exercism.org/tracks/rust/exercises)**,所有代码和测试都可以在本地跑,方便调试**。我周围很多Rust工程师就是通过刷题快速上手Rust然后被委任去重写一些Java项目。这个方法你也可以参考。
正好陈天老师的Rust专栏提供了很多动手的实战小项目弥补了市面上各种Rust书籍的缺点也避免了最后停留在学习语言本身的误区上。毕竟语言是用来解决实际问题的。我们学习Rust也不是为了掉书袋而是为了让程序创造价值。
其实我当时很犹豫要不要买课因为语法知识点在官方的the book和死灵书上都讲得很详细了。但是一看到第六讲的实战项目就毫不犹豫下单了我自己对compiler就很感兴趣能手撸一个SQL解析器还是用Rust一石二鸟岂不美哉。
### 我是怎么学专栏的
在这里也分享一下我自己是怎么学习这门课的,希望能给你参考。
* 1-3讲 内存前置知识
如果想搞清楚内存是如何被管理的或者想深入理解程序的address space推荐上一上《Computer Systems: A Programmers Perspective》([CSAPP](https://csapp.cs.cmu.edu/))。这门课的教授Dave说“如果你的一生只上一门计算机系统基础CSAPP就够了”。我后来补了一部分这个课的的确确帮助我理解了许多系统底层原理。
简单来说在机器码或者汇编层面没有ownership一说也没有lifetime有的只是数据和一连串的指令。CPU只知道执行指令、数据传输、读写各种寄存器以及内存例如程序员视角的stack和heap。
Owership和lifetime只是high level语言层面的抽象属于Rust语言的一部分并不是计算机最后执行的机器码的一部分。就像算法里面的loop invariant一样通过在高级语言语法层面的规则限制保证最后编译出的代码不会在runtime出现导致内存安全的错误。
* 4-6讲 get hands dirty
我第一遍学的时候就快速过了一遍不求完全理解语法细节。大概知道用Rust写项目很灵活、Rust支持很多domain就行了。这几节课的信息量有点大很容易劝退新手暂时搞不懂的就放在那里等以后学到了再回来过一遍。
* 7-14讲 Ownership & Containers
基础中的基础。首先了解ownership和lifetime这是Rust相比于C要解决的核心问题内存安全。这些课程的例子我都是自己亲手一行一行打的。先把例子过一遍然后自己写一遍。毕竟根据[学习金字塔](https://en.wikipedia.org/wiki/Learning_pyramid)原理动手实践的学习效果比单纯只是阅读要强50%。之后弄明白smart pointer和各种基础数据结构才能更快上手项目或者刷题。
* 18讲 错误处理
重点中的重点也是Rust吸收其他语言优点的例子。built-in的语法支持让Rust区别于其他主流语言例如C/CPP、Java。错误处理的方式也可以窥见Rust的安全设计思想。
* 12-14、23-25 Traits
Rust的核心之一就是Traits是Rust语言抽象的地基。熟悉面向接口编程的抽象风格才能跟上课程里的各种项目。很多Traits必须熟练掌握比如AsRef、From、Deref、Drop、Send/Sync等等。这些Traits就像构建Rust世界的基础元素。如果不熟悉就很难读文档、设计接口。
* 21-22、26、36-37、41-42 KV server实操系列
这个系列第一遍学可以暂时放一下等Rust知识点集齐了再拉通一起学习更好。课程的安排是穿插学习KV server中途不断补充新的知识点然后不断用新的语法糖迭代这个项目。但是这个项目的代码量其实并不小中途很容易忘记项目里面各种细节和上下文。我自己学的时候觉得拉通学习这个项目趁热打铁效果更好。
* 其他讲
剩下的基本上都是项目实战主要是熟悉各种IO和接口、系统设计。除了跟着老师的思路一步一步敲代码我想不出更好的办法。老师的项目实战经验很丰富很多设计我都需要推敲很久才能理解。越学到后面跟上老师就越费劲因为不仅要学习老师的设计思想同时还要学习Rust的各种知识点。只能说一门课当两门课上非常实惠。
### 我的学习方法
第一个方法是**画思维导图,一图胜千言**。用自己的语言描述学过的知识点才能内化。老师在这方面真的是很好的榜样,每节课开头就是一张知识地图。
第二个方法就是**构建自己的知识体系**,核心思想是[holisitic learning](https://www.scotthyoung.com/blog/Programs/HolisticLearningEBook.pdf)。你学的每个知识点都是一座岛屿,将它们能相互连接,你才能触类旁通,学过的知识就很难被忘记。
打个比方,如果各个知识点没有连接,就变成了孤岛,容易被人遗忘。当知识连接多了,孤岛就变成了城市。当你在城市迷路,很容易通过到新的导航达到目的地。但如果你在荒郊野岭迷路了,就需要付出相当大的代价才能达到目的地。很多时候,这样的代价是重头开始学。
我学习Rust的时候就喜欢和C、CPP、Golang对比把相似的知识点串联起来。
举个例子CPP里面的template、RAII就和Rust里面的generics、Drop相对应Golang里面的interface就和Rust的trait相似都是interface oriented programming 面向接口编程。Rust唯一和其他语言不同的就是安全模型。因此我们在学习的时候可以重点掌握owership、lifetime和thread safety。
第三点就是**勤动手**。私以为写代码99%都是熟练工没有捷径也不需要天赋有高中的数理逻辑就可以。行业内只有1%的人能做mathematical programming也就是创造、研究、优化和编写核心算法。成为这1%的人,才需要谈天赋。
Rust之所以难不是因为编码者天赋不够而是因为它要求编码者有良好的底层基础、和对内存模型有很好的认识。学Rust遇到瓶颈学不下去了不妨退一步补一补基础。这里再推一下CSAPP。
第四点前面提过了,**除了跟着老师撸项目,还可以刷题**。我在对刷题答案的时候注意到很多同学喜欢通过函数式编程把复杂的逻辑揉成一行。这就像当年那些Python一行流炫耀自己能一行刷一道题。Python这么写可以因为没人会苛求Python代码有很好的性能。Rust这么写就不太合适了。
Rust语言虽然其可表达性很强同时也鼓励大家使用函数式但是它还是一门底层语言。**底层语言最重要的特性就是可读性、可优化性**。当你把很复杂的程序压缩成一行或者一个statement时候你很难看出哪里需要优化。周围一些Rust工程师也告诉我实战中没人会那么写代码。大部分时候他们采用的是最简单直接的API、一目了然的Generics、以及面向接口编程的设计理念。
最后一点就是**复盘**。
往小了说,就是及时复习。老调重弹一下中学学过的[艾宾浩斯遗忘曲线](https://en.wikipedia.org/wiki/Forgetting_curve)。根据这个粗糙模型一天不复习就会忘70%。隔一周忘77%。现在社会人比较忙,一周内抽空复习一下就好。不然学了、忘了,最后缓解了焦虑、感动了自己。
这里推荐一下大神Jon Gjengset分享的方法上课的时候他不会去记笔记而是会全神贯注听力求课上搞懂课下的时候他会使用[康奈尔笔记](https://zh.wikipedia.org/wiki/%E5%BA%B7%E5%A5%88%E5%B0%94%E7%AC%94%E8%AE%B0%E6%B3%95)法Cornell Notes system做笔记。这种笔记法专门为复习、抗遗忘而设计的。亲测有效。很多笔记软件都内置康奈尔笔记法模板。
往大了说就是建立知识体系和方法论。课后总结学到的知识点通过前面提到的holistic learning的思路将刚学的与之前学过的知识建立联系顺便也复习之前的知识。
除了复盘知识点也可以复盘自己的学习方法是否有效学习计划安排得是否合理。复盘是一个非常自律的过程我也在不断摸索。希望2022年和大家一起进步不断成长。
### 学习资料
* [Computer Systems: A Programmers Perspective](https://csapp.cs.cmu.edu/)[B站视频](https://www.bilibili.com/video/BV1XW411A7fB?share_source=copy_web)[课件链接](https://www.cs.cmu.edu/~213/schedule.html)。可以通过这门课补各种底层知识,比如内存是怎么被程序管理的、如果写简单的汇编代码。
* [lifetime misconceptions](https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md)常见lifetime误区与答疑。
* [rustnomincon](https://doc.rust-lang.org/nomicon/lifetimes.html) Rust死灵书高级版的the book。
* [Jon Gjengset, Crust of rust](https://youtu.be/rMGWeSjctlY)作者是MIT神课[分布式系统6.824](https://pdos.csail.mit.edu/6.824)的助教。他最近出的书《[rust for rustaceans](https://nostarch.com/rust-rustaceans)》也可关注。
* [baby steps](http://smallcultfollowing.com/babysteps/blog/2016/04/27/non-lexical-lifetimes-introduction/)Niko MatsakisRust compiler开发者的博客不定期会分享compiler内部实现细节。
* [explaine.rs](https://jrvidal.github.io/explaine.rs/)Rust知识点可视化。当你遇到问题但不知道问问题的方向时可以考虑直接把代码放进去。
* [too many linked list](https://rust-unofficial.github.io/too-many-lists/first-layout.html)挑战不违背safety rules的前提下实现链表。
* [https://fasterthanli.me/series](https://fasterthanli.me/series)老一辈Rust布道者blog质量很高。
* [rust quiz](https://dtolnay.github.io/rust-quiz/30)非常晦涩的语法题作者是Rust大神 [David Tolnay](https://github.com/dtolnay)anyhow和thiserror的作者及贡献者。
* [rust book list](https://lborb.github.io/book/title-page.html)追踪了网上各种Rust书籍和学习资料。
* [writing os in rust](https://os.phil-opp.com/)采用Rust的OS底层学习教程。
* [pingCAP talent plan](https://github.com/pingcap/talent-plan)Rust网络编程Golang的系列教程也相当精彩。
* [rust forum](https://users.rust-lang.org/)钻牛角尖或者迷失学习方向的时候上forum贴个帖子会有很多热心大神免费答疑。[Reddit](https://www.reddit.com/r/rust)也不错,经常也有高质量发言。
* * *
这是今天课代表Marvichov同学的分享如果你有自己的Rust学习故事欢迎在下方留言区留言互相交流互相映证共同学习共同进步。
第三辑见~