第一个程序 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) }}#![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} let age = 2; let new_age = if age == 2 { 5 }else { 10 }; println!("{}", age) // .chars 将字符串类型转换为可迭代对象iter for i in text.chars(){ println!("{}",i); }; // 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"), };// 考虑下面这段代码 在内存的角度发生了什么?let name = String::from("abc");abc的ptr 0 aabc的len 1 babc的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())// 注: 所有者有且只能有一个// 这个me就是String的所有者ownershiplet 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#![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 User{ name: String, age: i64} let user = User{name:String::from("zhangJiAn"), age: 123};// 相当于go中的 func (this *User) getUser() {}#[derive(Debug)]struct User{ name: String, age: u8}// 实现方法的关键词implimpl 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)// 泛型就是 一个函数中传形参的时候 我可以 传入不同类型的参数 给形参 // 这个形参的类型 由我引用的的时候自己指定即可// 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,Bimpl <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.rspub 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 类似于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// model/book_model.rs#[derive(Debug)]pub struct Book { pub id: i32, pub price: f32}// api/prods.rsuse 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// api/prods.rsuse 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())}// api/stock.rsuse crate::model::book_model::Book;pub trait Stock{ fn get_stock(&self) -> i32;}impl Stock for Book { fn get_stock(&self) -> i32 { 1000 }}//main.rsuse 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())}// 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);}生命周期
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))& 引用的概念是借用的意思 被借走的数据如果没有被归还 是无法被修改使用的
#[derive(Debug)]struct User<'a> { id : &'a i32}fn main() { let mut id = 109; // 好比是声明一个汽车 let u = User{id: &id}; // 引用& 就是车被struct借走了 id=108; // 这个时候我想开车 肯定开不了 这里就报错了 println!("{:?}", u); // 在这执行完车才归还给我 我在下面执行才能开车 }// 之前写的&'static str 这个是贯穿全局的生命周期声明// 在输入值和输出值 生命周期相同 或者输入>输出生命周期时, 程序才允许编译fn show_name<'a> (name: &'a str) -> &'a str { name}fn main() { let name = "zhangsan"; show_name(name);}数组: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);}