这部分我们学习 rust 语言的 变量、数据类型、函数、注释、流程控制 这五个方面的内容。前文介绍了前两个内容,本文介绍后三个内容。

函数

函数在 rust 代码普遍存在,我们也已经见过了它的主函数 main 函数了,它是进入程序的入口。我们也见过了 fn 关键字了,它是用来声明函数的。



特别说明一下:rust 语言的函数和变量都是以小写字母和下划线命名的,如果以其它方式命名,你会收到一个警告。

函数说明

函数是以 fn 关键字打头,然后是函数名字和小括号,最后的大括号是用来告诉编译器函数体的开始和结束。我们也可以通过函数名字和小括号来调用我们定义的函数,定义的函数可以在主函数前面,也可以在主函数后面。rust 不关心定义的位置,只要你在某个地方定义了它。我们来看个简单的例子吧:

  1. fn main() {
  2. println!("Hello, world!");
  3. another_function();
  4. }
  5. fn another_function() {
  6. println!("另一个函数");
  7. }

运行结果:

  1. cargo run
  2. Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
  3. Finished dev [unoptimized + debuginfo] target(s) in 0.57s
  4. Running `target/debug/hello_cargo`
  5. Hello, world!
  6. 另一个函数

函数参数

函数也可以附带一些参数,函数和参数共同构成函数声明。当我们调用函数的时候,也需要把函数需要的参数传给它。我们直接看个例子吧:

  1. fn main() {
  2. another_function(5, 6);
  3. }
  4. fn another_function(x: i32, y: i32) {
  5. println!("x 的值是: {}", x);
  6. println!("y 的值是: {}", y);
  7. }

运行的结果是:

  1. cargo run
  2. Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
  3. Finished dev [unoptimized + debuginfo] target(s) in 0.23s
  4. Running `target/debug/hello_cargo`
  5. The value of x is: 5
  6. The value of y is: 6

例子传了两个参数,5 传给了 x,6 传给了 y。

函数体可以包含语句和表达式

函数体是由一系列语句的集合,并以表达式结束组合而成的。我们还没有使用过表达式结尾的函数,但是我们即将看到表达式作为函数体语句的一部分。因为 rust 是一种基于表达式的语言,这对于理解 rust 语言是很重要的,其他语言没有这样的设计,接下来我们来看一下这是一种什么样的设计。

我们在之前章节也使用过语句和表达式。语句是一些操作的集合而不返回值,表达式是用来返回结果的。在其他语言中,我们可以把代码写成 x = y = 6,使得 x 和 y 都为 6,但是在 rust 语言中不允许这样。

表达式返回值是 rust 语言特有的风格:

  • 一些简单的数学算式,比如 5 + 6 就是一个返回 11 的表达式。
  • 表达式也是语句的一部分,比如 6 是语句 let y = 6 中的返回值为 6 的表达式。
  • 函数调用也是一种表达式。
  • 宏指令调用也是一种表达式。
  • 使用 {} 创建的新作用域也是一种表达式。

直接上代码来看一下这一条说明吧:

  1. fn main() {
  2. let x = 5;
  3. let y = {
  4. let x = 3;
  5. x + 1
  6. };
  7. println!("y 的值是: {}", y);
  8. }

在这里,很容易看到的一个表达式是:

  1. {
  2. let x = 3;
  3. x + 1
  4. };

因为这块在 {} 创建的新作用域中,它返回的值是 4,而 4 这个值赋给 let 语句的变量 y 中。特别说明:x + 1 结尾不带分号,因为表达式不能带有分号,如果添加了分号,则会自动转成语句,就不会返回 4 这个值了,这一点要牢记。

函数返回值

函数可以给调用它的代码返回函数计算结果。我们不需要给返回值命名,但是需要在符号 -> 后面声明返回值的类型。在 rust 中,函数返回值就是函数体结尾的表达式。当然我们也可以使用 return 关键字来返回值,但是大部分函数都是以最后的表达式作为返回值的。我们直接看例子吧:

  1. fn main() {
  2. let x = plus_one(5);
  3. println!("x 的值是: {}", x);
  4. }
  5. fn plus_one(x: i32) -> i32 {
  6. x + 1
  7. }

这里的 let x = plus_one(5) 就相当于 let x = 6。我们定义了函数 plus_one,它的返回值类型是 i32,返回的值是 x + 1,这里不能加分号。

注释

