20|4 Steps :如何更好地阅读Rust源码?
陈天
该思维导图由 AI 生成,仅供参考
你好,我是陈天。
到目前为止,Rust 的基础知识我们就学得差不多了。这倒不是说已经像用筛子一样,把基础知识仔细筛了一遍,毕竟我只能给你提供学习 Rust 的思路,扫清入门障碍。老话说得好,师傅领进门修行靠个人,在 Rust 世界里打怪升级,还要靠你自己去探索、去努力。
虽然不能帮你打怪,但是打怪的基本技巧可以聊一聊。所以在开始阶段实操引入大量新第三方库之前,我们非常有必要先聊一下这个很重要的技巧:如何更好地阅读源码。
其实会读源码是个终生受益的开发技能,却往往被忽略。在我读过的绝大多数的编程书籍里,很少有讲如何阅读代码的,就像世间的书籍千千万万,“如何阅读一本书”这样的题材却凤毛麟角。
当然,在解决“如何”之前,我们要先搞明白“为什么”。
为什么要阅读源码?
如果课程的每一讲你都认真看过,会发现时刻都在引用标准库的源码,让我们在阅读的时候,不光学基础知识,还能围绕它的第一手资料也就是源代码展开讨论。
如果说他人总结的知识是果实,那源代码就是结出这果实的种子。只摘果子吃,就是等他人赏饭,非常被动,也不容易分清果子的好坏;如果靠朴素的源码种子结出了自己的果实,确实前期要耐得住寂寞施肥浇水,但收割的时刻,一切尽在自己的掌控之中。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了如何更好地阅读 Rust 源码以及阅读源码的三大功用。作者以第三方库 Bytes 为例,详细讲解了如何从大纲开始、深入阅读代码。通过阅读源码,读者可以更好地理解代码的功能和使用方式,学习到技巧,积累素材,开拓思路,最终形成自己的智慧。文章提供了很好的指导和方法论,对于想要提高阅读 Rust 源码能力的读者来说,具有很高的参考价值。文章内容包括了阅读源码的四个步骤,以及如何熟悉核心 trait 的行为和掌握主要的 struct。通过深入阅读源码,读者可以学习到高手定义 trait 的思路,了解数据结构的内部结构和设计,以及如何实现需要的标准 trait。这篇文章对于 Rust 开发者来说,是一份非常有用的指南,可以帮助他们更好地理解和应用 Rust 源码。文章还提供了一些思考题,帮助读者更深入地理解所学内容。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
《陈天 · Rust 编程第一课》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(18)
- 最新
- 精选
- Geek_1b6d74陈天大神太强了,学习他的课程不仅学习了一门新的语言,还弄明白了很多编程底层原理
作者回复: 过奖了!:)
2021-10-1315 - 核桃老师,专门开一期如何读开源项目源码吧,真的,这个比懂任何技巧都更有意义,目前也没有教这个的。
作者回复: :) 掌握好这一章就好了啊
2021-11-206 - 枸杞红茶我原本准备去超市摸鱼,陈天老师给我渔船把我扔到了大海里
作者回复: 哈哈,放下你泡好枸杞红茶的保温杯,一起死磕 Rust :)
2021-10-315 - Marvichov1. 我们一起大致分析了 Bytes 的 clone() 的使用的场景,你能用类似的方式研究一下 drop() 是怎么工作的么? 如果是Shared, 就像Arc那样decrease counter; 如果是KIND_VEC, with unique ownership, deallocate memory immediately. unsafe fn promotable_odd_drop(data: &mut AtomicPtr<()>, ptr: *const u8, len: usize) { data.with_mut(|shared| { let shared = *shared; let kind = shared as usize & KIND_MASK; if kind == KIND_ARC { release_shared(shared as *mut Shared); } else { debug_assert_eq!(kind, KIND_VEC); drop(rebuild_boxed_slice(shared as *mut u8, ptr, len)); } }); } 2. 仔细看 Buf trait 里的方法,想想为什么它为 &mut T 实现了 Buf trait,但没有为 &T 实现 Buf trait 呢?如果你认为你找到了答案,再想想为什么它可以为 &[u8] 实现 Buf trait 呢? 因为advance method需要更改T内部状态 fn advance(&mut self, cnt: usize) { 3. 花点时间看看 BufMut trait 的文档。Vec 可以使用 BufMut 么?如果可以,试着写写代码在 Vec 上调用 BufMut 的各种接口,感受一下。 只能在`Vec<u8>` 上用; 跟着doc试了一下. 值得注意的是, `advance_mut`是 `unsafe`: #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { let len = self.len(); let remaining = self.capacity() - len; assert!( cnt <= remaining, "cannot advance past `remaining_mut`: {:?} <= {:?}", cnt, remaining ); self.set_len(len + cnt); } 4. 如果有余力,可以研究一下 BytesMut。重点看一下 split_off() 方法是如何实现的。 `split_off` 也是根据kind来: - 如果是KIND_VEC, 就变成两个Arc, 共享同一个buf pointer - 如果是KIND_ARC, 就increase ref count, 设置不同的start, end 感觉真正困难的是 `reserve` 和 `resize`; 这两个method要求KIND_ARC; 这样, 所有outgoing的`BytesMut` 能view underlying Vec pointer change during reallocation
作者回复: 👍
2021-11-082 - Geek2014而 data 这个 AtomicPtr 指针,在指向 Shared 结构时,这个结构的对齐是 2/4/8 字节(16/32/64 位 CPU 下),末尾一定不为 0: 老师,为啥对齐2/4/8字节,末尾一定不为0呢
作者回复: 啊,多谢发现!这里是笔误,应该是一定为 0。为 0 才可以借用最后一位设置是否是 shared 标志。这是上下文的逻辑。我让编辑更新一下。
2021-10-082 - Geek_b52974看後面的解釋還是有點懵,我試著照自己的理解說明 最後一位是用來記錄是否是 shared 但是我們會需要知道升級成 shared 前最後一位是 odd 還是 event 所以用 PROMOTABLE_ODD_VTABLE PROMOTABLE_EVENT_VTABLE 來做不同的 clone 方式 ``` unsafe fn promotable_even_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes { let shared = data.load(Ordering::Acquire); let kind = shared as usize & KIND_MASK; if kind == KIND_ARC { shallow_clone_arc(shared as _, ptr, len) } else { debug_assert_eq!(kind, KIND_VEC); let buf = (shared as usize & !KIND_MASK) as *mut u8; shallow_clone_vec(data, shared, buf, ptr, len) } } ``` promotable_event_clone 相比 promotable_odd_clone 多了下面這個操作 let buf = (shared as usize & !KIND_MASK) as *mut u8; 先把最後一位還原成原本的樣子,再進行 clone 不知道這樣理解對不對
作者回复: 对
2021-11-051 - 25ma值得反复深度阅读,很有收获
编辑回复: 👍
2022-07-08 - 施泰博看完我觉得值得,得反复看很多编了。
作者回复: 👍
2021-12-18 - overheatBytes可以支持反序吗?我想要从结尾往开头操作。。。
作者回复: 不支持,你需要先做 reverse 的操作
2021-12-103 - 小康老师,目前中国rust岗位很多都是区块链相关的技术岗位呀???java转Rust跨度会不会太大???
作者回复: 1. 目前是,以后基础软件会有越来越多的 Rust 职位 2. 不会
2021-11-13
收起评论