Rust快速入门

安装

linux & mac OS

1curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

创建项目

1cargo new hello
2cd hello
3
4cargo build
5cargo run
6cargo check

基本语法

变量

 1// 1. 定义变量  let name :类型 =;
 2let a = 1;
 3// a = 2; // error
 4let b: u32 = 2;
 5let mut c = 3;
 6c = 5;
 7
 8// 2. 隐藏 将上面的a=1隐藏,后续在使用a变量对应的值为10
 9let a = 10;
10
11// 3. 常量 定义在main方法顶部
12const MAX_VALUE: u32 = 10000;

数据类型

  • Rust是静态类型语言,即编译时必须知道所有变量的类型
  • 编译器具有自动推导能力

基础数据类型

名字零值长度描述
boolfalsefalse 或者 true
char32bit值可以是 ‘a’ ‘中’
i8,i16,i32,i64, u8,u16,u32,u640数字类型 i符号,u无符号
isize, usize自适应类型, 获取当前机器的usize最大值usize::max_value();
[Type; size]数组, let arr: [u32; 5] = [1, 2, 3, 4, 5]; , 当数组作为参数时, size也是数组的一部分, 用于限制参数:类型+size
()元组, let tup: (i32, f32, char) = (1, 3.14, ‘你’); println!("{}", tup.0);

函数

  1. 返回类型

    1fn 方法的名字(参数: 参数类型, .....) -> 返回数据类型 {
    2    return 返回值;
    3}
    
  2. 返回结果

    1fn login(t: i32, name: String) -> bool {
    2    println!("type: {}, name: {}", t, name);
    3    let result: bool = true;
    4    // return result;
    5
    6    // 直接返回  不需要增加result和分号;
    7    result
    8}
    
  3. 表达式变量

    1let value = {
    2    let age = 18;
    3    age + 1
    4}
    

控制流

if

 1
 2let t = 1;
 3if t == 1 {
 4    println!("{}", t);
 5} else if t > 1{
 6    println!("{}", t);
 7} else {
 8    println!("{}", t);
 9}
10
11let condition = true;
12let x = if condition {
13    5
14} else {
15    6
16    // "root" 出现error, 数据类型需要与if中的一致
17};

loop

 1let mut conuter = 0;
 2loop {
 3    println!("{}", conuter);
 4    if counter >= 10 {
 5        break;
 6    }
 7    counter = counter + 1;
 8    // counter += 1;
 9}
10
11let sum = loop {
12    counter += 1;
13    if counter >= 10 {
14        break counter * 2;
15    }
16};

while

 1let mut i = 0;
 2while i != 10 {
 3    i += 1;
 4}
 5println!("i: {}", i);
 6
 7let arr: [u32; 5] = [1, 2, 3, 4, 5];
 8// for element in &arr {
 9for element in arr.iter() {
10    println!("element: {}", element);
11}

所有权

  • Rust通过所有权机制来管理内存, 编译器在编译机会根据 所有权规则对内存的使用进行检查

    • 规则1: ***
    • 规则2: s
    • 规则3: 2
  • 堆栈

    • 编译的时候数据类型大小是固定的, 就是分配在栈上
    • 编译的时候数据类型大小不固定, 就分配到堆上
  • 作用域: {}

    1fn main() {
    2  let x:i32 = 1;
    3  {
    4      let y: i32 = 1;
    5      println!("x: {}", x);
    6      println!("y: {}", y);
    7  }// y被销毁
    8} // x会被销毁
    
  • String内存回收

  • 移动

  • clone

    • 堆上分配 堆内存分配

    • code

       1fn main() {
       2    {
       3        // 内存分配
       4        let s1 = String::from("hello");// 编译器不知道当前String的大小, 已在后面是可以push_str操作
       5        // s1.push_str(" world");
       6        println!("s1: {}", s1); // 输出 hello
       7
       8        // move 移动
       9        let s2 = s1;
      10        println!("s2: {}", s2); // 输出 hello
      11        println!("s1: {}", s1); // error, 因为此时已经发生了 move 动作,s1的所有权已经给s2了, s1无效了
      12
      13        // clone
      14        let s3 = s2.clone();
      15        println!("s3: {}", s3); // 输出 hello
      16        println!("s2: {}", s2); // 输出 hello
      17    }
      18
      19    // 栈上数据拷贝
      20}
      

      移动 s2=s1

  • 栈上数据拷贝

    copy traint需要实现此特征

    常用具有copy traint特征有:

    • 所有整型
    • 浮点型
    • 布尔值
    • 字符类型 char
    • 元组
    1fn main() {
    2
    3  let a = 1;
    4  let b = a;
    5  println!("a: {}, b={}", a, b)
    6}
    
  • 函数和作用域

     1fn move_ownership(value: String) {
     2  println!("move_ownership: {}", value);
     3}
     4
     5fn move_ownership_back(value: String) -> String {
     6  println!("move_ownership: {}", value);
     7  value
     8}
     9
    10fn copy_value(i: i32) {
    11  println!("copy_value: {}", i);
    12}
    13
    14fn main() {
    15  let s = String::from("hello");
    16  let s1 = move_ownership_back(s);
    17  println!("double get s1: {}", s1); // ok, move后有又将所有权返回了
    18
    19  move_ownership(s1);
    20  println!("double get s: {}", s1); // error  已经发生move了
    21
    22  let x = 5; // 在栈上 ,具有  copy traint特性,是允许的
    23  copy_value(x);
    24  println!("double get x: {}", x); // it's ok
    25}
    

