Rust 简明笔记
这里仅仅是笔记而已,方便快速查阅,如果还没有阅读官方文档,那么先去参阅一下官方文档吧
传送~~ 走你!!!
官方的Rust程序设计文档:https://doc.rust-lang.org/book/
官方的标准库文档:https://doc.rust-lang.org/std/index.html
官方的各种手册文档:https://www.rust-lang.org/zh-CN/learn
社区的Rust程序设计文档:https://kaisery.github.io/trpl-zh-cn/title-page.html
[目录](./SUMMARY.md)
基础语法篇
安装
linux
$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
MacOS
xcode-select --install
Windows
下载 https://www.rust-lang.org/install.html
需要安装 Build Tools for Visual Studio 2019
运行
主函数
fn main() {
println!("Hello, world!");
}
文件后缀
.rs
编译
$ rustc main.rs
执行
$ main.exe
Cargo管理工具
创建一个项目
cargo new hello_cargo
编译项目
cargo build
运行项目
cargo run
快速检查代码
cargo check
编译发布
cargo build --release
变量
定义一个变量
{% hint style="warning" %} 变量x默认是不可变的,不可以改变变量的值 {% endhint %}
定义一个可以改变值得变量
let mut x = 5;
{% hint style="success" %} 至于变量的类型,是可以自动识别的 {% endhint %}
get一个新操作---变量隐藏
let x = 5
{
let x = "6"
}
{% hint style="info" %} 第二个被let申明的x把第一个x隐藏了
let可以定义重复的变量名称
同时变量的值也是可以改变的
更重要的是,当块{...}执行结束后,外面的x还是5,你说厉害不。厉害了~! {% endhint %}
常量
定义一个常量
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
{% hint style="info" %} 单词大写,下划线链接
冒号后面必须加类型 {% endhint %}
数据类型
变量类型
整型
8-bit | i8 | u8 |
---|---|---|
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
浮点
f32
和 f64
布尔型
bool
char
let c = 'z';
复合类型
元组 tuple
函数
定义
{% hint style="warning" %}
- 表达式结果会直接给res {% endhint %}
注释
使用注释
Page 1
if
loop 死循环
while
for
数组
数组
元素的个数是固定的,元素的类型是相同的
那么如何定义一个二位的数组
遍历数组
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {}", element);
}
}
可变长数组vector
字符串
Rust 的核心语言中只有一种字符串类型:
str
,字符串 slice,它通常以被借用的形式出现,&str
新建字符串
更新字符串
索引字符串
遍历字符串的方法
HashMap
高级进阶篇
description: 待补充
所有权
所有权
- Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
- 值在任一时刻有且只有一个所有者。
- 当所有者(变量)离开作用域,这个值将被丢弃。
实现了copy trait的类型,不会转移所有权
- 所有整数类型,比如
u32
。 - 布尔类型,
bool
,它的值是true
和false
。 - 所有浮点数类型,比如
f64
。 - 字符类型,
char
。 - 元组,当且仅当其包含的类型也都实现
Copy
的时候。比如,(i32, i32)
实现了Copy
,但(i32, String)
就没有。
引用
& 符号就是 引用,它们允许你使用值但不获取其所有权
解引用
* 符号就是解引用
借用
创建一个引用的行为
结构体
定义结构体
使用结构体
fn main() {
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
user1.email = String::from("anotheremail@example.com");
}
结构体嵌套
fn main() {
// --snip--
let user2 = User {
email: String::from("another@example.com"),
..user1
};
}
..
语法指剩余没有指明的字段,来自user1
元组类型结构体
struct Color(i32, i32, i32);
没有任何字段的结构体
结构体实现
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// 关联函数,有点构造函数的意思
fn square(size: u32) -> Rectangle {
Rectangle {
width: size,
height: size,
}
}
// 实现的方法
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
let sq = Rectangle::square(3); // 使用关联函数用 ::
println!(
"The area of the rectangle is {} square pixels.",
rect1.area() // 调用方法用 .
);
}
使用impl实现结构体,可以有多个实现,名称也可以一样
description: 枚举是enums, 匹配是match,Option是一种特殊的枚举,if let是一种特殊的match,说到匹配,这里没有Switch!!!
枚举
enums定义
Option
https://doc.rust-lang.org/std/option/enum.Option.html Option的文档,提供了方法
匹配match
if let
错误处理
示例代码
// 这是一个package的开始
use std::fs::File;
use std::io;
use std::io::Read;
fn main() {
panic!("抛出了一个错误"); //抛出一个错误,程序中断
// enum Result<T, E> {
// Ok(T),
// Err(E),
// }
let f = File::open("hello.txt"); //返回一个Result的enums类型
let _ff = match f { // 没有被使用的变量可以加上下划线前缀 _ff ff没有被使用
Ok(_file) => println!("exits"),
Err(error) => panic!("Problem opening the file: {:?}", error),
};
// unwrap() expect(string) 俩个函数都是如果发生错误就直接panic! 否则返回正确的值,expect则允许传一个字符串作为错误提示
let _f = File::open("hello.txt").unwrap();
let _f = File::open("1.txt").expect("出错了");
let _g = open_file();
}
直接抛出错误
- panic!(“出错了”) - 直接抛出一个错误后,程序中断
- unwrap() - 对于返回类型是Result的结果,返回错误的话就直接panic!了,返回正确的话就得到正确的值
- expect(“出错了”) - 和unwrap一个,区别在于可以传递一个自定义的错误信息
函数返回错误
- 函数返回结果是Result类型的话,可以直接使用?来直接return err,错误信息会传递给Result.
- 这里最后一行结果会默认return给Result
trait
trait限定
Where关键字
fn foo<T: A, K: A + C, B> (a: T, b: K, c: B) {}
优化为:
fn foo<T, K, B> (a: T, b: K, c: B) where T: A, K: A + C {}
where 关键字 用来给泛型T增加trait限定
项目实践篇
description: 自定义一个crate,并发布到crates.io,然后在项目中引用crate
自定义包并发布
1、首先得有个包
创建一个crate库
定义模块以及函数
目录结构如下:
businessfn:
----src
---------arr.rs
---------lib.rs
----.gitignore
----Cargo.lock
----Cargo.toml
----README.md
arr.rs:
/// 获取二维数组的列,返回一个包含该列所有值的一维数组
///
/// # Examples
///
/// ```
/// use businessfn::hello;
///
/// fn main() {
/// hello();
/// }
/// ```
pub fn array_columns() -> i64 {
return 1
}
lib.rs:
Cargo.toml:
编译发布版本
2、其次得做些准备
注册一个github账号并且创建一个businessfn的仓库
注册github账号,点击[走你](https://github.com),自行注册即可,若有账号,继续下一步
创建github公开仓库,自行百度,不再赘述
然后你就有一个类似这样的仓库了 :https://github.com/finewenmu/businessfn
使用ssh-keygen生成本地秘钥。然后配置到github->setting->ssh设置中
这一步也不再细说,自行百度ssh-keygen -t rsa -c "xxx@gmail.com"
在businessfn中绑定你的仓库,并将代码push到仓库中
这一步也不再细说,自行百度git的使用
现在取crates.io注册一下账号,这个账号目前只能是用github授权的方式绑定
创建API token
注册授权登录之后,在个人中心->Account setting->Api Token页面,点击New Token即可生成
3、发布自定义库到Crates.io
本地登录Crates.io账号
打开终端执行命令:
cargo login [token]
// 比如
cargo login xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//提示登录成功
在项目businessfn根目录执行发布
$cargo publish
Updating crates.io index
Packaging businessfn v0.1.0
Verifying businessfn v0.1.0
Compiling businessfn v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 2.06s
Uploading businessfn v0.1.0
4、使用自定义库
创建一个项目
在Cargo.toml添加依赖
在main.rs中使用
use businessfn::hello;
fn main() {
hello();
}
运行
$cargo run
Updating crates.io index
Compiling businessfn v0.1.0
Compiling businessfn_test v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 5.52s
Running `target\debug\businessfn_test.exe`
i num : 1
结束
恭喜!你成功了!庆贺吧!去搓一顿吧!!!
businessfn库
http库
https://hyper.rs/ 用于 Rust 语言的快速且安全的 HTTP
附录
一些函数
dbg!
dbg!
宏会打印到标准错误控制台流(stderr
),与println!
不同,后者会打印到标准输出控制台流(stdout
)。
fn main() {
let scale = 2;
let rect1 = Rectangle {
width: dbg!(30 * scale), // 打印stderr日志,并且返回计算结果
height: 50,
};
dbg!(&rect1); // 打印stderr日志
}
assert_eq!
格式化输出
{}
输出标准数据类型
{:?}
输出复合数据类型
{:#?}
复合类型的格式化输出
知识碎片
Rust
- 语法参考
- cargo管理工具
- rustc编译器
- 标准库
- crate.io库管理
一些问题
{} 和 {:?} 的区别
println!("x is {}", x); // {}指的是任意变量内容 println!("y is {:?}", y);//fmt::Debug:使用 {:?} 标记。格式化文本以供调试使用。{:#?}提供了 “美化打印” 的功能//fmt::Display:使用 {} 标记。以更优雅和友好的风格来格式化文本。
代码块{}的最后表达式加不加分号“;”的区别
let y = { let x_squared = x * x; let x_cube = x_squared * x; // 将此表达式赋给 `y` x_cube + x_squared + x};let z = { // 分号结束了这个表达式,于是将 `()` 赋给 `z` 2 * x;};
给变量赋值()是什么意思
//单元类型(unit type):()。其唯一可能的值就是 () 这个空元组let z = ()
println!() 为啥要加个!号
//println! 是一个宏(macros),可以将文本输出到控制台(console)
Rust的代码文件是以.rs结尾的
$rustc hello.rs
Rust的注释
//rust的注释是// 或者 /*块注释*/
Rust的文档注释
//rust的注释是/// 或者//!
struct Structure(i32) 定义一个结构体
struct Structure(i32) //定义一个元组结构体,包含一个 `i32` 元素// 元组结构体struct Pair(i32, f32);
#![crate_attribute] 是啥意思
#![crate_attribute] //作用在crate的属性#[item_attribute] //作用在模块、项的属性
//属性的格式#[attribute = "value"]#[attribute(key = "value")]#[attribute(value)]
#[allow(dead_code)]啥意思
//死代码,不被调用的代码#[allow(dead_code)]fn unused_function() {}
\
错误检查
error: a bin target must be available for cargo run
cargo run 会找
src/main.rs
或src/bin/*.rs去运行,如果没有这些文文件,只有src/lib.rs,那么可以执行cargo test单元测试即可
国内镜像
修改~/.cargo/config 文件,如果没有就创建
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'tuna'
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
#replace-with = 'ustc'
#[source.ustc]
#registry = "git://mirrors.ustc.edu.cn/crates.io-index"