当前位置: 首页 > 科技观察

自从学了Rust,我就踏上了自虐之旅,连编译都没有成功过!

时间:2023-03-22 13:18:34 科技观察

张大胖被赋予了一门新语言:Rust。作为一名编程语言爱好者,他自然是想要尝试一下。第一个程序当然是helloworld,太简单了,懒得写了,直接看看:fnmain(){println!("helloworld");}张大发以前用的是C语言,并且当时觉得很不舒服。它没有内置的常用数据结构,比如可以动态增长的数组。生锈怎么样?fnmain(){letv=Vec::new();//创建一个数组v.push(4);//向数组中添加一个元素}张大胖写了let,意识到这里是绑定值(数组)到变量v,它应该是从Lisp的模式匹配中借来的。可以预见,以后我们还会遇到这样的代码:let(name,age)=("Andy",30);另外,Rust有自动类型推断能力,这是相当不错的。编译!哎,失败了。错误信息是:不能将`v`借用为可变的,因为它没有被声明为可变的Rust编译器:我们将对象分为可变的和不可变的。对于不可变的,一旦创建,就无法更改。然后加一个关键字mut,让它可变:letmutv=Vec::new()张大发想起了《effective java》的一个做法:把可变性限制在最小。他喃喃自语:“好吧,Rust默认是不可变的,这个想法可能是对的。”所有权他探索并编写了一些代码:fnmain(){//以另一种方式创建了一个变量Vectorletmutv=vec![1,2];letv1=v;println!("the1stelementis{}",v[0]);}编译,又失败了,卧槽!到底是怎么回事?这么简单的程序也会出错?!Rust编译器:谁让你便宜!加了一行代码:letv1=v张大胖:有什么关系?在Java中,这相当于为同一个对象添加另一个引用!Rust编译器:这就是Java。在Rust中,你必须放下对Java的执着!了解所有权问题。张胖子:什么归属?Rust编译器:对于任何给定的对象,只有一个绑定。你使用letmutv=Vec::new()这意味着v绑定到这个Vector对象!现在v拥有该对象的所有权。这行代码letv1=v转移所有权,现在v1是新的所有者。v不能再访问这个Vector,我把这种情况称为“传输语义”。码友注意:其实Rust也支持Copy语义,这里就不赘述了。张胖子不满道:这不是增加不必要的麻烦吗?如果我将v传递给另一个函数怎么办?fnmain(){letmutv=vec![1,2,3,4];//创建一个变量Vectorprint_vector(v);println!("the1stelementis{}",v[0]);}fnprint_vector(v:Vec){foriinv{println!("{}",i);}}编译还是出错!Rust编译器:这个和之前的道理是一样的。v的所有权在传递给函数的时候就被拿走了,所以在main中就不能再访问v了!借用张大发:太变态了,我就是想调用print_vector之后再访问再访问变量v怎么办?Rust编译器:可以暂时借用(&v)所有权给print_vector,等函数返回后再使用。fnmain(){letmutv=vec![1,2,3,4];//创建一个变量Vectorprint_vector(&v);println!("the1stelementis{}",v[0]);}fnprint_vector(v:&Vec){...}这个借用相当于Java语言的引用。张大发认为print_vector函数“借”了所有权,应该可以为所欲为,于是在函数中做了修改:fnprint_vector(v:&Vec){v.push(3);...}再次编译,再次失败!张胖子感觉自己快要吐血了,这拉斯特也太不讲理了。Rust编译器:“如果要更改原始对象,则必须添加&mut!”fnmain(){letmutv=vec![1,2,3,4];//创建了一个Vectorprint_vector(&mutv);println!("the1stelementis{}",v[0]);}fnprint_vector(v:&mutVec){v.push(3);...}总结一下:张胖子继续写代码,想继续测试这个所谓的“借用”:fnmain(){letmutx=String::from("hello");letx1=&x;letx2=&mutx;println!("{}",x1);}编译或报错:'x'已经有不可变借用,不能再以可变方式借用!张胖子彻底懵了!我想我在编程世界里混了很多年,先后学过C、C++、Java、Ruby、Python。从来没见过这么复杂的语言,这么简单的程序也编译不出来。Rust编译器:原因很简单。x1是不可变引用,x2是可变引用。使用x1的“用户”不希望访问x1时数据发生变化。告诉你一个简单的公式,以后遇到问题就能解决:sharingisnotmutable,mutableisnotshared。(严格来说是这样的:同一时间要么只有一个可变(&mut)借用,要么有多个不可变(&)借用,可变和不可变借用不能同时存在。(两者都做一个object读操作,安全!)(只有小张会写,因为他是变量借用)张大发想了想,这个公式用人话来说就是这样的:当大家都在读某个东西的时候,它是写不出来的。一个人在写,其他人不能读,这不是经典的读写锁问题吗?这个Rust居然在编译器层面做了这个限制!Rust编译器:我之所以有这么严格的限制,是为了内存安全。我的系统不需要GC,只要你能遵守我的规则,内存安全是可以保证的。张胖子:你,为了偷懒省事,把虚拟机能自动完成的事情都交给程序员了。这让我们筋疲力尽!Rust编译器:你做过系统吗?没有关卡编程吗?系统级编程要求:1.非常快2.运行时很小(虚拟机是一个巨大的Runtime)3.可以直接访问内存,内存是安全的。C、C++基本满足,但内存不安全,像Java、Python、Ruby除了内存安全不满足,只适合应用层编程。张胖子无语。这家伙的目标是取代C/C++。他还编写了很多C代码。由于内存问题,不知道他破坏了多少程序。悬垂的指针就像幽灵一样飘来飘去,无影无踪。可以跟着它,然后在不知名的地方,不知名的时刻,突然爆裂。在这个Rust中,每一个对象都有一个独一无二的“主人”,然后就有了如此严格的读写限制。如果程序员掌握了,确实比C语言更安全。我最好继续学习!【本文为专栏作者“刘鑫”原创稿件,转载请通过作者微信获取授权公众号coderising】点此查看作者更多好文