Skip to content

✍️ 필사 모드: Rustプログラミング入門ガイド — 所有権、ライフタイム、安全なシステムプログラミング

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

目次

  1. なぜRustなのか
  2. 所有権(Ownership)
  3. ライフタイム
  4. 列挙型とパターンマッチング
  5. エラー処理
  6. 構造体とトレイト
  7. 非同期プログラミング
  8. Cargoパッケージマネージャ
  9. 実践Rust
  10. Rust in 2026

1. なぜRustなのか

1.1 C/C++の問題点

システムプログラミングの分野において、CとC++は数十年にわたり支配的な地位を占めてきました。しかし、これらの言語には根本的な問題があります。

問題の種類説明結果
バッファオーバーフロー配列境界を超えるアクセスセキュリティ脆弱性
ダングリングポインタ解放済みメモリの参照未定義動作
二重解放同じメモリを2回解放クラッシュやセキュリティ脅威
データ競合同時アクセス時の同期不足非決定的バグ
ヌルポインタ逆参照null値の逆参照プログラムクラッシュ

Microsoftによると、Windowsのセキュリティ脆弱性の約70%がメモリ安全性の問題に起因しています。GoogleのChromeチームも同様の数字を報告しています。

1.2 Rustの解答

Rustはコンパイル時にメモリ安全性を保証しながら、ガベージコレクタ(GC)なしで動作します。これがRustをユニークにする核心です。

  • ゼロコスト抽象化: ランタイムオーバーヘッドのない高水準抽象化
  • 所有権システム: コンパイラがメモリを追跡
  • スレッド安全性: データ競合をコンパイル時に防止
  • 豊富な型システム: 多くのバグをコンパイル時に検出

1.3 Rustの人気上昇

Stack Overflowの調査で、Rustは2016年から2025年まで10年連続「最も愛される言語」1位を獲得しました。2024〜2026年の間には、産業での採用率も大幅に増加しました。

  • Linuxカーネル: Rustを公式第2言語として採用
  • Android: 新しいシステムコンポーネントにRustを使用
  • AWS: Firecracker、BottlerocketなどコアインフラにRustを活用
  • Microsoft: WindowsカーネルコードをRustで書き直し開始
  • Cloudflare: ネットワークプロキシをRustに移行

2. 所有権(Ownership)

2.1 所有権の3つのルール

Rustの核心概念である所有権は、3つのルールに要約されます。

  1. Rustのすべての値には所有者(owner) がいる
  2. ある時点で所有者は1つだけである
  3. 所有者がスコープを離れると、値は自動的に解放される
fn main() {
    let s1 = String::from("hello"); // s1がStringの所有者
    let s2 = s1;                     // 所有権がs2に移動(move)
    // println!("{}", s1);           // コンパイルエラー!s1はもう有効ではない
    println!("{}", s2);              // OK
} // s2がスコープを離れるとメモリ解放

2.2 ムーブ(Move)とコピー(Copy)

デフォルトでRustは値をムーブ(move) します。ただし、Copyトレイトを実装した型はコピーされます。

// 整数型はCopyトレイトを実装 - コピーされる
let x = 5;
let y = x;
println!("x = {}, y = {}", x, y); // 両方使用可能

// StringはCopy未実装 - ムーブされる
let s1 = String::from("hello");
let s2 = s1; // ムーブ!
// s1は使用不可

// 明示的なコピーが必要ならcloneを使用
let s3 = String::from("world");
let s4 = s3.clone();
println!("s3 = {}, s4 = {}", s3, s4); // 両方使用可能

Copyを実装する型: 整数(i32u64など)、浮動小数点数(f32f64)、ブール値(bool)、文字(char)、これらのみで構成されるタプル。

2.3 借用(Borrowing)と参照

所有権を移さずに値を使うには、参照(reference) を使用します。

fn calculate_length(s: &String) -> usize {
    s.len()
} // sは参照なのでここでは解放されない

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1); // 借用(不変参照)
    println!("'{}'の長さ: {}", s1, len); // s1はまだ有効
}

2.4 可変参照と不変参照

Rustは参照に対して厳格なルールを適用します。

fn main() {
    let mut s = String::from("hello");

    // 不変参照は複数同時に可能
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);

    // 可変参照は1つだけ可能
    let r3 = &mut s;
    r3.push_str(", world");
    println!("{}", r3);

    // 不変参照と可変参照を同時に持てない
    // let r4 = &s;
    // let r5 = &mut s; // コンパイルエラー!
}

