基本型別

Rust 語言有許多被認為是「基本」(primitive)的型別。 這代表它們是內建在語言內的。 Rust 標準函式庫也提供許多基於這些基本型別的有用型別,它們也是基本型別。

布林(Booleans)

Rust 內建布林型別,叫做 bool。 他有兩種值,truefalse

let x = true;

let y: bool = false;

布林通常用在 if 條件運算式

你可以在 標準函式庫文件 中找到更多關於 bool 的文件。

char

char 型別代表一個 Unicode 值。 你可以以單引號(')建立 char

let x = 'x';
let two_hearts = '💕';

不像其他語言,這代表 Rust 的 char 並非一個位元組,而是四個。

你可以在 標準函式庫文件 中找到更多關於 char 的文件。

數字型別

Rust 有許多數字型別,分為一些不同類型:帶號(signed)和非帶號(unsigned),固定長度和可變長度,浮點數和整數。

這些型別包含兩部分:類型和大小。 例如,u16 是一個 16 位元大小的非帶號型別。 更多位元能讓你有更大的數字。

如果數字在字面上沒有其他東西可以推測他的型別,它會使用預設型別:

let x = 42; // x has type i32

let y = 1.0; // y has type f64

這裡有一份不同數字型別的清單,以及它們在標準函式庫中的文件連結:

讓我們依照分類走一輪吧:

帶號(Signed)及非帶號(Unsigned)

整數型別有兩種變形:帶號跟非帶號。 要了解差異之處,讓我們試想有一個 4 位元大小的數字。 如果是帶號整數,4 位元可以讓你儲存 -8+7 的數字。 代號數字使用「二補數表示法」(two's complement)。 一個非帶號的 4 位元數字因為不需要儲存負號,所以可以儲存 0+15 的數字。

非帶號型別使用 u 作為分類,而帶號型別使用 ii 代表「integer」。 所以 u8 代表一個 8 位元的非代號數字,而 i8 代表 8 位元的帶號數字。

固定大小型別

固定大小型別的表現方式有一些特定數量的位元。 有效的位元大小有 8163264。 所以 u32 是一個非帶號的 32 位元整數,而 i64 是一個帶號的 64 位元整數。

可變大小型別

Rust 也有提供一些大小依賴於底層機器的指標大小的型別。 這些型別的分類是「size」,且分為帶號跟非帶號。 他分為兩類:isizeusize

浮點數型別

Rust 也有兩種浮點數:f32f64。 他們對應到 IEEE-754 的單精準度和雙精準度浮點數。

陣列(Arrays)

跟很多程式語言一樣,Rust 有用來表現一組事物的清單型別。 最基本的就是 陣列(array),一個固定大小、有相同型別的元素清單。 陣列預設是不可變的(immutable)。

let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // m: [i32; 3]

陣列的型別是 [T; N]。 我們將在 泛型的章節 提到 T 標記。 N 是一個編譯期的常數,代表陣列的長度。

有一個可以初始化陣列中所有元素為同一個值的簡寫。 在以下範例,所有 a 中的元素將被初始化為 0

let a = [0; 20]; // a: [i32; 20]

你可以透過 a.len() 取得 a 陣列中元素的個數:

let a = [1, 2, 3];

println!("a has {} elements", a.len());

你也可以使用 下標(subscript)的標記方式存取陣列中特定元素:

譯註:此處的 下標 應指 [n] 這個標記方式。

let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]

println!("The second name is: {}", names[1]);

與其他大多數程式語言一樣,下標從零開始,所以第一個元素名稱是 names[0],第二個名稱是 names[1]。 上述範例會印出 The second name is: Brian。 如果你嘗試使用超出陣列的下標,你會得到錯誤訊息:陣列存取會在執行期做邊界檢查。 在其他系統程式語言中,這種不當存取是許多程式錯誤(bug)的根源。

你可以在 標準函式庫文件 中找到更多關於 array 的文件。

Slices

一個「slice」是一個其他資料結構的 reference(或「視圖」)。 它允許安全、有效的存取陣列的一部份而不用複製陣列。 例如,你可能只想要參考讀到記憶體中的檔案中的某一行。 本質上,一個「slice」不是直接建立的,而要從一個已經存在的變數綁定中建立。 Slices 會定義長度,它可以是可變(mutable)或不可變(immutable)。

從內部來看,slices 像是一個指向資料開頭的指標,和它的長度。

Slicing 語法

你可以使用 &[] 的組合去從許多資料結構建立 slice。 & 說明了 slices 跟 參照(references)很類似,我們會在本節的後面說到細節。 [] 帶有範圍的資訊,讓你定義 slice 的長度。

let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // A slice containing all of the elements in a
let middle = &a[1..4]; // A slice of a: only the elements 1, 2, and 3

Slices 的型別是 &[T]。 我們將會在 泛型 談到 T

你可以在 標準函式庫文件 中找到更多關於 slices 的文件。

str

Rust 的 str 型別是最基本的字串型別。 跟 動態大小型別 一樣,它本身不是很有用,但當它放在 reference 之後就很有用了,像是 &str。 當我們談到 字串參照(references)的時候再來細說。

你可以在 標準函式庫文件 中找到更多關於 str 的文件。

多元組(Tuples)

一個多元組(tuple)是一組固定大小的有序(ordered)清單。 就像:

let x = (1, "hello");

這是長度為 2 的多元組,由括弧和逗號組成。 以下是同樣的程式碼,但是多了型別註釋:

let x: (i32, &str) = (1, "hello");

如你所見,多元組的型別與多元組很像,只是各個位置是型別名稱而不是數值。 心細的讀者會注意到多元組是異質的(heterogeneous):我們在一個多元組中同時有 i32&str。 在系統程式語言中,字串會比其他語言複雜一點。 現在,把 &str 當作 字串 slice,我們很快就會說到。

當兩個多元組有相同的型別和 元數(arity)時,你可以把一個多元組賦值給另一個。 相同長度的多元組有著相同的元數。

let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)

x = y;

你可以透過 destructuring let 存取多元組的欄位。 以下是範例:

let (x, y, z) = (1, 2, 3);

println!("x is {}", x);

還記得 之前 當我提到 let 陳述式的左邊遠比賦值綁定還強大嗎? 這就是了。 我們可以放一個模式(pattern)在 let 的左邊,然後如果它跟右邊相符,我們就可以一次賦值多個綁定。 在這情形下,let「解構」或「拆開」多元組,然後賦值到三個綁定上。

這樣的模式非常強大,我們將會在後面一直看到。

在括號中只有一個值時,在值後面加上逗號,可以消歧義確定它是一個單元素的多元組:

(0,); // single-element tuple
(0); // zero in parentheses

多元組索引(Tuple Indexing)

你也可以用索引語法去存取多元組的欄位:

let tuple = (1, 2, 3);

let x = tuple.0;
let y = tuple.1;
let z = tuple.2;

println!("x is {}", x);

就像陣列的索引,它從零開始,但是不像陣列所以,它使用 . 而不是 []

你可以在 標準函式庫文件 中找到更多關於多元組的文件。

函式

函式也有型別! 它們像這樣:

fn foo(x: i32) -> i32 { x }

let x: fn(i32) -> i32 = foo;

在這個例子中,x 是「函式指標」,指向一個有 i32 參數並回傳 i32 的函式。

commit 228afd7