Rust 语法 
基础 
- 输出 
println!("a is {0} and b is {1}", a,b)println!("struct can be {:#?}", st1)
 - 输出 
use std::io::stdin;let mut str = String::new()stdin().read_line(&mut str).unwrap();
 - 命令参数 
let args = std::env::args()for i in args{}
 - 变量 let 
- 变量不变类型
 - 修改要加mut
 - 重影 重新使用变量名
 
 - 常量 const 只能赋值一次
 - 静态 static 
- 程序内共享
 - 可以加mut (不安全)
 
 - 数据类型 
- 整数 
- (u/i) + (8/16/32/64/128)
 - 1_000_000 0xff 0o77 0b1111_0000 b'A'
 - 不支持 ++ --
 
 - 浮点 
- f32 f64
 - .sin/cos/tan/sqrt/ln/power(4)
 
 - 布尔 
- true false
 - 与01不能直接自动转换
 > >= == != ! && || ^ & |
 - 字符 char utf-8
 - 字符串常量 &str 
let s1: &str = "abc";let s2: String = String::from("abc");- push push_str len eq chars().nth(2).unwrap()
 &s[0..3]
 - 元组 
(i32, f64, char)- tup.0/1/2/3 不能用
[0] 
 - 数组 
[i32; 5]arr[0/1/2].len()iter()
 - 切片 
&s[1..]: &str&arr[..4]: &[i32]- 本质是对数据的部分引用
 - 字符串常量本质就是切片引用类型
 
 
 - 整数 
 - 流程控制 
if bool {}else if bool {} else {}bool不写括号let num = if a>0 {1} else {-1}没有三元match op {0=>{}, 1|-1 =>{}, _=>{}}while bool {}for i in 迭代器{}非迭代的for用while1..5arr.iter()0..arr.len()
loop{}无限循环等breaklet v = loop{ if arr[i]>0 {break i;}}支持表达式
 
函数 
rust
// 声明
fn func(a: i32, b: i32)->i32{
  // a+b
  return a+b;
}
// 函数表达式
let y = {
  let a = 2;
  let b = 2;
  a+b+3
};
// 函数变量
let mut fun: fn();
fun = func;
fun();
// 闭包 lambda 匿名函数
let lb = |a: i32, b: i32|->i32{
  return a+b;
}
let lb = |x: i32| x+1;所有权 
- 理念 
- 变量是数据对象的所有者
 - 一个数据只有一个所有者
 - 所有者不可用时数据销毁
 
 - 概念 
- 转移 
let y = x后x失去数据 适用于引用类型 - 复制 x仍保有数据 适用于数字 布尔 字符 相应元组
 - 引用 
let s2 = &s1借用数据 数据只有一份- 常用于不支持复制的数据传递
 - 垂悬引用 借用失去的数据 不允许 如函数返回变量引用
 - 可变引用 
&mut可改变指向的地址 - 解引用 
*可改变该地址下本体值 实现交换函数 
 
 - 转移 
 - 函数相关 
func(a)a根据类型发生转移和复制func(&a)借用 不失去所有权return b;返回时给出所有权return &b;垂悬引用
 
复合类型 
结构体 
- 定义和实例化 
struct Site{domain: String}let site = Site {domain: String::from("abc")}name: name可以简写let obj2 = Obj {name, ..obj1}继承
 - 所有权 
- 字段赋值类似变量 会发生转移或复制
 - 字段若采用引用类型会报错 例如
&str- 需要加上生命周期标识符 
<'a>&'a str 
 - 需要加上生命周期标识符 
 
 - 结构体方法 
impl Site{}fn plus(&self)->i32{self.ip + self.port}self不用类型site1.plus()
 - 元组结构体 
struct Color(u8,u8,u8)let black = Color(0,0,0)black.0/1/2
 - 单元结构体 