このルールのおかげで、データ競合がコンパイル時に防止されます。

2.5 スライス

スライスはコレクションの一部を参照する方法です。

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

fn main() {
    let s = String::from("hello world");
    let word = first_word(&s);
    println!("最初の単語: {}", word); // "hello"
}

3. ライフタイム

3.1 ライフタイムが必要な理由

ライフタイムは参照が有効な範囲を示します。コンパイラは、参照が指すデータより長く存続しないことを保証する必要があります。

// このコードはコンパイルされない - ダングリング参照を防止
// fn dangle() -> &String {
//     let s = String::from("hello");
//     &s  // sが関数の終わりで解放されるため参照が無効
// }

// 正しい方法: 値を直接返す
fn no_dangle() -> String {
    let s = String::from("hello");
    s // 所有権が呼び出し元に移動
}

3.2 ライフタイムアノテーション

コンパイラが参照の有効期間を推論できない場合、明示的なライフタイムアノテーションが必要です。

// 2つの文字列スライスのうち長い方を返す
// 戻り値のライフタイムは2つの引数の短い方に従う
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let string1 = String::from("long string");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
        println!("より長い文字列: {}", result); // ここではOK
    }
    // println!("{}", result); // string2が解放されているためエラーの可能性
}

3.3 構造体のライフタイム

構造体が参照を含む場合、ライフタイムを明示する必要があります。

struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }

    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("注目! {}", announcement);
        self.part
    }
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence;
    {
        let i = novel.find('.').unwrap_or(novel.len());
        first_sentence = &novel[..i];
    }
    let excerpt = ImportantExcerpt {
        part: first_sentence,
    };
    println!("引用: {}", excerpt.part);
}

3.4 静的ライフタイム

'staticライフタイムは、プログラム全体の実行期間中有効な参照を意味します。

// 文字列リテラルは常に'static
let s: &'static str = "この文字列はプログラム全体の寿命中有効です";

// 注意: 'staticを乱用しないでください
// ほとんどの場合、より短いライフタイムで十分です

3.5 ライフタイム省略規則

Rustコンパイラは3つのルールでライフタイムを自動推論します。

  1. 各参照パラメータは固有のライフタイムを受け取る
  2. 参照パラメータが1つだけなら、戻り値の型のライフタイムはそれに従う
  3. メソッドで&selfまたは&mut selfがある場合、戻り値の型のライフタイムはselfに従う
// ライフタイム省略適用 - ルール2
fn first_word(s: &str) -> &str {
    // コンパイラが fn first_word<'a>(s: &'a str) -> &'a str と推論
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}

4. 列挙型とパターンマッチング

4.1 列挙型(enum)

Rustの列挙型は他の言語よりもはるかに強力です。各バリアントにデータを含めることができます。

// 基本的な列挙型
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

// データを含む列挙型
enum Message {
    Quit,                        // データなし
    Move { x: i32, y: i32 },    // 名前付きフィールド
    Write(String),               // 単一のString
    ChangeColor(i32, i32, i32),  // 3つのi32
}

impl Message {
    fn call(&self) {
        match self {
            Message::Quit => println!("終了"),
            Message::Move { x, y } => println!("移動: ({}, {})", x, y),
            Message::Write(text) => println!("メッセージ: {}", text),
            Message::ChangeColor(r, g, b) => {
                println!("色変更: ({}, {}, {})", r, g, b)
            }
        }
    }
}

4.2 Option型

Rustにはnullがありません。代わりにOption列挙型を使用します。

enum Option<T> {
    None,
    Some(T),
}

fn divide(numerator: f64, denominator: f64) -> Option<f64> {
    if denominator == 0.0 {
        None
    } else {
        Some(numerator / denominator)
    }
}

fn main() {
    let result = divide(10.0, 3.0);

    // matchで処理
    match result {
        Some(value) => println!("結果: {:.2}", value),
        None => println!("ゼロで割ることはできません"),
    }

    // if letで簡潔に
    if let Some(value) = divide(10.0, 0.0) {
        println!("結果: {}", value);
    } else {
        println!("除算失敗");
    }

    // unwrap_orでデフォルト値を指定
    let safe_result = divide(10.0, 0.0).unwrap_or(0.0);
    println!("安全な結果: {}", safe_result);
}

4.3 パターンマッチング(match)

matchはRustで最も強力な制御フロー構文の1つです。

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

enum UsState {
    Alabama,
    Alaska,
    Arizona,
    // ...
}

