Rust语言开发

Rust开发

碳达峰、碳中和政策下,开发者可以考虑采用 Rust 为节能做贡献。

第一个程序 
fn main() {
    println!("Hello, world!");  // 带!号的都是宏 并不是函数
}

fn main() {
    let name = "peter";
    println!("{}{}","Hello, world!", name);
}

cargo new projectname // 创建一个rust项目
cargo build  // 构建程序为可执行程序
cargo run  // 运行构建好的可执行程序


  • 创建自定义函数

#![allow(non_snake_case)]
fn main() {
    let name = "peter";
    println!("{}{}","Hello, world!", name);
    show_me()
}


fn show_me() {
    let name = "peter";
    let age = 21;
    println!("my name is {}, age is {}", name, age)
}

  • 创建模块 使用模块
#![allow(non_snake_case)]
fn main() {
    let name = "peter";
    println!("{}{}","Hello, world!", name);
    lib::show_me()  // 引用模块内的函数 ::
}

mod lib {
  // pub声明函数是公有地 可以使用 模块进行调用函数执行
    pub fn show_me() {
        let name = "peter";
        let age = 21;
        println!("my name is {}, age is {}", name, age)
    }
}



  • 函数传参 定义str类型 int i32 i64 类型
#![allow(non_snake_case)]


fn main() {
    let name = "peter";
    println!("{}{}","Hello, world!", name);
    // lib::show_me();
    let uid = 101;
    println!("{}", get_user(uid))
}


// &'static str 声明str类型
// i64 i32 声明int类型 
fn get_user(uid:i64) -> &'static str {
    return if uid == 101 {
        "root"
    } else if uid == 102 {
        "$pub"
    } else {
        "error"
    }
}

上边的写法 可以换成下方这种

#![allow(non_snake_case)]


fn main() {
    let name = "peter";
    println!("{}{}","Hello, world!", name);
    // lib::show_me();
    let uid = 101;
    println!("{}", get_user(uid));

}


fn get_user(uid:i64) -> &'static str {

    let ret = if uid == 101 {
        "root"
    } else if uid == 102 {
        "$pub"
    } else {
        "error"
    };
    ret
}
  • if 的高阶写法

    let age = 2;
    let new_age = if age == 2 {
        5
    }else {
        10
    };

    println!("{}", age)

  • for 循环

    // .chars 将字符串类型转换为可迭代对象iter
    for i in text.chars(){
        println!("{}",i);
    };

  • switch 写法 =>match
    // rust中的switch写法match
    match text.len() {
        // 如果长度等于4 打印ok
        4 => println!("ok!"),
      	// 1..=3是[1,2,3] 全部闭合        
      	//1..3 是[1,2] 左开右闭合
        // 如果text长度在5-20之间打印normal 
        5..=20 => println!("normal"),
        // _ 否则
        _ => println!("sorry"),
    };

  • string 堆栈
// 考虑下面这段代码  在内存的角度发生了什么?

let name = String::from("abc");


abc的ptr            0  a
abc的len            1  b
abc的cap						 2  c

  堆                 栈

堆放具体的数据   栈存在数据的地址及数据的基本信息(长度, 容量, 内存地址)
语言的垃圾回收 回收的是堆   
栈存放的主要是函数之类的 调用完自动回收 无需使用语言的垃圾回收器回收

RUST 常见的符号 
:? -> debug
:o -> 8进制数
:x -> lower 小写16进制数
:X -> upper 大写16进制数
:p -> Pointer 指针
:b -> Binary  二进制

例子 :
    let test = String::from("abc");
    // 打印内存地址
    println!("{:p}", test.as_ptr())




  • 所有者 (rust语言很重要的特性ownership)
// 注: 所有者有且只能有一个


// 这个me就是String的所有者ownership
let me = String::from("abc");


// 例如 将me赋值给you  me变量将失去所有String的权利属性  you将获得所有权变为所有者
let me = String::from("123");
let you = me;

// 解决这种问题 
// 1.可以使用me.clone() 将堆栈复制开辟新的内存空间
let you = me.clone();
// 2.可以使用&me引用的方式, 这种方式you 就是me的所有者 me就是String的所有者  
let you = &me;



// 如果使用下面的是没有问题的&str不是string 执行String才会有所有权的问题
let me = "123";
let you = me; 


  • 所有者理解
