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. SCryptPasswordEncoder 单向加密 --- 心得

    1.前言 * BCryptPasswordEncoder相关知识:* 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的s ...

  2. vert.x框架与tomcat的关系

    1.前言 大学4年,老师唯一让我们学习的web服务器是tomcat,配置方式是先从官网下载阿帕奇的tomcat文件,然后在开发平台导入,然后再配置web.xml等文件, 是一个可同步可异步请求的服务器 ...

  3. Linux上天之路(十四)之Linux数据处理

    主要内容 数据检索 数据排序 数据去重 重定向 1. 数据检索 常和管道协作的命令 – grep grep:用于搜索模式参数指定的内容,并将匹配的行输出到屏幕或者重定向文件中,常和管道协作的命令 – ...

  4. Redis内存分析工具之redis-rdb-tools的安装与使用

    操作系统:Centos7    1.redis-rdb-tools工具是用python语言编写的,所以首先需要安装python: 安装: (1)用 wget 下载 python 2.7 并解压( 如果 ...

  5. 读《疯狂Java讲义》笔记总结一

    最近在读<疯狂Java讲义>,现把其中遇到的一些自己以前没掌握的点儿记录下来. 1.字符串相关 字符串不是基本类型,字符串是一个类,也就是一个引用类型. 字符串转int类型String a ...

  6. 【reverse】逆向5 标志寄存器

    [reverse]逆向5 标志寄存器 1.引言 通过一个creak.exe文件的爆破,引出现阶段需要学习的知识 2.标志寄存器 标志寄存器有上图这么多个 记住这几个寄存器的位置和名称 下面是6个状态标 ...

  7. 【解决了一个小问题】golang samara的kafka客户端中使用错误版本号导致初始化失败

    发现在如下代码中存储kafka生产者初始化失败: config.Version = sarama.V0_10_2_1 //V2_2_0_0 producer, err := sarama.NewSyn ...

  8. Cesium和Kaarta用高分辨率激光雷达可视化室内和地下环境

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Cesium使急救人员和军事操作人员更容易快速评估和了解密集和不 ...

  9. 推荐一个github国内访问加速神器GitHub520

    一.介绍 对 GitHub 说"爱"太难了:访问慢.图片加载不出来. 注: 本项目还处于测试阶段,仅在本机测试通过,如有问题欢迎提 issues 本项目无需安装任何程序,通过修改本 ...

  10. 为什么 Redis 的查询很快, Redis 如何保证查询的高效

    Redis 如何保证高效的查询效率 为什么 Redis 比较快 Redis 中的数据结构 1.简单动态字符串 SDS 对比 c 字符串的优势 SDS可以常数级别获取字符串的长度 杜绝缓冲区溢出 减少修 ...