fn value_in_cents(coin: &Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("ラッキーペニー!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("州クォーター: {:?}", state);
            25
        }
    }
}

4.4 高度なパターンマッチング

fn classify_number(n: i32) {
    match n {
        // 範囲マッチング
        1..=12 => println!("{}月", n),
        13..=19 => println!("ティーンエイジャー"),

        // ガード条件
        x if x % 2 == 0 => println!("偶数: {}", x),
        x if x < 0 => println!("負数: {}", x),

        // 複数パターン
        20 | 30 | 40 => println!("10の倍数"),

        // その他すべて
        _ => println!("その他: {}", n),
    }
}

// 構造体のデストラクチャリング
struct Point {
    x: f64,
    y: f64,
}

fn describe_point(point: &Point) {
    match point {
        Point { x: 0.0, y: 0.0 } => println!("原点"),
        Point { x, y: 0.0 } => println!("x軸上: {}", x),
        Point { x: 0.0, y } => println!("y軸上: {}", y),
        Point { x, y } => println!("({}, {})", x, y),
    }
}

5. エラー処理

5.1 Result型

Rustは回復可能なエラーにResultを使用します。

use std::fs::File;
use std::io::{self, Read};

enum Result<T, E> {
    Ok(T),
    Err(E),
}

fn read_file_content(path: &str) -> Result<String, io::Error> {
    let mut file = File::open(path)?;
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    Ok(content)
}

fn main() {
    match read_file_content("config.toml") {
        Ok(content) => println!("ファイル内容: {}", content),
        Err(e) => eprintln!("ファイル読み取り失敗: {}", e),
    }
}

5.2 ? 演算子

?演算子はエラーの伝播を簡潔にします。

use std::fs;
use std::io;
use std::num::ParseIntError;

#[derive(Debug)]
enum AppError {
    IoError(io::Error),
    ParseError(ParseIntError),
}

impl From<io::Error> for AppError {
    fn from(e: io::Error) -> Self {
        AppError::IoError(e)
    }
}

impl From<ParseIntError> for AppError {
    fn from(e: ParseIntError) -> Self {
        AppError::ParseError(e)
    }
}

fn read_and_parse(path: &str) -> Result<i32, AppError> {
    let content = fs::read_to_string(path)?; // io::Error -> AppError
    let number = content.trim().parse::<i32>()?; // ParseIntError -> AppError
    Ok(number * 2)
}

5.3 anyhowとthiserror

実際の開発ではanyhowthiserrorクレートがよく使われます。

// thiserror - ライブラリ用の具体的なエラー型定義
use thiserror::Error;

#[derive(Error, Debug)]
enum DatabaseError {
    #[error("接続失敗: {0}")]
    ConnectionFailed(String),

    #[error("クエリ実行エラー: {0}")]
    QueryError(String),

    #[error("レコードが見つかりません: {id}")]
    NotFound { id: u64 },
}

// anyhow - アプリケーション用の簡便なエラー処理
use anyhow::{Context, Result};

fn load_config() -> Result<Config> {
    let content = fs::read_to_string("config.toml")
        .context("設定ファイルを読み取れません")?;

    let config: Config = toml::from_str(&content)
        .context("設定ファイルのパースに失敗しました")?;

    Ok(config)
}

5.4 panicと回復不可能なエラー

// panic!はプログラムを即座に中断
fn check_positive(n: i32) {
    if n < 0 {
        panic!("負の数が入力されました: {}", n);
    }
}

// 配列インデックス範囲外もpanic
let v = vec![1, 2, 3];
// let element = v[99]; // panic!

// 安全なアクセス
match v.get(99) {
    Some(value) => println!("値: {}", value),
    None => println!("インデックス範囲外"),
}

6. 構造体とトレイト

6.1 構造体(struct)の定義

#[derive(Debug, Clone)]
struct User {
    username: String,
    email: String,
    age: u32,
    active: bool,
}

impl User {
    // コンストラクタパターン(慣例的にnew)
    fn new(username: String, email: String, age: u32) -> Self {
        User {
            username,
            email,
            age,
            active: true,
        }
    }

    // メソッド(&selfで不変借用)
    fn is_adult(&self) -> bool {
        self.age >= 18
    }

    // 可変メソッド(&mut self)
    fn deactivate(&mut self) {
        self.active = false;
    }

    // 所有権を取るメソッド
    fn into_username(self) -> String {
        self.username
    }
}

