1. 工具简介
位置是在 ~/.cargo/bin 下面
- rustup 版本控制工具
- rustc 编译命令
- cargo 包管理工具
- rustfmt 自动化格式工具
rustup self uninstall
2. 基本入门
cargo new
==cargo check
创建新的项目,toml
制定了 项目的名称、版本、作者以及要使用的 Rust 版本,dependencies
指定了依赖的版本- 代码包被称为
crates
。也就是库文件 cargo run
构建并运行项目cargo build --release
发布release
文件到target/release
目录下- 变量默认不可变,声明变量使用
let
::new
关联函数,也叫静态方法&
表示这个参数是一个 引用(reference)expect
方法是std::result
的一个方法- 以下为几个常用的库
- use std::io;
- use std::cmp::Ordering;
- use rand::Rng;
- 分支(
arms
)
3. 数据类型
- 标量类型(scalar):类型代表一个单独的值,四种基本的标量类型:整型、浮点型、布尔类型和字符类型
- debug 模式整型溢出会panic,release模式不检出
- isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的。
- 基础数据类型
- 整型
- i8 u8
- i16 u16
- i32 u32
- i64 u64
- i128 u128
- isize usize
- 浮点(默认类型是 f64):
- f32
- f64
- 布尔
- true
- false
- 字符类型(char 由单引号指定,不同于字符串使用双引号 类型的大小为四个字节(four bytes),并代表了一个 Unicode 标量值
- 在 Rust 中,拼音字母(Accented letters),中文、日文、韩文等字符,emoji(绘文字)以及零长度的空白字符都是有效的 char 值。Unicode 标量值包含从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF 在内的值。
- 复合类型
- 元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。模式匹配解构外,也可以使用点号(.)后跟值的索引来直接访问它们
-
let tup: (i32, f64, u8) = (500, 6.4, 1);
-
- 元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。模式匹配解构外,也可以使用点号(.)后跟值的索引来直接访问它们
- 数组类型
- 与元组不同,数组中的每个元素的类型必须相同,因为 Rust 中的数组是固定长度的:一旦声明,它们的长度不能增长或缩小。
- 当你想要在栈(stack)而不是在堆(heap)上为数据分配空间(第四章将讨论栈与堆的更多内容),或者是想要确保总是有固定数量的元素时,数组非常有用。但是数组并不如 vector 类型灵活。vector 类型是标准库提供的一个 允许 增长和缩小长度的类似数组的集合类型。当不确定是应该使用数组还是 vector 的时候,你可能应该使用 vector
- let a = [3; 5];
- let a: [i32; 5] = [1, 2, 3, 4, 5]; 如果我们访问数组结尾之后的元素会发生什么呢?比如你将上面的例子改成下面这样,这可以编译通过,不过在运行时会因错误而退出:
- 整型
4. 函数
- 字母都是小写并使用下划线分隔单词
- 函数定义以 fn 开始并在函数名后跟一对圆括号
- 函数参数
- fn another_function(x: i32)
- 我们用来创建新作用域的大括号(代码块),{},也是一个表达式
- 表达式不带分号,携带分号的是语句
5. 表达式
- if 表达式 后面没有括号
- loop、while 和 for。
6. 所有权(ownership)
- 无需垃圾回收(garbage collector)即可保障内存安全
6.1. 栈(Stack)与堆(Heap)
- 入栈比在堆上分配内存要快,因为(入栈时)操作系统无需为存储新数据去搜索内存空间;其位置总是在栈顶。
6.2. 所有权规则
-
Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
-
值在任一时刻有且只有一个所有者。
-
当所有者(变量)离开作用域,这个值将被丢弃。
-
所以能够存储在编译时未知大小的文本。可以使用 from 函数基于字符串字面值来创建 String
-
s 离开作用域的时候。当变量离开作用域,Rust 为我们调用一个特殊的函数。这个函数叫做 drop
-
字符串拷贝是移动,是浅拷贝,拷贝完了会被释放,深度拷贝是clone
-
如果是简单标量,是可以直接等于的,如果是需要分配内存的,是不可以直接等于的,如果等于的话所有权释放
-
引用可以规避作用域,符号为 & 解引用为 *
-
一个作用域只能有一个可变应用,编译时就避免数据竞争
-
不能在拥有不可变引用的同时拥有可变引用
-
悬垂引用(Dangling References)所谓悬垂指针是其指向的内存可能已经被分配给其它持有者
6.2.1. 所有权原则
- 在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
- 引用必须总是有效的。
6.3. slice
- 字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内
7. 结构体
- 添加trait #[derive(Debug)]
- 关联函数不同于方法不 以 self 作为参数的函数,每个结构体都允许拥有多个 impl 块。
8. 枚举
- 示例 enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), }
- option 用来表示None值所需 enum Option { Some(T), None, }
9. 方法式编程
- 闭包(Closures),一个可以储存在变量里的类似函数的结构
- 迭代器(Iterators),一种处理元素序列的方式