Rust

作者: 谭英智 | 来源:发表于2022-10-07 18:33 被阅读0次

    解决了什么问题

    • 内存安全问题
    • 所有权辅助了可以更好的编译优化代码,达到更高的性能

    语言基础

    • 变量

      fn main() {
        let x = 5;  //常量
        let mut y = 5; //变量
        println!("x: {}", x);
        y = 6;
        println!("y: {}", y);
          let x = 6; //覆盖
      }
      
    • 数据类型

      let guess: u32 = "42".parse().expect("Not a number!"); //pass
      let guess = "42".parse().expect("Not a number!"); //complie error 因为类型推断不出来guess是整形
      

      整型

      长度 有符号 无符号
      8-bit i8 u8
      16-bit i16 u16
      32-bit i32 u32
      64-bit i64 u64
      arch isize usize
      数字字面值 例子
      Decimal 98_222
      Hex 0xff
      Octal 0o77
      Binary 0b1111_0000
      Byte (u8 only) b'A'

      在debug模式,如果整型溢出,会panic,在release模式,不检测溢出

      浮点型

      默认是f64

      fn main() {
        let x = 2.0; // f64
        let y: f32 = 3.0; /f32
      }
      

      布尔型

      fn main() {
          let t = true;
          let f: bool = false; // 显式指定类型注解
      }
      

      字符类型

      char是 Unicode标量

      fn main() {
          let c = 'z';
          let z = 'ℤ';
          let heart_eyed_cat = '😻';
      }
      

      元组类型

      fn main() {
          let tup: (i32, f64, u8) = (500, 6.4, 1);
          let tup = (500, 6.4, 1);
          let (x, y, z) = tup;
          let z = tup.0;
          println!("The value of y is: {}", y);
      }
      

      数组

      固定长度

      fn main() {
          let a = [1, 2, 3, 4, 5];
          let a: [i32; 5] = [1, 2, 3, 4, 5];
          let first = a[0];
      }
      

      rust会在运行时检测数组越界并panic

      函数

      fn main() {
          let x = plus_one(5);
      
          println!("The value of x is: {}", x);
      }
      
      fn plus_one(x: i32) -> i32 {
          x + 1  //不加;,表示返回值
      }
      

      控制流

      fn main() {
          let number = 3;
      
          if number < 5 {
              println!("condition was true");
          } else {
              println!("condition was false");
          }
          let condition = true;
          let number = if condition {
              5
          } else {
              6
          };
      }
      
      
          loop {
              println!("again!");
          }
        let result = loop {
              counter += 1;
      
              if counter == 10 {
                  break counter * 2; //跳出循环并返回
              }
          };
        while number != 0 {
              println!("{}!", number);
      
              number = number - 1;
          }
          let a = [10, 20, 30, 40, 50];
      
          for element in a.iter() {
              println!("the value is: {}", element);
          }
      
      

    所有权

    作用域

    变量离开作用域,则自动释放内存

    移动

    let s1 = String::from("hello");
    le s2 = s1; //类似c++的move
    println!("{}, world!", s1); //编译失败
    
    rust-move
    克隆
    let s1 = String::from("hello");
    let s2 = s1.clone(); //深拷贝
    
    println!("s1 = {}, s2 = {}", s1, s2);
    

    引用

    要么 只能有一个可变引用,要么 只能有多个不可变引用 ,为了解决数据竞争问题。rust通过编译来做这些限制

    fn main() {
        let s1 = String::from("hello");
    
        let len = calculate_length(&s1);
    
        println!("The length of '{}' is {}.", s1, len);
    }
    
    fn calculate_length(s: &String) -> usize { //常量引用
        s.len()
    }
    
    
    fn main() {
        let mut s = String::from("hello");
    
        change(&mut s);
    }
    
    fn change(some_string: &mut String) { //可变引用
        some_string.push_str(", world");
    }
    
    

    悬垂引用

    fn dangle() -> &String {
        let s = String::from("hello");
    
        &s //编译失败
    }
    

    slice

    返回string的一段

    let s = String::from("hello world");
    
    let hello = &s[0..=4];
    let world = &s[6..=10];
    
    rust-slice
    fn first_word(s: &String) -> &str {
        let bytes = s.as_bytes();
    
        for (i, &item) in bytes.iter().enumerate() {
            if item == b' ' {
                return &s[0..i];
            }
        }
    
        &s[..]
    }
    
    fn main() {
        let mut s = String::from("hello world");
    
        let word = first_word(&s);
    
        s.clear(); // 编译失败,内存已经被清空,word不再有效
    
        println!("the first word is: {}", word);
    }
    
    

    结构体

    # #[derive(Debug)]
    # struct Rectangle {
    #     width: u32,
    #     height: u32,
    # }
    #
    impl Rectangle { 
        fn area(&self) -> u32 { //成员函数
            self.width * self.height
        }
    }
    
    impl Rectangle {
        fn can_hold(&self, other: &Rectangle) -> bool {
            self.width > other.width && self.height > other.height
        }
    }
    fn main() {
        let rect1 = Rectangle { width: 30, height: 50 };
        let rect2 = Rectangle { width: 10, height: 40 };
        let rect3 = Rectangle { width: 60, height: 45 };
    
        println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
        println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
    }
    
    
    

    枚举

    enum IpAddrKind {
        V4,
        V6,
    }
    let four = IpAddrKind::V4;
    
    enum IpAddr {
        V4(String),
        V6(String),
    }
    
    let home = IpAddr::V4(String::from("127.0.0.1"));
    
    let loopback = IpAddr::V6(String::from("::1"));
    
    

    枚举与控制流:

    # #[derive(Debug)]
    # enum UsState {
    #    Alabama,
    #    Alaska,
    # }
    #
    # enum Coin {
    #    Penny,
    #    Nickel,
    #    Dime,
    #    Quarter(UsState),
    # }
    #
    fn value_in_cents(coin: Coin) -> u32 {
        match coin {
            Coin::Penny => 1,
            Coin::Nickel => 5,
            Coin::Dime => 10,
            Coin::Quarter(state) => {
                println!("State quarter from {:?}!", state);
                25
            },
        }
    }
    
    

    Option枚举

    它用来表示一个变量是Null或者有值

    enum Option {
        Some(T),
        None,
    }
    let some_number = Some(5);
    let some_string = Some("a string");
    
    let absent_number: Option<i32> = None;
    
    
    fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }
    
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    
    
    let some_u8_value = Some(0u8);
    if let Some(3) = some_u8_value {
        println!("three");
    }
    

    集合

    vector

    变长数组

    let v: Vec<i32> = Vec::new();
    let v = vec![1, 2, 3];
    v.push(5); //追加
    v.pop();
    let third: &i32 = &v[2];
    let does_not_exist = &v[100]; //panic
    let does_not_exist = v.get(100); //返回None
    let first = &v[0]; //借用
    v.push(6); //error, first的内存可能已经被释放
    
    

    遍历

    let v = vec![100, 32, 57];
    for i in &v { //常量引用
        println!("{}", i);
    }
    
    let mut v = vec![100, 32, 57];
    for i in &mut v { //可变引用
        *i += 50;
    }
    

    string

    新建:

    let mut s = String::new();
    let s = "initial contents".to_string();
    let s = String::from("initial contents");
    

    追加:

    s.push_str("bar");
    

    拼接:

    let s1 = String::from("Hello, ");
    let s2 = String::from("world!");
    let s3 = s1 + &s2; // 注意 s1 被移动了,不能继续使用
    

    string的add函数原型如下:

    fn add(self, s: &str) -> String {
    

    s2以常量引用的方式传入add

    s1以移动的方式传入add

    s1不再拥有所有权

    所有权被移交到s3中

    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");
    
    let s = format!("{}-{}-{}", s1, s2, s3);
    

    通过format,s1 s2 s3的所有权都得以保留

    索引

    let s1 = String::from("hello");
    let h = s1[0]; //error
    

    字符串不能索引,因为String支持的编码类型复杂

    遍历

    for c in "नमस्ते".chars() {
        println!("{}", c);
    }
    for b in "नमस्ते".bytes() {
        println!("{}", b);
    }
    

    哈希map

    新建

    use std::collections::HashMap;
    let mut map = HashMap::new();
    

    插入

    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");
    map.insert(field_name, field_value);
    // 这里 field_name 和 field_value 不再有效
    map.insert(String::from("Hate"), String::from("Red"));
    map.entry(String::from("OK")).or_insert(String::from("Yello")); //只有键不存在时插入,返回value的指针
    println!("{:?}", map);
    

    访问

    let name = String::from("OK");
    let color = map.get(&name);
    for (key, value) in &map { //常量引用s
        println!("{}: {}", key, value);
    }
    

    错误

    panic

    不可恢复异常,程序会输出bt

    fn main() {
        panic!("crash and burn");
    }
    fn main() {
        let v = vec![1, 2, 3];
    
        v[99]; //越界,panic
    }
    

    result

    可恢复错误

    use std::io;
    use std::io::Read;
    use std::fs::File;
    
    fn read_username_from_file() -> Result<String, io::Error> {
        let f = File::open("hello.txt");
    
        let mut f = match f {
            Ok(file) => file,
            Err(e) => return Err(e),
        };
    
        let mut s = String::new();
    
        match f.read_to_string(&mut s) {
            Ok(_) => Ok(s),
            Err(e) => Err(e),
        }
    }
    
    

    泛型

    struct Point<T> {
        x: T,
        y: T,
    }
    
    impl<T> Point<T> {
        fn x(&self) -> &T {
            &self.x
        }
    }
    
    fn main() {
        let p = Point { x: 5, y: 10 };
    
        println!("p.x = {}", p.x());
    }
    
    impl Point<f32> { //对f32单态化后,实现函数
        fn distance_from_origin(&self) -> f32 {
            (self.x.powi(2) + self.y.powi(2)).sqrt()
        }
    }
    
    

    trait

    接口

     pub trait Summary {
         fn summarize(&self) -> String;
     }
    
    pub struct NewsArticle {
        pub headline: String,
        pub location: String,
        pub author: String,
        pub content: String,
    }
    
    impl Summary for NewsArticle {
        fn summarize(&self) -> String {
            format!("{}, by {} ({})", self.headline, self.author, self.location)
        }
    }
    
    pub struct Tweet {
        pub username: String,
        pub content: String,
        pub reply: bool,
        pub retweet: bool,
    }
    
    impl Summary for Tweet {
        fn summarize(&self) -> String { //多态
            format!("{}: {}", self.username, self.content)
        }
    }
    
    let tweet = Tweet { //实例化
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    
    println!("1 new tweet: {}", tweet.summarize());
    
    

    接口作为参数

    pub fn notify(item: impl Summary) {
        println!("Breaking news! {}", item.summarize());
    }
    fn some_function<T, U>(t: T, u: U) -> i32
        where T: Display + Clone,
              U: Clone + Debug
    {
    }
    
    fn returns_summarizable(switch: bool) -> impl Summary {
        if switch {
            NewsArticle {
                headline: String::from("Penguins win the Stanley Cup Championship!"),
                location: String::from("Pittsburgh, PA, USA"),
                author: String::from("Iceburgh"),
                content: String::from("The Pittsburgh Penguins once again are the best
                hockey team in the NHL."),
            }
        } else {
            Tweet {
                username: String::from("horse_ebooks"),
                content: String::from("of course, as you probably already know, people"),
                reply: false,
                retweet: false,
            }
        }
    }
    
    

    泛型与trait

    Copy代表类型T可以被拷贝

    PartialOrd代表T为数字类型

    Display 代表T可以被打印

    fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
        let mut largest = list[0];
    
        for &item in list.iter() {
            if item > largest {
                largest = item;
            }
        }
    
        largest
    }
    
    fn main() {
        let number_list = vec![34, 50, 25, 100, 65];
    
        let result = largest(&number_list);
        println!("The largest number is {}", result);
    
        let char_list = vec!['y', 'm', 'a', 'q'];
    
        let result = largest(&char_list);
        println!("The largest char is {}", result);
    }
    
    

    生命周期省略

    fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
        if x.len() > y.len() {
            x
        } else {
            y
        }
    }
    
    
    • 每一个引用参数都有它的生命周期参数
    • 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数
    • 如果有多个输入生命周期参数,且其中一个参数被标记&self,那么self的生命周期被赋予所有输出生命周期

    智能指针

    以引用计数来管理内存

    在堆创建数据

    fn main() {
        let b = Box::new(5);
        println!("b = {}", b);
    }
    

    创建递归类型

    enum List {
        Cons(i32, Box<List>),
        Nil,
    }
    
    use crate::List::{Cons, Nil};
    
    fn main() {
        let list = Cons(1,
            Box::new(Cons(2,
                Box::new(Cons(3,
                    Box::new(Nil))))));
    }
    
    

    提早释放

    fn main() {
        let c = CustomSmartPointer { data: String::from("some data") };
        println!("CustomSmartPointer created.");
        drop(c);
        println!("CustomSmartPointer dropped before the end of main.");
    }
    

    增加引用

    enum List {
        Cons(i32, Box<List>),
        Nil,
    }
    
    use crate::List::{Cons, Nil};
    
    fn main() {
        let a = Cons(5,
            Box::new(Cons(10,
                Box::new(Nil))));
        let b = Cons(3, Box::new(a)); //move
        let c = Cons(4, Box::new(a)); //error
    }
    
    
    

    正确的做法:

    enum List {
        Cons(i32, Rc<List>),
        Nil,
    }
    
    use crate::List::{Cons, Nil};
    use std::rc::Rc;
    
    fn main() {
        let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
        let b = Cons(3, Rc::clone(&a)); //增加计数,只读引用,数据不可变
        let c = Cons(4, Rc::clone(&a)); //增加计数,只读引用,数据不可变
    }
    
    

    可变引用,计数增加:

    enum List {
        Cons(Rc<RefCell<i32>>, Rc<List>),
        Nil,
    }
    
    use crate::List::{Cons, Nil};
    use std::rc::Rc;
    use std::cell::RefCell;
    
    fn main() {
        let value = Rc::new(RefCell::new(5));
    
        let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
    
        let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a)); 
        let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a));
    
        *value.borrow_mut() += 10;
    
        println!("a after = {:?}", a);
        println!("b after = {:?}", b);
        println!("c after = {:?}", c);
    }
    
    

    解决循环引用

    使用weak代替Rc

    并行编程

    多线程

    use std::thread;
    use std::time::Duration;
    
    fn main() {
        let handle = thread::spawn(|| {
            for i in 1..10 {
                println!("hi number {} from the spawned thread!", i);
                thread::sleep(Duration::from_millis(1));
            }
        });
    
        for i in 1..5 {
            println!("hi number {} from the main thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    
        handle.join().unwrap();
    }
    
    

    线程使用主线程变量

    use std::thread;
    
    fn main() {
        let v = vec![1, 2, 3];
    
        let handle = thread::spawn(move || {
            println!("Here's a vector: {:?}", v);
        });
    
        handle.join().unwrap();
    }
    
    

    消息传递

    # use std::thread;
    # use std::sync::mpsc;
    # use std::time::Duration;
    #
    # fn main() {
    // --snip--
    
    let (tx, rx) = mpsc::channel();
    
    let tx1 = mpsc::Sender::clone(&tx); //多生产者
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];
    
        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    
    thread::spawn(move || {
        let vals = vec![
            String::from("more"),
            String::from("messages"),
            String::from("for"),
            String::from("you"),
        ];
    
        for val in vals {
            tx.send(val).unwrap(); //val所有权转移
            thread::sleep(Duration::from_secs(1));
        }
    });
    
    for received in rx {
        println!("Got: {}", received);
    }
    
    // --snip--
    # }
    
    

    多线程共享可变变量

    use std::sync::{Mutex, Arc};
    use std::thread;
    
    fn main() {
        let counter = Arc::new(Mutex::new(0)); //Arc是带有原子性的智能指针,Rc是不带原子性的智能指针
        let mut handles = vec![];
    
        for _ in 0..10 {
            let counter = Arc::clone(&counter);
            let handle = thread::spawn(move || {
                let mut num = counter.lock().unwrap();
    
                *num += 1;
            });
            handles.push(handle);
        }
    
        for handle in handles {
            handle.join().unwrap();
        }
    
        println!("Result: {}", *counter.lock().unwrap());
    }
    
    

    相关文章

      网友评论

          本文标题:Rust

          本文链接:https://www.haomeiwen.com/subject/hopbartx.html