fn main() {
    let mut user = User::new(
        "rustacean".to_string(),
        "rust@example.com".to_string(),
        25,
    );

    println!("成人かどうか: {}", user.is_adult());
    user.deactivate();
    println!("ユーザー: {:?}", user);
}

6.2 トレイト(Trait)

トレイトは共有の振る舞いを定義する方法です。他の言語のインターフェースに似ています。

trait Summary {
    fn summarize_author(&self) -> String;

    // デフォルト実装を提供可能
    fn summarize(&self) -> String {
        format!("{}さんの記事をもっと読む...", self.summarize_author())
    }
}

struct Article {
    title: String,
    author: String,
    content: String,
}

impl Summary for Article {
    fn summarize_author(&self) -> String {
        self.author.clone()
    }

    fn summarize(&self) -> String {
        format!("{}, by {} - {}...",
            self.title, self.author,
            &self.content[..50.min(self.content.len())]
        )
    }
}

struct Tweet {
    username: String,
    content: String,
}

impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
    // summarizeはデフォルト実装を使用
}

6.3 ジェネリクスとトレイトバウンド

// ジェネリック関数 + トレイトバウンド
fn notify(item: &impl Summary) {
    println!("速報! {}", item.summarize());
}

// 同等の表現(トレイトバウンド構文)
fn notify_verbose<T: Summary>(item: &T) {
    println!("速報! {}", item.summarize());
}

// 複数のトレイトバウンド
fn display_and_summarize<T: Summary + std::fmt::Display>(item: &T) {
    println!("表示: {}", item);
    println!("要約: {}", item.summarize());
}

// where句で可読性向上
fn complex_function<T, U>(t: &T, u: &U) -> String
where
    T: Summary + Clone,
    U: std::fmt::Display + std::fmt::Debug,
{
    format!("{} - {:?}", t.summarize(), u)
}

6.4 ジェネリック構造体

struct Stack<T> {
    elements: Vec<T>,
}

impl<T> Stack<T> {
    fn new() -> Self {
        Stack {
            elements: Vec::new(),
        }
    }

    fn push(&mut self, item: T) {
        self.elements.push(item);
    }

    fn pop(&mut self) -> Option<T> {
        self.elements.pop()
    }

    fn peek(&self) -> Option<&T> {
        self.elements.last()
    }

    fn is_empty(&self) -> bool {
        self.elements.is_empty()
    }

    fn size(&self) -> usize {
        self.elements.len()
    }
}

// 特定の型に対する追加実装
impl<T: std::fmt::Display> Stack<T> {
    fn print_top(&self) {
        if let Some(top) = self.peek() {
            println!("最上段: {}", top);
        }
    }
}

7. 非同期プログラミング

7.1 async/awaitの基礎

Rustの非同期プログラミングはasync/awaitキーワードを使用します。

// async fnはFutureを返す
async fn fetch_data(url: &str) -> Result<String, reqwest::Error> {
    let response = reqwest::get(url).await?;
    let body = response.text().await?;
    Ok(body)
}

// asyncブロック
let future = async {
    let data = fetch_data("https://api.example.com/data").await;
    println!("データ受信完了");
    data
};

7.2 Tokioランタイム

Rustで最も人気のある非同期ランタイムであるTokioの使い方です。

use tokio;
use std::time::Duration;

#[tokio::main]
async fn main() {
    // 複数のタスクを同時に実行
    let (result1, result2) = tokio::join!(
        async_task("タスク1", 2),
        async_task("タスク2", 1),
    );

    println!("結果: {:?}, {:?}", result1, result2);
}

async fn async_task(name: &str, seconds: u64) -> String {
    println!("{} 開始", name);
    tokio::time::sleep(Duration::from_secs(seconds)).await;
    println!("{} 完了", name);
    format!("{} 結果", name)
}

7.3 チャネルと並行性

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    // マルチプロデューサー、シングルコンシューマーチャネル
    let (tx, mut rx) = mpsc::channel::<String>(100);

    // 複数のプロデューサーを作成
    for i in 0..5 {
        let tx_clone = tx.clone();
        tokio::spawn(async move {
            let msg = format!("メッセージ {}", i);
            tx_clone.send(msg).await.unwrap();
        });
    }
    // 元のtxをドロップ(すべてのプロデューサーが終了するとチャネル閉鎖)
    drop(tx);

    // コンシューマー
    while let Some(message) = rx.recv().await {
        println!("受信: {}", message);
    }
}