#![allow(non_snake_case)]

fn show_len(s: &String) { // &传入指针 就不会出现所有者 转移的情况
    println!("{}", s.len())
}


pub fn test() {

    let test = String::from("abc");
    show_len(&test);  // 这里如果传入的不是指针 就相当于let s = test; 所有者转移 后边的内存地址是打印不出来的

    // 打印内存地址
    println!("{:p}", test.as_ptr())

}


// 所以在进行函数传参时 除非这个参数后边不在用了只给函数用了 否则我们要传指针&类型 
  • 可变参数 mut
// 上述的参数都不是可变参数定义之后不可修改 声明可变参数关键词为mut
#![allow(non_snake_case)]

fn show_len(s: &mut String) { // &传入指针 就不会出现所有者 转移的情况
    println!("{}", s.len());
    s.push_str("123")
}


pub fn test() {

    let mut test = String::from("abc");
    show_len(&mut test);  // 这里如果传入的不是指针 就相当于let s = test; 所有者转移 后边的内存地址是打印不出来的

    // 打印内存地址
    println!("{:p} {}", test.as_ptr(), test)
    
}


  • 结构体 struct
struct User{
    name: String,
    age: i64
}

    let user = User{name:String::from("zhangJiAn"), age: 123};

  • Sturct 定义方法进行面向对象
// 相当于go中的 func (this *User) getUser() {}

#[derive(Debug)]
struct User{
    name: String,
    age: u8
}

// 实现方法的关键词impl
impl User{
    fn version(&self){
        println!("测试rust中的方法面向对象");
    }
    fn to_String(&self) -> String{
        format!("{}{}", self.name, self.age)
    }
}



    let user = User{name:String::from("zhangJiAn"), age: 123};
    println!("{:?}", user);
		// User { name: "zhangJiAn", age: 123 }
    user.version();
		// 测试rust中的方法面向对象
    println!("{}", user.to_String())
		// zhangJiAn123
  • 数组
    // 同let me: &str = "fgag"
		// let tags = ["python", "vue", "js", "golang", "rust"];
    let tags: [&str; 5] = ["python", "vue", "js", "golang", "rust"];
		
    for i in tags {
        println!("{}", i)
    }

  • 创建空数组 , 并赋值
    let mut tags: [u8; 10] = [0;10];
    for item in 0..tags.len() {
        tags[item] = item as u8;
    }
    println!("{:?}", tags)



  • 元祖
    let tags: (&str, i32) = ("", 10);
    println!("{:?}",tags)
		// ("", 10)

  • rust 泛型

// 泛型就是 一个函数中传形参的时候 我可以 传入不同类型的参数 给形参 
// 这个形参的类型 由我引用的的时候自己指定即可

// model/user_model.rs
#[derive(Debug)]
pub struct UserScore <A,B>{
    pub user_id: A,
    pub score: B,
    pub comment: &'static str,
}

pub fn get_user_score_first() -> UserScore<i32, i32> {

    UserScore {
        user_id: 1,
        score: 90,
        comment: "A类用户",
    }
}

// 泛型的关键  就在这 可以允许传入不同的类型的A,B  例如 [int, str, bool] and [str, float, bool] 可以提取出bool
// UserScore中有了泛型  impl中也需要标明泛型A,B
impl <A,B> UserScore<A,B> {
    pub(crate) fn get_uid(&self) -> &'static str {
        &self.comment
    }
}

pub fn get_user_score_second() -> UserScore<&'static str, f32> {

    UserScore {
        user_id: "xxx111100",
        score: 90.0,
        comment: "B类用户",
    }
}


// model/mod.rs
pub mod user_model;


// main.rs
    let mut score = model::user_model::get_user_score_first();
    score.score = 10;
    println!("{:?}", score.get_uid());

    let score = model::user_model::get_user_score_second();
    println!("{:?}", score.get_uid());
		// "A类用户"
		// "B类用户"

  • trait 共享行为 (接口设计)

trait 类似于java中的抽象类 将公共的方法抽离出来 可以被子类继承


// api/prods.rs 
use crate::model::book_model::Book;

// 定义好公共函数
pub trait Prods {
    fn get_price(&self) -> f32 ;
}