所有的程序员都力求他们写的程序可以很容易地被其他人理解,所以会在程序中写一些说明。这些笔记、说明会被编译器忽略,但是对于阅读源码的人是相当有用的。



在 rust 中,注释是以两个斜线开头,直到行结束为止。

流程控制

在大部分程序语言中,是否运行这部分代码取决于条件语句是否为真,是否持续运行这部分代码取决于条件是否持续为真。这部分我们来学习 rust 的判断和循环两种控制流程。

判断

判断语句根据条件来判断执行哪个分支的代码。

if

所有的判断表达式都是使用 if 打头,然后紧跟条件表达式。我们直接来看例:

  1. fn main() {
  2. let number = 3;
  3. if number < 5 {
  4. println!("条件为真");
  5. } else {
  6. println!("条件为假");
  7. }
  8. }

如果变量 number 比 5 小,就打印 条件为真,否则就打印 条件为假。在 if 这里也可以考虑一下 match 关键字。再说一下 else 表达式,主要是提供一个条件为假时的代码,如果不提供 else 表达式,程序会直接跳过 if 表达式。

tips:if 后面的表达式必须是 bool 类型的,这点和 ruby、javascript语言是不同的。

else if

我们也可以使用 if、else if、else 结合起来写多条件判断的代码,直接看个例子:

  1. fn main() {
  2. let number = 6;
  3. if number % 4 == 0 {
  4. println!("能被 4 整除");
  5. } else if number % 3 == 0 {
  6. println!("能被 3 整除");
  7. } else if number % 2 == 0 {
  8. println!("能被 2 整除");
  9. } else {
  10. println!("不能被 2, 3, 4 整除");
  11. }
  12. }

如果使用了太多的 else if 表达式会使代码显得很乱,可以考虑 match 关键字来代替,后文再介绍这个内容。

使用 let 接收 if 的值

因为 if 是个表达式,可以使用 let 语句来接收 if 表达式返回的值。内容比较简单,直接看代码:

  1. fn main() {
  2. let condition = true;
  3. let number = if condition {
  4. 5
  5. } else {
  6. 6
  7. };
  8. println!("结果是: {}", number);
  9. }

运行的结果是:

  1. cargo run
  2. Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
  3. Finished dev [unoptimized + debuginfo] target(s) in 0.23s
  4. Running `target/debug/hello_cargo`
  5. 结果是: 5

if 和 else 返回值的类型必须是相同的。

循环

关于循环,rust 提供了几种循环的方法: loop、while、for,我们依次看一下:

loop

loop 关键字是告诉 rust 重复执行后面的代码块,直到代码明确告诉 rust 停止,比如:

  1. fn main() {
  2. loop {
  3. println!("重复打印");
  4. }
  5. }

这里会重复打印 重复打印 这 4 个字,直到我们使用 ctrl-c 结束程序。还可以在循环代码块中使用 break 关键字跳出循环。

使用 let 接收 loop 的值

loop 表达式也可以和 if 表达式一样返回一个值,赋给 let 语句。返回的表达式可以跟在 break 关键字的后面。看个例子:

  1. fn main() {
  2. let mut counter = 0;
  3. let result = loop {
  4. counter += 1;
  5. if counter == 10 {
  6. break counter * 2;
  7. }
  8. };
  9. println!("结果是 {}", result);
  10. }

代码的结果是 20,相对比较简单,不说了。

while

如果执行循环前需要进行条件判断,则使用 while 关键字。当条件为真时,执行循环体,循环体中也可以使用 break 关键字来停止。这块直接看个例子:

  1. fn main() {
  2. let mut number = 3;
  3. while number != 0 {
  4. println!("{}!", number);
  5. number -= 1;
  6. }
  7. println!("结束");
  8. }

因为这块内容和其他语言差不多,这里就不讲解了。

for

如果想要遍历数组,则使用 for 关键字。当然也可以使用 while 关键字,先看 while 关键字的例子:

  1. fn main() {
  2. let a = [10, 20, 30, 40, 50];
  3. let mut index = 0;
  4. while index < 5 {
  5. println!("值是: {}", a[index]);
  6. index += 1;
  7. }
  8. }

会根据索引依次打印数组中的 5 个值,再看 for 关键字的例子:

  1. fn main() {
  2. let a = [10, 20, 30, 40, 50];
  3. for element in a.iter() {
  4. println!("值是: {}", element);
  5. }
  6. }

