初學 Rust 有感而發 20221221

宇潤發表於2022-12-22

前言

最近,宇潤突然想學下很火熱的 Rust 語言,畢竟連著名大噴子 linus 都接納了 Rust,肯定有它的可取之處。

透過這篇文章來分享一下,我學習 Rust 語言的經驗心得,如有說得不對請輕噴。

Rust 語言官網:https://www.rust-lang.org/zh-CN

竟然有官方中文,表揚!

安裝

首先要來安裝 Rust,我是打算在 wsl 裡開發,所以安裝了 Linux 版本。(當然 Windows 甚至有安裝包,也是很方便)

Rust 安裝:https://www.rust-lang.org/zh-...

一句話安裝:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

跟我想象中的完全不一樣,不用梯子也可以很快下載好,安裝也不用很繁瑣的步驟,讓我不敢相信已經裝完了。

編輯器

我是 VSCode 的忠實使用者,寫 PHP、H5、C、C++ 都是用 VScode 寫的,這次學 Rust 也不例外。

搜了一下 “Rust” 關鍵詞,遇事不決,選擇下載量最多的:rust-analyzer

如何學習

好久沒有學過新的語言了,反正每次剛入門的時候都是最頭大的。

我選擇直接看官方文件,透過一些例子來了解語言的基本特性和寫法等等。

學習 Rust:https://www.rust-lang.org/zh-...

練手專案

接下來就是找個小專案練練手,融會貫通,爭取成功入門。

現在新生代的語言出廠自帶包管理器已經成為了標配,Rust 的包管理器叫作 Cargo。

我先建立一個專案目錄,然後在裡面執行:cargo init

這樣一個專案骨架就生成好了。

接下來就是將前面學習基本特性階段的知識拿過來搭積木了,當然中間遇到了很多問題,透過查文件、百度、Google、不斷除錯最終都順利解決。


cargo 拉依賴如果慢的話,需要在 ~/.cargo/config.toml 中配置國內映象源:

[source.crates-io]
replace-with = 'ustc'

[source.ustc]
registry = "https://mirrors.ustc.edu.cn/crates.io-index"

經過我的努力,終於完成了一個簡易 Webhook 服務,支援 Gitee 和 Github。

rust-webhook:https://github.com/Yurunsoft/...

由於是一個非常非常非常簡單的小專案,裡面用到的特性非常少,可能離入門還有很長一段距離。

總結

變數預設不可變

Rust 的變數預設是不可變的,我覺得他就不應該叫他變數。

fn main() {
    let a = 1;
    a = 2; // 編譯不透過,變數 a 不可變
    println!("a={}!", a);
}

你得給變數宣告 mut,那這個變數才是可變的。

fn main() {
    let mut a = 1;
    a = 2;
    println!("a={}!", a);
}

值得一提的是,大部分場景,編譯器會猜測你的變數型別,而不必宣告型別。當然你也可以宣告變數型別。

記憶體管理

Rust 不像 C/C++ 需要 mallocfree,或者 newdelete,也不像其它高階語言一樣有引用計數自動垃圾回收機制。

Rust 是透過借用機制管理記憶體的,這也是為什麼 Rust 號稱比 C/C++ 更加記憶體安全,並且比其它高階語言效能更好。

例子1-編譯報錯:

fn main() {
    let a = String::from("test");
    let b = a; // 賦值:a 被 b 借用,a 變數不再可用
    println!("a={}!", a); // 編譯不透過,a 變數被借用不可用
    println!("b={}!", b);
}

例子1-透過編譯:

fn main() {
    let a = String::from("test");
    let b = &a; // 引用
    println!("a={}!", a);
    println!("b={}!", b);
}

例子2-編譯報錯:

fn main() {
    let a = String::from("test");
    test(a); // 傳參:a 被傳參借用,a 變數不再可用
    println!("a={}!", a); // 編譯不透過,a 變數被借用不可用
}

fn test(str: String) {
    println!("str={}!", str);
}

例子2-透過編譯:

fn main() {
    let a = String::from("test");
    test(&a); // 引用傳參
    println!("a={}!", a);
}

fn test(str: &String) {
    println!("str={}!", str);
}

錯誤處理

Rust 預設不會捕獲錯誤,我們需要在每個方法呼叫之後,跟上 .unwrap() 讓它自動處理,如果這個函式返回錯誤就失敗。

use std::fs;

fn main() {
    let data = fs::read("1.txt").unwrap();
    println!("data={:?}", data);
}

或者捕獲後丟擲自定義資訊:

use std::fs;

fn main() {
    let data = fs::read("1.txt").expect("我是錯誤資訊");
    println!("data={:?}", data);
}

個人感覺 Rust 的錯誤處理相比 Go 要好一些,但也不是太優雅,會造成程式碼非常囉嗦。

最後總結

Rust 語言是一個非常“陰間”的程式語言,寫起來跟我們通常用的程式語言思路都不一樣。

初上手時候,腦細胞會消耗得非常多,如果你也在學 Rust,不妨多吃點補腦食物。

符號過多也是個問題,閱讀程式碼有些眼花繚亂。

這篇水文主要列了一些跟主流語言差異大的部分,並不是覺得這些特性不好,只不過我還沒習慣。

目前也只是淺嘗輒止,後面我會尋找使用場景,繼續深入研究。

相關文章