经典 Rust 面试题六道
今天在电报群由 @wayslog 提出的六道面试题目,wayslog 老师称之为“经典六道”:
RwLock<T>
对想要在多线程下正确使用,T的约束是?- 如下代码:
trait A{ fn foo(&self) -> Self; }
Box<Vec<dyn A>>;
是否可以通过编译?为什么?
3. Clone
与 Copy
的区别是什么?
4. deref
的被调用过程?
5. Rust里如何实现在函数入口和出口自动打印一行日志?
6. Box<dyn (Fn() + Send +'static)>
是什么意思?
读者们又会几道呢~
一个在终端音乐播放器
十分适合在写命令的时候播放自己喜欢的音乐,有节奏才能更快地编写代码~ 仓库地址: https://github.com/Bluemi/musicus_rs
duplex -- 提供双工与半双工特质
双工 Duplex
意味着通道可以同时进行输入及输出。Read
和 Write
特质的串流通常需要 &mut self
而不能同时使用读端和写端。除了 Duplex
特质,该库还为实现了 Duplex + Read + Write
特质的类型提供 HalfDuplex
特质的实现,为实现了 Duplex + AsyncRead + AsyncWrite
特质的类型提供 FullDuplex
特质的实现。
仓库地址:https://github.com/sunfishcode/duplex
仓库地址:https://github.com/sunfishcode/duplex
评论区
写评论过程宏解法不太对吧,如果函数体内有‵return`语句就不行了。在函数入口输出比较容易,出口的话,我觉得用析构函数比较好
同求电报群地址。。:)
第五题过程宏的简单实现:
使用方法:
过程宏库:
现在公布 @wayslog 提供的答案:
我还以为第五题是类似有
Drop
之类的语言层面提供的机制。你这么一说我豁然开朗了,原来这题目是想要Rust实现一个类似Python的装饰器的函数装饰功能。确实,过程宏可以做到这一点。找到了一个现成的实现:https://github.com/gsingh93/trace。用法:
某个输出:
--
👇
pfcoder: 5 应该用过程宏实现吧?
5 应该用过程宏实现吧?
刚好刚刚在张汉东老师的书里面
5.1 通用概念
看到了值语义和引用语义这一块:不知道这样理解对不对。
可以发下电报群地址吗?
5可能旨在考察drop的顺序?实现一个new和drop的时候打印日志的guard type来实现?
业余新手,开卷强答,抛砖引玉一下:
RwLock<T>
对想要在多线程下正确使用,T的约束是?Send
和Sync
,前者是表示其可以跨线程,后者表示其用于不同线程的并发读取。是否可以通过编译?为什么?
trait object
需要trait
是object-safe
的,这要求Self
不能作为返回类型,因为它的类型在运行时才知晓。vtable
,这要求编译器就要知道这函数的返回类型。所以函数返回值需要修改,不能为Self
。Vec
内包含的内容需要是定长的,而dyn A
不能做到这点。所以应该写为Vec<Box<dyn A>>
。Clone
与Copy
的区别是什么?copy
标识的数据,在需要move
时通常是复制一份副本进去,本身依然存在。a
持有只实现了Clone
的数据,传入一个函数时数据是直接move
进去的,它会失去这个数据的所有权。Clone
这个trait
会提供一个方法clone()
来保证你想复制变量而不是move
变量时,复制整个变量来使用。deref
的被调用过程?deref
的数据类型T
,可以通过*T
调用deref
的函数。deref
的数据类型T
,在使用时,假如要求的类型是U
deref
直到类型不可deref
或类型为U
。*U
是T
时,无法匹配。Box<dyn (Fn() + Send +'static)>
是什么意思?dyn (Fn() + Send +'static)
代表的是一个trait object
,它必须是一个函数对象。Send
这个trait
以便跨线程,实现了``static`标注其生命周期是整个程序运行时。Box
封装是为了让这个对象在编译期有长度。Box
是一个在栈上的智能指针,指向函数对象,而函数对象本身被放在堆上。