自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一網(wǎng)打盡 Rust 語法

開發(fā) 前端
thread::spawn? 要求閉包具有 'static 生命周期,這意味著它不會(huì)從周圍范圍借用任何東西,并且可以在整個(gè)程序的持續(xù)時(shí)間內(nèi)存在。

1. 構(gòu)建運(yùn)行環(huán)境

我們?cè)赗ust環(huán)境配置和入門指南中詳細(xì)介紹了

  • 如何安裝Rust環(huán)境
  • 構(gòu)建一個(gè)Rust應(yīng)用
  • 編譯和運(yùn)行的區(qū)別
  • 使用Cargo構(gòu)建Rust應(yīng)用

下面,我們就之間直入主題了。

通過創(chuàng)建一個(gè)名為 main.rs 的文件并將以下代碼放入其中來編寫我們的第一個(gè) Rust 代碼:

fn main() {
    println!("Hello, Front789!");
}

然后通過運(yùn)行 rustc main.rs 和 ./main.exe 來運(yùn)行這個(gè)程序,就像運(yùn)行 C 程序一樣。

Cargo 是 Rust 的構(gòu)建系統(tǒng)和包管理器

我們也可以使用 cargo 創(chuàng)建項(xiàng)目。

  • cargo new hello_cargo:初始化一個(gè)新項(xiàng)目。
  • cargo build:構(gòu)建一個(gè) cargo 項(xiàng)目。
  • cargo run:運(yùn)行一個(gè) cargo 項(xiàng)目,這將編譯并運(yùn)行代碼。
  • cargo check:檢查是否有編譯錯(cuò)誤,它比cargo build速度更快。
  • cargo build --release:這將使用優(yōu)化進(jìn)行編譯,用于最終生產(chǎn)構(gòu)建。

2. 變量類型

在 Rust 中,默認(rèn)情況下「變量是不可變」的,這意味著一旦給變量賦值,其值就不會(huì)改變。

所以如果想要一個(gè)可變的,即可改變的值,使用 mut。

let a = 5;
let mut b = 5; // 可變的
  • 整數(shù):有各種大小的有符號(hào)和無符號(hào)整數(shù)(例如,i8、i16、i32、i64、u8、u16、u32、u64)

圖片圖片

let number: i32 = 42;
  • 浮點(diǎn)數(shù):單精度和雙精度浮點(diǎn)數(shù)(例如,f32、f64)

圖片圖片

let pi: f64 = 3.14159;
  • 布爾值:Rust的布爾類型只擁有兩個(gè)可能的值true和false,它「只會(huì)占據(jù)單個(gè)字節(jié)的空間大小」。使用bool來表示一個(gè)布爾類型。
let is_rust_cool: bool = true;
  • 字符:在Rust中char類型「占4字節(jié)」,是一個(gè)Unicode標(biāo)量值,這意味著它可以表示比ASCII多的字符內(nèi)容。使用char 類型表示一個(gè)字符類型
let heart_emoji: char = '?';
  • 字符串:可變字符串

圖片圖片

let mut s = String::from("front789");
  • 字符串切片:不可變且借用的字符串切片
let s1: &str = "front789";
  • 數(shù)組:數(shù)組中每一個(gè)元素都必須是「相同類型」。 Rust中「數(shù)組擁有固定的長度,一旦聲明就再也不能隨意更改大小」
let array: [i32; 3] = [1, 2, 3];
let a = [3; 5]; // 用值 3 初始化大小為 5 的數(shù)組
  • 元組

圖片圖片

為了從元組中獲得單個(gè)的值,可以使用「模式匹配」來解構(gòu)元組

還可以通過「索引」并使用點(diǎn)號(hào)(.)來訪問元組中的值

let tup = (500, 6.4, 1);
let (x, y, z) = tup;
let aa = tup.0; // 引用元組中的第一個(gè)項(xiàng)目
  • 向量

圖片圖片

  • 指針和引用

指針是一個(gè)變量,它存儲(chǔ)了一個(gè)值的「內(nèi)存地址」

Rust 中最常見的指針是引用。引用以 & 符號(hào)為標(biāo)志并「借用了它們所指向的值」。除了引用數(shù)據(jù)沒有任何其他特殊功能。它們也沒有任何額外開銷,所以應(yīng)用得最多。

