Rust 勸退系列 03:變量

大家好,我是站長 polarisxu。

這是 Rust 勸退系列的第 3 個教程,探討 Rust 中的變量。

01 變量和綁定

變量指定了某存儲單元(Memory Location)的名稱,該存儲單元會存儲特定類型的值。

Rust 是靜態類型語言,不能在運行期改變變量類型。

和你熟悉的大部分編程語言不一樣,Rust 中變量一般不叫聲明,而叫做綁定(這是從函數式語言中借鑑的,使用關鍵字 let 綁定),那有什麼區別呢?

在 Go 語言中一般有下面幾種聲明變量的方式:

var age = 10
var age int
var age int = 10
age := 10 // 只能在函數內部使用
// 可以分組
var (
 age = 10
  birthday = "01-01"
)

Go 中聲明變量,可以不指定類型(會進行類型推導),也可以不給初始值(會有默認初始值)。

而 Rust 中,形式比較少,主要有兩種:

let age = 10;
let age: i32 = 10;

和 Go 一樣,大部分時候,Rust 也能夠推導出類型。在顯示指定類型時,需要加上 :。關於類型,後續講解。

那爲什麼 Rust 中變量創建一般叫做綁定呢?

1)Rust 和 C 一樣,變量創建後必須初始化後才能使用(未使用的變量會警告)。以下代碼編譯報錯:

fn main() {
    let age: i32;
    println!("age is {}", age);
}
// error[E0381]: borrow of possibly-uninitialized variable: `age`

2)Rust 中,通過 let 關鍵字,在標識符(如變量 age)與值(如 10)之間建立起一種關聯關係。表明所有權關係。也就是說這塊內存現在屬於 age 了。

熟悉 JS 的朋友,應該對 var 和 let 很親切,不過兩者的區別和 Go 中的 var 與 Rust 的 let 區別不一樣。

02 可變性

第一次看到下面的代碼報錯,你肯定特別的驚訝:

fn main() {
    let age = 10;
    println!("age is {}", age);
    age = 11;
    println!("age is {}", age);
}
// error[E0384]: cannot assign twice to immutable variable `age`

沒錯,Rust 中的變量默認是不可變的(好吧,變量不可變。。。但又不是常量)。這也是 Rust 中內存管理很重要的一個特性。

如果我想變量可變,怎麼辦?Rust 提供了關鍵字 mut,這叫做可變綁定:

fn main() {
    let mut age = 10;
    println!("age is {}", age);
    age = 11;
    println!("age is {}", age);
}

通常,我們應該優先創建不可變變量,只有真的需要時,才使用可變變量。

03 隱藏(shadow)

因爲變量默認不可變,Rust 中還存在這樣「詭異」的情況。下面代碼一切正常:

fn main() {
    let age = 10;
    println!("age is {}", age);
    let age = 11;
    println!("age is {}", age);
}

在 Go 中,肯定報重複聲明。

這種「重複」創建同名變量的語法,Rust 中叫做隱藏(Shadow)。也就是說上次創建的被這次創建的隱藏了。具體有什麼用呢?

比如類似這樣的代碼,在 Go 中還是比較常見的:

ageStr := req.FormValue("age")
age, err := strconv.Atoi(ageStr)

也就是說,同樣的數值,因爲類型不同,需要用兩個不同名稱的變量表示。但 Rust 中可以這樣:

fn main() {
    let age = "10";
    let age = age.parse::<i32>().unwrap();
    println!("age is {}", age);
}

不過這種語法有好處也有弊端。當涉及到作用域時,要特別注意隱藏的問題。這和 Go 中的簡短聲明(:=)的「坑」很像。類似下面這樣的代碼,最後的 age 依然是 10:(實際中的代碼一般不會這麼明顯)

fn main() {
    let age = 10;
    {
        let age = "abc";
        println!("age is {}", age);
    }
    println!("age is {}", age);
}
// age is abc
// age is 10

可見,隱藏只會其所屬作用域內生效。

04 小結

Rust 是靜態類型語言,運行期間不能改變變量類型。

本節內容還是比較簡單的,但要注意和你所學語言不同的點以及可能的坑。沒被勸退吧~

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/VheT027N71946GyoT3BxTw