cargo new xxx;cargo build;cargo run;cargo check(检查语法)
执行的文件在target的debug内
变量
mut 可变变量
隐藏,在同一个代码段同名变量定义时具有隐藏性,即第二次定义后使用的是使用的第二次定义的类型,将第一次定义的变量隐藏
const 定义常量: const MAXX:u32 = 10000;
数据类型(编译器具有自动推导功能,不必须写上变量类型)
bool型
char型在rust语言里面是32位的!char可以是一个汉字
i8 i16 i32 i64 u8 u16 u32 u64 f32 f64
自适应类型(与机器平台有关系) isize usize println!("max = {}",usize::max_value());
数组 [Type; size] size也是数组类型的一部分
let arr: [u32; 5] = [1,2,3,4,5];
show(arr);  // 这里会报错,因为size不一致而size也是数组类型的一个部分
fn show(arr:[u32;3]){
    for i in &arr{
        println!("{}",i);
    }
}
元组 复合类型
let tup: (i32,f32,char) = (-3,3.69,‘赞‘);
println!("{}",tup.0);
println!("{}",tup.1);
println!("{}",tup.2);
let tup = (-3,3.69,‘赞‘); //自动推导
//元组可拆解
let (x,y,z) = tup;
println!("{}",x);
函数 蛇形命名法 常量大写字母 类的首字母大写 一般函数等用小写字母
fn other_fun(){
	println!("This is a function!");
}
fn other_fun1(a:i32,b:u32){
    println!("a = {},b = {}",a,b);
}
fn other_fun2(a:i32,b:i32) -> i32{
    let result = a + b;
    return result;
}
fn other_fun3(a:i32,b:i32) -> i32{
    a + b
}
函数定义的时候传入的变量需要有类型
语句 执行操作 但是不返回值得指令
let y = 1; //语句,不返回值
let x = (let y = 1);  //错误的,因为无返回值,与C++不一样
表达式 会计算一些值
let y = {
	let x = 1;
    x + 1; //错误 无发返回
	x + 1 //正确,输出y为2
}
控制流
? println!("y==other");
if y == 1 {
	println!("y==1");
}else{
    println!("y!=1");
}
if y == 1 {
	println!("y==1");
}else if y == 0{
    println!("y==0");
}else{
    println!("y==other");
}
let中也可以使用if,且if else中得类型应该保持一致
let condition = true;
let x = if condition{
	5
}else{
	6
};
println!("{}",x);
loop loop 也可以赋值给let
let mut counter = 0;
loop{
	println!("loop");
	if counter == 10{
		break;
	}
	counter = counter + 1;
}
let mut c = 1;
let result = loop{
    c += 1;
    if c == 20{
        break c * 2;
    }
};
println!("{}",result); //result为40
while 循环
let mut i = 0;
while i !=10 {
	i += 1;
}
println!("i={}",i);
for 循环
let arr:[u32;5] = [1,2,3,4,5];
//用迭代器
for element in &arr{
	println!("element={}",element);
}
所有权
堆和栈
编译的时候数据的类型大小是固定的,就是分配在栈上的
编译的时候数据的类型大小不是固定的,就是分配在堆上的
作用域: {}
let x:i32 = 1;
{
	let y:i32 = 2;
	println!("{}",x);
}
println!("{}",y);
// y的作用域在{}之内,因此下面无法访问到y的值
借用/移动
let s1 = String::from("abc");
let s2 = s1;
println!("{}",s1);//报错
类似于C++中的浅拷贝,只是对指针复制,没有对指针所指的区域的进行复制
RUST中拷贝后默认s1无效,即s1的所有权移植给了s2,因此s1处于空,无效状态
同时RUST中string存在内存回收,在离开作用域时会自动调用drop完成内存的回收操作,类似于类的析构
clone/深拷贝
let s1 = String:from("abc");
let s2 = s1.clone();
再访问s1可以访问,clone可以拷贝数据即进行深拷贝
栈上的数据拷贝
let a = 1;
let b = a;
println!("a = {} , b = {}",a,b);
在栈上的数据执行等号的时候默认进行copy(相当于深拷贝)
类似于C++中int char等相等之后也可以用,但是class类需要自定义深拷贝clone函数
常用的具有copy trait有
所有的整型 浮点型 布尔型 字符类型(char) 元组 数组
函数和作用域
fn fun(some_string: String){
    println!("{}",some_string);
}
fn fun2(i:i32){
    println!("i = {}",i);
}
fn main(){
    let s = String::from("hello");
    fun(s);
    println!("{}",s);//报错 S已经在离开作用域的时候被drop回收了
    let x = 5;
    fun2(x);
    println!("{}",x); //可以使用,x分配在栈上,是直接进行copy而不是clone
}
引用和借用
fn main(){
	let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
    
    println!("Hello world!");
}
fn gives_ownership() -> String {
    let s = String::from("hello");
    s
}
fn takes_and_gives_back(s: String) -> String {
    s
}
因为是调用gives_ownership函数,因此调用后将s的作用域返回给s1
因为s2的使用权将传递给s3,所以如果在最后再次调用s2会发现无法使用
会发现上面十分麻烦,所以RUST中存在了引用这个功能
// 引用: 用法&,
// 让我们创建一个指向值的应用,但是并不拥有它,因为不拥有这个值,所以,当引用离开其值指向的作用域后也不会被丢弃
// 借用:&mut
fn length(s: &String) -> usize{
    s.len()
}
fn modify_s(s: &mut String){
    s.push_str(",world");
}
fn main(){
    let mut s1 = String::from("hello");
    let len = length(&s1);
    let s = &s1;
    println!("s = {}",s);
    println!("s1 = {}",s1);
    println!("len = {}",len);
    modify_s(&mut s1);
    println!("s1 = {}",s1);
}
引用无法对值进行修改,只是可以去完成访问,如果需要修改一类操作,需要借用
RUST推荐每个变量只有一个数据拥有权(引用or借用),即不可变引用和可变借用不可以针对于同一个变量同时存在,也就是可读和可读可写不能同时存在
但是当我对其中某一个运用完后可以调用另外一个,即可变以后要重新去进行借用,示例代码如下
fn main(){
    let mut s = String::from("hello");
    let s1 = &s;
    println!("{}",s1);
    let s2 = &mut s;
    s2.push_str(",world!");
    println!("{}",s2);
}
泉水引用 Wrong
fn main(){
	let ref_s = dangle();
}
fn bcyx() -> &String{
	let s = String::from("hello");
	&s 
}
作用域在函数内回收掉了,但是引用仍然指向内存,并且返回引用,会报错
slice
let s = String::from("hello world!");
let h = &s[0..5];
let h = &s[..5];
let h = &s[0..=4];
let h = &s[..=4];
let w = &s[6..];//第六位到结尾
let a = [1,2,3,4];
let sss = &a[1..3];
println!("sss1 = {}",sss[0]);
println!("h = {}",h); //输出hello 上面四个情况均一致
结构体
定义结构体
 #[derive(Debug)]
    struct User {
        name: String,
        count:String,
        nonce: u64,
        active: bool,
    }
