Rust 学习(2)

        

五. 结构体

5.1 结构体定义

struct xxx{}

//定义结构体
#[derive(Debug)]
struct User{
    name:String,
    age:u32,
    active:bool,
}
//元组结构体
#[derive(Debug)]
struct Color(i32, i32, i32);
//空结构体
struct AlwaysEqual;

fn main(){
    let mut user = User{//实例
        name:String::from("john"),
        age:20,
        active:true,
    };
    user.name = String::from("jane");
    user.age = 21;
    println!("{:?}",user);
    //简写语法
    let name = String::from("jane");
    let age = 21;
    let user = User{
        name,
        age,
        active:true,
    };
    println!("{:?}", user);
    //简写语法2
    let user2 = User{
        active:true,
        ..user
    };
    println!("{:?}", user2, );

    //
    let c = Color(1,2,3);
    println!("{:?}",c);

}

5.2 结构体使用

#[derive(Debug)]
struct Demo {
    height: u32,
    width: u32,
}
fn main() {
    let d = Demo {
        height: 10,
        width: 10,
    };
    println!("{:?}", area(&d));//100
}

fn area(d: &Demo) -> u32 {
    d.height * d.width
}

5.3 方法语法

impl. 

所有在 impl 块中定义的函数被称为关联函数;

每个结构体都允许拥有多个 impl 块;

#[derive(Debug)]
struct Demo {
    height: u32,
    width: u32,
}
impl Demo {
    fn area(&self)->u32{
        self.height * self.width
    }
}
fn main() {
    let d = Demo {
        height: 10,
        width: 10,
    };
    println!("{:?}", area(&d));//100
    println!("{:?}", d.area());//100
}

fn area(d: &Demo) -> u32 {
    d.height * d.width
}

六. 枚举和模式匹配

6.1 定义枚举

enum IpAddr {
    IpV4,
    IpV6,
}
//定义枚举
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
fn main() {
    let home = IpAddr::IpV4;
    match home {
        IpAddr::IpV4 => println!("home is ipv4"),
        IpAddr::IpV6 => println!("home is ipv6"),
    }
}

6.2 Option 枚举

Option 是标准库定义的另一个枚举;


#![allow(unused)]
fn main() {
    enum Option<T> {
        Some(T),
        None,
    }
}

Rust 并没有空值,不过它确实拥有一个可以编码存在或不存在概念的枚举。这个枚举是 Option<T>

6.3 match 匹配

fn main() {

    let dice_roll = 9;
    match dice_roll {
        3 => add_fancy_hat(),
        7 => remove_fancy_hat(),
        _ => (),//通配模式和 _ 占位符
    }

    fn add_fancy_hat() {}
    fn remove_fancy_hat() {}
}

if let 获取通过等号分隔的一个模式和一个表达式。它的工作方式与 match 相同,这里的表达式对应 match 而模式则对应第一个分支。

七. 包管理

一个包可以包含多个二进制 crate 项和一个可选的 crate 库

  • Packages): Cargo 的一个功能,它允许你构建、测试和分享 crate。
  • Crates :一个模块的树形结构,它形成了库或二进制项目。
  • 模块Modules)和 use: 允许你控制作用域和路径的私有性。
  • 路径path):一个命名例如结构体、函数或模块等项的方式

7.1 包和crate

一个包中至多 只能 包含一个库 crate(library crate);包中可以包含任意多个二进制 crate(binary crate);包中至少包含一个 crate,无论是库的还是二进制的。

我们用关键字 mod 定义一个模块,指定模块的名字,并用大括号包围模块的主体。

路径有两种形式:

绝对路径absolute path)从 crate 根部开始,以 crate 名或者字面量 crate 开头。

相对路径relative path)从当前模块开始,以 selfsuper 或当前模块的标识符开头。

pub 对外暴露/公用;

使用super 起始的相对路径;

pub fn add_fancy_hat(){}

mod front_of_house{
    pub mod hosting{
        pub fn eat_at_restaurant(){
            println!("Eat at home");
        }
    }
    fn _greeting(){
        println!("Hello from the front of house");
        //super
        super::add_fancy_hat();
    }
}


fn main(){
    //绝对路径
    crate::front_of_house::hosting::eat_at_restaurant();
    //相对路径
    front_of_house::hosting::eat_at_restaurant();
}

use 引入; as 重命名

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {
            println!("add to waitlist");
        }
    }
}
//use
use crate::front_of_house::hosting as host;
pub fn eat_at_restaurant() {
    host::add_to_waitlist();
}

使用pub use 导出重用

引入外部包;

[dependencies]
rand = "0.8.3"

