Rust
エンジニアのためのWebチートシート
Rustは、安全性、速度、並行性を重視したシステムプログラミング言語です。 所有権システムによりメモリ安全性をコンパイル時に保証します。 基本構文、所有権、データ型、トレイト、エラー処理、コレクションなどをチートシートにまとめました。
基本構文
変数と定数
let, let mut, const によるバインディングと型推論、シャドーイングです。
// 不変バインディング(デフォルト) let x = 5; let name: &str = "Rust"; // 可変バインディング let mut count = 0; count += 1; // 定数(コンパイル時に評価、型注釈必須) const MAX_SIZE: u32 = 100; const PI: f64 = 3.141592653589793; // 型推論 let x = 42; // i32 let y = 3.14; // f64 let flag = true; // bool // シャドーイング(同名で再束縛可能) let x = 5; let x = x + 1; // 6 let x = "hello"; // 型も変更可能
Rustの基本データ型の一覧です。
| 型 | 説明 |
|---|---|
i8, i16, i32, i64, i128 | 符号付き整数 |
u8, u16, u32, u64, u128 | 符号なし整数 |
isize, usize | ポインタサイズ整数(64bit環境では64bit) |
f32, f64 | 浮動小数点数 |
bool | true / false |
char | Unicodeスカラー値(4バイト) |
&str | 文字列スライス(不変参照) |
String | ヒープ割り当て文字列(可変、所有) |
() | ユニット型(値なし) |
出力とフォーマット
println!, format! マクロによる出力とフォーマット指定です。
// 基本出力 println!("Hello, World!"); // 改行付き print!("Hello "); // 改行なし eprintln!("Error!"); // 標準エラー出力 // フォーマット println!("Name: {}", name); println!("{} + {} = {}", 1, 2, 3); // 名前付きパラメータ println!("{name} is {age}", name="Rust", age=9); // デバッグ出力 println!("{:?}", vec![1, 2, 3]); // [1, 2, 3] println!("{:#?}", my_struct); // 整形出力 // 数値フォーマット println!("{:.2}", 3.14159); // 3.14 println!("{:08b}", 42); // 00101010(2進数) println!("{:x}", 255); // ff(16進数) println!("{:>10}", "right"); // 右寄せ println!("{:<10}", "left"); // 左寄せ // format! で文字列生成 let s = format!("Hello, {}!", name);
所有権と参照
所有権ルール
所有権の3つのルール、ムーブセマンティクス、スコープです。
// ルール1: 各値は1つの所有者を持つ // ルール2: 所有者は一度に1つだけ // ルール3: 所有者がスコープを抜けると値は破棄される // ムーブ(所有権の移動) let s1 = String::from("hello"); let s2 = s1; // s1 の所有権が s2 にムーブ // println!("{}", s1); // コンパイルエラー!s1は無効 // 関数への受け渡しでもムーブが発生 fn take_ownership(s: String) { println!("{}", s); } // s はここで drop される let s = String::from("hello"); take_ownership(s); // println!("{}", s); // コンパイルエラー! // 所有権を返す fn give_back(s: String) -> String { s // 所有権を呼び出し元に返す } // スコープと Drop { let s = String::from("hello"); // s を使用 } // s はここで自動的に drop される
借用と参照
&参照、&mut参照、借用ルールです。
// 不変参照(&T): 複数可能 let s = String::from("hello"); let r1 = &s; let r2 = &s; println!("{}, {}", r1, r2); // OK // 可変参照(&mut T): 1つだけ let mut s = String::from("hello"); let r = &mut s; r.push_str(", world"); println!("{}", r); // "hello, world" // 借用ルール // 1. 不変参照は同時に複数OK // 2. 可変参照は同時に1つだけ // 3. 不変参照と可変参照は同時に存在不可 let mut s = String::from("hello"); let r1 = &s; // OK let r2 = &s; // OK // let r3 = &mut s; // コンパイルエラー! println!("{}, {}", r1, r2); // r1, r2 はここで使われなくなる let r3 = &mut s; // OK(r1, r2 のスコープ外) // 関数で借用 fn calc_length(s: &String) -> usize { s.len() // 所有権を奪わない }
Copy と Clone
Copy trait、Clone trait、値型と参照型の違いです。
// Copy trait: スタック上のデータをビットコピー // 以下の型は Copy を実装している let x: i32 = 42; let y = x; // コピー(x はまだ有効) println!("{}", x); // OK // Copy を実装する型: // 整数型, 浮動小数点型, bool, char // Copy な型のみのタプル: (i32, f64) // Clone trait: 明示的なディープコピー let s1 = String::from("hello"); let s2 = s1.clone(); // ヒープデータもコピー println!("{}, {}", s1, s2); // 両方有効 // 自作型に Copy/Clone を導出 #[derive(Copy, Clone)] struct Point { x: f64, y: f64, } // Clone のみ(ヒープデータを含む場合) #[derive(Clone)] struct User { name: String, // String は Copy でない age: u32, }
データ型
文字列
String と &str の違い、変換、主要メソッドです。
// &str: 文字列スライス(不変、スタック or 静的領域) let s: &str = "hello"; // String: ヒープ割り当て(可変、所有) let mut s = String::from("hello"); s.push_str(", world"); s.push('!'); // 変換 let s1: String = "hello".to_string(); let s2: String = String::from("hello"); let s3: &str = &s1; // String → &str let s4: &str = s1.as_str(); // String → &str // 主要メソッド s.len(); // バイト数 s.is_empty(); // 空判定 s.contains("world"); // 部分文字列検索 s.starts_with("hello"); // 前方一致 s.replace("world", "Rust"); s.trim(); // 空白除去 s.to_uppercase(); s.to_lowercase(); s.split(',').collect::<Vec<&str>>(); // 文字列結合 let s = format!("{} {}", "hello", "world"); let s = ["hello", " ", "world"].concat();
配列・タプル・スライス
固定長配列、タプル、スライスです。
// 配列(固定長、同一型) let arr: [i32; 5] = [1, 2, 3, 4, 5]; let zeros = [0; 10]; // [0, 0, ..., 0](10要素) let first = arr[0]; // インデックスアクセス let len = arr.len(); // 5 // スライス(配列の参照) let slice: &[i32] = &arr[1..3]; // [2, 3] let all: &[i32] = &arr[..]; // 全要素 // タプル(異なる型を格納可能) let tup: (i32, f64, &str) = (42, 3.14, "hello"); // 分配束縛 let (x, y, z) = tup; println!("{}, {}, {}", x, y, z); // インデックスアクセス let first = tup.0; // 42 let second = tup.1; // 3.14 // ユニットタプル let unit: () = ();
型変換
as キャスト、From/Into、TryFrom/TryInto です。
// as キャスト(プリミティブ型間) let x: i32 = 42; let y: f64 = x as f64; let z: u8 = 255; let w: i8 = z as i8; // -1(オーバーフロー注意) // From / Into トレイト let s: String = String::from("hello"); let n: i64 = i64::from(42i32); // Into(From の逆方向) let n: i64 = 42i32.into(); // TryFrom / TryInto(失敗する可能性のある変換) use std::convert::TryFrom; let n: Result<u8, _> = u8::try_from(256i32); // Err(256はu8に収まらない) // 文字列 ↔ 数値 let n: i32 = "42".parse().unwrap(); let s: String = 42.to_string(); // parse にターボフィッシュ構文 let n = "42".parse::<i32>().unwrap();
制御フロー
if / else
式としての if、if let です。
// 基本 if x > 0 { println!("positive"); } else if x == 0 { println!("zero"); } else { println!("negative"); } // 式としての if(値を返す) let result = if x > 0 { "positive" } else { "negative" }; // if let(パターンマッチの糖衣構文) let opt: Option<i32> = Some(42); if let Some(value) = opt { println!("Got: {}", value); } else { println!("None"); } // let-else(Rust 1.65+) let Some(value) = opt else { println!("None"); return; }; println!("Got: {}", value);
match & パターンマッチ
match式、パターン、ガード、分配束縛です。
// 基本の match(全パターンを網羅する必要あり) match value { 1 => println!("one"), 2 | 3 => println!("two or three"), 4..=9 => println!("four to nine"), _ => println!("other"), // ワイルドカード } // 式として使う let msg = match status { 200 => "OK", 404 => "Not Found", 500 => "Internal Server Error", _ => "Unknown", }; // 分配束縛 let point = (3, 5); match point { (0, 0) => println!("origin"), (x, 0) => println!("x-axis: {}", x), (0, y) => println!("y-axis: {}", y), (x, y) => println!("({}, {})", x, y), } // ガード条件 match num { n if n < 0 => println!("negative"), n if n > 100 => println!("large"), n => println!("{}", n), }
ループ
loop, while, for, break値返却, continue, ラベルです。
// loop(無限ループ) loop { break; // 脱出 } // loop で値を返す let result = loop { if condition { break 42; // 値を返して脱出 } }; // while let mut n = 0; while n < 10 { n += 1; } // while let let mut stack = vec![1, 2, 3]; while let Some(top) = stack.pop() { println!("{}", top); // 3, 2, 1 } // for(範囲) for i in 0..5 { println!("{}", i); // 0, 1, 2, 3, 4 } for i in 0..=5 { println!("{}", i); // 0, 1, 2, 3, 4, 5 } // for(イテレータ) let nums = vec![10, 20, 30]; for n in &nums { println!("{}", n); } // ラベル付きループ 'outer: for i in 0..5 { for j in 0..5 { if i + j > 4 { break 'outer; } } }
関数とクロージャ
関数定義
パラメータ、戻り値、式ベースの戻り値です。
// 基本 fn greet(name: &str) -> String { format!("Hello, {}!", name) } // 式ベースの戻り値(セミコロンなし = return) fn add(a: i32, b: i32) -> i32 { a + b // return 不要 } // 複数の戻り値(タプル) fn swap(a: i32, b: i32) -> (i32, i32) { (b, a) } let (x, y) = swap(1, 2); // 参照を受け取る fn first_word(s: &str) -> &str { let bytes = s.as_bytes(); for (i, &b) in bytes.iter().enumerate() { if b == b' ' { return &s[..i]; } } s } // 関数ポインタ fn apply(f: fn(i32) -> i32, x: i32) -> i32 { f(x) } let result = apply(|x| x * 2, 5); // 10
クロージャ
|x| 構文、キャプチャ方式(Fn/FnMut/FnOnce)です。
// 基本構文 let add = |a, b| a + b; let result = add(1, 2); // 3 // 型注釈付き let add = |a: i32, b: i32| -> i32 { a + b }; // 環境のキャプチャ let x = 10; let add_x = |n| n + x; // x を借用 println!("{}", add_x(5)); // 15 // キャプチャ方式 // Fn: &self (不変借用) // FnMut: &mut self(可変借用) // FnOnce: self (所有権をムーブ) // move クロージャ(所有権を強制的にムーブ) let name = String::from("Rust"); let greet = move || { println!("Hello, {}!", name); }; greet(); // println!("{}", name); // エラー! // 関数の引数としてクロージャ fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 { f(x) }
イテレータ
iter(), map, filter, collect, fold, enumerate です。
let nums = vec![1, 2, 3, 4, 5]; // iter(): 不変参照のイテレータ // into_iter(): 所有権を消費するイテレータ // iter_mut(): 可変参照のイテレータ // map & collect let doubled: Vec<i32> = nums.iter() .map(|&x| x * 2) .collect(); // [2, 4, 6, 8, 10] // filter let evens: Vec<&i32> = nums.iter() .filter(|&&x| x % 2 == 0) .collect(); // [2, 4] // fold(累積計算) let sum = nums.iter().fold(0, |acc, &x| acc + x); // enumerate(インデックス付き) for (i, val) in nums.iter().enumerate() { println!("{}: {}", i, val); } // チェーン let result: Vec<i32> = (1..=10) .filter(|x| x % 2 == 0) .map(|x| x * x) .collect(); // [4, 16, 36, 64, 100] // その他のメソッド nums.iter().any(|&x| x > 3); // true nums.iter().all(|&x| x > 0); // true nums.iter().find(|&&x| x > 3); // Some(&4) nums.iter().sum::<i32>(); // 15 nums.iter().min(); // Some(&1) nums.iter().max(); // Some(&5) nums.iter().count(); // 5
構造体・列挙型・トレイト
構造体 & メソッド
struct 定義、impl、&self/&mut self、関連関数です。
// 構造体定義 struct User { name: String, age: u32, active: bool, } // インスタンス生成 let user = User { name: String::from("Alice"), age: 30, active: true, }; // フィールド初期化省略記法 let name = String::from("Bob"); let user2 = User { name, age: 25, active: true }; // 構造体更新構文 let user3 = User { age: 35, ..user2 }; // メソッド & 関連関数 impl User { // 関連関数(コンストラクタ) fn new(name: &str, age: u32) -> Self { Self { name: name.to_string(), age, active: true } } // メソッド fn greet(&self) -> String { format!("Hi, I'm {} ({})", self.name, self.age) } // 可変メソッド fn set_age(&mut self, age: u32) { self.age = age; } } let mut u = User::new("Alice", 30); u.set_age(31);
列挙型
enum 定義、データ付きバリアント、Option/Result です。
// 基本 enum Direction { Up, Down, Left, Right, } let dir = Direction::Up; // データ付きバリアント enum Message { Quit, Echo(String), Move { x: i32, y: i32 }, Color(u8, u8, u8), } // match で処理 match msg { Message::Quit => println!("quit"), Message::Echo(text) => println!("{}", text), Message::Move { x, y } => println!("{},{}", x, y), Message::Color(r, g, b) => println!("#{:02x}{:02x}{:02x}", r, g, b), } // Option<T>(null の代わり) let some_val: Option<i32> = Some(42); let no_val: Option<i32> = None; // Result<T, E> let ok_val: Result<i32, String> = Ok(42); let err_val: Result<i32, String> = Err("error".into());
トレイト
trait 定義、impl Trait、デフォルト実装、トレイト境界です。
// トレイト定義 trait Summary { fn summarize(&self) -> String; // デフォルト実装 fn preview(&self) -> String { format!("{}...", &self.summarize()[..20]) } } // トレイト実装 struct Article { title: String, content: String } impl Summary for Article { fn summarize(&self) -> String { format!("{}: {}", self.title, self.content) } } // トレイト境界(ジェネリクス) fn notify(item: &impl Summary) { println!("Breaking: {}", item.summarize()); } // where 句 fn notify<T>(item: &T) where T: Summary + Clone { println!("{}", item.summarize()); } // derive マクロ(よく使うトレイトの自動実装) #[derive(Debug, Clone, PartialEq)] struct Point { x: f64, y: f64 }
エラーハンドリング
Result & Option
Ok/Err、Some/None、unwrap、expect です。
// Result<T, E> fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err("division by zero".to_string()) } else { Ok(a / b) } } match divide(10.0, 3.0) { Ok(result) => println!("{:.2}", result), Err(e) => println!("Error: {}", e), } // Option<T> fn find_user(id: u32) -> Option<String> { if id == 1 { Some("Alice".to_string()) } else { None } } // unwrap / expect(None/Err で panic) let val = Some(42).unwrap(); // 42 let val = Some(42).expect("msg"); // 42 // None.unwrap(); // panic! // unwrap_or / unwrap_or_else let val = None.unwrap_or(0); // 0 let val = None.unwrap_or_else(|| compute_default());
? 演算子 & チェーン
?演算子、map、and_then、unwrap_or です。
// ? 演算子(Err/None を早期リターン) fn read_file(path: &str) -> Result<String, std::io::Error> { let content = std::fs::read_to_string(path)?; Ok(content.to_uppercase()) } // チェーン fn first_line(path: &str) -> Result<String, std::io::Error> { let content = std::fs::read_to_string(path)?; let line = content .lines() .next() .ok_or(std::io::Error::new( std::io::ErrorKind::InvalidData, "empty file" ))?; Ok(line.to_string()) } // Option のメソッドチェーン let result = Some("42") .map(|s| s.parse::<i32>()) // Some(Ok(42)) .and_then(|r| r.ok()); // Some(42) // map, and_then, unwrap_or let val: Option<i32> = Some(5); val.map(|x| x * 2); // Some(10) val.and_then(|x| Some(x + 1)); // Some(6) val.unwrap_or(0); // 5 val.is_some(); // true val.is_none(); // false
カスタムエラー
Error trait 実装、thiserror/anyhow の紹介です。
// カスタムエラー型 #[derive(Debug)] enum AppError { NotFound(String), InvalidInput(String), Io(std::io::Error), } impl std::fmt::Display for AppError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { AppError::NotFound(msg) => write!(f, "Not found: {}", msg), AppError::InvalidInput(msg) => write!(f, "Invalid: {}", msg), AppError::Io(e) => write!(f, "IO error: {}", e), } } } impl std::error::Error for AppError {} // From で自動変換(? 演算子で使用可能に) impl From<std::io::Error> for AppError { fn from(e: std::io::Error) -> Self { AppError::Io(e) } } // thiserror クレート(ボイラープレート削減) // #[derive(thiserror::Error, Debug)] // enum AppError { // #[error("Not found: {0}")] // NotFound(String), // } // anyhow クレート(アプリケーション向け簡易エラー) // fn main() -> anyhow::Result<()> { // let content = std::fs::read_to_string("file.txt")?; // Ok(()) // }
コレクション
Vec
生成、push、pop、インデックス、スライス、イテレーションです。
// 生成 let mut v: Vec<i32> = Vec::new(); let v2 = vec![1, 2, 3, 4, 5]; let v3 = vec![0; 10]; // [0, 0, ..., 0] // 追加・削除 v.push(1); v.push(2); v.push(3); let last = v.pop(); // Some(3) // アクセス let first = v[0]; // パニックの可能性あり let first = v.get(0); // Option<&i32>(安全) // スライス let slice = &v[1..3]; // イテレーション for val in &v { println!("{}", val); } for val in &mut v { *val *= 2; } // その他 v.len(); // 長さ v.is_empty(); // 空判定 v.contains(&2); // 存在確認 v.sort(); // ソート v.dedup(); // 連続する重複を除去 v.retain(|&x| x > 2); // 条件に合う要素のみ残す v.extend([4, 5, 6]); // 複数追加
HashMap
insert、get、entry API、イテレーションです。
use std::collections::HashMap; // 生成 let mut map = HashMap::new(); map.insert("Alice", 30); map.insert("Bob", 25); // Vec から生成 let keys = vec!["Alice", "Bob"]; let vals = vec![30, 25]; let map: HashMap<_, _> = keys.into_iter() .zip(vals.into_iter()) .collect(); // アクセス let age = map.get("Alice"); // Option<&i32> let age = map["Alice"]; // パニックの可能性あり // 存在確認 map.contains_key("Alice"); // true // entry API(キーが無い場合のみ挿入) map.entry("Charlie").or_insert(35); // 値の更新(ワードカウント例) let text = "hello world hello rust"; let mut counts = HashMap::new(); for word in text.split_whitespace() { let count = counts.entry(word).or_insert(0); *count += 1; } // イテレーション for (key, val) in &map { println!("{}: {}", key, val); } // 削除 map.remove("Bob"); map.len(); // 要素数
イテレータパターン
メソッドチェーン、collect、変換パターンです。
// メソッドチェーン let words = vec!["hello", "world", "rust"]; let result: String = words.iter() .map(|w| w.to_uppercase()) .collect::<Vec<_>>() .join(", "); // "HELLO, WORLD, RUST" // flatten(ネストしたイテレータを平坦化) let nested = vec![vec![1, 2], vec![3, 4]]; let flat: Vec<i32> = nested.into_iter() .flatten() .collect(); // [1, 2, 3, 4] // zip(2つのイテレータを結合) let names = vec!["Alice", "Bob"]; let ages = vec![30, 25]; let pairs: Vec<_> = names.iter() .zip(ages.iter()) .collect(); // [("Alice", 30), ("Bob", 25)] // partition(条件で分割) let nums = vec![1, 2, 3, 4, 5]; let (evens, odds): (Vec<i32>, Vec<i32>) = nums .into_iter() .partition(|&x| x % 2 == 0); // chunks(チャンク分割) let data = vec![1, 2, 3, 4, 5]; for chunk in data.chunks(2) { println!("{:?}", chunk); // [1, 2], [3, 4], [5] } // windows(スライディングウィンドウ) for w in data.windows(3) { println!("{:?}", w); // [1,2,3], [2,3,4], [3,4,5] }
モジュール & Cargo
モジュールシステム
mod, use, pub, super, crate です。
// モジュール定義 mod math { pub fn add(a: i32, b: i32) -> i32 { a + b } fn private_fn() {} // 非公開 pub mod advanced { pub fn sqrt(x: f64) -> f64 { x.sqrt() } } } // 使用 use math::add; use math::advanced::sqrt; add(1, 2); // 複数インポート use std::collections::{HashMap, HashSet}; // リネーム use std::io::Result as IoResult; // グロブインポート(非推奨) use std::collections::*; // 再エクスポート pub use math::add; // ファイル構成 // src/ // main.rs (crate root) // lib.rs (library crate root) // math/ // mod.rs (mod math) // advanced.rs (mod advanced) // super, crate, self mod parent { pub fn hello() {} pub mod child { pub fn call_parent() { super::hello(); // 親モジュール crate::some_fn(); // クレートルート } } }
Cargo コマンド
よく使うCargoのCLIコマンドです。
# プロジェクト作成 cargo new myproject # バイナリプロジェクト cargo new mylib --lib # ライブラリプロジェクト cargo init # 既存ディレクトリで初期化 # ビルド & 実行 cargo build # デバッグビルド cargo build --release # リリースビルド cargo run # ビルド & 実行 cargo run --release # リリースモードで実行 # テスト cargo test # 全テスト実行 cargo test test_name # 特定のテスト実行 cargo test -- --nocapture # stdout を表示 # 依存関係 cargo add serde # クレート追加 cargo add tokio --features full cargo update # 依存関係の更新 # コード品質 cargo fmt # コードフォーマット cargo clippy # リンター(警告と提案) cargo check # コンパイルチェック(ビルドなし) cargo doc --open # ドキュメント生成 & 表示
引用・参考リンク
Related Cheatsheets
- 正規表現-正規表現(Regular Expression)は、文字列のパターンマッチングに使われる強力なツールです。 基本構文、量指定子、文字クラス、アンカー、グループ化、先読み・後読みなどをチートシートにまとめました。
- Python-Pythonは、シンプルで読みやすい構文が特徴の汎用プログラミング言語です。 データ型、制御構文、関数、クラス、リスト操作、ファイル操作などの基本をチートシートにまとめました。
- Go-Go(Golang)は、Googleが開発した静的型付けのコンパイル言語です。 シンプルな構文、高速なコンパイル、組み込みの並行処理(goroutine)が特徴です。 基本構文、データ型、関数、構造体、エラー処理、並行処理などをチートシートにまとめました。
- Flutter / Dart-Flutter は Google が開発したクロスプラットフォームUIフレームワークで、Dart 言語を使用します。 1つのコードベースで iOS、Android、Web、デスクトップアプリを開発できます。 Dart の基本構文、Null Safety、クラス、非同期処理、Widget、レイアウト、ナビゲーション、状態管理などをチートシートにまとめました。
Related Goods
WebTerm - Recommended tools
WebTermは、ブラウザでLinuxコマンド・Gitコマンドを安全に実行でき、チュートリアル式で学べるターミナルサンドボックスです。
AIコーディングツールの普及に伴い、CLIの基礎知識を身につける重要性は増しています。実際のターミナルを操作するのに抵抗がある方でも、WebTermはローカル環境を壊す心配がありません。「会員登録不要・無料」で利用でき、学習環境として最適です。

WebTerm
Browser Terminal Sandbox for Learning CLI
開く
All Cheatsheets
エンジニア・プログラマー向けの便利なチートシートを多数まとめています(SP/Tablet/PC対応)
すべてのチートシートを見る