struct Unit 
枚举 
- 定义和实例化 
enum Color{Red,Green,Blue}let color = Color::Red
enum Book{Idx(u32),Name(String)}let book = Book::Idx(100)let book = Book::Name(String::from("hello"))
enum Book{Site{ip:String,port:u32},Student{name:String}}let ebook = Book::Site{ip:String::from("fdsf"),port:2077}
 - match 
match book{}Book::Idx (index)=>{}Book::Site {ip}=>{}
 - if let 
if let Book::Site {ip} = book{println!("",ip)}else{}
 - 枚举方法 
impl Book{}fn setBook(&mut self){*self = Book::Name(String::from("hello"))}
 
泛型 
- 泛型函数 
fn func<T>(arr: &[T])-> &T{&arr[arr.len()-1]}
 - 泛型结构体 
struct Point<T>{x:T,y:T}struct Point<T1, T2>{x:T1,y:T2}let point = Point::<i32>{x:1,y:2}
 - 泛型枚举 
enum Shape<T>{Rect(T,T),Cube(T,T,T)}let s = Shape::Cube(1,1,1)
 - impl 泛型 
impl<T> Point<T>{}第一个t表示要用泛型 第二个t表示类型fn get_x(&self) -> &T{&self.x}impl<A,B> Data<A,B>{}fn mix<C,D>(self, other: Date<C,D>)->Data<A,D>{Data{x:self.x,y:other.y}}
 
错误处理 
- 不可恢复错误 
panic!("error")输出错误停止运行.unwrap().expect("wrong")将可恢复错误转不可恢复 停止程序
 - 可恢复错误 
- Result 
enum Result<T,E>{Ok(T),Err(E)}match res{}Ok(val)=>{}Err(err)=>{}
 - 传递 
-> Result<i32,&'static str>return Result::Ok(a)return Result::Err("errer")- 若当前函数返回值类型与调用函数一致 可以用?直接传递错误
 let a = func(x)?;
 - 错误类型 
Err(e)=>{match e.kind(){}} 
 - Result 
 - Null Option 
- rust任何变量都不能是Null 空指针 空引用
 enum Option<T>{None,Some(T)}some 表示有值fn func()-> Option<usize>{}return Option::Some(i)return Option::None
if let Some (i) = func() {println!("{}",i)}else{}let opt = func().except("none")也可以直接停止
 
模块 
- 箱 包 模块 
mod模块类型pub默认私有 使之公有super类似..use把某嵌套模块下的东西引入当前作用域
 - 多文件程序 
modu.rspub fn func(){}main.rsmod modu;fn main(){modu::func();}
 - cargo 
cargo new nameinit在当前目录新建buildrundoc库名称 = "0.1.1"extern crate randuse rand::Rng;
 
接口 trait 
- 定义和实现 
trait Tools {}fn less(&self, b: &Self)-> bool&self自身和&Self同类impl Tools for Structure{}fn less(&self, b: &Structure)->{true}
 - 一个类多种接口 一个impl只能实现一种接口 并且只能写接口里的方法
 - 默认特性 可以在定义的时候写上默认函数实现 impl里面没写的话就会调用默认
 - 接口做参数 
fn func(arr: &mut [&impl Tools])impl Tools for f64{}func(&mut arr64)- 泛型函数 
fn func<T: Tools>(a:T){}用于impl了Tools的类的对象 多参数类型要一样 
 - 接口叠加类型 
fn func(a: impl Tools1 + Tools2){}fn func<T: Tools1+Tools2, U: Tools2+Tools3>(t:T, u:U){}fn func<T, U>(t:T, u:U)where T:Tools1+Tools2, U: Tools2+Tools3
 - 返回接口 
fn func() -> impl Tools{}- 返回实现了该接口的对象 但只能是一种类型的对象(多条件分支下)
 
 - 有条件的实现 
struct A<T>;trait B{}impl<T: B> A<T>{}A类型只有在T实现了B的前提下才能调用impl
 
文件 
- 文件和流 
- 文件可以看成一种数据结构
 - 流描述的是数据传输
 
 - 读 
use std::fs;use std::io::Readlet txt = fs::read_to_string("./hello.txt").unwrap();字符串read()二进制open()File对象file.read_to_end(&mut u8Vec)一次性读入
 - 写 
use std::fs::Fileuse std::io::Write``let mut file = File::create(path)创建/覆写file.write(b"hello")写入
 - 其它模式 
use std::fs::OpenOptionsOpenOptions::new().append(true).open(path).write(b"hello")- read write append create create_new truncate
 
 - 二进制 
to_ne_bytesto_le_bytesto_be_bytescpu字节序 小端 大端 转二进制f64::from__ne/le/be_bytes(buffer)从二进制读入
 - 目录 
- 列出 
fs::read_dir(path)i.file_name().to_str()
 - 创建 
fs::create_dir(path)fs::create_dir_all(path)
 - 删除 
fs::remove_dir(path)fs::remove_dir_all(path)
 
 - 列出 
 
数据结构 
- 线性数据结构 
- 数组链表 用链表存放数组 
- 用固定大小的数组保存元素再把数组像链表一样连起来
 
 - 链表数组 用数组存放链表
 
 - 数组链表 用链表存放数组 
 - Vec 
let vect: Vec<i32> = Vec::<i32>::new()let vect = vec![1,2,3]push pop remove(i) append(&mut v2) get_mut
 use std::collections::LinkedList/VecDeque/HashMap/BTreeMap/Set/BinaryHeap- VecDeque 
push_back(i) - LinkedList 链表
 - String 
数据.to_string()push('w') push_str("wold")let s4 = s1 + &s2 + &s3s4会获得s1的所有权let str = format!("{}年{:02}月{:02}日",y,m,d)- 截取 
&str[1..4]str.chars().nth(2)字符
 - 长度 
.len()中文长度3str.chars().count()
 - HashMap 映射 
let mut map = HashMap::<&str, &str>::new().insert("name","ok").get("name")- 其它类型需实现Hash Eq两个接口
 - BTreeMap 有序映射
 
 - Set 
let mut sets = HashSet::<&str>::new().insert("h")- 其它类型需实现Hash Eq(PartialEq)两个接口
 - BTreeSet 有序集
 
 - 堆 树状有序数据结构 适用于频繁插入取出的场合 
let mut heap = BinaryHeap::<u32>::new()let heap = BinaryHeap::from(vec).push(i) .pop()for i in heap{}
 
 
面向对象 
- 类 
structimpl - 对象 
impl实现new()方法 返回结构体实例 - 封装 
mod - 继承 结构体嵌套
 - 多态 
trait的不同实现 
堆内存 Box 
- 用于在编译时无法确定大小或生命与函数不同的情况
 Box::new(St{})
rust
// 递归嵌套的结构体符合使用条件
struct Link{
  val: i32,
  next: Option<Box<Link>>
}
fn main(){
  let link = Some(Box::new(Link{
    val:1,
    next:Some(Box::new(Link{
      data:2,
      next:None
    }))
  }));
  let mut l = &link;
  loop{
    if let Some(b) = l{
      l = &b.next;
    }else{
      break;
    }
  }
}进阶 
- Rc 引用计数 
let data = Rc::new(St{val: 1})- 可以让数据被多次克隆 引用数量为1时释放
 - 本质为多个引用
 
 - Mutex 互斥锁 
let m = Mutex::new(100).lock().unlock()在还没解锁的时候会等待
 - 运算符重载 
impl Add for St{}fn add(self, ta:Self)->Self{}Self{a: self.a + ta.a}
 - 属性 
- 条件编译属性 
#[cfg(target_os = "linux")]#[test]cfg_attr
 - 派生属性 自动为类型生成实现 
#[derive(Clone)]
 - 诊断属性 
#[warn(missing_docs)]deprecate标记过时#[must_use]没用到的元素会警告
 - 模块路径属性 确定路径 
#[path = "sub_mod/the_mod.rs"]
 - 其它属性
 
 - 条件编译属性 
 - 宏 预定义规则生成代码 
