開源學村

2022年,從學習Rust開始

Rust 是一個相對新的編程語言(2015年上線),如今已經獲得許多的程序員的青睞,成為「最受喜愛編程語言」。羅馬並非一日建成,Rust 仍然建立在以往我們所熟悉的事物上。雖然您可能會感到 Rust 與曾經所學過的 Python、JAVA、C++ 等這些語言有很大區別,但它們都是基於您與 CPU 和 NUMA 架構之間互動(不管您是否知道這種互動的存在),因此 Rust 裡面一些新的東西又會讓你感到熟悉。

現在,我並非一個專業的程序員,沒有耐心但是又十分執著去做某件事,當一種編程語言無法按照自己的想法快速地得到我想要的結果,那麼下次我也不會首先使用這個語言去完成我想做的事。Rust 語言便嘗試平衡這兩個互相矛盾的事情:現代的電腦要求安全且標準的結構化代碼;而程序員們希望成功的完成一件事情的同時,儘可能地減少工作量。

安裝 Rust

可以通過Rust-lang.org 安裝 Rust 並且查閱 Rust 的文檔,通常情況下,它就像下載並安裝 sh.rustup.rs 腳本並運行它一樣簡單:

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs
$ less sh.rustup.sh
$ sh ./sh.rustup.rs

沒有類

Rust 中並沒有類(class)這種數據類型而是使用結構體(struct),struct 用於描述一組不同類型數據的數據對象。在 Rust 我們會使用 struct 來創造一個「虛擬對象」 :

struct Penguin {
    genus: String,
    species: String,
    extinct: bool,
    classified: u64,
}

您可以像使用類一樣使用結構體。例如,定義了 Penguin 結構體後,您可以創建它的實例,像如下例子:

struct Penguin {
    genus: String,
    species: String,
    extinct: bool,
    classified: u64,
}

fn main() {
    let p = Penguin { genus: "Pygoscelis".to_owned(),
         species: "R adeliæ".to_owned(), 
         extinct: false, 
         classified: 1841 };

    println!("Species: {}", p.species);    
    println!("Genus: {}", p.genus);
    println!("Classified in {}", p.classified);
    if p.extinct == true {
        println!("Sadly this penguin has been made extinct.");
    }

}

通過 implstruct 兩種數據類型的混合使用,您可以創造包含函數的結構體,並且您也可以實現繼承或者其他和類相似的功能。

函數

Rust 中的函數與其他大多數語言中的函數相同,每個函數都代表著一個特定的功能,使用的時候再調用它。同樣,至少需要調用主函數 main

使用函數需要用 fn 關鍵字來聲明,後面接著函數名和接受的參數:

fn foo() {
  let n = 8;
  println!("Eight is written as {}", n);
}

通過參數可以將信息從一個函數傳遞到另一個函數。例如,我們已經創建了 Penguins 類,並且已經將其實例化為 p,當要求將 p 中屬性從一個函數傳遞到另一個函數時,我們需要明確 p 作為接受 Penguins 類型的目標函數:

fn main() {
  let p = Penguin { genus: "Pygoscelis".to_owned(), 
    species: "R adeliæ".to_owned(), 
    extinct: false, classified: 1841 };
  printer(p);
}

fn printer(p: Penguin) {
  println!("Species: {}", p.species);    
  println!("Genus: {}", p.genus);
  println!("Classified in {}", p.classified);
  if p.extinct == true {
      println!("Sadly this penguin has been made extinct.");
  }
}

變數

通常情況下,Rust 創建的是不可變的變數,您不可以改變該變數的值。像這段代碼,雖然不起眼,但是不能夠被編譯的:

fn main() {
 let n = 6;
 let n = 5;
 }

應該使用 mut 關鍵字,聲明一個可變變數,這樣子代碼才會被成功編譯:

fn main() {
 let mut n = 6;
 println!("Value is {}", n);
 n = 5;
 println!("Value is {}", n);
}

編譯器

Rust 的編譯器,至少就其錯誤信息提示而言,它是最好編譯器之一。當您在 Rust 編程中出錯時,Rust 的編譯器會提示您的錯誤所在。實際上,僅僅通過編譯器中的錯誤提示,我就了解了 Rust 中那些細微之處(就我目前對 Rust 的細微差別的了解而言)。即使編譯器顯示的錯誤信息太過模糊以至於我們無法直接了解錯誤所在,我們也可以很容易地在網上找到解釋。

最簡單的開始 Rust 編程的方法是使用 cargo,Rust 的軟體包管理和建立系統:

$ mkdir myproject
$ cd myproject
$ cargo init 

它為我們提供一個項目的基本架構,值得注意的是 src 子目錄下的main.rs 文件。打開該文件,並黏貼到文章中的示例代碼中去:

struct Penguin {
    genus: String,
    species: String,
    extinct: bool,
    classified: u64,
}

fn main() {
    let p = Penguin { genus: "Pygoscelis".to_owned(), species: "R adeliæ".to_owned(), extinct: false, classified: 1841 };
    printer(p);
    foo();
}

