2019/07/15

Rust Programming Language

今年的 Stack Overflow 調查報告中,發現 Rust 是目前最受歡迎的程式語言。因此我們了解一下Rust 程式語言的定位是:一種撰寫可靠且有效率的軟體的程式語言。 A language empowering everyone to build reliable and efficient software. Rust 是 Mozilla 開發的程式語言,2010 年誕生,目前是 1.34.2 版,其設計目的是開發大型 server 端軟體,強調安全性、記憶體處理及並行處理。雖然效能比 C++ 稍差一點點,但提供了安全的保障。

調查9萬名程序員後,我們發現了一堆不為人知的秘密 Stack Overflow 的年度開發者調查是面向全球開發者的規模最大、最全面的調查,每年的調查內容會涵蓋開發人員最喜歡的技術以及工作偏好等內容。今年是 Stack Overflow 連續第九年進行開發者調查,吸引了將近 9w 名開發人員參加。今年的調查報告結果:Rust 是最受喜愛的編程語言,Python 則是增長最快的。今年 Python 超過 Java 在開發者最喜愛的編程語言榜中排名第二。

一般在討論 Rust 的時候,會跟 C++ 一起比較,通常會使用 C++ 是因為要開發貼近硬體,高速且穩定的系統程式,因為要接近 real time,就不能使用高階語言的 GC 機制,C/C++ 可以開發出高效率的軟體,但常會遇到有關記憶體的問題,也經常發生在底層 library 發生安全漏洞時,導致使用這些 library 的軟體一夕崩壞的問題。

C++ 的發展初期,為了跟 1972年誕生的 C 語言相容,保留了很多設計上的相容性,卻也留下很多問題。而 Rust 是一個沒有歷史包袱的程式語言,當然能吸收新的設計理念,解決安全性的問題,沒有 GC 機制,可直接編譯為machine code,可以直接跟 C 語言互通。

另一種討論,是將 Rust 跟 Golang 比較,Go 有 GC 機制,但 Rust 沒有。Rust 的語法比 Go 複雜,但 Go 更常發生執行期的 crash,Rust 支援泛型。Golang 的目標,應該是取代 Java, Python 在後端運算的地位,但 Rust 的目標,是 C/C++ 的環境,基本上,Rust 跟 Golang 的使用情境應該沒有衝突。

另外,Rust 最常被討論的,是學習曲線陡峭的問題,雖然 Rust 受到開發者的推崇,但實際上,使用 Rust 的開發者並不多,主要原因是 Rust 的用意是取代 C++,而 C++ 的學習曲線比 Rust 更陡峭,而 Rust 本身的困難點在於它接近作業系統,常常會遇到要跟 C/C++ 互通的狀況,還有 Rust 有著其他程式語言不存在的語言特性。

Installation

在 mac/linux 安裝測試環境

curl https://sh.rustup.rs -sSf | sh

他會將 rust 安裝在 $HOME/.rustup,將 cargo 安裝在 $HOME/.cargo,cargo是 rust 的套件管理工具。

另外會在 $HOME/.profile 增加 PATH 環境變數,裡面有常用的指令:rustc, cargo, and rustup

export PATH="$HOME/.cargo/bin:$PATH"

確認是否有安裝完成

$ rustc --version
rustc 1.34.2 (6c2484dc3 2019-05-13)

如果要移除就要

rustup self uninstall

官方網站提供的書本有兩本

The Rust Programming Language

Rust by example

Hello World

hello.rs

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

編譯後,就會產生執行檔

$ rustc hello.rs
$./hello
Hello, World!

另一種開發方式,是利用 cargo 產生專案

cargo new --bin hello
cd hello/

然後修改 main.rs 內容跟剛剛的 hello.rs 一樣,再利用 cargo 編譯 hello project

$ cargo run
   Compiling hello v0.1.0 (/Users/charley/Downloads/hello)
    Finished dev [unoptimized + debuginfo] target(s) in 1.44s
     Running `target/debug/hello`
Hello, world!

如果要產生 release 版,沒有 debug message 的 執行檔,就要加上 build --release 參數

cargo build --release

另外類似 Go 內建程式碼 format 工具,rust 提供 rustfmt 工具,可用 cargo 安裝這個套件

cargo install rustfmt

在 project 中,可用以下指令重排專案

cargo fmt

如果執行時發生下錯誤

$ cargo fmt
error: 'cargo-fmt' is not installed for the toolchain 'stable-x86_64-apple-darwin'
To install, run `rustup component add rustfmt --toolchain stable-x86_64-apple-darwin`

依照說明,再安裝 rustfmt component 即可

rustup component add rustfmt --toolchain stable-x86_64-apple-darwin

Multi Thread

use std::thread;

// 產生 10 個 concurrent thread
fn main() {
    // 因 greeting 是不可變的,可以安全地同時被多個線程使用
    let greeting = "Hello";

    let mut threads = Vec::new();
    // for 可處理任何實作 iterator 特型的類別
    for num in 0..10 {
        threads.push(thread::spawn(move || {
            println!("{} from thread number {}", greeting, num);
        }));
    }

    // 等待所有 thread 結束
    for thread in threads {
        thread.join().unwrap();
    }
}

執行結果

Hello from thread number 0
Hello from thread number 2
Hello from thread number 3
Hello from thread number 1
Hello from thread number 4
Hello from thread number 5
Hello from thread number 6
Hello from thread number 7
Hello from thread number 8
Hello from thread number 9

thead之間是透過 channel 傳遞訊息

use std::thread;
use std::sync::mpsc::channel;

fn main() {
    // 產生 channel,channel 有 tx, rx 兩端
    let (tx, rx) = channel();

    // spawn a new thread,在 thread 中持續使用 channel 的 rx 接收訊息
    let join_handle = thread::spawn(move || {
        // 在 loop 中持續接收訊息,直到 tx 被 dropped
        // recv() 是 blocking method
        while let Ok(n) = rx.recv() {
            println!("Received {}", n);
        }
    });

    // 因為 rx 已經被 thread 使用了,不能在這邊使用到 rx,如果用到就會產生 compile error
    // 透過 tx 發送 10 個訊息
    // 如果接收端 被 dropped,那麼呼叫 unwrap() 就會發生 crash
    for i in 0..10 {
        tx.send(i).unwrap(); // send() 不是 blocking call
    }

    // drop tx 時,會讓 rx.recv() 收到 Err(_)
    drop(tx);

    // 等待 thread 結束
    join_handle.join().unwrap();
}

執行結果

Received 0
Received 1
Received 2
Received 3
Received 4
Received 5
Received 6
Received 7
Received 8
Received 9

Web Framework

如果要開發 web project,參考這兩個網頁的資訊

What are the best web frameworks for Rust?

Rust web framework comparison

可選用Actix 或是 Rocket,其中 Actix 的支援範圍最廣,支援 https, http client, WebSocket, asynchronous

另外因為 Rust 可直接編譯為 WebAssembly,故可以在網頁上運作。

使用 Actix 開發的 web project,雖然看起來不適合開發大型動態網頁的資料,但應該會適合開發 microservice,提供網頁微服務。

References

Rust wiki

「Rust」可進行安全的系統程式設計

如何看待 Rust 的應用前景?

[Rust] 程式設計教學:基礎概念

【譯】Tokio 內部機制:從頭理解 Rust 非同步 I/O 框架

我們為什麼要選擇小眾語言 Rust 來實現 TiKV?

【譯】Rust vs. Go

明明很好很強大,Rust 卻還是那麼小眾

「RustConAsia 2019」如何高效學習Rust

沒有留言:

張貼留言