Open malongshuai opened 3 years ago
教练,我想学rust
教练,我想学rust
支持
感谢博主的奉献,这书的质量真心高
期待下一次更新,建议博主可以在其他平台多多推广,
写得非常好,干货,没废话。期待更新,能完成全部章节内容。
博主的书写得很好,内容讲的很深入,特别是那些解释“为什么这么做”的内容特别透彻是很多书籍里面没有提到的也没有说明白的,希望博主继续完成全部内容
@quhxuxm 博主的书写得很好,内容讲的很深入,特别是那些解释“为什么这么做”的内容特别透彻是很多书籍里面没有提到的也没有说明白的,希望博主继续完成全部内容
感谢支持。因为忙着自己的事,博客已经停更好几个月了。近期写了一些Rust异步和Tokio相关的成系列的文章,等完成了会发布上来。
真不错
非常不错的文章,谢谢。 结合rust官方的教程,非常有帮助。 确实句句是精华。
很期待 “异步IO/fs/Stream/Frame” 这一节,特别是Frame这部分,如何正确使用Encoder/Decoder是我目前遇到的问题,比如Encoder里面如何处理网络io里面数据读完的情况
不错的教程,受益匪浅,感谢作者。网站好像挂了,希望能修复一下
有关move,你讲的最清楚。
@hdilw16 有关move,你讲的最清楚。
个人以为,所有权问题本身是没有难度的,里面涉及到的只是一种种需要掌握的概念。我在学习所有权相关问题时,似乎没有遇到过理解不通透或者需要抓耳挠腮去理清楚的地方,学习的时候多数内容的逻辑都比较顺畅(当然,也有理解错误时候)。可能和个人学习经历有关,也可能是网上对它的宣传和解说加重了学习过程中的心理压力。
@quhxuxm 很期待 “异步IO/fs/Stream/Frame” 这一节,特别是Frame这部分,如何正确使用Encoder/Decoder是我目前遇到的问题,比如Encoder里面如何处理网络io里面数据读完的情况
抱歉。这部分的内容之前已经写的差不多了,但是需要找空闲时间去整理以及还需要少量内容的补充。我这几个月重度用了一段时间的tokio,有些用法且关键的地方在官方手册上并没有提及过,也需要去整理补充完善。但过去很长一段时间以及未来几个月可能还会处于忙碌期。
写的真的非常细致,感谢
无意间发现博主写的《Rust入门秘籍》,太棒了~先打赏再看,哈哈哈
无意间发现博主写的《Rust入门秘籍》,太棒了~先打赏再看,哈哈哈
感谢,感谢支持哦
无意中发现了《Rust入门秘籍》,发现还是 junmajinlong 这个博主(之前看过ssl 等系列文章),顿时感觉质量有保障了。 暂时看了几个部分(match、类型),发现博主解决了我许多疑惑(比如,match 返回值),而许多其它的文章都语焉不详的。 感谢博主。已经打赏,聊表心意。
@knull-cn 感谢支持
看到第6.2章,其中 “对于那些没有实现Clone Trait的自定义类型,需要手动实现Clone Trait。在自定义类型之前加上#[derive(Copy, Clone)]即可。” ,这里为什么不直接#[derive(Clone)]呢?根据我从其他地方学习到的:Copy是继承于Clone,所以实现Copy必须同时实现Clone。Clone似乎没有这样的限制,可以直接实现。
@Mota-Link 谢谢指正噢,刚才去看了下,确实多写了Copy进去。
6.4章可变引用那里应该是读写锁
建议添加下面几项:
可能是讲tokio最清晰的一本中文书吧 条理清晰,读来醍醐灌顶
@gelove 6.4章可变引用那里应该是读写锁
6.4章的功能应该是 None Lexical Lifetimes (NLL) ,详见RFC: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md
@Mota-Link
@gelove 6.4章可变引用那里应该是读写锁
6.4章的功能应该是 None Lexical Lifetimes (NLL) ,详见RFC: https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md
他们也说了可以用锁来理解,我想这个锁应该是读写锁
对于Trait A,写法dyn A表示Trait A的Trait Object类型,由于Trait Object的大小不固定,因此几乎总是使用Trait Object的引用方式&dyn A,Trait Object保存在栈中,包含两份数据:Trait Object所指向数据的指针和指向一个虚表vtable的指针。
这个说法感觉不太对, 存在栈上的是&dyn A, 是trait object的引用。trait object是DST不能存在栈上的。
对于Trait A,写法dyn A表示Trait A的Trait Object类型,由于Trait Object的大小不固定,因此几乎总是使用Trait Object的引用方式&dyn A,Trait Object保存在栈中,包含两份数据:Trait Object所指向数据的指针和指向一个虚表vtable的指针。
这个说法感觉不太对, 存在栈上的是&dyn A, 是trait object的引用。trait object是DST不能存在栈上的。
非常正确,感谢指正。
《再次理解Move》写的太好了,正是有这个疑问搜到的,感谢
https://rust-book.junmajinlong.com/ch100/06_task_state_sync.html 第二行代码好像是错了的 ,不应该是
let rwlock = Arc::new(Mutex::RwLock());
可能是
let rwlock = Arc::new(RwLock::new(1));
https://rust-book.junmajinlong.com/ch100/06_task_state_sync.html 第二行代码好像是错了的 ,不应该是
let rwlock = Arc::new(Mutex::RwLock());
可能是
let rwlock = Arc::new(RwLock::new(1));
谢谢,确实写错了
https://rust-book.junmajinlong.com/ch100/09_async_stream_sink_codec_framed.html
这里的sink 是个什么呀 ?有点摸不着头脑了。是怎么创建出来的呀?依赖于哪个包?能补上嘛 ?
https://rust-book.junmajinlong.com/ch100/09_async_stream_sink_codec_framed.html
这里的sink 是个什么呀 ?有点摸不着头脑了。是怎么创建出来的呀?依赖于哪个包?能补上嘛 ?
Stream和Sink一个是读,一个是写。类比一下,IO读read()、写write()都是直接读写字节的,但很多时候其实按字符串读写更直接简便:将读取的字节自动转换为字符串,或者将字符串自动转换为字节写入。这样可以省的手动去做重复的Bytes <-> String
之间的转换。在这里,可以认为字符串是比Bytes让读写变得更简单的类型,也是对程序来说更有意义的数据类型,毕竟在程序里想要操作的是字符串。
类比于IO的读写,Stream的读和Sink的写,是对更有意义的数据的更简单的读写方式。当然也可以将想要读写的数据在YourDataType <-> Bytes
之间进行手动的转换后再读写,但是复杂啰嗦且不必要。比如,使用Sink,可以直接将一个Struct类型的数据(当然要满足某些条件)写入TCP连接发送出去,不用转换为字节再发送,同理,通过Stream可以直接从TCP连接中读取字节数据并自动转换为想要的Struct类型。
其中,最常用的符合Stream读和Sink写的类型是Codec的Framed。Framed即实现了Sink,也实现了Stream。
至于你最后问的怎么创建出来、依赖于哪个包。
use futures_util::stream::{SplitSink, SplitStream};
use futures_util::{SinkExt, StreamExt};
use tokio::net::TcpStream;
use tokio_util::codec::{Framed, LinesCodec};
let conn = TcpStream::connect("127.0.0.1:12345").await.unwrap();
// Framed既是Stream,也是Sink
// Stream用于读(Framed负责将底层字节转换为Frame,然后被Stream读取),
// Sink用于写(Framed负责将用户层的Frame转换为底层字节,然后写入Sink),
// StreamExt和SinkExt提供了相关的方便的方法
let framed = Framed::new(conn, LinesCodec::new());
let (mut sink, mut stream) = framed.split::<String>();
在你发的链接那篇文章的最开头有解释,Stream和Sink同时存在于futures、futures_util、futures_core这三个库里,这三个库这几个类型完全相同,追踪其本源,都来自于futures_core。当然,如果只用Stream,那么还可以使用tokio_stream。
https://rust-book.junmajinlong.com/ch6/03_ref_ownership_borrow.html
使用引用借用变量所有权时,【借完】之后会自动交还所有权,从而使得原变量不丢失所有权。至于什么时候【借完】,尚无法在此深究。
现在Rust有了NLL后,是否可以将【借完】的时机理解为引用作用域结束的时候?
https://rust-book.junmajinlong.com/ch6/05_re_understand_move.html
let user2 = &(*user); // 不报错,解引用得到值后,对这个值创建引用,不会消耗值
这段代码实际上会报错,因为结构体User没有实现Deref
Trrait,换一个例子是否更好?虽然知道这章想表达的点并不在这上,但可能会有人像我一样把这段代码复制粘贴到编辑器里看,结果发现只报了这一个错,把这行注释掉其他行才有报错,这可能会有点误导人(虽然最大的锅应该还是在rust编译器上)。
10.3章对枚举的解构应该是这样写的(漏加成员名了):
enum IPAddr {
IPAddr4(u8,u8,u8,u8),
IPAddr6(String),
}
fn main(){
let ipv4 = IPAddr::IPAddr4(127,0,0,1);
match ipv4 {
// 丢弃解构后的第四个值
IPAddr::IPAddr4(a,b,c,_) => println!("{},{},{}", a,b,c),
IPAddr::IPAddr6(s) => println!("{}", s),
}
}
10.3章对枚举的解构应该是这样写的(漏加成员名了):
enum IPAddr { IPAddr4(u8,u8,u8,u8), IPAddr6(String), } fn main(){ let ipv4 = IPAddr::IPAddr4(127,0,0,1); match ipv4 { // 丢弃解构后的第四个值 IPAddr::IPAddr4(a,b,c,_) => println!("{},{},{}", a,b,c), IPAddr::IPAddr6(s) => println!("{}", s), } }
好的。感谢指正提醒,谢谢。
https://rust-book.junmajinlong.com/ch6/05_re_understand_move.html 感谢您的书,我在这个章节的最后一个代码块发现一个错误,let user2 = &(*user); 并不像代码中提示不报错,而是报 type User
cannot be dereferenced,可能存在笔误
https://rust-book.junmajinlong.com/ch10/03_deconstruction.html 页面接近最下方的内容 解引用(deref)的所有权转移问题 连接失效啦
非常感谢你的细心和提醒。这个链接对应的是再次理解Move的最后一段,以前我写了一大段关于解引用的所有权相关问题,但是后来总结成了一句话放在这个最后一段中。
失效链接暂时无法去更新,抱歉。
https://rust-book.junmajinlong.com/ch6/05_re_understand_move.html 感谢您的书,我在这个章节的最后一个代码块发现一个错误,let user2 = &(*user); 并不像代码中提示不报错,而是报 type
User
cannot be dereferenced,可能存在笔误
关于这个代码片段里的问题,错在 user 不是引用类型,所以*user
是错的,如果user是一个User的引用,那么&(*user)是无措的。
啥时候能录点0基础rust?现在网上能找到的视频门槛都太高了,全是照着文档念,根本没有说明rust中弄出这种新东西到底有什么好处。看了很多教程太劝退了。
啥时候能录点0基础rust?现在网上能找到的视频门槛都太高了,全是照着文档念,根本没有说明rust中弄出这种新东西到底有什么好处。看了很多教程太劝退了。
零基础本来就不适合学习Rust。如果完全没有编程语言基础,暂时放下Rust作为第一门语言会比较好。如果有其它语言的基础,学习熟悉Rust的语法和特性,熬过第一阶段,写个完整的程序,就会变得很好了。
博主的书简单易懂有深度,非常感谢博主关于Rust内存的介绍。
我想和博主讨论一下,是否可以在可变引用排他性的解释中,拓展“独占锁”的生成方式。
https://rust-book.junmajinlong.com/ch6/04_understand_mutable_ref.html
可以将可变引用看作是一把独占锁。在当前作用域内,从第一次使用可变引用开始创建这把独占锁,之后无论使用原始变量(即所有权拥有者)、可变引用还是不可变引用都会抢占这把独占锁,以保证只有一方可以访问数据,每次抢得独占锁后,都会将之前所有引用变量给锁住,使它们变成不可用状态。当离开当前作用域时,当前作用域内的所有独占锁都被释放。
fn main() {
let mut x = Box::new(42); // 1
// 创建x的不可变引用,出现x的独占锁
let mut z = &x; // 2
// 在考虑引用检查问题和生命周期问题时,循环结构for {} 和多个独立的大括号 {} 是等价的
for i in 0..100 {
// 使用z的不可变引用
println!("{}", z); // 3
// 抢占x的独占锁,使得z不再可用
x = Box::new(i); // 4
// 因此下面的代码会报错
// println!("{}", z);
// 虽然z不可用,但z自身可以被重新赋值,重新赋值将丢弃z之前对x的引用,
// 注意这里使用了x的不可变引用,它会抢占x的独占锁,
// 虽然这里z重新引用了x,但和赋值之前引用的x已经不一样,它是一个新的引用,
// 并且z在这里抢占到了新的x独占锁,而赋值之前的x独占锁已经被代码行4抢占
z = &x; // 5
}
}
在上面解释中,我的理解是第一次使用变量的可变引用时,这个独占锁才会出现。但给出的这段复杂代码是一个不可变引用和变量重新赋值的形式,它也会出现报错。
我想这种情况下是不是将 “独占锁” 生成的时机改成 “第一次使用可变引用开始或变量被重新赋值创建” 会更好一点。
rust新学徒,请博主赐教 :)
@azin-cn 博主的书简单易懂有深度,非常感谢博主关于Rust内存的介绍。
我想和博主讨论一下,是否可以在可变引用排他性的解释中,拓展“独占锁”的生成方式。
https://rust-book.junmajinlong.com/ch6/04_understand_mutable_ref.html
可以将可变引用看作是一把独占锁。在当前作用域内,从第一次使用可变引用开始创建这把独占锁,之后无论使用原始变量(即所有权拥有者)、可变引用还是不可变引用都会抢占这把独占锁,以保证只有一方可以访问数据,每次抢得独占锁后,都会将之前所有引用变量给锁住,使它们变成不可用状态。当离开当前作用域时,当前作用域内的所有独占锁都被释放。
fn main() { let mut x = Box::new(42); // 1 // 创建x的不可变引用,出现x的独占锁 let mut z = &x; // 2 // 在考虑引用检查问题和生命周期问题时,循环结构for {} 和多个独立的大括号 {} 是等价的 for i in 0..100 { // 使用z的不可变引用 println!("{}", z); // 3 // 抢占x的独占锁,使得z不再可用 x = Box::new(i); // 4 // 因此下面的代码会报错 // println!("{}", z); // 虽然z不可用,但z自身可以被重新赋值,重新赋值将丢弃z之前对x的引用, // 注意这里使用了x的不可变引用,它会抢占x的独占锁, // 虽然这里z重新引用了x,但和赋值之前引用的x已经不一样,它是一个新的引用, // 并且z在这里抢占到了新的x独占锁,而赋值之前的x独占锁已经被代码行4抢占 z = &x; // 5 } }
在上面解释中,我的理解是第一次使用变量的可变引用时,这个独占锁才会出现。但给出的这段复杂代码是一个不可变引用和变量重新赋值的形式,它也会出现报错。
我想这种情况下是不是将 “独占锁” 生成的时机改成 “第一次使用可变引用开始或变量被重新赋值创建” 会更好一点。
rust新学徒,请博主赐教 :)
sorry,我写错了,你是对的。刚开始let mut z = &x;
是不可变引用,还没有创建“独占锁”。
我也是新学徒。如果发现有什么错误或描述不清、解释不好的地方,尽可以提出来,我会改正以及尽量解惑。写了很久代码,有些基础性的东西反而记忆不深刻了。
请教下博主的mdbook 是如何能够在右侧显示大纲的,博主可以分享下么。我看了一遍文档没找到比较直接的方式。
请教下博主的mdbook 是如何能够在右侧显示大纲的,博主可以分享下么。我看了一遍文档没找到比较直接的方式。
右侧有标题目录吗,我的浏览器里都没有啊。我以前确实添加过生成目录的代码,但是后来发现就没有了,也就没管它了。我也忘记了是怎么搞的了,过去好久了。
是。我看你写的《Rust入门秘籍》 是有的。应该是book.toml 要设置啥,之前没找到,现在找到了一个模板: rust-by-practice/zh-CN/book.toml at master · sunface/rust-by-practice (github.com) https://github.com/sunface/rust-by-practice/blob/master/zh-CN/book.toml [image: image.png]
masuai @.***> 于2023年10月22日周日 19:13写道:
请教下博主的mdbook 是如何能够在右侧显示大纲的,博主可以分享下么。我看了一遍文档没找到比较直接的方式。
右侧有标题目录吗,我的浏览器里都没有啊。我以前确实添加过生成目录的代码,但是后来发现就没有了,也就没管它了。我也忘记了是怎么搞的了,过去好久了。
— Reply to this email directly, view it on GitHub https://github.com/malongshuai/malongshuai.github.io/issues/190#issuecomment-1774065221, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUZYF4TWNSWYXZYX3VOZU7LYAT5W5AVCNFSM4VSZVGJKU5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCNZXGQYDMNJSGIYQ . You are receiving this because you commented.Message ID: @.***>
太感谢了,感觉很有帮助,觉得的确对知识点写得很详细,比如刚好搜到内存相关的讲解。知识点资料太多,能找到遇到适合自己能容易接受的,太不容易了。作者辛苦了
https://www.junmajinlong.com/rust/index/
Rust入门秘籍以书籍方式发布。 #—-> 链接:Rust入门秘籍 <—-#