1. &str:字串切片
&str 是字串切片,代表指向一段 UTF-8 編碼文字的參考,通常來自字串常值或 String 的借用,內容不可變。
範例:
fn main() {
let s_literal: &str = "hello"; // 字串常值型別就是 &str
println!("{}", s_literal);
let s = String::from("world");
let slice: &str = &s[..]; // 從 String 借用成 &str
println!("{}", slice);
}
輸出:
hello
world
2. String:擁有型字串
String 是 Rust 提供的可成長、可變的字串型別,存在堆積 (heap) 上,可以動態新增內容,也可以透過 & 借用轉成 &str。
範例:
fn main() {
let mut s = String::from("hello");
s.push_str(", world!"); // 可變
println!("{}", s);
}
輸出:
hello, world!
3. String 與 &str 的關係
String 是擁有者,可以修改內容。&str 是借用的一段文字,通常不可變。
幾乎所有需要字串參數的函數,習慣寫成 &str,因為更通用,其可以接受字串常值和 String。
範例:
fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let s1 = String::from("Alice");
let s2 = "Bob";
greet(&s1); // String 借用成 &str
greet(s2); // 字串常值直接就是 &str
}
輸出:
Hello, Alice!
Hello, Bob!
4. 轉換方法
&str → String:使用 to_string() 或 String::from()。
String → &str:用 &s 或 &s[..]。
範例:
fn main() {
let slice: &str = "hello";
let s: String = slice.to_string(); // &str → String
let slice2: &str = &s; // String → &str
println!("slice = {}, s = {}, slice2 = {}", slice, s, slice2);
}
輸出:
slice = hello, s = hello, slice2 = hello
5. 常見錯誤:ownership 與借用
fn main() {
let s = String::from("hello");
let slice = &s[0..2]; // &str
println!("slice = {}", slice);
// s.push('!'); //編譯錯:因為有不可變借用存在,不能同時有可變借用」。
}
這提醒我:String 和 &str 的關係其實就是擁有和借用。
6. 學習心得與補充
今天的學習讓我把字串這一塊弄得更清楚了。以前用 C/C++ 處理字串常常要注意字元陣列和指標,而在 Rust 裡 String 和 &str 的分工就很乾淨,一個是擁有的可變字串,另一個是借用的不可變切片。這也讓我理解為什麼大多數函數都用 &str 當參數,因為它更通用,不論是字串常值還是 String 都能直接使用。連接到前幾天學到的所有權和切片,我覺得 String 與 &str 就是最常見的實際案例,它把借用和不可變性的概念結合起來了。雖然一開始覺得兩種字串型別讓事情更複雜,但實際練習後反而覺得設計得很合理,因為它把責任和用途切分得清楚,讓程式意圖更明確。