- 定义和使用 
macro_rules! 宏名 {}($参数名: 宏参数类型)=>{}($($x: expr), *)可变参数个数宏名!()/{}/[]调用
 - 可有多种参数形式 用于实现重载
 - 过程宏 
- 函数宏 形如函数,并像函数一般调用
 - 派生宏 能够为结构体、枚举等实现特征
 - 属性宏 用于结构体、字段、函数等,为其指定属性
 
 
 - 定义和使用 
 - 不安全领域 
unsafe{}- 使用原始指针 
let ptr = 0xABCDEF as *const/mut i32;let ptr = &mut number as *mut i32;
 - 使用不安全的函数和方法 
unsafe fn func(){}定义- 只能在领域内使用
 
 - 直接改变静态变量 
static mut num = 100unsafe{num+=1;}
 - 实现不安全的接口 
unsafe trait Tool{}unsafe impl Tool for St{}
 - 访问共用体字段 
union Num{i: u64, f: f64}let num = Num{f:3.14159}unsafe{printfln("{}",num.i)}
 
 - 使用原始指针 
 
多线程 
rust
use std::thread;
fn sub(){
  for i in 1..5{
    println!("sub {}",i);
  }
}
fn main(){
  // thread::spawn(sub);
  thread::spawn(sub).join();
  for i in 1..5{
    println!("main {}",i);
  }
  thread::sleep(Duration::from_millis(200))
}rust
use std::sync::mpsc;
fn main(){
  let (sender,recver) = mpsc::channel();
  
  thread::spawn(move ||{
    sender.send("hello")
  })
  println("{}",recver.recv())
}rust
use std::thread
use std::sync::{Arc, Mutex, mpsc}
fn main(){
  let (s1,r1) = mpsc::channel();
  let (s2,r2)= mpsc::channel();
  let sum = Arc::new(Mutex::new(0_u32));
  let copy_1 = sum.clone();
  thread::spawn(move ||{
    let mut sum value = copy_l.lock().unwrap();
    for i in 1..11{ *sum value += i;}
    sl.send(0).unwrap();
  });
  let copy_2 = sum.clone();
  thread::spawn (move ||{
    let mut sum value = copy 2.1ock().unwrap();
    for i in 11..21{*sum value += i;}
    s2.send(0).unwrap();
  } );
  rl.recv().unwrap();
  r2.recv().unwrap();
  let locked_sum = sum.lock().unwrap();
  println!("sum is (]",locked_sum);
}rust
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
fn main() {
    let (s1, r1) = mpsc::channel();
    let (s2, r2) = mpsc::channel();
    let data = Arc::new(Mutex::new((1_u32, 2_u32)));
    let copy_1 = data.clone();
    thread::spawn(move || {
        let mut data = copy_1.lock().unwrap();
        (*data).0 += (*data).1;
        s1.send(0).unwrap();
    });
    let copy_2 = data.clone();
    thread::spawn(move || {
        let mut data = copy_2.lock().unwrap();
        (*data).1 += (*data).0;
        s2.send(0).unwrap();
    });
    rl.recv().unwrap();
    r2.recv().unwrap();
    let locked_data = data.lock().unwrap();
    println!("data =[:?]", locked_data);
}
// 标志互斥锁
let flag  = Arc::new(Mutex::new(0));网络通信 
- Tcp 
use std::net::TcpStream;let s = TcpListener::bind("127.0.0.1:8080")let mut c = TcpStream::connect("127.0.0.1:8080")let (c,addr) = s.accept()c.write(b"hello");while c.read(&buffer)>0{vect.push(buffer[0])}for c in s.incoming(){}循环accept
 - Udp 
let skt = UdpSocket::bind("127.0.0.1:8080")skt.send_to(b"hello","ip:port")let (size, addr) = skt.recv_from(buffer)let (size, addr) = skt.peek_from(buffer)不会将数据从缓冲中移除
 - http 
- 用tcp发送含html内容的字符串