fn main() {
    // 標(biāo)量類型
    let number: i32 = 42;
    let pi: f64 = 3.14159;
    let is_rust_cool: bool = true;
    let heart_emoji: char = '?';

    // 復(fù)合類型
    let array: [i32; 3] = [1, 2, 3];
    let tuple: (i32, f64, char) = (10, 3.14, 'a');
    let slice: &[i32] = &[1, 2, 3];
    let string: String = String::from("Hello, Front789!");
    let string_slice: &str = "Hello, Front789!";

    // 特殊類型
    let reference_to_number: &i32 = &number;
    let optional_value: Option<i32> = Some(42);
    let result_value: Result<i32, &str> = Ok(42);
}

以上內(nèi)容就是Rust中所涉及到的各種數(shù)據(jù)類型,我們可以從以下的鏈接中找到更為詳細(xì)的解釋

  • 基礎(chǔ)概念
  • 集合
  • 智能指針

3. 操作數(shù)組

不可變數(shù)組:

不可變數(shù)組在 Rust 中用 [T; N] 語法來聲明,其中 T 表示數(shù)組元素的類型,而 N 表示數(shù)組的長度。

對(duì)于不可變數(shù)組,我們可以使用下標(biāo)訪問其元素,但不能修改元素的值。

let array = [1, 2, 3, 4, 5];
let first_element = array[0]; // 訪問第一個(gè)元素
arr[0] = 6; // 這行代碼會(huì)導(dǎo)致編譯錯(cuò)誤,因?yàn)閿?shù)組是不可變的

// 迭代
// 使用 for 循環(huán)
for &num in &array {
    println!("{}", num);
}
// 另一種迭代器
array.iter().for_each(|&num| {
    println!("{}", num);
});

let slice = &array[1..3]; // 從索引 1 到索引 2(包括)切片

可變數(shù)組

Vec<T> 是 Rust 中可變長數(shù)組的實(shí)現(xiàn),它允許您動(dòng)態(tài)地增加或減少數(shù)組的大小。

let mut array = [1, 2, 3, 4, 5];
array[0] = 10; // 修改第一個(gè)元素

let mut vec = Vec::new(); // 創(chuàng)建一個(gè)空 Vec
vec.push(1); // 向 Vec 中添加一個(gè)元素
vec.push(2);
vec.push(3);

// 使用 iter() 遍歷元素

for item in array.iter() {
    println!("{}", item);
}

// iter_mut() 方法返回一個(gè)可變的迭代器,允許修改 Vec 中的元素
for item in array.iter_mut() {
    *item += 1; // 對(duì)每個(gè)元素加 1
}

// map
let doubled_array: Vec<_> = 
    array.iter()
    .map(|&num| num * 2)
    .collect();

// filter
let even_elements: Vec<_> = 
    array.iter()
    .filter(|&&num| num % 2 == 0)
    .collect();

// len() 方法返回 Vec 中元素的數(shù)量
array.len()

// remove() 方法移除指定索引位置的元素,并返回該元素。如果索引越界,它將導(dǎo)致 panic。
let removed_item = array.remove(2) // removed_item 為3

4. 操作字符串

let s1 = String::from("Hello, ");
let s2 = String::from("Front789!");
let combined = s1 + &s2; // 注意:s1 在這里被移動(dòng),之后不能再使用
println!("{}", combined); // 打印 "Hello, Front789!"

let mut s = String::from("Hello, ");
s.push_str("Front789!");
println!("{}", s); // 打印 "Hello, Front789!"

// 獲取字符
let s = String::from("hello");
let first_char = s.chars().nth(0); // 訪問第一個(gè)字符

// 子字符串
let s = String::from("hello Front789");
let substring = &s[0..5]; // 提取 "hello"

// len()
let s = String::from("hello");
let length = s.len(); // 字符串的長度

// replace
let s = String::from("hello");
let replaced = s.replace("l", "z"); // 替換 "l" 為 "z"

// split
let s = String::from("hello Front789");
let words: Vec<&str> = s.split_whitespace().collect(); // 分割成單詞

// 轉(zhuǎn)換 &str 和 String
let s = String::from("hello");
let s_ref: &str = &s; // 將 String 轉(zhuǎn)換為 &str
let s_copy: String = s_ref.into(); // 將 &str 轉(zhuǎn)換為 String

5. 操作向量

let mut v1 = vec![1, 2, 3]; // 使用 vec![] 宏
let mut v2: Vec<i32> = Vec::new(); // 使用 Vec::new() 構(gòu)造函數(shù)

let mut v = Vec::new();
v.push(1);
v.push(2);

let first_element = v[0]; // 訪問第一個(gè)元素

// 迭代
// 使用 for 循環(huán)
for num in &v {
    println!("{}", num);
}

// 使用迭代器
v.iter().for_each(|&num| {
    println!("{}", num);
});

// slice
let slice = &v[1..3]; // 從索引 1 到索引 2(包括)提取元素

// remove
let removed_element = v.remove(1); // 移除索引為 1 的元素(返回被移除的元素)

// sort()
v.sort();

// join
let tt= vec!["hello", "Front789"];
let joined_string = tt.join(", "); // 使用逗號(hào)和空格連接元素

6. 函數(shù)

Rust代碼使用「蛇形命名法」來作為規(guī)范函數(shù)和變量名稱的風(fēng)格。蛇形命名法「只使用小寫的字母進(jìn)行命名,并以下畫線分隔單詞」。

  • 參數(shù),它們是一種「特殊的變量,并被視作函數(shù)簽名的一部分」。當(dāng)函數(shù)存在參數(shù)時(shí),你需要在「調(diào)用函數(shù)時(shí)為這些變量提供具體的值」
  • 在Rust中,「函數(shù)的返回值等同于函數(shù)體的最后一個(gè)表達(dá)式」。

語法

fn 函數(shù)名(參數(shù)1: 類型1, 參數(shù)2: 類型2) -> 返回類型 {
    // 函數(shù)體
    // 可選的表達(dá)式
}

最后一行返回值時(shí)不需要調(diào)用 return。

fn add_numbers(x: i32, y: i32) -> i32 {
    let sum = x + y;
    sum // 函數(shù)中的最后一個(gè)表達(dá)式會(huì)隱式返回
}

如果想要一個(gè)無返回值的函數(shù),不要定義返回類型。

我們可以在基礎(chǔ)概念_函數(shù)部分查看更詳細(xì)的解釋

7. 輸入/輸出

輸入

要讀取一個(gè)值,使用 io stdin 并給出變量的值,在失敗時(shí)需要提供 expect 消息,否則會(huì)出錯(cuò)。

let mut guess = String::new();    
io::stdin().read_line(&mut guess).expect("該行讀取失敗");

輸出 / 打印

println!("輸出對(duì)應(yīng)的變量信息 {}", guess); // 這里的 guess 是變量名。

你也可以在末尾有變量

let y = 10;

println!("y + 2 = {}", y + 2);

8. Shadowing

在Rust中,一個(gè)「新的聲明變量可以覆蓋掉舊的同名變量」,我們把這一個(gè)現(xiàn)象描述為:「第一個(gè)變量被第二個(gè)變量遮蔽Shadow了」。這意味著隨后使用這個(gè)名稱時(shí),它指向的將會(huì)是第二個(gè)變量。

fn main() {
    let x = 5; // 定義值為 5 的變量 x
    println!("原始值 x: {}", x); // 打印 "原始值 x: 5"
    
    let x = 10; // Shadowing:定義一個(gè)新的值為 10 的變量 x
    println!("Shadowed x: {}", x); // 打印 "Shadowed x: 10"
}

圖片圖片

9. 控制塊

圖片圖片

If else

if condition1 {
    // 如果 condition1 為真,則執(zhí)行的代碼
} else if condition2 {
    // 如果 condition2 為真,則執(zhí)行的代碼
} else {
    // 如果 condition1 和 condition2 都為假,則執(zhí)行的代碼
}

10. 循環(huán)

Rust提供了3種循環(huán)

  • loop
  • while
  • for

loop

loop {
    println!("永無止境的執(zhí)行");
}

While 循環(huán)

let mut count = 0;
while count < 5 {
    println!("Count: {}", count);
    count += 1;
}

For 循環(huán)

for i in 0..5 {
    println!("{}", i);
}

foreach

當(dāng)然也少不了對(duì)數(shù)值的遍歷操作。

(1..=5).for_each(|num| {
    println!("Number: {}", num);
});
// Number: 1
// Number: 2
// Number: 3
// Number: 4
// Number: 5

