一. rust 安装;
## 安装
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
## 更新
rustup update
## 查看版本;
rustc --version
rust 版本分3种: 1. stable(稳定的),2. nightly(试验性功能版本),3. Bate(测试)
## 切换版本
rustup override add nightly
## 设置默认版本
rustup default nightly
二. 项目构建
Cargo 是 Rust 的构建系统和包管理器
## 查看版本
cargo --version
## 创建项目
cargo new hello_cargo
## 代码格式化
cargo fmt
## 运行项目
cargo run
## 项目编译
cargo build
cargo build --release //构建发布代码
## 项目检测
cargo check
## 项目单元测试
cargo test
三. 通用编程概念
3.1 变量和可变性
fn main() {
let a = 5; //不可变变量
let mut b = 10; //可变变量;
b = b + 1;
const C: u32 = 10; //定义常量,必须要大写,标注类型;
//rust 遮掩
{
let b = b * b;
println!("b = {}", b); //b = 121
}
println!("a = {} b = {} c = {}", a, b, C); //a = 5 b = 11 c = 10
}
3.2 数据类型
3.2.1 标量类型
rust 有 4 个基本的标量类型:整型、浮点型、布尔型和字符
fn main(){
//整型
let _a:i8 = 1;//8位有符号类型
let _b:u8 = 2;//8位无符号类型
let _c:i16 = 3;//16位有符号类型
let _d:u16 = 4;//16位无符号类型
let _e:i32 = 5;//32位有符号类型
let _f:u32 = 6;//32位无符号类型
let _g:i64 = 7;//64位有符号类型
let _h:u64 = 8;//64位无符号类型
let _i:i128 = 9;//128位有符号类型
let _j:u128 = 10;//128位无符号类型
let _k:isize = 11;//与usize类型一样,是int类型的无符号版本
let _l:usize = 12;//与isize类型一样,是uint类型的无符号版本
//浮点型
let _m:f32 = 13.14;//32位浮点型
let _n:f64 = 14.14;//64位浮点型
//字符类型
let _o:char = 'a';//字符类型
//布尔类型
let _p:bool = true;//布尔类型
}
整型溢出 debug 模式panic 异常,在当使用 --release
参数进行发布(release)模式构建时,Rust 不检测会导致 panic 的整型溢出。会进行二进制补码
3.2.2 复合类型
可以将多个值组合成一个类型。Rust 有两种基本的复合类型:元组(tuple)和数组(array)
fn main() {
let x = (1, 2, "a");//定义元组
let (a, b, _) = x;
println!("{} {} {}", a, b, x.2);//1 2 4
let y = [1, 2, 3, 4, 5];//定义数组
let z = [3; 5];//定义数组 数组里面变量类型必须一直
println!("{:?}", y);//[1, 2, 3, 4, 5]
println!("{:?}", z);//[3, 3, 3, 3, 3]
//取参数
println!("{:?}", y[1]);//2
}
rust 访问不存在的数组元素会报错;
3.3 函数
Rust 代码中的函数和变量名使用下划线命名法(snake case,直译为蛇形命名法)规范风格
语句(statement)是执行一些操作但不返回值的指令。
表达式(expression)计算并产生一个值;
3.4 注释
在 Rust 中,惯用的注释形式以两个斜杆开头,直到该行尾结束。对于超出单行的注释,需要在每行的行首加上 //
注释也可以放在包含代码的行后面:
3.5 控制流
1. if{}else{} 2.while condition{} 3.loop{} 4. for xxx in xxx {}
fn main() {
let number = 5;
//if
if number < 5 {
// 条件必须是bool 值
println!("condition was true");
} else {
println!("condition was false");
}
// let if
let con = true;
let number = if con { 5 } else { 6 };
println!("{}", number); //5
//循环
let mut count = 0;
// while
while count < 10 {
println!("count is {}", count);
count += 1;
}
//loop
let mut count = 0;
'counting_up: loop {
//循环标签 counting_up
println!("count = {}", count);
let mut remaining = 10;
loop {
println!("remaining = {}", remaining);
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up; //外层break;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {}", count);//2
//for
let b = [3;5];
for i in &b {
println!("{}", i);//
}
}
四. 所有权;
Rust 采用所有权机制来保障内存安全,无需垃圾回收器 ;
Rust 通过所有权系统管理内存,编译器在编译时会根据一系列的规则进行检查来避免程序运行时的时间消耗;
所有权规则:
1. 每个值都拥有一个所有者;并且在任何时候有且只有一个所有者;
2. 当值离开作用域,值自动被丢弃;
fn main(){
{//进入作用域
let s = "a";
}//离开作用域 s无效
}
4.1 String 类型
就字符串字面量来说,我们在编译时就知道其内容,所以文本被直接硬编码进最终的可执行文件中。这使得字符串字面量快速且高效;
对于 String
类型,为了支持一个可变,可增长的文本片段,需要在堆上分配一块在编译时未知大小的内存来存放内容。
fn main(){
let a = String::from("value");
//clone
let _e = a.clone();//a 有效,
//move
let _b = a;// a 无效;
let c = "a";
//实现了 copy trait 在编译时已知大小的类型被整个存储在栈上,所以拷贝其实际的值是快速的
let _d = c; //c 有效,
}
copy trait 默认实现(四种基础类型和数组);
4.2 所有权与函数
fn main(){
let s = String::from("hello");
t1(s);// s离开作用域
let s = 2;
t2(s);// s发生cope s依旧有效
}
fn t1(str:String){
println!("{}",str);
}
fn t2(int:i32) {
println!("{}",int);
}
4.3 引用和借用
& 符号就是 引用,它们允许你使用值但不获取其所有权;引用分为可变和不可变引用;
在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
引用必须总是有效的。
4.4 切片类型
没有所有权的数据类型slice;
字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内
fn main(){
let a = "aaddseedd";
//slice
let b = &a[0..4];
println!("{}",b);//aadd
}