結(jié)構(gòu)體可以用于組織不同類型的數(shù)據(jù),和一些面向?qū)ο裾Z言中的 類
是很像的例书。
這篇博客包含以下內(nèi)容
- 結(jié)構(gòu)體的定義
- 通過一個函數(shù)艘策,創(chuàng)建并返回一個結(jié)構(gòu)體
- 定義一個結(jié)構(gòu)體,但數(shù)據(jù)來自另外一個結(jié)構(gòu)體
- 元祖結(jié)構(gòu)體
結(jié)構(gòu)體的定義
#[derive(Debug)] // 加上這一句通熄,就可以使用 println!("{:?}", xxx); 打印
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
結(jié)構(gòu)體以 struct
開頭,后面是我們自定義的這個結(jié)構(gòu)體類型的名字找都,里面每一個字段唇辨,以 字段名: 數(shù)據(jù)類型
的形式定義
結(jié)構(gòu)體開頭那個
#[derive(Debug)]
是為了打印而加的,也可以不加能耻,這個的意思會在后面章節(jié)學(xué)習到赏枚,現(xiàn)在我也不知道具體意思亡驰,反正加上就可以使用{:?}
的形式打印。
下面這段代碼創(chuàng)建一個結(jié)構(gòu)體實例
fn main() {
let mut user = User {
username: String::from("someone"),
email: String::from("someone@outlook.com"),
sign_in_count: 1,
active: false,
};
// 打印這個結(jié)構(gòu)體的內(nèi)容
println!("{:?}", user);
// 因為創(chuàng)建 user 的時候加了 mut饿幅,所以可以修改里面字段的內(nèi)容
user.active = true;
println!("Changed: {:?}", user);
}
通過一個函數(shù)凡辱,創(chuàng)建并返回一個結(jié)構(gòu)體
fn build_user(_username: String, _email: String) -> User {
User {
username: _username,
email: _email,
sign_in_count: 2,
active: false,
}
}
// 如果參數(shù)名和結(jié)構(gòu)體的字段名相同,則可以直接按下面的方式去賦值栗恩,
// 不需要再 aaa:bbb 這樣的形式透乾,并且順序也無所謂
fn build_user2(username: String, email: String) -> User {
User {
email,
username,
sign_in_count: 2,
active: false,
}
}
定義一個結(jié)構(gòu)體,但數(shù)據(jù)來自另外一個結(jié)構(gòu)體
#[derive(Debug)]
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user = User {
username: String::from("someone"),
email: String::from("someone@outlook.com"),
sign_in_count: 1,
active: false,
};
println!("{:?}", user);
let user2 = User {
username: String::from("user2"),
email: String::from("user2@outlook.com"),
sign_in_count: user.sign_in_count, // 使用 user 實例的數(shù)據(jù)
active: user.active, // 這個也使用 user 實例的數(shù)據(jù)
};
// 除了 username 和 email, 其他字段都使用 user 的值
let user3 = User {
username: String::from("user3"),
email: String::from("user3@outlook.com"),
..user
};
}
上面的代碼摄凡,使用其他結(jié)構(gòu)體數(shù)據(jù)续徽,創(chuàng)建新的結(jié)構(gòu)體時,我們使用的都是 簡單
的 數(shù)據(jù)類型
亲澡。如果使用 String 類型的字段钦扭,例如 username 或 email,則原有結(jié)構(gòu)體實例的數(shù)據(jù)床绪,會移動到新的結(jié)構(gòu)體實例客情。看下面的代碼癞己。
下面這段代碼編譯會出錯膀斋。
#[derive(Debug)]
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user = User {
username: String::from("someone"),
email: String::from("someone@outlook.com"),
sign_in_count: 1,
active: false,
};
let user2 = User {
..user
};
// !!!! 這一句編譯會出錯,因為我們創(chuàng)建 user2 的時候痹雅,使用了所有 user的數(shù)據(jù)仰担,
// 因為 username 和 email是String類型的,所以 所有權(quán) 會移動到 user2的對應(yīng)字段中
// 所以這句就會報錯 !!!
println!("{:?}", user.username);
}
如果要修復(fù)錯誤绩社,可以使用我們上一節(jié)學(xué)到的切片摔蓝,直接看下面的代碼
#[derive(Debug)]
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user = User {
username: String::from("someone"),
email: String::from("someone@outlook.com"),
sign_in_count: 1,
active: false,
};
let user2 = User {
username: String::from(&user.username[..]), // !!! 注意看這句
email: String::from(&user.email[..]), // !!! 還有這一句
..user
};
println!("{:?}", user.username);
println!("{:?}", user);
println!("{:?}", user2);
}
上面的代碼,在創(chuàng)建 user2 時愉耙,String類型的字段贮尉,我們通過切片,創(chuàng)建了新的 String 數(shù)據(jù)朴沿,所以沒有導(dǎo)致 所有權(quán)
轉(zhuǎn)移猜谚。
元祖結(jié)構(gòu)體
有一種結(jié)構(gòu)體,沒有具體的字段名赌渣,只有類型魏铅,這種結(jié)構(gòu)體,稱為 元祖結(jié)構(gòu)體 (tuple structs)
坚芜÷倭悖看下面的代碼
#[derive(Debug)]
struct Color(i32, i32, i32, i32);
fn main() {
let bg_color = Color(255, 0, 0, 255);
println!("{:?}", bg_color);
// 通過所引,訪問結(jié)構(gòu)體里的某個元素,與 元祖 的訪問方式一樣
let r = bg_color.0;
let g = bg_color.1;
let b = bg_color.2;
let a = bg_color.3;
}
這一節(jié)聊了一下結(jié)構(gòu)體的基本知識著隆,下一節(jié)將聊一下更多關(guān)于結(jié)構(gòu)體的東西湃窍。