..:它表示一個(gè)擴(kuò)展運(yùn)算符,表示從第一個(gè)數(shù)字到最后一個(gè)數(shù)字生成。

我們也可以在循環(huán)中使用 continue 和 break。

11. 所有權(quán)

圖片圖片

這個(gè)概念是需要特別注意和反復(fù)觀看的部分。

MOVE(或)重新分配變量

當(dāng)變量值被重新分配時(shí),值會(huì)給新的所有者,并且舊的所有者被丟棄。

這種行為在字符串中經(jīng)??吹剑皇瞧渌愋?,如下所示:

let s1 = String::from("hello");
let s2 = s1;

println!("{}, world!", s1);

這將導(dǎo)致錯(cuò)誤,因?yàn)?nbsp;s1 在 s2=s1 之后不再有效。

如何解決上面的問題呢,我們可以使用 Clone:

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

某些類型隱式實(shí)現(xiàn)了 Clone。

let x = 5; // x 擁有整數(shù) 5
let y = x; // 將 x 的值復(fù)制到 y,不傳遞所有權(quán)

例如,整數(shù)隱式實(shí)現(xiàn)了 Clone,因此這段代碼不會(huì)報(bào)錯(cuò)。

圖片圖片

所有權(quán)和函數(shù)

fn main() {
    let s = String::from("hello");  // s 進(jìn)入作用域

    takes_ownership(s);             // s 的值移動(dòng)進(jìn)入函數(shù)...
                                    // ... 所以這里不再有效

    let x = 5;                      // x 進(jìn)入作用域

    makes_copy(x);                  // x 會(huì)移入函數(shù),
                                    // 但 i32 是 Copy,所以在之后繼續(xù)使用 x 是可以的

} // 在這里,x 超出作用域,然后是 s。但因?yàn)?s 的值被移動(dòng)了,所以沒有什么特別的發(fā)生。

fn takes_ownership(some_string: String) { // some_string 進(jìn)入作用域
    println!("{}", some_string);
} // 在這里,some_string 超出作用域,調(diào)用 drop。內(nèi)存被釋放。

fn makes_copy(some_integer: i32) { // some_integer 進(jìn)入作用域
    println!("{}", some_integer);
} // 在這里,some_integer 超出作用域。沒有什么特別的發(fā)生。

如果我們像在變量被移動(dòng)后,繼續(xù)使用,那么我們就使用 takes_ownership(s.clone()); (或者)在 takes_ownership 函數(shù)中返回值,像這樣:

fn main() {
    let s2 = String::from("hello");     // s2 進(jìn)入作用域
    let s3 = takes_and_gives_back(s2);  // s2 移入并被返回
}

fn takes_and_gives_back(a_string: String) -> String { 
    a_string  // 返回并移出到調(diào)用函數(shù)
}

借用 — 所有權(quán)

傳遞變量的引用,所有權(quán)不會(huì)被傳遞。

我們稱「創(chuàng)建引用的操作為借用」。就像現(xiàn)實(shí)生活中,如果一個(gè)人擁有一樣?xùn)|西,你可以從他們那里借來。借了之后,你必須歸還。你不擁有它。

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()
}

針對(duì)此處更詳細(xì)的內(nèi)容,可以翻看我們之前的所有權(quán)

12. 結(jié)構(gòu)體

struct,或者 structure,是一個(gè)「自定義數(shù)據(jù)類型」,允許我們命名和包裝多個(gè)相關(guān)的值,從而形成一個(gè)有意義的組合。

圖片圖片

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("front789"),
        email: String::from("front789@example.com"),
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

在 user2 中,你會(huì)看到 ..,它是擴(kuò)展運(yùn)算符,將 user1 中剩余的值傳遞給 user2(除了已經(jīng)定義的 email)。

結(jié)構(gòu)體的方法

使用 impl 結(jié)構(gòu)體名,并在其中定義函數(shù)。

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "長方形的面積為 {}",
        rect1.area()
    );
}

圖片圖片

針對(duì)此處更詳細(xì)的內(nèi)容,可以翻看我們之前的結(jié)構(gòu)體

13. 枚舉

枚舉,也被稱作 enums。枚舉允許你通過「列舉可能的成員variants來定義一個(gè)類型」

enum IpAddrKind {
    V4,
    V6,
}

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

