ชีตสรุป Rust
เอกสารอ้างอิง Rust ที่ค้นหาและพิมพ์ได้: ownership และ borrowing, traits, pattern matching, Option และ Result, iterators และ Cargo ฟรี
Basics
10let x = 5;
let mut count = 0; count += 1;
let x = "5"; let x: i32 = x.parse()?;
i32, u64, f64, bool, char, usize
let t = (1, "a"); t.0
let a = [0u8; 16];
const MAX_USERS: u32 = 100;
let n = big as u8;
let s: String; let sl: &str;
println!("{name} has {count}");
Ownership, borrowing & lifetimes
10let b = a; // a is moved
let b = a.clone();
fn read(s: &String) / read(&s)
fn edit(s: &mut String) / edit(&mut s)
// no &mut while & borrows live
fn greet(name: &str)
i32, bool, char, &T are Copy
fn first<'a>(a: &'a str, b: &str) -> &'a str
struct View<'a> { text: &'a str }
let s: &'static str = "literal";
Structs, enums & impl
10struct User { name: String, age: u32 }
let u = User { name, age: 30 };
let u2 = User { age: 31, ..u };
struct Meters(f64);
impl User { fn new(name: String) -> Self { ... } }
fn label(&self) -> String
fn rename(&mut self, n: String)
enum Shape { Circle(f64), Rect { w: f64, h: f64 } }
#[derive(Debug, Clone, PartialEq)]
let cfg = Config::default();
Pattern matching
10match n { 0 => "zero", _ => "other" }
match shape { Shape::Circle(r) => ... }
match n { 1..=5 => "low", _ => "high" }
match p { Point { x, y: 0 } => ... }
Some(n) if n > 10 => "big"
id @ 1..=9 => use(id)
if let Some(v) = opt { use(v); }
let Some(v) = opt else { return; };
while let Some(x) = stack.pop() { ... }
matches!(status, Status::Active)
Option & Result
12let opt: Option<i32> = Some(5);
let res: Result<T, E> = Ok(v);
let v = load()?;
opt.unwrap_or(0)
opt.unwrap_or_else(|| compute())
opt.unwrap_or_default()
opt.map(|v| v * 2)
opt.and_then(|v| v.checked_mul(2))
opt.ok_or(MyError::Missing)?
res.map_err(|e| AppError::Io(e))
opt.is_some(); res.is_err();
let v = opt.take();
Traits & generics
11trait Greet { fn hello(&self) -> String; }
trait Greet { fn wave(&self) { ... } }
impl Greet for User { ... }
fn welcome<T: Greet>(x: &T)
fn f<T>(x: T) where T: Greet + Clone
fn welcome(x: &impl Greet)
fn make() -> impl Iterator<Item = u32>
let objs: Vec<Box<dyn Greet>> = ...;
impl From<u32> for Meters { ... }
let m: Meters = 5u32.into();
impl fmt::Display for User { ... }
Collections
12let mut v = vec![1, 2, 3];
v.push(4); v.pop();
v.get(0) // Option<&T>
for x in &v { ... }
v.sort(); v.sort_by_key(|u| u.age);
v.retain(|x| *x > 0);
let mut m = HashMap::new(); m.insert(k, v);
*counts.entry(word).or_insert(0) += 1;
m.contains_key(&k); m.get(&k);
s.push_str("more"); format!("{a}{b}")
s.chars().rev().collect::<String>()
names.join(", ")
Iterators & closures
14v.iter().map(|x| x * 2).collect::<Vec<_>>()
.filter(|x| **x > 0)
.filter_map(|s| s.parse().ok())
.sum::<i32>(); .count(); .max()
.fold(0, |acc, x| acc + x)
.enumerate()
.zip(other.iter())
.take(5); .skip(2); .rev()
.flat_map(|l| l.split(' '))
.any(|x| x < 0); .all(|x| x > 0)
.find(|u| u.id == id); .position(...)
iter() &T; iter_mut() &mut T; into_iter() T
let add = move |x| x + base;
.collect::<HashMap<_, _>>()
Error handling
11fn run() -> Result<(), Box<dyn Error>>
fn main() -> anyhow::Result<()>
file.read().context("reading config")?;
anyhow::bail!("invalid input: {x}");
#[derive(thiserror::Error, Debug)]
#[error("user {0} not found")] NotFound(u64),
#[error(transparent)] Io(#[from] std::io::Error),
enum AppError { Db(String), Timeout }
let n = do_it()?; // Err auto-converts
opt.expect("config must be loaded")
eprintln!("error: {e:#}");
Smart pointers & interior mutability
11let b = Box::new(BigStruct::new());
enum List { Node(i32, Box<List>), Nil }
let a = Rc::new(data); let b = Rc::clone(&a);
let a = Arc::new(data);
let c = RefCell::new(0); *c.borrow_mut() += 1;
Rc<RefCell<T>>
let m = Mutex::new(0); *m.lock().unwrap() += 1;
Arc<Mutex<T>>
let l = RwLock::new(map); l.read(); l.write();
Cell::new(5).set(6);
let w = Rc::downgrade(&a); w.upgrade()
Concurrency & async
13let h = thread::spawn(|| work()); h.join()
thread::spawn(move || use(data))
thread::scope(|s| { s.spawn(|| ...); })
let (tx, rx) = mpsc::channel();
tx.send(job)?; let job = rx.recv()?;
let n = Arc::new(Mutex::new(0));
#[tokio::main] async fn main() { ... }
async fn fetch() -> Result<Data>
let data = fetch().await?;
let h = tokio::spawn(fetch()); h.await??;
let (a, b) = tokio::join!(f1(), f2());
tokio::time::sleep(Duration::from_secs(1)).await;
tokio::select! { r = f1() => ..., _ = f2() => ... }
Cargo CLI
12cargo new my-app
cargo add serde --features derive
cargo run
cargo build --release
cargo check
cargo test
cargo clippy -- -D warnings
cargo fmt
cargo doc --open
cargo update
cargo install ripgrep
cargo tree
ไม่มีรายการที่ตรงกับ “:q”
เกี่ยวกับ ชีตสรุป Rust
Rust cheat sheet นี้จัดภาษาตามแนวคิดไว้ในหน้าเดียวที่ค้นหาได้: พื้นฐาน, ownership, borrowing และ lifetimes, struct, enum และบล็อก impl, pattern matching, Option และ Result, traits และ generics, คอลเลกชัน, iterators และ closures, การจัดการข้อผิดพลาด, smart pointers และ interior mutability, concurrency และ async และบรรทัดคำสั่ง Cargo
Ownership คือส่วนที่คนมักกลับมาเปิดดู จึงมีส่วนของตัวเองอยู่ถัดจาก lifetimes, กฎของ borrowing, Box, Rc, Arc และ RefCell พร้อมไวยากรณ์ที่ใช้ทุกวัน เช่น match arms, ตัวดำเนินการ ?, iterator adapters และการ derive traits
เช่นเดียวกับ cheat sheet ทุกชุดในกลุ่มนี้ ใช้ฟรีและทำงานฝั่งไคลเอนต์: กรองแถวแบบเรียลไทม์ด้วยช่องค้นหา ข้ามระหว่างส่วนต่างๆ ด้วยสารบัญที่ติดอยู่ คัดลอกตัวอย่างโค้ดด้วยคลิกเดียว และพิมพ์หน้านี้เป็นเอกสารอ้างอิงบนโต๊ะทำงาน
วิธีใช้ ชีตสรุป Rust
- เปิดชีตและดูแต่ละส่วน ตั้งแต่ Basics และ Ownership & borrowing ไปจนถึง Cargo CLI
- ค้นหาด้วยคำสำคัญ เช่น lifetime, match หรือ Arc เพื่อกรองชีตแบบเรียลไทม์
- ข้ามไปที่ Option & Result หรือ Error handling เมื่อคุณต้องการวิธีจัดการความล้มเหลวแบบ idiomatic
- คลิกที่ตัวอย่างโค้ดหรือไอคอนคัดลอกเพื่อคัดลอกโค้ด Rust ไปยังคลิปบอร์ด
- ใช้ Print เพื่อพิมพ์เอกสารอ้างอิง Rust ฉบับเต็มลงกระดาษ