Borrowing & References
TypeScript ส่ง reference อย่างอิสระ — Rust track ทุก reference
หัวข้อที่มีชื่อว่า “TypeScript ส่ง reference อย่างอิสระ — Rust track ทุก reference”ใน TypeScript การส่ง object ไปให้ function ส่ง reference ให้ ทั้ง caller และ callee สามารถอ่านและเขียน object พร้อมกันได้ ภาษาไม่มีข้อจำกัดว่ามี reference กี่ตัวหรือทำอะไรได้บ้าง
Borrow checker ของ Rust บังคับใช้กฎเข้มงวดเกี่ยวกับ reference ตั้งแต่ compile time กฎเหล่านี้ป้องกัน data race, dangling pointer, และ use-after-free — ทั้งหมดโดยไม่มีต้นทุน runtime
Shared reference — &T
หัวข้อที่มีชื่อว่า “Shared reference — &T”Shared reference (&T) ให้คุณอ่าน value โดยไม่รับ ownership สามารถมี shared reference ได้หลายตัวพร้อมกัน
// TypeScript — ส่ง reference แค่นั้น (ไม่มีกฎ)function getLength(s: string): number { return s.length;}
const greeting = "hello";const len = getLength(greeting);console.log(greeting, len); // ทั้งคู่ยังใช้ได้fn get_length(s: &String) -> usize { s.len() // เรา borrow s — ไม่สามารถ move ออกจากมัน}
fn main() { let greeting = String::from("hello"); let len = get_length(&greeting); // ยืม greeting ให้ function println!("{} has {} chars", greeting, len); // greeting ยังใช้ได้ — เราแค่ยืมมัน}Mutable reference — &mut T
หัวข้อที่มีชื่อว่า “Mutable reference — &mut T”Mutable reference (&mut T) ให้คุณทั้งอ่านและแก้ไข value แต่ Rust มีกฎ exclusive: ตราบใดที่ &mut reference ยังอยู่ ห้ามมี reference อื่นใด — ไม่ว่า shared หรือ mutable — พร้อมกัน
// TypeScript — ไม่มีข้อจำกัดสำหรับ read + write พร้อมกันfunction appendWorld(s: { value: string }): void { s.value += ", world";}
const msg = { value: "hello" };appendWorld(msg);console.log(msg.value); // "hello, world"fn append_world(s: &mut String) { s.push_str(", world");}
fn main() { let mut s = String::from("hello"); append_world(&mut s); println!("{}", s); // "hello, world"
// หลาย shared ref ใช้ได้ — ไม่มีการ mutate let r1 = &s; let r2 = &s; println!("{} and {}", r1, r2);}Error ของ borrow checker แบบ classic
หัวข้อที่มีชื่อว่า “Error ของ borrow checker แบบ classic”นี่คือ error ที่พบบ่อยที่สุดสำหรับ Rust developer มือใหม่ โค้ดด้านล่างพยายาม hold shared reference และ mutable reference พร้อมกัน:
fn main() { let mut s = String::from("hello");
let r1 = &s; // shared borrow เริ่ม let r2 = &s; // shared borrow อีกตัว — ยังโอเค let r3 = &mut s; // ERROR: cannot borrow `s` as mutable because it is also borrowed as immutable
println!("{}, {}, {}", r1, r2, r3);}// error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable// --> src/main.rs:6:14// |// 4 | let r1 = &s;// | -- immutable borrow occurs here// 6 | let r3 = &mut s;// | ^^^^^^ mutable borrow occurs here// 7 | println!("{}, {}, {}", r1, r2, r3);// | -- immutable borrow later used hereการแก้ไขง่าย: ทำให้แน่ใจว่า shared และ mutable borrow ไม่ overlap กัน ให้ shared borrow จบก่อน (จบเมื่อถูกใช้ครั้งสุดท้าย) แล้วค่อย take mutable borrow:
ลองเขียนเอง
หัวข้อที่มีชื่อว่า “ลองเขียนเอง”fn append_world(s: &mut String) { s.push_str(", world");}
fn main() { let mut s = String::from("hello"); append_world(&mut s); println!("{}", s);
// multiple shared refs are fine let r1 = &s; let r2 = &s; println!("{} and {}", r1, r2);}Compiling…