枚舉的成員位于其標(biāo)識(shí)符的「命名空間中」,并「使用兩個(gè)冒號(hào)分開」。

match

這是類似于 switch 的東西,

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }

    let number = 5;

    match number {
        1 => println!("One"),
        2 => println!("Two"),
        3 | 4 | 5 => println!("Three, Four, or Five"),
        _ => println!("Other"), // 默認(rèn)情況
    }
}

每個(gè)分支相關(guān)聯(lián)的代碼是一個(gè)表達(dá)式,而表達(dá)式的結(jié)果值將作為整個(gè) match 表達(dá)式的返回值。

Option 枚舉和其相對(duì)于空值的優(yōu)勢

圖片圖片

if Let

這是一種使用 if 的花式方式,我們?cè)谄渲卸x一個(gè)表達(dá)式。

fn main() {
    let optional_number: Option<i32> = Some(5);

    // 使用 if let 匹配 Some 變體并提取內(nèi)部值
    if let Some(num) = optional_number {
        println!("Value: {}", num);
    } else {
        println!("No value");
    }
}

14. 并發(fā)性

并發(fā)編程和并行編程

圖片圖片

代碼實(shí)現(xiàn)

為了創(chuàng)建一個(gè)新線程,需要調(diào)用 thread::spawn 函數(shù)并「傳遞一個(gè)閉包」,并在其中包含希望在新線程運(yùn)行的代碼。

可以通過將 thread::spawn 的「返回值儲(chǔ)存在變量中來修復(fù)新建線程部分沒有執(zhí)行或者完全沒有執(zhí)行的問題」。thread::spawn 的返回值類型是 JoinHandle。JoinHandle 是一個(gè)「擁有所有權(quán)的值」,當(dāng)「對(duì)其調(diào)用 join 方法時(shí),它會(huì)等待其線程結(jié)束」。

use std::thread;

fn main() {
    // 數(shù)據(jù)
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // 將數(shù)據(jù)分成兩部分
    let mid = numbers.len() / 2;
    let (left, right) = numbers.split_at(mid);

    // 生成兩個(gè)線程來計(jì)算每一半的總和
    let handle1 = thread::spawn(move || sum(left));
    let handle2 = thread::spawn(move || sum(right));

    // 等待線程完成并獲取它們的結(jié)果
    let result1 = handle1.join().unwrap();
    let result2 = handle2.join().unwrap();

    // 計(jì)算最終總和
    let total_sum = result1 + result2;

    println!("Total sum: {}", total_sum);
}

fn sum(numbers: &[i32]) -> i32 {
    let mut sum = 0;
    for &num in numbers {
        sum += num;
    }
    sum
}

thread::spawn 要求閉包具有 'static 生命周期,這意味著它不會(huì)從周圍范圍借用任何東西,并且可以在整個(gè)程序的持續(xù)時(shí)間內(nèi)存在。

因此,我們使用move 閉包,其經(jīng)常與 thread::spawn 一起使用,因?yàn)樗试S我們「在一個(gè)線程中使用另一個(gè)線程的數(shù)據(jù)」。

責(zé)任編輯:武曉燕 來源: 前端柒八九
相關(guān)推薦

2021-08-05 06:54:05

流程控制default

2024-02-27 10:11:36

前端CSS@規(guī)則

2021-10-11 07:55:42

瀏覽器語法Webpack

2013-08-02 10:52:10

Android UI控件

2024-04-07 08:41:34

2024-08-26 10:01:50

2024-06-12 00:00:05

2010-08-25 01:59:00

2011-12-02 09:22:23

網(wǎng)絡(luò)管理NetQos

2013-10-16 14:18:02

工具圖像處理

2023-04-06 09:08:41

BPM流程引擎

2019-07-24 15:30:00

SQL注入數(shù)據(jù)庫

2021-05-20 11:17:49

加密貨幣區(qū)塊鏈印度

2021-10-29 09:32:33

springboot 靜態(tài)變量項(xiàng)目

2023-09-06 18:37:45

CSS選擇器符號(hào)

2020-02-21 08:45:45

PythonWeb開發(fā)框架

2020-10-19 06:43:53

Redis腳本原子

2023-04-03 08:30:54

項(xiàng)目源碼操作流程

2009-04-02 10:17:00

交換機(jī)產(chǎn)品選購

2023-09-26 00:29:40

CSS布局標(biāo)簽
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)