// 在需要使用公共函数的方法中 实现这个 函数方法 即可
impl Prods for Book {
    fn get_price(&self) -> f32 {
        &self.price + 10.0
    }
}


// model/book_model.rs

#[derive(Debug)]
pub struct Book {
    pub id: i32,
    pub price: f32
}

pub fn new_book(id: i32, price: f32) -> Book {
    Book{
        id,
        price,
    }
}

main.rs

    let book = model::book_model::new_book(1, 99.9);
    println!("{:?}", book.get_price())
		// 109.9

  • trait 简便实例化函数
// model/book_model.rs
#[derive(Debug)]
pub struct Book {
    pub id: i32,
    pub price: f32
}

// api/prods.rs
use crate::model::book_model::Book;

// 定义好公共函数
pub trait Prods {
    fn new(id: i32, price: f32) -> Self;
    fn get_price(&self) -> f32 ;
}

// 在需要使用公共函数的方法中 实现这个 函数方法 即可  (基于Book结构体实现的Prods trait实现的方法)
impl Prods for Book {
    // 基于trait实现的方法可以直接 通过方法实例化
    fn new(id: i32, price: f32) -> Book {
        Book{
            id,
            price
        }
    }
    fn get_price(&self) -> f32 {
        &self.price + 10.0
    }
}


// main.rs
    // 这样使用需要 声明book 所对应实现的struct结构体
    let book: Book = api::prods::Prods::new(2, 88.8);
    println!("{:?}", book.get_price())
		// 98.8




  • 在函数中传递两个trait
// api/prods.rs
use crate::model::book_model::Book;
use crate::model::iphone_model::Phone;

// 定义好公共函数
pub trait Prods {
    fn new(id: i32, price: f32) -> Self;
    fn get_price(&self) -> f32 ;
}


// 在需要使用公共函数的方法中 实现这个 函数方法 即可  (基于Book结构体实现的Prods trait实现的方法)
impl Prods for Book {
    // 基于trait实现的方法可以直接 通过方法实例化
    fn new(id: i32, price: f32) -> Book {
        Book{
            id,
            price
        }
    }
    fn get_price(&self) -> f32 {
        &self.price + 10.0
    }
}

impl Prods for Phone {
    fn new(id: i32, price: f32) -> Self {
        Self {
            id,
            price
        }
    }

    fn get_price(&self) -> f32 {
        &self.price + 22.0
    }
}


// main.rs
    let book: Book = api::prods::Prods::new(2, 88.8);
    let iphone: Phone = api::prods::Prods::new(3, 1500.5);

    sum(book, iphone);
		// 商品总价为1621.3

// 传入两个trait的泛型声明
fn sum<T: Prods, U: Prods>(p1: T, p2: U) {
    println!("商品总价为{}", p1.get_price()+ p2.get_price())
}


  • 一个struct 对应着多个trait共享
// api/stock.rs
use crate::model::book_model::Book;

pub trait Stock{
    fn get_stock(&self) -> i32;
}

impl Stock for Book {
    fn get_stock(&self) -> i32 {
        1000
    }
}

//main.rs
use crate::api::prods::Prods;
use crate::model::book_model::Book;
use crate::model::iphone_model::Phone;
use crate::api::stock::Stock;

    // 商品库存
    let book_stock: Book = api::prods::Prods::new(32, 88.0);
    show_detail(book_stock)
		// 商品库存为1000

// 传入两个 trait使用+号声明
fn show_detail<T>(p: T)
    where T: Stock + Prods{
    println!("商品库存为{}", p.get_stock())
}

  • Trait 操作符重载 (例如 +号 : 1+1 返回的是2 i32类型 重载 例如我不想他返回结果2 而是返回结果的长度 len 就是使用到操作符重载 diy )

// api/prods.rs

// +号定义的位置
// std::ops::Add 基于+号的trait共享行为 实现struct 
impl std::ops::Add<Book> for Book {
    type Output = f32;

    fn add(self, rhs: Book) -> Self::Output {
        self.get_price() + rhs.get_price()
    }
}

//main.rs 

    let book: Book = api::prods::Prods::new(2, 88.8);
    // 商品库存
    let book_stock: Book = api::prods::Prods::new(32, 88.0);
    sum(book, book_stock);