7.4 Mutexと共有状態

use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = tokio::spawn(async move {
            let mut num = counter.lock().await;
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.await.unwrap();
    }

    println!("最終カウンター: {}", *counter.lock().await);
}

8. Cargoパッケージマネージャ

8.1 Cargo.tomlの構造

[package]
name = "my-project"
version = "0.1.0"
edition = "2021"
authors = ["Developer <dev@example.com>"]
description = "A sample Rust project"
license = "MIT"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
anyhow = "1.0"
thiserror = "2.0"
clap = { version = "4", features = ["derive"] }

[dev-dependencies]
criterion = "0.5"
mockall = "0.13"

[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true

8.2 主要なCargoコマンド

# プロジェクト作成
cargo new my-project       # バイナリプロジェクト
cargo new my-lib --lib     # ライブラリプロジェクト

# ビルドと実行
cargo build                # デバッグビルド
cargo build --release      # リリースビルド
cargo run                  # ビルド後実行
cargo run -- --arg1 value  # 引数を渡す

# テスト
cargo test                 # 全テスト実行
cargo test test_name       # 特定のテストのみ
cargo test -- --nocapture  # 出力を表示

# 検査と分析
cargo check                # コンパイル確認(ビルドより速い)
cargo clippy               # リントチェック
cargo fmt                  # コードフォーマット

# ドキュメント
cargo doc --open           # ドキュメント生成後ブラウザで開く

# 依存関係管理
cargo add serde            # 依存関係追加
cargo update               # 依存関係更新
cargo tree                 # 依存関係ツリー確認

8.3 ワークスペース

大規模プロジェクトはワークスペースで管理します。

# ルートCargo.toml
[workspace]
members = [
    "crates/core",
    "crates/api",
    "crates/cli",
]

[workspace.dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
# crates/core/Cargo.toml
[package]
name = "my-core"
version = "0.1.0"
edition = "2021"

[dependencies]
serde = { workspace = true }

8.4 クレートの公開

# crates.ioアカウント設定
cargo login

# 公開前チェック
cargo publish --dry-run

# 実際の公開
cargo publish

9. 実践Rust

9.1 CLIツール (clap)

use clap::Parser;
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(name = "file-analyzer")]
#[command(about = "ファイル分析ツール", long_about = None)]
struct Cli {
    /// 分析するファイルパス
    #[arg(short, long)]
    path: PathBuf,

    /// 出力形式
    #[arg(short, long, default_value = "text")]
    format: String,

    /// 詳細出力
    #[arg(short, long)]
    verbose: bool,

    /// 最大深度
    #[arg(short, long, default_value_t = 3)]
    depth: u32,
}

fn main() {
    let cli = Cli::parse();

    if cli.verbose {
        println!("ファイルパス: {:?}", cli.path);
        println!("出力形式: {}", cli.format);
        println!("最大深度: {}", cli.depth);
    }

    analyze_file(&cli.path, cli.depth);
}

fn analyze_file(path: &PathBuf, depth: u32) {
    println!("分析中: {:?} (深度: {})", path, depth);
    // ファイル分析ロジック...
}

9.2 Webサーバー (Axum)

use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::Json,
    routing::{get, post},
    Router,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::Mutex;

#[derive(Debug, Serialize, Deserialize, Clone)]
struct Todo {
    id: u64,
    title: String,
    completed: bool,
}

type AppState = Arc<Mutex<Vec<Todo>>>;

#[tokio::main]
async fn main() {
    let state: AppState = Arc::new(Mutex::new(Vec::new()));

    let app = Router::new()
        .route("/todos", get(list_todos).post(create_todo))
        .route("/todos/:id", get(get_todo))
        .with_state(state);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await
        .unwrap();
    println!("サーバー起動: http://localhost:3000");
    axum::serve(listener, app).await.unwrap();
}

async fn list_todos(
    State(state): State<AppState>,
) -> Json<Vec<Todo>> {
    let todos = state.lock().await;
    Json(todos.clone())
}

async fn create_todo(
    State(state): State<AppState>,
    Json(payload): Json<CreateTodo>,
) -> (StatusCode, Json<Todo>) {
    let mut todos = state.lock().await;
    let todo = Todo {
        id: todos.len() as u64 + 1,
        title: payload.title,
        completed: false,
    };
    todos.push(todo.clone());
    (StatusCode::CREATED, Json(todo))
}

#[derive(Deserialize)]
struct CreateTodo {
    title: String,
}

async fn get_todo(
    State(state): State<AppState>,
    Path(id): Path<u64>,
) -> Result<Json<Todo>, StatusCode> {
    let todos = state.lock().await;
    todos
        .iter()
        .find(|t| t.id == id)
        .cloned()
        .map(Json)
        .ok_or(StatusCode::NOT_FOUND)
}

9.3 WebAssembly (WASM)

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
    if n <= 1 {
        return n as u64;
    }
    let mut a: u64 = 0;
    let mut b: u64 = 1;
    for _ in 2..=n {
        let temp = b;
        b = a + b;
        a = temp;
    }
    b
}