使用{} 引入多个,使用* 引入所有;

文件分割      mod name/fn name
 

八. 数据结构集合

集合指向的数据是储存在堆上的,这意味着数据的数量不必在编译时就已知,并且还可以随着程序的运行增长或缩小。每种集合都有着不同功能和成本;rust 常见的3种集合实现;

vector 允许我们一个挨着一个地储存一系列数量可变的值

字符串string)是字符的集合。我们之前见过 String 类型;

哈希 maphash map)允许我们将值与一个特定的键(key)相关联。这是一个叫做 map 的更通用的数据结构的特定实现。

详细说明:std::collections - Rust

Rust 的集合可以分为四个主要类别:

8.1 vector

fn main() {
    //new vec
    let mut v = Vec::new();
    v.push(1);
    v.push(2);
    println!("{:?}", v);
    let _b = vec![1,2,4];
}

8.2 String

fn main() {
    //new string
    let v = String::new();
    //to string
    let data = "dddd";
    let s = data.to_string(); //String::from(self)
    //push_str
    let mut s = String::from("hello");
    s.push_str(" world"); //
    s.push('!');//push
    println!("{}", s); //hello world!
}

8.3 哈希map

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    println!("{:?}", scores); //{"Yellow": 50, "Blue": 10}

    let teams = vec![String::from("Blue"), String::from("Yellow")];
    let initial_scores = vec![10, 50];
    let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
    println!("{:?}", scores) /*{"Blue": 10, "Yellow": 50}*/;
    //获取值
    println!("{:?}", scores.get(&String::from("Blue")));
    //更新
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 20);
    //没有值时插入
    scores.entry(String::from("Blue")).or_insert(50);
    
    println!("{:?}", scores);

}

九. 错误处理

rust 错误分为可恢复(Result<T, E>)和不可恢复的(panic!);

9.1 不可恢复painc

当出现 panic 时,程序默认会开始 展开unwinding),这意味着 Rust 会回溯栈并清理它遇到的每一个函数的数据,不过这个回溯并清理的过程有很多工作。另一种选择是直接 终止abort),这会不清理数据就退出程序。那么程序所使用的内存需要由操作系统来清理

[profile.release]
panic = 'abort'
 

9.2 可恢复Result!

use std::{fs::File, io::ErrorKind};
fn main() {
    let f: Result<File, std::io::Error> = File::open("hello.txt");
    let _f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => panic!("Problem opening the file: {:?}", other_error),
        },
    };
}

传播错误简介:?运算符 ;错误返回传递->Result<T,E>

十. T/trait/生命周期

泛型是具体类型或其他属性的抽象替代;

trait这是一个定义泛型行为的方法;

生命周期lifetimes)Rust 的生命周期功能允许在很多场景下借用值的同时仍然使编译器能够检查这些引用的有效性。

10.1 范型

Rust 通过在编译时进行泛型代码的 单态化(monomorphization)来保证效率。单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。

10.2 trait

trait 告诉 Rust 编译器某个特定类型拥有可能与其他类型共享的功能。可以通过 trait 以一种抽象的方式定义共享的行为。可以使用 trait bounds 指定泛型是任何拥有特定行为的类型。

#![allow(unused)]
fn main() {
    pub trait Summary {
        fn summarize(&self) -> String {
            String::from("(Read more...)")
        }
    }
}


//trait bound
pub fn notify<T: Summary>(item: T) {
    println!("Breaking news! {}", item.summarize());
}
//多个 trait
pub fn notify(item: impl Summary + Display) {

//T
pub fn notify<T: Summary + Display>(item: T) {

//where
fn some_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
{
}



10.3 生命周期

'xxxx  代表/   'static  代表静态的生命周期;

十一. 自动化测试

让我们看看 Rust 提供的专门用来编写测试的功能:test 属性、一些宏和 should_panic 属性。

11.1 测试编写


fn main() {}
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

使用should_panic 检测异常

fn main() {}
pub struct Guess {
    value: i32,
}

// --snip--

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 {
            panic!("Guess value must be greater than or equal to 1, got {}.",
                   value);
        } else if value > 100 {
            panic!("Guess value must be less than or equal to 100, got {}.",
                   value);
        }

        Guess {
            value
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[should_panic(expected = "Guess value must be less than or equal to 100")]
    fn greater_than_100() {
        Guess::new(200);
    }
}

Result 测试


#![allow(unused)]
fn main() {
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }
}
}

11.2 测试运行

cargo test -- --test-threads=1//并行

cargo test -- --show-output//输出

cargo test one_hundred//制定名字

cargo test -- --ignored //忽略 #[ignore]

十二 I/O 项目(忽略)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值