引用 &, 借用 & mut

创建一个指向值的应用, 但是不拥有这个值, 所以, 当引用离开其指向的作用域后不会被丢弃

在任意给定时间, 要么只能有一个可变引用, 要么只能有多个不可变的引用

 1fn calcute_len(s:&String) -> usize {
 2    s.len()
 3}
 4
 5fn update(s: & mut String) {
 6    s.push_str(" world");
 7}
 8fn main() {
 9    let mut s1 = String::from("hello");
10    let s = &s1;
11    let len = calcute_len(s);
12    println!("s1: {}", s1);
13    println!("len: {}", len);

借用

 1fn calcute_len(s:&String) -> usize {
 2    s.len()
 3}
 4
 5fn update(s: & mut String) {
 6    s.push_str(" world");
 7}
 8fn main() {
 9    let mut s1 = String::from("hello");
10    let s = &s1;
11    let len = calcute_len(s);
12    println!("s1: {}", s1);
13    println!("len: {}", len);
14
15    // 借用
16    update(&mut s1);
17
18    let r1 = &s1;
19    let r2 = &s1;
20    let r3 = &mut s1;
21    println!("r1: {}, r2: {}, r3: {}", r1, r2, r3); // error, 因为 r3已经法伤mut了 之后又在使用 是不允许的
22
23    let r4 = &s1;
24    let r5 = &s1;
25    println!("r1: {}, r2: {}", r4, r5); // ok
26
27    let r6 = &mut s1;
28    r6.push_str(" world");
29    println!("r1: {}, r2: {}", r4, r5); // error
30    println!("r4: {}, r5: {}, r6: {}", r4, r5, r6); // error, 借用只有 又在使用
31
32}

悬垂引用

1fn main() {
2    let ref_s = dangle(); // ref_s 执行了一个已经回收的内存了
3
4}
5
6fn dange() -> &String {
7    let s = Stirng::from("");
8    &s
9} // s被销毁了

String的slice

 1let s = String::from("hello world");
 2
 3let len = &s[0..=6];
 4let len = &s[0..=5];
 5let len = &s[..=5];
 6let len = &s[2..];
 7
 8
 9let v = String::from("你好");
10let len = &v[0..2]; // error是不允许的的不v

结构体

 1fn main() {
 2    #[derive(Debug)]
 3    struct User {
 4        name: String,
 5        password: String,
 6    }
 7
 8    let admin = User {
 9        name: String::from("admin"),
10        password: String::from("123456"),
11    };
12
13    let mut guest = User {
14        name: String::from("guest"),
15        password: String::from("123456"),
16    };
17
18    guest.password = String::from("guest");
19
20    println!("guest: {:?}", guest);
21
22    let name = String::from("root");
23    let password = String::from("root");
24    let root= User {
25        name,
26        password,
27    };
28    println!("root: {:?}", root);
29
30    let user1  = User {
31        ..admin
32    };
33    println!("user1: {:?}", user1);
34
35    let user2  = User {
36        name: String::from("user2"),
37        ..user1
38    };
39    println!("user2: {:?}", user2);
40    println!("user2: {:#?}", user2);
41
42
43    // 元组结构体
44    // 1. 字段没有名字
45    // 2. 圆括号
46    struct Point(i32, i32);
47
48    let a = Point(10, 20);
49    println!("a.x = {}, a.y={}",a.0, a.1);
50}

Options

// todo

Vector

 1let v: Vec<i32> = Vec::new(); // 不能push 是不可变的
 2
 3let mut vv: Vec<i32> = Vec::new(); 
 4vv.push(1);
 5
 6let t: i32 = &vv[2]; // 越界 异常了
 7
 8// 推荐使用方法
 9let mut w = vec![1, 2, 3];
10match w.get(1) { // 越界不会异常
11    Some(value)=> println!("value: {}", value);
12    _ => println!("None found");
13}
14
15// 更新
16let mut u: Vec<i32> = Vec::new();
17u.push(1);
18u.push(2);
19u.push(3);
20for i in &u {
21    println!("item: {}", i);
22}
23// mut update
24for i in & mut u {
25    *i += 1;
26}
27// readonly
28for i in &u {
29    println!("item: {}", i);
30}
31
32// 注意 rust规避bug的一种表现
33let mut k = vec![1, 2, 3];
34let first = &k[0]; // 不可变引用
35k.push(6); // 可变引用, 之后不允许在使用不可变引用
36println!("first: {}", first); // error 

String

 1fn main() {
 2    let mut name = String::new();
 3    name.push_str("admin"); // 如果不声明 mut 在此处会error
 4    let mut pwd = String::from("123456");
 5    let pwd1 = "123456abc".to_string();
 6    println!("pwd: {}, pwd1: {}", pwd, pwd1);
 7
 8    pwd.push_str(".");
 9    pwd.push('m');
10    // pwd.push('xx'); error
11    // pwd.push("x"); error
12    pwd.push_str(&pwd1);
13    println!("pwd: {}, pwd1: {}", pwd, pwd1);
14
15    let prefix = "t_".to_string();
16    let table = String::from("user");
17
18    let table_name = prefix + &table;
19    println!("table name: {}", table_name);
20    // println!("prefix: {}", prefix); // error , 已经prefix的所有权给 table_name了
21    println!("table: {}", table); // &table是引用, 不会获取所有权 ,所以可以再次使用
22    
23    let auth = String::from("guest");
24    let title = String::from("计算机"); // uncode 3个字节 -> 中文
25    // auth[0];  // error
26    let desc = "中国";   
27    let a = &desc[0..3];
28    // let b = &desc[0..2]; // error
29    let b = "0";
30    println!("auth len: {}, title: {}, a: {}, b: {}", auth.len(), title.len(), a, b);
31
32    for c in title.chars() {
33        println!("{}", c);
34    }
35    for d in title.bytes() {
36        println!("{}", d);
37    }
38}

HashMap

 1use std::collections::HashMap;
 2
 3fn main() {
 4    let mut cache: HashMap<String, i32> = HashMap::new();
 5    // 插入数据
 6    cache.insert(String::from("admin"), 10); 
 7    cache.insert(String::from("root"), 20); 
 8    // key不存在才插入
 9    cache.entry(String::from("guest")).or_insert(30); 
10    cache.entry(String::from("root")).or_insert(25); 
11    println!("{:?}", cache);
12
13    // 遍历插入
14    let keys = vec![String::from("admin"), String::from("root")];
15    let values = vec![10, 20];
16    let data: HashMap<_, _> = keys.iter().zip(values.iter()).collect();
17
18    // get value
19    let search = String::from("admin");
20    let v = data.get(&search); 
21    match v {
22        Some(value) => println!("key: {}, value: {}", search, value),
23        _ => println!("Not Found"),
24    }
25
26    if let Some(vvv) = data.get(&search) {
27        println!("key: {}, value: {}", search, vvv);
28    }
29
30    // 遍历
31    for (k, v) in &data {
32        println!("key: {}, value: {}", k, v); // 乱序
33    }
34}

Result

 1use std::fs::File;
 2
 3fn main() {
 4    let f  = File::open("config.yml");
 5    let r = match f {
 6        Ok(file) => file,
 7        Err(err) => panic!("Couldn't open, {:?}", err),
 8    };
 9
10    let f = File::open("config.yml").unwrap();
11    let f = File::open("config.yml").expect("Failed to open");
12}

trait & impl & Result

 1trait Authorization {
 2    fn login(&self) -> Result<&str, String>;
 3}
 4
 5struct UsernamePassword {
 6    name: String,
 7    password: String,
 8}
 9
10impl Authorization for UsernamePassword {
11    fn login(&self) -> Result<&str, String> {
12        if self.name == "admin" && self.password == "123456" {
13            return Ok("144-258b-804e-3ac5-c9ebd3485b2f");
14        }
15        return Err("账号密码错误!".to_string());
16    }
17}
18
19fn main() {
20    let user = UsernamePassword {
21        name: "admin".to_string(),
22        password: "123456.".to_string(),
23    };
24    match user.login() {
25        Ok(token) => println!("{}", token),
26        Err(msg) => println!("{}", msg),
27    }
28}