这是使用的是迭代器 iter(),当然也可以使用 Range 关键字,如下:

  1. fn main() {
  2. for number in (1..4).rev() {
  3. println!("{}!", number);
  4. }
  5. println!("结束");
  6. }

rev() 方法是把 1,2,3,4 倒序变量 4,3,2,1。

欢迎阅读单鹏飞的学习笔记

Rust 入门 (三)_下的更多相关文章

  1. Rust 入门 (三)_上

    这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.本文我们介绍前两个内容,下一篇文章介绍后三个内容. 变量 默认情况下,rust 语言中声明的变量是不可变的,比 ...

  2. ArcGIS for Desktop入门教程_第三章_Desktop软件安装 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第三章_Desktop软件安装 - ArcGIS知乎-新一代ArcGIS问答社区 1 软件安装 1.1 安装前准备 请确认已经收到来自Esri中国( ...

  3. JavaWeb-RESTful(三)_使用SpringMVC开发RESTful_下

    JavaWeb-RESTful(一)_RESTful初认识 传送门 JavaWeb-RESTful(二)_使用SpringMVC开发RESTful_上 传送门 JavaWeb-RESTful(三)_使 ...

  4. Rust入门篇 (1)

    Rust入门篇 声明: 本文是在参考 The Rust Programming Language 和 Rust官方教程 中文版 写的. 个人学习用 再PS. 目录这东东果然是必须的... 找个时间生成 ...

  5. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...

  6. GEF入门实例_总结_06_为编辑器添加内容

    一.前言 本文承接上一节:GEF入门实例_总结_05_显示一个空白编辑器 在上一节我们为我们的插件添加了一个空白的编辑器,这一节我们将为此编辑器添加内容. 二.GEF的MVC模式 在此只简单总结一下, ...

  7. GEF入门实例_总结_05_显示一个空白编辑器

    一.前言 本文承接上一节:GEF入门实例_总结_04_Eclipse插件启动流程分析 在第三节( GEF入门实例_总结_03_显示菜单和工具栏  ),我们创建了菜单和工具栏. 这一节,我们来实现:点击 ...

  8. GEF入门实例_总结_04_Eclipse插件启动流程分析

    一.前言 本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏 注意到app目录下的6个类文件. 这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们 ...

  9. GEF入门实例_总结_03_显示菜单和工具栏

    一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar   含义 a ...

随机推荐

  1. Dubbo学习系列之十六(ELK海量日志分析框架)

    外卖公司如何匹配骑手和订单?淘宝如何进行商品推荐?或者读者兴趣匹配?还有海量数据存储搜索.实时日志分析.应用程序监控等场景,Elasticsearch或许可以提供一些思路,作为业界最具影响力的海量搜索 ...

  2. 你必须知道的容器监控 (3) Prometheus

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章.上一篇介绍了Google开发的容器监控工具cAdvisor,但是其提供的操作界面 ...

  3. 【排列组合】给定一个M*N的格子或棋盘,从左下角走到右上角的走法总数(每次只能向右或向上移动一个方格边长的距离)

    版权声明:本文为CSDN博主「梵解君」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/hadeso/art ...

  4. 前后端对称加密(AES)

    后端实现(JAVA) package com.vcgeek.hephaestus.demo; import org.apache.commons.codec.binary.Base64; import ...

  5. vue项目如何在node启动

    首先将vue项目通过命令npm run build 打包,然后创建start.js,代码如下: // const userApi = require('./api'); const fs = requ ...

  6. <script>属性async和defer的区别

    async:可选.表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或 等待加载其他脚本.只对外部脚本文件有效. defer:可选.表示脚本可以延迟到文档完全被解析和显示之后再执行.只 ...

  7. MIT线性代数:17.正交矩阵和Cram-Schmidt正交化

  8. Springboot中使用自定义参数注解获取 token 中用户数据

    使用自定义参数注解获取 token 中User数据 使用背景 在springboot项目开发中需要从token中获取用户信息时通常的方式要经历几个步骤 拦截器中截获token TokenUtil工具类 ...

  9. 1、Hibernate-入门

    一.概述 1.什么是Hibernate: Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,h ...

  10. Go 程序的性能监控与分析 pprof

    你有没有考虑过,你的goroutines是如何被go的runtime系统调度的?是否尝试理解过为什么在程序中增加了并发,但并没有给它带来更好的性能?go执行跟踪程序可以帮助回答这些疑问,还有其他和其有 ...