fn sum(p1: Book, p2: Book) {
    // println!("商品总价为{}", p1.get_price()+ p2.get_price())

    println!("商品总价为{}", p1 + p2);
}

  • 生命周期

    • 1.作用域的生命周期
    fn max (a: i32, b: i32) -> i32 {
        if a> b {
            a
        }else {
            b
        }
    }
    
    
        let a = 10;
        let b = 100;
        println!("{}", max(a, b))
    
    // 如果程序这样运行 就不会出现生命周期的问题  因为a,b 两个参数传参的时候相当于copy 开辟了新的内存空间存放数据  如果使用&引用 也就是指针就会出现变量的生命周期问题 
    
    
    // 引用生命周期 解决方法 
    // 这个 &' 就是生命周期的写法 标记生命周期 
    fn max<'a> (a: &'a i32, b: &'a i32) -> &'a i32{
        if a> b {
            a
        }else {
            b
        }
    }
    
        let a = 10;
        let b = 100;
        println!("{:?}", max(&a, &b))
    
    

& 引用的概念是借用的意思 被借走的数据如果没有被归还 是无法被修改使用的

  • 生命周期 - struct中使用引用

#[derive(Debug)]

struct User<'a> {
  id : &'a i32
}

fn main() {
  let mut id = 109; // 好比是声明一个汽车 
  let u = User{id: &id}; // 引用& 就是车被struct借走了
  
  id=108; // 这个时候我想开车 肯定开不了 这里就报错了 
  println!("{:?}", u); // 在这执行完车才归还给我  我在下面执行才能开车
  
}

  • 生命周期 - &str
// 之前写的&'static str 这个是贯穿全局的生命周期声明

// 在输入值和输出值 生命周期相同 或者输入>输出生命周期时, 程序才允许编译
fn show_name<'a> (name: &'a str) -> &'a str {
  name
}

fn main() {
  
  let name = "zhangsan";
  show_name(name);
}

  • vector 集合

数组:
1.存在栈上
2.数组是rust内置的数据类型
3.长度固定

vector 与数组正好相反 
1.存在堆上
2.长度可以自动扩容
3.第三方库


    // let vec_tags = vec!["go", "py", "rust"];
		// 两种声明是相同的 写法不同 
    let mut vec_tags = Vec::new();
    // 注: &str 是不可变类型
    vec_tags.push(String::from("go"));
    vec_tags.push(String::from("vue"));
    vec_tags.push(String::from("js"));


    for i in &mut vec_tags {
        // i = i+"1";
      	// 如果要对vec集合中的元素 进行修改 需要保证遍历的元素是可修改的  *是反解&的  &就是引用内存地址 加上*之后 是显示真实数据
        *i += "hae";
        println!("{:?}", i)
    }
    println!("{:?}", vec_tags);
		// ["gohae", "vuehae", "jshae"]

  • 枚举

枚举理解下来 应该是用来约束数据类型的


#[derive(Debug)]
enum Sex {
    Male(String), // ()内可以定义多个类型 例如(String, i32)
    FeMale(String)
}
#[derive(Debug)]
struct User {
    id: i32,
    sex: Sex
}

fn check_sex(u: User) {

    // 判断 u.sex 数据类型 和 Sex是否匹配
    if let Sex::Male(s) = u.sex {
        println!("{:?}", s)
    }
}

// enumerate 枚举例子
fn enumerate() {
    println!("{:?}", Sex::Male(String::from("man")
    ));
    // Male("man")
    println!("{:?}", User{id:1, sex:Sex::Male(String::from("man"))});
    // User { id: 1, sex: Male("man") }
    let u = User{id:1, sex:Sex::Male(String::from("man"))};
    check_sex(u);

}

  • 内置枚举 取代 自定义枚举

    #[derive(Debug)]
    struct User {
        id: i32,
        // sex: Sex
        sex: Option<String>
    }
    
    fn check_sex(u: User) {
    
        // 判断 u.sex 数据类型 和 Sex是否匹配
        // if let Sex::Male(s) = u.sex {
        if let Some(s) = u.sex {
            println!("{:?}", s)
            // "man"
        }
    }
    
    // enumerate 枚举例子
    fn enumerate() {
        let u = User{id:1, sex: Some(String::from("man")) };
        check_sex(u);
    }
    
posted @ 2022-02-18 14:31  听风走了八千里  阅读(709)  评论(0编辑  收藏  举报