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);
    }

Rust语言开发的更多相关文章

  1. 我持续推动Rust语言支持Windows XP系统

    前言 Rust好像长期以来不支持Windows XP系统.有不少用户发帖提议官方支持XP,基本上都被Rust官方开发人员明白的拒绝了.他们的对话大致上是以这种形式開始和结束的(当中乙方代表官方及其拥趸 ...

  2. 微软看上的Rust 语言,安全性真的很可靠吗

    摘要:近几年,Rust语言以极快的增长速度获得了大量关注.其特点是在保证高安全性的同时,获得不输C/C++的性能.在Rust被很多项目使用以后,其实际安全性表现到底如何呢? 近几年,Rust语言以极快 ...

  3. Rust语言:安全地并发

    http://www.csdn.net/article/2014-02-26/2818556-Rust http://www.zhihu.com/question/20032903 Rust是近两年M ...

  4. Rust语言之HelloWorld

    Rust语言之HelloWorld 参考文档: http://doc.crates.io/guide.html 1 什么是Cargo 相当于maven/ant之于java, automake之于c, ...

  5. Rust语言

    Rust语言 https://doc.rust-lang.org/stable/book/ http://www.phperz.com/article/15/0717/141560.html Rust ...

  6. 半个月使用rust语言的体验

    从第一次下载rust语言的编译器到今天刚好第14天. 简单说一下对这个语言的感觉吧. 一.性能 把以前用java写的一个中文地址切分的算法,用rust重新实现了一下(https://github.co ...

  7. Atitit.rust语言特性 attilax 总结

    Atitit.rust语言特性 attilax 总结 1. 创建这个新语言的目的是为了解决一个顽疾:软件的演进速度大大低于硬件的演进,软件在语言级别上无法真正利用多核计算带来的性能提升.1 2. 不会 ...

  8. Rust语言——无虚拟机、无垃圾收集器、无运行时、无空指针/野指针/内存越界/缓冲区溢出/段错误、无数据竞争

    2006年,编程语言工程师Graydon Hoare利用业余时间启动了Rust语言项目.该项目充分借鉴了C/C++/Java/Python等语言的经验,试图在保持良好性能的同时,克服以往编程语言所存在 ...

  9. 5分钟APIG实战: 使用Rust语言快速构建API能力开放

    序言:Rust语言简介 参与过C/C++大型项目的同学可能都经历过因为Null Pointer.Memory Leak等问题“被” 加班了不知道多少个晚上.别沮丧,你不是一个人,Mozilla Fir ...

随机推荐

  1. Java反射给泛型集合赋值

    Java反射给泛型集合赋值 泛型 Java泛型简单描述下: 比如创建一个List集合,我想在里边只放Student对象信息,就需要写成 List<Student> studentList ...

  2. Redhat 如何使用yum 源(转)

    1.需要把Redhat注册的信息给解决掉 This system is not registered with an entitlement server. You can use subscript ...

  3. ES6随笔D1

    1.数值解构赋值 ES6 允许按照一定模式,可以从数组中提取值,按照对应位置,对变量赋值,这被称为解构. 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象.由于undefined和n ...

  4. CentOS 7安装Odoo 15社区版的详细操作指南

    我之前的文章介绍过在Windows环境下安装Odoo 15,如果您需要在Windows部署,具体可参考我文末的微信号<10分钟教你本机电脑安装Odoo 15,并启用一个内置的项目APP应用> ...

  5. Cesium源码剖析---Ambient Occlusion(环境光遮蔽)

    Ambient Occlusion简称AO,中文没有太确定的叫法,一般译作环境光遮蔽.百度百科上对AO的解释是这样的:AO是来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果,可以解决或改善漏光 ...

  6. 513. Find Bottom Left Tree Value

    Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 ...

  7. openSUSE修改grub来修复对win8的引导

    前言:继上一次安装试用各版本linux发行版后,由于做项目将机器纯windows了一把,现在又想安回centos,各种挫折折腾两天玩残一个u盘日,其中包括自己本本的原装系统也崩了,各种泪奔,下面记录一 ...

  8. C++多线程之互斥锁和超时锁

    #include<iostream> #include<thread> #include<mutex> using namespace std; mutex mu; ...

  9. MySQL数据类型操作(char与varchar)

    目录 一:MySQL数据类型之整型 1.整型 2.验证不同类型的int是否会空出一个存储正负号 3.增加约束条件 去除正负号(unsigned) 二:浮点型 1.浮点型 2.验证浮点型精确度 三:字符 ...

  10. 国内外免费对象存储和CDN加速额度

    标题: 国内外免费对象存储和CDN加速额度 作者: 梦幻之心星 sky-seeker@qq.com 标签: [#免费,#对象存储,#CDN] 日期: 2022-01-29 国内对象存储和CDN加速 七 ...