#[wasm_bindgen]
pub struct ImageProcessor {
    width: u32,
    height: u32,
    pixels: Vec<u8>,
}

#[wasm_bindgen]
impl ImageProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new(width: u32, height: u32) -> Self {
        ImageProcessor {
            width,
            height,
            pixels: vec![0; (width * height * 4) as usize],
        }
    }

    pub fn grayscale(&mut self) {
        for chunk in self.pixels.chunks_mut(4) {
            let avg = ((chunk[0] as u16 + chunk[1] as u16 + chunk[2] as u16) / 3) as u8;
            chunk[0] = avg;
            chunk[1] = avg;
            chunk[2] = avg;
        }
    }

    pub fn pixels(&self) -> *const u8 {
        self.pixels.as_ptr()
    }
}

10. Rust in 2026

10.1 LinuxカーネルのRust

Linux 6.1(2022年)からRustが公式にカーネルに導入され、2026年現在、ドライバ、ファイルシステム、ネットワークサブシステムなどでRustコードが拡大しています。

  • ドライバ: GPU、NVMeなど新しいドライバをRustで作成
  • バインディング: 既存のCカーネルAPIに対する安全なRustバインディングの拡充
  • ツール: rustfmtclippyなどカーネルRustツールチェーンの安定化

10.2 Androidとモバイル

GoogleはAndroidの新しいシステムコンポーネントをRustで書いています。

  • Bluetoothスタック、キーストア、DNSリゾルバなどにRustを適用
  • メモリ安全性の脆弱性が大幅に減少
  • AndroidにおけるRustコードの割合が継続的に増加

10.3 クラウドインフラ

AWS、Azure、GCPのすべてがコアインフラにRustを活用しています。

組織プロジェクト説明
AWSFirecrackerサーバーレスVM管理
AWSBottlerocketコンテナ専用OS
CloudflarePingoraHTTPプロキシエンジン
Discordメッセージインフラ読み取り状態サービスの書き直し
Figmaサーバーサイドマルチプレイヤーサーバー
1Passwordコアエンジンクロスプラットフォームコア

10.4 Rustの将来展望

2026年時点で、Rustの将来は明るいです。

成長分野:

  • 組み込み/IoT: no_std環境での安全なプログラミング
  • ゲーム開発: Bevyエンジンの成熟
  • AI/MLインフラ: PyTorch、Hugging FaceなどでコアコンポーネントとしてのRust活用
  • ブロックチェーン: Solana、Polkadotなど主要ブロックチェーンがRustベース

言語の進化:

  • 非同期の改善: async traitの安定化、async closure
  • エディション: Rust 2024エディションの安定化
  • GAT: ジェネリック関連型の活用拡大
  • コンパイル速度: ビルド時間の継続的改善

まとめ

Rustは単なるC/C++の代替ではありません。所有権システムと型システムを通じて、安全性とパフォーマンスを同時に達成する新しいパラダイムを提示しています。

Rustを学ぶ過程で「ボローチェッカーとの戦い(fighting the borrow checker)」を経験しますが、これはコンパイラがランタイムに発生するバグを事前にキャッチしてくれることです。時間が経つにつれて所有権システムが自然になり、他の言語でもより安全なコードを書けるようになります。

Rust入門者に推奨する学習順序:

  1. The Rust Programming Language (The Book) を読む
  2. Rustlings の練習問題を解く
  3. 小規模なCLIツールを作る
  4. WebサーバーやAPIを構築する
  5. オープンソースプロジェクトに貢献する

Rustのコミュニティは親切で活発です。公式フォーラム、Discord、そしてRedditのr/rustで助けを得ることができます。2026年、Rustはシステムプログラミングの未来を牽引しています。

현재 단락 (1/767)

1. [なぜRustなのか](#1-なぜrustなのか)

작성 글자: 0원문 글자: 17,197작성 단락: 0/767