创建结构体实例
    let xiaoming = User {
        name: String::from("xiaoming"),
        count: String::from("80001000"),
        nonce: 10000,
        active:true,
    };
    println!("xiaoming = {:?}", xiaoming);//横着打出来
    println!("xiaoming = {:#?}", xiaoming);//结构体
修改结构体字段
    let mut xiaohuang = User {
        name: String::from("xiaohuang"),
        count: String::from("80001000"),
        nonce: 10000,
        active:true,
    };
	xiaohuang.nonce = 20000;
参数名字和字段名字同名的简写方法
let name = String::from("xiaoxiao");
let count = String::from("89077777");
let nonce = 200000;
let active = false;
let user1 = User {
    name,
    count,
    nonce,
    active,
};
从其他结构体创建实例
let user2 = User {
    name: String::from("user2"),
    ..user1
};
println!("name = {}", user2.name);
println!("nonce = {}", user2.nonce);
元组结构体
//(1)字段没有名字直接.0和.1等
//(2)圆括号
struct Point(i32, i32);
let a = Point(10, 20);
let b = Point(30, 11);
println!("a.x = {}, a.y = {}", a.0, a.1);
没有任何字段的类单元结构体
struct A{};
打印结构体
//结构体前添加  #[derive(Debug)]
# [derive(Debug)]
println!("xiaoming = {:?}",xiaoming); //横着打印出来
println!("xiaoming = {:#?}",xiaoming) //自动换行打印
方法
# [derive(Debug)]
struct Dog {
    name: String,
    weight: f32,
    height: f32,
}
//简单理解成C++中的类函数
impl Dog {
    fn get_name(&self) -> &str {
        &(self.name[..])
    }
    fn get_weight(&self) -> f32 {
        self.weight
    }
    //fn get_height(&self) -> f32 {
    //    self.height
    //}
    fn show() {
        println!("oh oh oh");
    }
}
impl Dog{
    fn get_height(&self) -> f32 {
        self.height
    }
}
fn main() {
    let dog = Dog {
        name: String::from("wangcai"),
        weight: 100.0,
        height: 70.5,
    };
    println!("dog = {:#?}", dog);
    println!("name = {}", dog.get_name());
    println!("weight = {}", dog.get_weight());
    println!("height = {}", dog.get_height());
    Dog::show();
    println!("Hello, world!");
}
枚举类型与模式匹配
//1、类似于c语言的方式定义
enum IpAddrKind {
    V4,
    V6,
}
struct IpAddr {
    kind: IpAddrKind,
    address: String,
}
//2、rust语言提倡的方式定义
enum IpAddr2 {
    V4(String),
    V6(String),
}
//3、可以是不同类型
enum IpAddr3 {
    V4(u8, u8, u8, u8),
    V6(String),
}
//4、经典用法
enum Message {
    Quit,
    Move{x: i32, y: i32},
    Write(String),
    Change(i32, i32, i32),
}
//等同于
//struct QuitMessage; //类单元结构体
//struct MoveMessage {
//  x: i32,
//  y: i32,
//}
//struct WriteMessage(String) 
//struct Change(i32, i32, i32)
//5、枚举类型的方法以及match
impl Message {
    fn prin(&self) {
        match *self {
            Message::Quit => println!("Quit"),
            Message::Move{x, y} => println!("Move x = {}, y = {}", x, y),
            Message::Change(a, b, c) => println!("Change a = {}, b = {}, c = {}", a, b, c),
            _ => println!("Write")
            //Message::Write(&s) => println!("Write = {}", s)
        }
    }
}
fn main() {
    let i1 = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };
    let i2 = IpAddr {
        kind: IpAddrKind::V6,
        address: String::from("::1"),
    };
    let i1 = IpAddr2::V4(String::from("127.0.0.1"));
    let i2 = IpAddr2::V6(String::from("::1"));
    let i1 = IpAddr3::V4(127, 0, 0, 1);
    let i2 = IpAddr3::V6(String::from("::1"));
    let quit = Message::Quit;
    quit.prin();
    let mo = Message::Move{x: 10, y: 20};
    mo.prin();
    let wri = Message::Write(String::from("Hello"));
    wri.prin();
    let change = Message::Change(1, 2, 3);
    change.prin();
    println!("Hello, world!");
}
Option
option是标准库定义的一个枚举类型
match一定要处理完Option中所有的情况
enum Option<T> {
	Some(T),
	None,
}
fn main(){
    let some_number = Some(5);
    let some_string = Some(String::from("123"));
    let absent_number: Option<i32> = None;
    
    let x:i32 = 5;
    let y:Option<i32> = Some(5);
    let mut temp:i32 = 0 
    // let sum = x + y; x和y不是同一个类型
    match y{
        Some(i) => {temp = i ;}
        None => {println!("No");}
    }
    let sum = x + temp;
    let result = plus_one(y);
    match result {
        Some(i) => println!("result = {}", i),
        None => println!("nothing"),
    };
    println!("sum = {}",sum);
    if let Some(value) = plus_one(y) {
        println!("value = {}", value);
    }
    
    if let Some(value) = plus_one(y) {
        println!("value = {}", value);
    } else {
        println!("do nothing");
    }
}
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(x) => Some(x+1),
    }
}
Vector
fn main(){
    // 1. 创建空的vector
    let mut v:Vec<i32> = Vec::new();
    v.push(1);
    // 2. 创建包含初始值的vector
    let v = vec![1,2,3];
    // 3. 丢弃vector
    {
        let v1 = vec![1,2,3];
    }
    // 4. 读取元素
    let one: &i32 = &v[1];
    println!("{}",one);
    println!("{}",*one);
    //上面这两种输出的形式一样 应该是存在自动转换功能
    
    match v.get(1){
        Some(Value) => println!("value = {}",value),
        _ => None,
    }
    // 5. 更新
    let mut v2:Vec<i32> = Vec::new();
    v2.push(1);
    v2.push(2);
    v2.push(3);
    // 6. 遍历
    // 不可变的遍历
    for i in &v2{
        println!("{}",i);
    }
    // 可变的遍历
    for i in &mut v2{
        *i += 1;
        println!("{}",i);
    }
    // 7. 使用枚举
    enum Context {
        Text(String),
        Float(f32),
        Int(i32),
    };
    let c = vec![
        Context::Text(String::from("string")),
        Context::Int(-1),
        Context::Float(0.001)
    ];
    
    // 8. 补充
    let mut v = vec![1, 2, 3, 4, 5];
    let first = &v[0];
    
    v.push(6);
    //报错!!!!
    //不可变引用后使用可变引用不能再使用不可变引用了!!!!
    println!("first = {}", first);
    println!("Hello, world!");
}
String
//1、创建一个空String
//2、通过字面值创建一个String
//2.1、使用String::from()
//2.2、使用str的方式
//3、更新String
//3.1、push_str
//3.2、push
//3.3、使用“+”合并字符串
//3.4、使用format!
//4、String 索引
//5、str 索引
//6、遍历
//6.1、chars
//6.2、bytes
fn main() {
    let mut s0 = String::new();
    s0.push_str("hello");
    println!("s0 = {}", s0);
    let s1 = String::from("init some thing");
    println!("{}", s1);
    let s1 = "init some thing".to_string();
    println!("{}", s1);
    let mut s2 = String::from("hello");
    s2.push_str(", world");
    let ss = " !".to_string();
    s2.push_str(&ss);//用ss的引用
    println!("{}", s2);
    println!("ss = {}", ss);
    let mut s2 = String::from("tea");
    s2.push(‘m‘);
    //s2.push(‘mx‘); //error
    //s2.push("x");  //error
    println!("{}", s2);
    let s1 = "hello".to_string();
    let s2 = String::from(", world");
    let s3 = s1 + &s2;
    println!("s3 = {}", s3);
    //println!("s1 = {}", s1);
    println!("s2 = {}", s2);
    let s341 = String::from("tic");
    let s342 = String::from("tac");
    let s343 = String::from("toe");
    let s344 = format!("{}-{}-{}", s341, s342, s343); //format!和println!类似
    println!("s344 = {}", s344);
    println!("s341 = {}", s341);
    println!("s342 = {}", s342);
    println!("s343 = {}", s343);
    let s4 = String::from("hello");
    //let s41 = s4[0];
    println!("s4.len = {}", s4.len());
    
    let s4 = String::from("你好");
    println!("s4.len = {}", s4.len());
    //let s41 = s4[0];
    let hello = "你好";
    let h5 = &hello[0..3];
    println!("h5 = {}", h5);
    //let h6 = &hello[0..2];
    //println!("h6 = {}", h6);
    //chars
    for c in s4.chars() {
        println!("c = {}", c);
    }
    println!("+++++++++++++++");
    //bytes
    for b in s4.bytes() {
        println!("b = {}", b);
    }
    println!("+++++++++++++++");
    println!("Hello, world!");
}
HashMap
//1、HashMap<K, V>
//2、创建HashMap
//3、读取
//4、遍历
//5、更新
use std::collections::HashMap;
fn main() {
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Red"), 20);
    let keys = vec![String::from("Blue"), String::from("Red")];
    let values = vec![10, 20];
    let scores: HashMap<_, _> = keys.iter().zip(values.iter()).collect();
    let k = String::from("Blue");
    if let Some(v) = scores.get(&k) { //get 返回的是一个Option
        println!("v = {}", v);
    }
    let k = String::from("Yellow");
    let v = scores.get(&k);
    match v {
        Some(value) => println!("v = {}", value),
        None => println!("None"),
    }
    println!("++++++++++++");
    //遍历:会以任意的顺序遍历出来
    for (key, value) in &scores {
        println!("{}, {}", key, value);
    }
    println!("++++++++++++");
    //直接插入
    let mut ss = HashMap::new();
    ss.insert(String::from("one"), 1);
    ss.insert(String::from("two"), 2);
    ss.insert(String::from("three"), 3);
    ss.insert(String::from("one"), 3);//覆盖前者
    println!("{:?}", ss);
    //键不存在的时候才插入
    let mut ss1 = HashMap::new();
    ss1.insert(String::from("one"), 1);
    ss1.insert(String::from("two"), 2);
    ss1.insert(String::from("three"), 3);
    ss1.entry(String::from("one")).or_insert(3);
    println!("ss1 = {:?}", ss1);
    //根据旧值来更新一个值
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("map = {:?}", map);
    println!("Hello, world!");
}
模块
定义
包和crate
mod factory {
    pub mod produce_refrigerator {
        pub fn produce_re() {
            println!("produce refrigerator!");
        }
    }
    mod produce_washing_machine {
        fn produce_washing() {
            println!("produce washing machine!");
        }
    }
}
fn main() {
    factory::produce_refrigerator::produce_re();
    println!("Hello, world!");
}
模块2
创建好的项目里cargo new --lib mylib
//factory.rs
pub mod produce_refrigerator {
    pub fn produce_re() {
        println!("produce refrigerator!");
    }
}
pub mod produce_washing_machine {
    pub fn produce_washing() {
        println!("produce washing machine!");
    }
    pub fn produce_re() {
        println!("produce washing machine!");
    }
}
//lib.rs
pub mod factory;
先在main的cargo里面添加
[dependencies]
mylib = {path = "./mylib"}
在main.rs中利用
//use mylib::factory::produce_refrigerator;
//use mylib::factory::produce_refrigerator::produce_re;
//use mylib::factory::produce_washing_machine;
//use mylib::factory::produce_washing_machine as A;
use mylib::factory::*;
fn main() {
    mylib::factory::produce_refrigerator::produce_re(); //绝对路径
    produce_refrigerator::produce_re();  //使用use
    produce_washing_machine::produce_re();
    //A::produce_re();
    println!("Hello, world!");
}
模块3
mod modA {
    #[derive(Debug)]
    pub struct A {
        pub number: i32,
        name: String,
    }
    impl A {
        pub fn new_a() -> A {
            A {
                number: 1,
                name: String::from("A"),
            }
        }
        pub fn print_a(&self) {
            println!("number: {}, name: {}", self.number, self.name);
        }
    }
    pub mod modB {
        pub fn print_B() {
            println!("B");
        }
        pub mod modC {
            pub fn print_C() {
                println!("C");
                super::print_B();
            }
        }
    }
}
//use modA::A;
use modA::A as A1;
fn main() {
    //let a = modA::A::new_a();
    //let a = A::new_a();
    let a = A1::new_a();
    a.print_a();
    let number = a.number;
    //let name = a.name;
    println!("+++++++++++++");
    modA::modB::modC::print_C();
    println!("Hello, world!");
}
模块4
错误1
//1、rust语言将错误分为两个类别:可恢复错误和不可恢复错误
//(1)可恢复错误通常代表向用户报告错误和重试操作是合理的情况,例如未找到文件。rust中使用Result<T,E>来实现。
//(2)不可恢复错误是bug的同义词,如尝试访问超过数组结尾的位置。rust中通过panic!来实现。
//2、panic!
//3、使用BACKTRACE=1
//4、Result<T, E>
//enum Result<T, E> {
//  Ok(T),
//  Err(E),
//}
//5、简写
use std::fs::File;
fn main() {
    //let f = File::open("hello.txt");
    //let r = match f {
    //    Ok(file) => file,
    //    Err(error) => panic!("error: {:?}", error),
    //};
    //let f = File::open("hello.txt").unwrap();
    let f = File::open("hello.txt").expect("Failed to open hello.txt");
    //panic!("crash here");
}
错误2
//1、当编写一个函数,但是该函数可能会失败,此时除了在函数中处理错误外,还可以将错误传给调用者,让调用者决定如何处理,这被称为传播错误。
//2、传播错误的简写方式,提倡的方式
//3、更进一步的简写
//4、什么时候用panic!,什么时候用Result
//(1)示例、代码原型、测试用panic!\unwrap\expect
//(2)实际项目中应该用Result
//5、Option和Result
use std::io;
use std::io::Read;
use std::fs::File;
fn main() {
    println!("Hello, world!");
    let r = read_username_from_file();
    match r {
        Ok(s) => println!("s = {}", s),
        Err(e) => println!("err = {:?}", e),
    }
}
//fn read_username_from_file() -> Result<String, io::Error> {
//    let f = File::open("hello.txt");
//    let mut f = match f {
//        Ok(file) => file,
//        Err(error) => return Err(error),
//    };
//
//    let mut s = String::new();
//    match f.read_to_string(&mut s) {
//        Ok(_) => Ok(s),
//        Err(error) => Err(error),
//    }
//}
//
//fn read_username_from_file() -> Result<String, io::Error> {
//    let mut f = File::open("hello.txt")?;
//
//    let mut s = String::new();
//    f.read_to_string(&mut s)?;
//    Ok(s)
//}
fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
    Ok(s)
}
原文:https://www.cnblogs.com/buchiyexiao/p/14644505.html