Rust 入门 (三)_上
这部分我们学习 rust 语言的 变量、数据类型、函数、注释、流程控制
这五个方面的内容。本文我们介绍前两个内容,下一篇文章介绍后三个内容。
变量
默认情况下,rust 语言中声明的变量是不可变的,比如如下代码:
fn main() {
let x = 5;
println!("x 的值是: {}", x);
x = 6;
println!("x 的值是: {}", x);
}
我们先来跑一下这段代码:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:4:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: make this binding mutable: `mut x`
3 | println!("x 的值是: {}", x);
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0384`.
通过运行结果,我们发现这段代码有问题的,然后我们从报错信息中抓取关键信息: cannot assign twice to immutable variable
,它的意思是 不可变变量不能进行二次赋值
。但是有些时候,我们也需要修改变量的值,应该怎么办呢,在变量名的前面,let 关键字的后面添加一个关键字 mut 就行了,我们来试试:
fn main() {
let mut x = 5;
println!("x 的值是: {}", x);
x = 6;
println!("x 的值是: {}", x);
}
运行一下代码:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 3.53s
Running `target/debug/hello_cargo`
x 的值是: 5
x 的值是: 6
这种不可变变量的设计有着很多安全方面的考虑,这里不再赘述。谈到这里,很容易联想到编程语言的另一个概念——常量,那二者有什么区别呢?
1.常量不能使用 mut 关键字修饰,常量在任何情况下都是不可变的(变量是在默认情况下不可变)。
2.常量使用 const 关键字来声明,而变量使用 let 关键字来声明。
3.常量需要在常量名后面紧跟冒号和类型,例如 const MAX_POINTS: u32 = 100_000;
,而变量可以省略冒号和类型的修饰。
4.常量的作用域是任何作用域,包括全局作用域。
5.常量只能使用常量表达式赋值,而不能使用函数结果或者其它运行时产生的值。
注:这是说明一下,常量通常使用大写字母和下划线 _ 来命名。
我们再来说一个变量的特性——覆盖。在上一篇写猜数字游戏的文章中,我们做数字类型转换的时候,新类型的名字使用了旧类型的名字,这种情况就是覆盖。先来个实例:
fn main() {
let x = 5;
println!("x 的值是: {}", x);
let x = 6;
println!("x 的值是: {}", x);
}
我们来看运行结果:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
Running `target/debug/hello_cargo`
x 的值是: 5
x 的值是: 6
通过结果可以发现,第二个使用 let 关键字修饰的不可变变量 x 把第一个 x 覆盖了,也就是说把 x 的值从 5 改成了 6。那这和 mut 有什么区别呢?
1.覆盖的第二个变量需要使用 let 关键字修饰,如果没有 let 关键字,则会报错。
2.覆盖的第二个变量不仅可以改变值,还可以修改变量的类型;而 mut 不可以改变类型。
这里举两个例子来说明第二个区别:
fn main() {
let space = "abc";
println!("space 代表的是:{}", space);
let space = space.len();
println!("space 代表的是:{}", space);
}
先来运行第一个例子:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.22s
Running `target/debug/hello_cargo`
space 代表的是:abc
space 代表的是:3
然后看第二个例子:
fn main() {
let mut space = "abc";
println!("space 代表的是:{}", space);
space = space.len();
println!("space 代表的是:{}", space);
}
跑一下第二个例子:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
error[E0308]: mismatched types
--> src/main.rs:4:13
|
4 | space = space.len();
| ^^^^^^^^^^^ expected &str, found usize
|
= note: expected type `&str`
found type `usize`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `hello_cargo`.
To learn more, run the command again with --verbose.
可以轻易看到二者的区别,好了,接下来我们看 rust 的基本类型。
数据类型
rust 的数据类型就是在编译期间告诉 rust 的编译器如何处理这些数据。在这里,我们会了解到两种数据类型:基本数据类型和组合数据类型。
基本数据类型
基本数据类型也就是简单值,rust 主要包含了 4 种基本数据类型,分别是整型、浮点型、布尔型和字符型。你可能在其他语言中见过这些类型,现在,我们来看一下它们在 rust 语言中是怎么样的。
整型
整型是不包含小数的数字类型。整型包含了两种类型:i 打头的有符号整型和 u 打头的无符号整型。我们使用一个表格来描述 rust 的整型:
占用空间 | 有符号整型 | 无符号整型 |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
格式 | i+长度 | u+长度 |
整型在使用过程中默认类型是 i32。
浮点型
浮点型包含了两种类型:单精度浮点型 f32,双精度浮点型 f64。浮点型在使用过程中默认类型是 f64。
数据操作
rust 支持的基本数据操作有:加 +,减 -,乘 *,除 /,取模 %。
布尔型
布尔型通常有两个值:true和false。它占用 1 个字节,使用 bool 关键字来声明。
字符型
rust 的字符类型占用 4 个字节,它的值是使用单引号 '
引起来的。
组合数据类型
组合数据类型是把多个值组合成一个类型。在 rust 中,组合数据类型有两种:元组和数组。
元组
元组是把多个基本类型组合成一个组合类型。它有一个确定的长度,一旦确定就不能再次加减元素了。我们先来看一个元组的实例:
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
println!("第0个值:{}, 第1个值:{}, 第2个值:{}", tup.0, tup.1, tup.2);
let (x, y, z) = tup;
println!("x的值:{}, y的值:{}, z的值:{}", x, y, z);
}
它运行的结果是:
cargo run
Compiling hello_cargo v0.1.0 (/Users/shanpengfei/work/rust-work-space/study/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.23s
Running `target/debug/hello_cargo`
第0个值:500, 第1个值:6.4, 第2个值:1
x的值:500, y的值:6.4, z的值:1
元组的取值有两种方式,一种是把元组解构成多个变量,另一种就是使用 .
的方式,顺序是从 0 开始。
数组
数组和元组不一样的地方是:数组只能使用相同的数据类型。数组和元组相同的地方是:长度一旦确定就不能加减元素了。如果想改变数组的长度,可以使用 vector 类型,后续文章会介绍 vector 类型的情况。而且数组还有一个特性,它会把数据分配到栈内存,而不是堆内存。下面举几个常用的数组的例子:
fn main() {
// 定义一个简单的数组
let a = [1, 2, 3, 4, 5];
// 定义一年 12 个月,而且不需要增减月份,那么可以直接定义包含 12 个月份的数组
let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
// 定义包含 5 个元素的 i32 类型的数组
let a: [i32; 5] = [1, 2, 3, 4, 5];
// 数组的值是 5 个 3
let a = [3; 5];
// 取值
println!("a[3]的值是:{}", a[3]);
println!("a[9]的值是:{}", a[9]); // 编译时这里会报错:error: index out of bounds: the len is 5 but the index is 9
}
数组的取值方式是以中括号 [0]
的方式,顺序是从 0 开始。如果取值越界,rust 会在编译期告诉你,这就是 rust 安全原则的第一个例子。
这一节未完,待续~~~
欢迎阅读单鹏飞的学习笔记
Rust 入门 (三)_上的更多相关文章
- Rust 入门 (三)_下
这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.前文介绍了前两个内容,本文介绍后三个内容. 函数 函数在 rust 代码普遍存在,我们也已经见过了它的主函数 ...
- ArcGIS for Desktop入门教程_第三章_Desktop软件安装 - ArcGIS知乎-新一代ArcGIS问答社区
原文:ArcGIS for Desktop入门教程_第三章_Desktop软件安装 - ArcGIS知乎-新一代ArcGIS问答社区 1 软件安装 1.1 安装前准备 请确认已经收到来自Esri中国( ...
- Rust入门篇 (1)
Rust入门篇 声明: 本文是在参考 The Rust Programming Language 和 Rust官方教程 中文版 写的. 个人学习用 再PS. 目录这东东果然是必须的... 找个时间生成 ...
- GEF入门实例_总结_06_为编辑器添加内容
一.前言 本文承接上一节:GEF入门实例_总结_05_显示一个空白编辑器 在上一节我们为我们的插件添加了一个空白的编辑器,这一节我们将为此编辑器添加内容. 二.GEF的MVC模式 在此只简单总结一下, ...
- GEF入门实例_总结_05_显示一个空白编辑器
一.前言 本文承接上一节:GEF入门实例_总结_04_Eclipse插件启动流程分析 在第三节( GEF入门实例_总结_03_显示菜单和工具栏 ),我们创建了菜单和工具栏. 这一节,我们来实现:点击 ...
- GEF入门实例_总结_04_Eclipse插件启动流程分析
一.前言 本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏 注意到app目录下的6个类文件. 这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们 ...
- GEF入门实例_总结_03_显示菜单和工具栏
一.前言 本文承接上一节: GEF入门实例_总结_02_新建初始RCP空项目 这一节,我们来给我们的插件加上菜单. 二.基础知识 1.action bar.menubar.coolbar 含义 a ...
- GEF入门实例_总结_02_新建初始RCP空项目
一.前言 本节承接上一节: GEF入门实例_总结_01_教程.源码.开发环境准备 这一节我们来创建一个空的RCP项目. 二.新建RCP项目 1. New 一个 Plug-in Project 2.输入 ...
- ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区
原文:ArcGIS for Desktop入门教程_第七章_使用ArcGIS进行空间分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 使用ArcGIS进行空间分析 1.1 GIS分析基础 G ...
随机推荐
- js检测页面上一个元素是否已经滚动到了屏幕的可视区域内
应用场景:只要页面加载了,其中在页面中出现的li就向控制台输出第几个发送请求:在本次加载的页面中,再将滚动条滚回前边的li,不再向控制台输出东西,也就是说已经显示过的li,不再向控制台输出东西. &l ...
- Java IO_002.InputStream与OutputStream--字节流对数据的操作(读取与写入)
Java IO之FileInputStream与FileOutputStream对象常用操作 涉及到文件(非文件夹)内容的操作,除了要用到File(见之前文章),另外就必须用到输入流或输出流. 输入流 ...
- javascript实用代码片段
持续积累中~ 拓展原型 Function.prototype.method = function(name, extend) { if(!this.prototype[name]) { this.pr ...
- Java基础(十三)内部类(inner class)
1.内部类是定义在另一个类中的类.使用内部类的原因有: 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据 内部类可以对同一个包中的其他类隐藏起来 当想要定义一个回调函数且不想编写大量代码 ...
- unity UI事件
由于工作需要到持续按键,所以了解了一下unity UI事件,本文主要转载于http://www.cnblogs.com/zou90512/p/3995932.html?utm_source=tuico ...
- malloc面试题目(转) - [C++]
试题4: void GetMemory( char *p ){ p = (char *) malloc( 100 );} void Test( void ) { char *str = NULL; G ...
- Airy Memory 内存清理 + 注册码
链接: https://pan.baidu.com/s/1ZGxDtJBMhrRtBISvL1Lv0w 提取码: ccjs
- SQL 中更新一个表的数据是从另外的表(或者自己本身的表)查询出来的
模板1: update 表1 set 表1.字段1 = ( select 表1字段或者表2字段 from 表2 where 表1主键 = 表2外键 及其他条件 ) where 表1.字段 = ...
- NIO 在Tomcat中的应用
对NIO的理解 个人单方面认为,NIO与BIO的最大区别在于主动和被动,使用BIO的方式需要等待被调用方返回数据,很明显此时调用者是被动的. 举个例子 阻塞IO 假设你是一个胆小又害羞的男孩子,你约了 ...
- Pandas 计算工具介绍
# 导入相关库 import numpy as np import pandas as pd 统计函数 最常见的计算工具莫过于一些统计函数了.首先构建一个包含了用户年龄与收入的 DataFrame i ...