原生類型
像其他現代編程語言一樣,Rust提供了一系列基礎的類型,我們一般稱之為原生類型。其強大的類型系統就是建立在這些原生類型之上的,因此,在寫Rust代碼之前,必須要對Rust的原生類型有一定的瞭解。
bool
Rust自帶了bool類型,其可能值為true或者false。
我們可以通過這樣的方式去聲明它:
#![allow(unused)] fn main() { let is_she_love_me = false; let mut is_he_love_me: bool = true; }
當然,bool類型被用的最多的地方就是在if表達式裡了。
char
在Rust中,一個char類型表示一個Unicode字符,這也就意味著,在某些語言裡代表一個字符(8bit)的char,在Rust裡實際上是四個字節(32bit)。
同時,我們可以將各種奇怪的非中文字符隨心所欲的賦值給一個char類型。需要注意的是,Rust中我們要用'來表示一個char,如果用"的話你得到的實際上是一個&'static str。
#![allow(unused)] fn main() { let c = 'x'; let cc = '王'; }
數字類型
和其他類C系的語言不一樣,Rust用一種符號+位數的方式來表示其基本的數字類型。可能你習慣了int、double、float之類的表示法,Rust的表示法需要你稍微適應一下。
你可用的符號有 i、f、u
你可用的位數,當然了,都是2的n次冪,分別為8、16、32、64及size。
你可以將其組合起來,形成諸如i32,u16等類型。
當然了,這樣的組合並不自由,因為浮點類型最少只能用32位來表示,因此只能有f32和f64來表示。
自適應類型
看完上面你一定會對isize和usize很好奇。這兩個是來幹啥的。這兩個嘛,其實是取決於你的操作系統的位數。簡單粗暴一點比如64位電腦上就是64位,32位電腦上就是32位,16位……呵呵噠。
但是需要注意的是,你不能因為你的電腦是64位的,而強行將它等同於64,也就是說isize != i64,任何情況下你都需要強制轉換。
數組 array
Rust的數組是被表示為[T;N]。其中N表示數組大小,並且這個大小一定是個編譯時就能獲得的整數值,T表示泛型類型,即任意類型。我們可以這麼來聲明和使用一個數組:
#![allow(unused)] fn main() { let a = [8, 9, 10]; let b: [u8;3] = [8, 6, 5]; print!("{}", a[0]); }
和Golang一樣,Rust的數組中的N(大小)也是類型的一部分,即[u8; 3] != [u8; 4]。這麼設計是為了更安全和高效的使用內存,當然了,這會給第一次接觸類似概念的人帶來一點點困難,比如以下代碼。
fn show(arr: [u8;3]) { for i in &arr { print!("{} ", i); } } fn main() { let a: [u8; 3] = [1, 2, 3]; show(a); let b: [u8; 4] = [1, 2, 3, 4]; show(b); }
編譯運行它你將獲得一個編譯錯誤:
<anon>:11:10: 11:11 error: mismatched types:
expected `[u8; 3]`,
found `[u8; 4]`
(expected an array with a fixed size of 3 elements,
found one with 4 elements) [E0308]
<anon>:11 show(b);
^
<anon>:11:10: 11:11 help: see the detailed explanation for E0308
error: aborting due to previous error
這是因為你將一個4長度的數組賦值給了一個只需要3長度數組作為參數的函數。那麼如何寫一個通用的show方法來展現任意長度數組呢?請看下節Slice
Slice
Slice從直觀上講,是對一個Array的切片,通過Slice,你能獲取到一個Array的部分或者全部的訪問權限。和Array不同,Slice是可以動態的,但是呢,其範圍是不能超過Array的大小,這點和Golang是不一樣的。
一個Slice的表達式可以為如下: &[T] 或者 &mut [T]。
這裡&符號是一個難點,我們不妨放開這個符號,簡單的把它看成是Slice的甲魚臀部——規定。另外,同樣的,Slice也是可以通過下標的方式訪問其元素,下標也是從0開始的喲。
你可以這麼聲明並使用一個Slice:
#![allow(unused)] fn main() { let arr = [1, 2, 3, 4, 5, 6]; let slice_complete = &arr[..]; // 獲取全部元素 let slice_middle = &arr[1..4]; // 獲取中間元素,最後取得的Slice為 [2, 3, 4] 。切片遵循左閉右開原則。 let slice_right = &arr[1..]; // 最後獲得的元素為[2, 3, 4, 5, 6],長度為5。 let slice_left = &arr[..3]; // 最後獲得的元素為[1, 2, 3],長度為3。 }
怎麼樣,瞭解了吧。
那麼接下來我們用Slice來改造一下上面的函數
fn show(arr: &[u8]) { for i in arr { print!("{} ", i); } println!(""); } fn main() { let a: [u8; 3] = [1, 2, 3]; let slice_a = &a[..]; show(slice_a); let b: [u8; 4] = [1, 2, 3, 4]; show(&b[..]); }
輸出
1 2 3
1 2 3 4
動態數組 Vec
熟悉C++ STL的同學可能對C++的vector很熟悉,同樣的,Rust也提供了一個類似的東西。他叫Vec。
在基礎類型裡講Vec貌似是不太合適的,但在實際應用中的應用比較廣泛,所以說先粗略的介紹一下,在集合類型的章節會有詳細講述。
在Rust裡,Vec被表示為 Vec<T>, 其中T是一個泛型。
下面介紹幾種典型的Vec的用法:
#![allow(unused)] fn main() { let mut v1: Vec<i32> = vec![1, 2, 3]; // 通過vec!宏來聲明 let v2 = vec![0; 10]; // 聲明一個初始長度為10的值全為0的動態數組 println!("{}", v1[0]); // 通過下標來訪問數組元素 for i in &v1 { print!("{}", i); // &Vec<i32> 可以通過 Deref 轉換成 &[i32] } println!(""); for i in &mut v1 { *i = *i+1; print!("{}", i); // 可變訪問 } }
輸出結果:
1
123
234
最原生字符串 str
你可以用str來聲明一個字符串,事實上,Rust中,所有用""包裹起來的都可以稱為&str(注意這個&,這是難點,不用管他,不是麼?),但是這個類型被單獨用的情況很少,因此,我們將在下一節著重介紹字符串類型。
函數類型 Functions
函數同樣的是一個類型,這裡只給大家普及一些基本的概念,函數類型涉及到比較高階的應用,希望大家能在後面的閉包章節仔細參讀
下面是一個小例子
#![allow(unused)] fn main() { fn foo(x: i32) -> i32 { x+1 } let x: fn(i32) -> i32 = foo; assert_eq!(11, x(10)); }