結(jié)構(gòu)體是創(chuàng)建更復(fù)雜的數(shù)據(jù)類型的一種方式。例如,如果我們做涉及在二維空間中的坐標(biāo)計(jì)算時(shí),我們可能既需要 x 的值,也需要 y 的值:
let origin_x = 0;
let origin_y = 0;
一個(gè)結(jié)構(gòu)體讓我們將二者結(jié)合成為一個(gè)單一的,統(tǒng)一的數(shù)據(jù)類型:
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
這里有許多東西需要講,所以先在這里打斷一下。我們用一個(gè) struct 關(guān)鍵字來(lái)聲明一個(gè)結(jié)構(gòu)體 ,同時(shí) struct 后跟著此結(jié)構(gòu)體的名字。按照慣例,結(jié)構(gòu)體以大寫(xiě)字母開(kāi)頭,同時(shí)都為駝峰式書(shū)寫(xiě):PointInSpace ,而不是Point_In_Space。
我們可以通過(guò) let 來(lái)創(chuàng)建一個(gè)我們的結(jié)構(gòu)體的實(shí)例,像往常一樣,但是我們使用一個(gè)關(guān)鍵字:值的語(yǔ)法風(fēng)格來(lái)設(shè)置每個(gè)字段。不要求順序與原始聲明的順序相同。
最后,因?yàn)樽侄涡枰Q,我們可以通過(guò)點(diǎn)符號(hào)來(lái)訪問(wèn)字段:origin.x。
在默認(rèn)情況下,結(jié)構(gòu)體中的值像 Rust 中的其他綁定一樣都是不可變的。我們使用 mut 關(guān)鍵字來(lái)使它們?yōu)榭勺儯?
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
println!("The point is at ({}, {})", point.x, point.y);
}
以上代碼將打印 The point is at (5, 0)。
Rust 在語(yǔ)言層面不支持字段可變性,所以你不能像以下這樣書(shū)寫(xiě)代碼:
struct Point {
mut x: i32,
y: i32,
}
可變性是綁定的一個(gè)屬性,而不是結(jié)構(gòu)體本身。如果你習(xí)慣于字段級(jí)別可變性,第一次用起來(lái)會(huì)感覺(jué)很奇怪,但是它極大的簡(jiǎn)化了一些東西。它甚至允許您使某東西為可變,但是僅僅適用于短時(shí)間內(nèi):
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
let point = point; // this new binding can’t change now
point.y = 6; // this causes an error
}
一個(gè)結(jié)構(gòu)體可以包含 .. 來(lái)表明你想要使用一些其他結(jié)構(gòu)體的副本用于某些值。例如:
struct Point3d {
x: i32,
y: i32,
z: i32,
}
let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };
以上代碼中給了 point 結(jié)構(gòu)體一個(gè)新的 y,但是仍然保持 x 和 z 的原來(lái)的值。它也并不一定是相同的結(jié)構(gòu)體,當(dāng)你想要添加新的變量時(shí)可以使用這個(gè)語(yǔ)法,同時(shí)它會(huì)復(fù)制你沒(méi)有指定的值:
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };
Rust 有另外一個(gè)數(shù)據(jù)類型就像一個(gè)數(shù)組與一個(gè)結(jié)構(gòu)體的混合,稱為“數(shù)組結(jié)構(gòu)體”。數(shù)組結(jié)構(gòu)體有一個(gè)名字,但是它們的字段沒(méi)有名字:
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
以上代碼中的兩個(gè)結(jié)構(gòu)體不相等,即使它們有相同的值:
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
與數(shù)組結(jié)構(gòu)體相比,使用結(jié)構(gòu)體幾乎總是比較好。我們可以像如下代碼一樣書(shū)寫(xiě) Color 和 Point:
struct Color {
red: i32,
blue: i32,
green: i32,
}
struct Point {
x: i32,
y: i32,
z: i32,
}
現(xiàn)在,我們有真正的名字,而不是位置。好名字固然重要,同時(shí),結(jié)構(gòu)體我們需要有真正的名字。
在一種情況下,數(shù)組結(jié)構(gòu)體非常有用,盡管,那樣一個(gè)數(shù)組結(jié)構(gòu)體僅包含一個(gè)元素。我們稱之為‘新型’模式,因?yàn)樗试S我們創(chuàng)建一個(gè)新的類型,不同于其包含的值,并表示它自己的語(yǔ)義:
struct Inches(i32);
let length = Inches(10);
let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
正如你所看到的,你可以通過(guò)一個(gè)非結(jié)構(gòu)化的 let 關(guān)鍵字來(lái)提取內(nèi)在的整數(shù)類型,正如通常的數(shù)組一樣。在這種情況下,let Inches(integer_length) 將 10 賦值給 integer_length。
你可以定義一個(gè)根本沒(méi)有任何成員的結(jié)構(gòu)體:
struct Electron;
這樣的結(jié)構(gòu)體被稱為 ‘unit-like’ ,因?yàn)樗愃朴诳諗?shù)組,(),有時(shí)被稱為 ‘unit’。與數(shù)組結(jié)構(gòu)體一樣,它定義了一個(gè)新的類型。
這種結(jié)構(gòu)體通常對(duì)自己沒(méi)有什么用處(雖然它有時(shí)可以作為一個(gè)標(biāo)記類型使用),但是結(jié)合其他的功能,它可以變的有用。例如,一個(gè)庫(kù)可能想要要求你創(chuàng)建一個(gè)可以實(shí)現(xiàn)某些特定特征的結(jié)構(gòu)體來(lái)處理事件。如果你沒(méi)有需要在結(jié)構(gòu)體中存儲(chǔ)的數(shù)據(jù),你可以只創(chuàng)建一個(gè) unit-like 結(jié)構(gòu)體。
更多建議: