CheatSheet
日本語 icon日本語English iconEnglish
チートシートとはカンニングペーパーのことです。それが転じて、本来覚えることをまとめておいたものです。
要点をすぐに参照できるようにまとめてみました。

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");  // 右寄せ
    
    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 はここで自動的に drop

借用と参照

  • &参照、&mut参照、借用ルールです。

    // 不変参照(&T): 複数可能
    let s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    println!("{}, {}", r1, r2);
    
    // 可変参照(&mut T): 1つだけ
    let mut s = String::from("hello");
    let r = &mut s;
    r.push_str(", world");
    // 借用ルール
    // 1. 不変参照は同時に複数OK
    // 2. 可変参照は同時に1つだけ
    // 3. 不変・可変参照は同時に存在不可
    
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    // let r3 = &mut s; // エラー!
    println!("{}, {}", 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: スタック上のデータをビットコピー
    let x: i32 = 42;
    let y = x;     // コピー(x はまだ有効)
    // Copy を実装: 整数型, f32/f64, bool, char
    
    // Clone trait: 明示的なディープコピー
    let s1 = String::from("hello");
    let s2 = s1.clone();  // ヒープデータもコピー
    println!("{}, {}", s1, s2);
    #[derive(Copy, Clone)]
    struct Point { x: f64, y: f64 }
    
    // Clone のみ(ヒープデータを含む場合)
    #[derive(Clone)]
    struct User {
        name: String,  // String は Copy でない
        age: u32,
    }

データ型

文字列

  • String と &str の違い、変換、主要メソッドです。

    let s: &str = "hello";         // 文字列スライス(不変)
    let mut s = String::from("hello"); // ヒープ割り当て(可変)
    s.push_str(", world");
    s.push('!');
    
    // 変換
    let s1: String = "hello".to_string();
    let s2: &str = &s1;           // String → &str
    // 主要メソッド
    s.len();             s.is_empty();
    s.contains("world"); s.starts_with("hello");
    s.replace("world", "Rust");
    s.trim();            s.to_uppercase();
    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]; // 10要素すべて0
    let first = arr[0];
    let slice: &[i32] = &arr[1..3]; // [2, 3]
    // タプル(異なる型を格納可能)
    let tup: (i32, f64, &str) = (42, 3.14, "hello");
    let (x, y, z) = tup;   // 分配束縛
    let first = tup.0;      // インデックスアクセス
    let unit: () = ();       // ユニットタプル

型変換

  • as キャスト、From/Into、TryFrom/TryInto です。

    // as キャスト
    let x: i32 = 42;
    let y: f64 = x as f64;
    let w: i8 = 255u8 as i8; // -1(オーバーフロー注意)
    
    // From / Into トレイト
    let s: String = String::from("hello");
    let n: i64 = i64::from(42i32);
    let n: i64 = 42i32.into();
    // TryFrom(失敗する可能性のある変換)
    use std::convert::TryFrom;
    let n: Result<u8, _> = u8::try_from(256i32); // Err
    
    // 文字列 ↔ 数値
    let n: i32 = "42".parse().unwrap();
    let n = "42".parse::<i32>().unwrap(); // ターボフィッシュ
    let s: String = 42.to_string();

制御フロー

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);
    }
    
    // let-else(Rust 1.65+)
    let Some(value) = opt else { return; };

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",
        _ => "Unknown",
    };
    // 分配束縛
    match (3, 5) {
        (0, 0) => println!("origin"),
        (x, 0) => println!("x-axis: {}", x),
        (x, y) => println!("({}, {})", x, y),
    }
    
    // ガード条件
    match num {
        n if n < 0 => println!("negative"),
        n => println!("{}", n),
    }

ループ

  • loop, while, for, break値返却, continue, ラベルです。

    // 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);
    }
    // for(範囲)
    for i in 0..5 { }   // 0, 1, 2, 3, 4
    for i in 0..=5 { }  // 0, 1, 2, 3, 4, 5
    
    // for(イテレータ)
    for n in &vec![10, 20, 30] {
        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 }
    
    // 複数の戻り値(タプル)
    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(): &T, into_iter(): T, iter_mut(): &mut T
    
    let doubled: Vec<i32> = nums.iter()
        .map(|&x| x * 2).collect(); // [2, 4, 6, 8, 10]
    let evens: Vec<&i32> = nums.iter()
        .filter(|&&x| x % 2 == 0).collect(); // [2, 4]
    let sum = nums.iter().fold(0, |acc, &x| acc + x);
    // チェーン
    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().find(|&&x| x > 3); // Some(&4)
    nums.iter().sum::<i32>();       // 15
    nums.iter().min();              // Some(&1)
    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 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 / Result
    let some_val: Option<i32> = Some(42);
    let ok_val: Result<i32, String> = Ok(42);

トレイト

  • 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!("{}", item.summarize());
    }
    
    // where 句
    fn process<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 です。

    fn divide(a: f64, b: f64) -> Result<f64, String> {
        if b == 0.0 { Err("division by zero".into()) }
        else { Ok(a / b) }
    }
    match divide(10.0, 3.0) {
        Ok(result) => println!("{:.2}", result),
        Err(e) => println!("Error: {}", e),
    }
    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();
    let val = Some(42).expect("msg");
    
    // デフォルト値
    let val = None.unwrap_or(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 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),
        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::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),
    // }

コレクション

Vec

  • 生成、push、pop、インデックス、スライス、イテレーションです。

    let mut v: Vec<i32> = Vec::new();
    let v2 = vec![1, 2, 3, 4, 5];
    let v3 = vec![0; 10]; // 10要素すべて0
    
    v.push(1); v.push(2);
    let last = v.pop();    // Some(2)
    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);
    
    let age = map.get("Alice"); // Option<&i32>
    map.contains_key("Alice");  // true
    map.entry("Charlie").or_insert(35); // キーが無い場合のみ挿入
    // ワードカウント例
    let mut counts = HashMap::new();
    for word in "hello world hello".split_whitespace() {
        *counts.entry(word).or_insert(0) += 1;
    }
    
    for (key, val) in &map { println!("{}: {}", key, val); }
    map.remove("Bob");

イテレータパターン

  • メソッドチェーン、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
    let pairs: Vec<_> = ["Alice", "Bob"].iter()
        .zip([30, 25].iter()).collect();
    
    // partition
    let (evens, odds): (Vec<i32>, Vec<i32>) =
        vec![1, 2, 3, 4, 5].into_iter()
        .partition(|&x| x % 2 == 0);
    
    // chunks / windows
    for chunk in [1,2,3,4,5].chunks(2) { } // [1,2],[3,4],[5]
    for w in [1,2,3,4,5].windows(3) { }    // [1,2,3],[2,3,4],...

モジュール & 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 std::collections::{HashMap, HashSet};
    use std::io::Result as IoResult;
    pub use math::add; // 再エクスポート
    // ファイル構成
    // src/main.rs, src/lib.rs
    // src/math/mod.rs, src/math/advanced.rs
    
    // 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 build               # デバッグビルド
    cargo build --release     # リリースビルド
    cargo run                 # ビルド & 実行
    # テスト
    cargo test                # 全テスト実行
    cargo test test_name      # 特定のテスト
    
    # 依存関係 & コード品質
    cargo add serde           # クレート追加
    cargo add tokio --features full
    cargo fmt                 # フォーマット
    cargo clippy              # リンター
    cargo check               # コンパイルチェック
    cargo doc --open          # ドキュメント生成