fn printer(p: Penguin) {
    println!("Species: {}", p.species);    
    println!("Genus: {}", p.genus);
    println!("Classified in {}", p.classified);
    if p.extinct == true {
        println!("Sadly this penguin has been made extinct.");
    }
}

fn foo() {
     let mut n = 6;
 println!("Value is {}", n);
 n = 8;
  println!("Eight is written as {}", n);
}

要編譯該代碼,使用 cargo build 指令:

$ cargo build

為了運行您的項目,需要執行 target 子目錄下的二進位文件,或者直接使用 cargo run

$ cargo run
Species: R adeliæ
Genus: Pygoscelis
Classified in 1841
Value is 6
Eight is written as 8

箱子(Crates)

其他語言中,會提供許多方便程序員編程的庫和模板。在 Rust 中,庫以「箱子(crates)「的形式進行分發和跟蹤。Creat.io網站就是一個很好的 crates 社區的註冊表

為了在您的 Rust 項目中加入 crates,要在 Cargo.toml 文件中列出它們。例如,要安裝一個隨機數函數,我們需要使用 rand 箱子,使用用 * 作為通配符以確保我們編譯時獲得的是最新的版本:

[package]
name = "myproject"
version = "0.1.0"
authors = ["Seth <seth@opensource.com>"]
edition = "2022"

[dependencies]
rand = "*"

在 Rust 代碼中使用它,需要在程序頂部用 use 來聲明:

use rand::Rng;

創建隨機數和控制隨機數範圍的示例:

fn foo() {
    let mut rng = rand::thread_rng();
    let mut n = rng.gen_range(1..99);

    println!("Value is {}", n);
    n = rng.gen_range(1..99);
    println!("Value is {}", n);
}

您可以使用 cargo run 來運行程序,它會檢測到程序的改變並觸發新的構建。構建過程中會下載 rand 箱子和它所需要的其他的 crate 箱子,編譯器將會編譯這段代碼,然後運行該代碼:

$ cargo run
Updating crates.io index
Downloaded ppv-lite86 v0.2.16
Downloaded 1 crate (22.2 KB) in 1.40s
 Compiling libc v0.2.112
 Compiling cfg-if v1.0.0
 Compiling ppv-lite86 v0.2.16
 Compiling getrandom v0.2.3
 Compiling rand_core v0.6.3
 Compiling rand_chacha v0.3.1
 Compiling rand v0.8.4
 Compiling rustpenguin v0.1.0 (/home/sek/Demo/rustpenguin)
 Finished dev [unoptimized + debuginfo] target(s) in 13.97s
 Running `target/debug/rustpenguin`

Species: R adeliæ
Genus: Pygoscelis
Classified in 1841
Value is 70
Value is 35

Rust Cheat sheet

Rust 是一個非常令人愉悅的語言,這要感謝它對在線註冊表的整合、好用的編譯器,和它直觀的語法,這些讓它更像一個現代的編程語言。

但我也要注意,它仍然是一個複雜的編程語言,擁有嚴格的數據類型,強作用域的變數,和許多內置方法。Rust 是一個值得您去學習的語言,如果您想進一步了解 Rust,你可以下載我們這份Rust Cheat sheet,可以讓您快速了解 Rust 的基礎知識。越早開始,您會越早學會 Rust。當然,你應該經常練習避免生鏽(Rusty)。


翻譯:xiaoqi
參考文章:
Learn Rust in 2022

對這篇文章感覺如何?

太棒了
3
不錯
1
愛死了
0
不太好
0
感覺很糟
1

You may also like

Leave a reply

您的電子郵箱地址不會被公開。 必填項已用 * 標註

此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

More in:開源學村

開源學村

SoCal Linux博覽會回歸20周年

現在已經是支持和推廣FOSS社區的第20個年頭了,SCaLE 20x - 南加州Linux博覽會將於2023年3月9日至12日在帕薩迪納會議中心舉行。 這個為期4天的年度活動彙集了充滿活力的開源用戶社 […]
開源學村

如何在Linux上殺死殭屍進程

消滅殭屍進程! 也稱為「defunct」或「dead」進程 - 簡單來說,殭屍進程是指已經結束,但仍存在於系統進程表中的進程。理想情況下,一旦進程完成其工作/執行,它應該從進程表中清除。但由於某些原因 […]
開源學村

使用 Linux 命令行解決Wordle 問題

你可以使用 Linux 的 grep 命令和 fgrep 命令來解決Wordle 問題(進行篩選排除),grep 命令使用正則表達式進行搜索,fgrep 命令也像 grep 一樣搜索文本,但不使用正則表達式,grep 和 fgrep 命令在掃描單詞列表時提供了極大的靈活性。
開源學村

如何殺死 Linux 中的殭屍進程

在使用操作系統工作時,要時刻注意保持對系統中進程的掌控。一旦殭屍進程佔滿了你的資源,就只能依靠重新啟動來挽回一切了。所以快來學慣用 kill 指令來殺滅殭屍進程吧!