果然连流程控制都这么不一样。转载本文请联系polarisxu公众号。大家好,我是polarisxu。这是Rust退出系列的第7篇教程,探索Rust中的流控制。注意,和其他语言一样,Rust中也有条件和循环,但没有switch,而是match模式匹配。这个系列正版的阅读量有点受不了,试试其他的吧。01Operator在开始讲解流控之前,先补充一个知识点,那就是Rust的Operator。Rust支持四种类型的算术运算符、关系运算符、逻辑运算符和位运算符。它们与其他语言没有什么不同,所以我不再赘述,只提醒一点:Rust运算符(--)中没有自增(++)和自减。++or--在Go中是语句,只有一种形式:后缀,即i++;而C等语言则支持前缀和后缀,如i++、++i。Rust根本没有它。吐槽:自增自减运算符有时候很有用,为什么Rust不支持?!(是不是没有必要,因为没有正则for循环?)02语句和表达式为什么要专门介绍语句和表达式?上面说了,Go中的自增自减是语句而不是表达式。有什么不同?很多语言基本上不区分和强调语句和表达式,所以很多人没有注意到两者的区别。但在Rust中,还是有必要区分它们的。其实Rust中的语法可以分为两类:语句(Statement)和表达式(Expression)。语句是指要执行的一些操作和产生副作用的表达式;表达式主要用于计算和评估。语句通常分为声明语句和表达式语句。像声明各种语言项,比如变量、常量、结构体、函数等,都是声明语句:leta=1;constPI:i32=3.14;而表达式语句是指以分号结尾的表达式,一般会涉及将多个表达式组合成语句。?表示Rust中的表达式一般分为“位置表达式”和“值表达式”。我们之所以使用表达式,是因为Rust中的一切都是表达式。罗里说了很多,但似乎没什么用。才知道有这么一回事。请记住,Rust中的一切都是表达式。03条件表达式你知道为什么要强调“表达式”吗?在通用语言中它被称为条件语句,但在Rust中它是条件表达式。首先,条件表达式的语法和其他语言的条件语句类似,支持if、elseif、else等,但和Go类似,条件默认不需要括号。但是因为是表达式,所以是有返回值的,而Rust是强类型语言,所以必须确定返回值的类型。比如下面的代码可以正常编译:fntestif()->&'staticstr{letname="polarisxu";ifname=="polarisxu"{"Welcome"}else{"Forbidden"}}你不明白。我们只关注if-else部分。在块表达式中(用{}括起来),直接是字符串字面量(这是一个值表达式),连分号都没有。Rust中没有分号与Go中没有分号具有不同的含义。Go语句以分号结尾。建议不要写分号,编译器会自动补上;Rust语句必须手动添加分号。如果没有分号,它就是一个表达式。一切都是表达式,用大括号括起来的就是块表达式。该块表达式的值是什么?它的值是里面一系列表达式中最后一个表达式的值。所以,上面的代码,不管是执行到if还是else,整个if表达式的值类型都是字符串。因此,上面的代码可以改成这样:fntestif()->&'staticstr{letname="polarisxu";letresult=ifname=="polarisxu"{"Welcome"}else{"Forbidden"};hello}expressif表达式的结果存储在result变量中。注意if表达式花括号末尾的分号。在这种情况下,不能省略分号。因此,在if表达式中,各个分支表达式的最终结果类型必须一致,否则会编译失败。这也是Rust不支持三元运算符?:的原因。if是一个表达式有它的好处。在Go语言中,经常会写成这样的代码:varresultstringifname==”polarisxu”{result="Welcome"}else{result="Forbidden"}在Rust代码中,result会少写很多次。但是需要注意各个分支结果类型的一致性。if表达式可以这样使用,其他流程控制表达式也可以这样使用。特别是一点。如果块表达式的最后一个表达式是语句,如:fntestif()->&'staticstr{letname="polarisxu";ifname=="polarisxu"{"Welcome";}else{"forbidden";}}这个在编译的时候会报错:mismatchedtypes。因为函数要求返回值类型为&str,而函数体的最后一个返回类型为空。这个空,在其他语言中一般没有返回值,或者void。但是在Rust中,这个void就是前面介绍类型的时候介绍的“单元”类型,也就是(),这个类型有一个唯一的值,也就是()。因此,我们可以去掉函数的返回值,或者return():fntestif()->(){letname="polarisxu";ifname=="polarisxu"{"Welcome";}else{"forbidden";}}很Alternative,有没有?!04循环表达式Rust包含三个循环表达式:while、loop和for...in。它的用法类似于其他编程语言中的相应语句。(注意Go中只有for循环语句。)loop循环比较特殊,一般语言中是没有的。它实际上是whiletrue{},相当于Go中的for{}。不得不说Go还是很简单的!while循环相当于Go中的forcondition{}。当条件为真时,执行循环体。你有没有注意到循环是如此复杂以至于其他语言中没有普通的for循环?因为for...in可以处理它。例如,对于i:=0;我<10;i++在Go中,在Rust中看起来像这样:foriin0..10{}。这是一个简单的例子,从1加到100:letmutsum=0;foriin1..=100{sum+=i;}println!("1+2+..+100={}",sum);小细节:1..10表示范围[1,10),1..=10表示范围[1,10]最后,与其他语言一样,循环支持continue和break语句。05总结Rust中的一切都是表达式。当某处需要表达式,但它是语句时,编译器会自动加上单位值,即(),这是一种特殊的表达式。虽然控制结构、if、循环等都是表达式,但为了不特化(毕竟你习惯了很多其他语言,特化很容易让你迷惑),建议你尽量不要把它们当成表达式,这与其他语言非常不同。正常写,应该有一个分号加一个分号。但是,如果您是编写Rust的Go程序员,您可能会忘记分号。在Rust中,有时可以带分号也可以不带分号编译,但意思可能会发生变化,所以要特别注意这一点。(PHPer说PHP和Go切换的时候,分号的问题很纠结,有没有?!)控制过程中的模式匹配,下节再说!
