Skip to content

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用while
      • 1..5
      • arr.iter()
      • 0..arr.len()
    • loop{} 无限循环等break
      • let 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(){}}
  • 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.rs pub fn func(){}
    • main.rs mod modu; fn main(){modu::func();}
  • cargo
    • cargo new name
    • init在当前目录新建
    • build
    • run
    • doc
    • 库名称 = "0.1.1"
    • extern crate rand use 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::Read
    • let txt = fs::read_to_string("./hello.txt").unwrap(); 字符串
    • read() 二进制 open() File对象 file.read_to_end(&mut u8Vec) 一次性读入
    • use std::fs::File use std::io::Write ``
    • let mut file = File::create(path) 创建/覆写
    • file.write(b"hello") 写入
  • 其它模式
    • use std::fs::OpenOptions
    • OpenOptions::new().append(true).open(path).write(b"hello")
      • read write append create create_new truncate
  • 二进制
    • to_ne_bytes to_le_bytes to_be_bytes cpu字节序 小端 大端 转二进制
    • 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 + &s3 s4会获得s1的所有权
    • let str = format!("{}年{:02}月{:02}日",y,m,d)
    • 截取
      • &str[1..4]
      • str.chars().nth(2) 字符
    • 长度
      • .len() 中文长度3
      • str.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{}

面向对象

  • struct impl
  • 对象 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 = 100
      • unsafe{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内容的字符串