開源學村

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:開源學村

柴米油鹽計劃

文件兄,我find到你了

文件找不到了,**window**上,大家習慣了右上角直接搜索,分分鐘就找回來了,但這樣操作真的安全嗎? 反正,這樣的「便宜」事就別想對**Linux**做了。 其實,**Linux**上的文件查找也並不難啦,而且安全性十足噠(特別花樣多,比格高),就小小的find的就能做到。
開源學村

Makefile 簡介

簡潔地介紹了 Makefile 這一強力的工具,對 Makefile 的規則和變數等內容沒有做出完整的描述,只是簡單進行了一點介紹,希望更多的人能了解並使用 Makefile。
開源學村

【開源學村】紀錄片《何其荒謬,軟體專利是如何破壞整個專利體系的》下載及徵集觀後感

講述軟體專利的電影《Patent Absurdity: how software patents broke the system》,我們把它翻譯為《何其荒謬,軟體專利是如何破壞整個專利體系的》,它是一部獲得自由軟體基金會(FSF)贊助的紀錄片,正如FSF的理念一般,這部片子也是開源的,你可以合法下載和持有本部電影。本次《開源學村》項目分享這部影片同時有獎徵集觀後感。