Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
OCHa Cafe S10 #3 Rustを学ぼう!
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
oracle4engineer
PRO
August 20, 2025
Video
Technology
360
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
OCHa Cafe S10 #3 Rustを学ぼう!
デモやサンプルで用いたソースコードは以下にあります。
https://github.com/oracle-japan/ochacafe-rust
oracle4engineer
PRO
August 20, 2025
Video
More Decks by oracle4engineer
See All by oracle4engineer
OCI Oracle AI Database Services新機能アップデート(2026/06-2026/08)
oracle4engineer
PRO
0
360
OKE の進化 - Oracle Cloud Infrastructure Kubernetes Engine の現在地 -
oracle4engineer
PRO
0
250
【Oracle AI Spotlight ウェビナー】クラウド移行の成否を分けるデータ基盤の配置戦略 ― マルチクラウドやソブリンクラウドで広がるデータ基盤の選択肢
oracle4engineer
PRO
1
68
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
220
Autonomous AI Databaseサービス・アップデート(FY27)/ adb-service-update-jp-fy27
oracle4engineer
PRO
0
160
【Oracle AI Spotlight ウェビナー】AWSか、Azureか、Google Cloudか。その議論にオラクルを含める意義。
oracle4engineer
PRO
2
260
Oracle AI Databaseデータベース・サービス: BaseDB/ExaDB-Dの可用性
oracle4engineer
PRO
2
1.2k
もうプロンプトは書かない!? ループエンジニアリング入門
oracle4engineer
PRO
2
570
[ OracleTechnologyNight#102]SQL性能改善の武器としてのパラレル実行詳細
oracle4engineer
PRO
1
280
Other Decks in Technology
See All in Technology
Azure Serverless 2026:Production-ready な AI エージェント基盤 / Azure Serverless 2026: Production-Ready AI Agent Platform
miyake
1
160
ソフトウェアDNAとクラウドエージェントのススメ
cloudace
0
110
CLIライブラリ開発を支える技術
htnabe
0
120
2026-09-11 【Snowflake World Tour Tokyo 2026】Snowflakeを起点に、AI Agentが自律稼働し続ける未来へ / Driving AI Agents with Snowflake
civitaspo
0
670
HHKBエバンジェリストになる方法
941
0
110
生成AIエージェントを用いた、 手動テスト手順書から自動テストへの 変換手法の検討
magicpod
0
160
AI時代の「技術的負債」の変質ー概念の終焉と再解釈、エージェントと共に向かう先
nwiizo
1
2.7k
Reactの設計論
uhyo
24
13k
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
4
3.1k
白金鉱業Meetup Vol.25 アウトカムが二値のデータに対するCausal Impact
brainpadpr
0
220
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
2k
AI時代、データエンジニアが一番おもろい
genshun9
0
640
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.3k
Music & Morning Musume
bryan
48
7.4k
Speed Design
sergeychernyshev
33
2.1k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
460
A designer walks into a library…
pauljervisheath
211
25k
4 Signs Your Business is Dying
shpigford
187
23k
Code Reviewing Like a Champion
maltzj
528
40k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
For a Future-Friendly Web
brad_frost
183
10k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
660
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
910
Chasing Engaging Ingredients in Design
codingconduct
0
310
Transcript
Rustを学ぼう! Oracle Cloud Hangout Café Season10 #3 Kyotaro Nonaka Solutions
Architect Oracle Corporation Japan Aug. 20, 2025
アジェンダ 2 Copyright © 2025, Oracle and/or its affiliates 1
2 3 4 5 6 はじめに Rustとは何か? Rustの特性と書き方 Rustのエコシステムとフレームワーク Rustを書いてみよう まとめ
自己紹介 Kyotaro Nonaka 野中恭大郎 Solutions Architect • Java EE/Messaging/NoSQL/Frontend •
Oracle Cloud Hangout Café メンバー • Oracle Groundbreakers Advocate • 元ERPパッケージ開発者 • 趣味は釣りとかキャンプとか • 最近は好きなバンドの来日公演が多くて嬉しいです。 - KASABIAN @ Zepp Haneda - 済 - MUSE @ Kアリーナ - OASIS @ 東京ドーム – New! - Franz Ferdinand @ 東京ガーデンシアター 3 Copyright © 2025, Oracle and/or its affiliates @non_kyon
本日のゴール Rust何もわからない... から Rustで何か作ってみよう! まで 4 Copyright © 2025, Oracle
and/or its affiliates
Rustとは何か?
Rustってどんな言語? “A language empowering everyone to build reliable and efficient
software.” — rust-lang.org パフォーマンス • 高速でメモリ効率が高い • ランタイムやガベージコレクタがない • 組込み機器上の実行も可能 信頼性 • メモリ安全性とスレッド安全性が保証 - 豊かな型システム - 所有権モデル • 様々な種類のバグをコンパイル時に排除 生産性 • 有用なエラーメッセージを備えた使いやすいコンパイラ • 統合されたパッケージマネージャとビルドツール • 多数のエディタに対応する自動補完と型検査機能 • 自動フォーマッタ 6 Copyright © 2025, Oracle and/or its affiliates
Rustの特徴 7 Copyright © 2025, Oracle and/or its affiliates メモリ安全
• 所有権 • 借用 • バグをコンパ イル時に防止 高速実行 • C/C++に匹 敵するネイ ティブパフォー マンス モダンな構文 • 型推論 • パターンマッチ • ジェネリクス 安全な並行性 • データ競合を 防ぐ設計 パッケージ管理 • cargoでビル ド・依存・実 行を一括管 理
なぜRustは「安全」で「高速」なのか? • コンパイル時にメモリ安全を保証 - 解放忘れ・二重解放・ポインタバグを防ぐ - 「実行してみないと分からない」ではなく「そもそもビルドが通らない」 • ガーベジコレクション不要 -
実行時オーバーヘッドがない - 代わりに「所有権」でライフタイムを管理 • データ競合のない並行処理 (Fearless Concurrency) - 複数スレッドを扱うときのデータ競合をコンパイル時に防ぐ • 高レベル抽象でもオーバーヘッドなし (ゼロコスト抽象化) - human readableな記述でもコンパイル時に最適化 8 Copyright © 2025, Oracle and/or its affiliates
Cloud NativeとRustの相性の良さ • 小さくて高速なCLIツール開発に最適 • Web Assembly (WASM) 対応が強力 •
KubernetesエコシステムにRust製ツールが増加中 - krustlet • KubernetesのノードとしてWASMを動かすためのkubelet実装 • Rustで書かれていて、安全かつ軽量なWASM実行環境を提供 - kube-rs • Kubernetes APIと連携するRustクレート(= ライブラリ) • Rustでk8sのControllerやOperatorを簡単に構築 - wasmtime • WASI準拠のWebAssemblyランタイム • Cloud Nativeなサーバーレス・サンドボックス環境で注目 9 Copyright © 2025, Oracle and/or its affiliates いつかWASM はOCHaCafe でやりたい
RustとWebAssembly (WASM) WASM • ブラウザやランタイムで動作するバイナリフォーマット • 高速・安全・移植性が高い - 移植性 :
WASMバイナリが環境やOSに縛られず動作する性質 RustがWASMに向いている理由 • メモリ安全をコンパイラが保証 → 安全にWASMへ変換可能 • C/C++の代替としての利用(低レベルの制御と高レベルの表現を両立) • エコシステムが充実 - wasm-pack : Rust → WASM コンパイラ - wasmtime : Rust製 WASM ランタイム 利用シーン • フロントエンド : ブラウザでの高速処理 • サーバーサイド : WASI (WebAssembly System Interface) を通じた安全な拡張 • Cloud Native : サービスメッシュの拡張/カスタマイズ (Envoy の WASM SDK も Rust をサポート) 10 Copyright © 2025, Oracle and/or its affiliates Rustは「安全・高速」をそのままWASMに持ち込める
Rustは他言語と何が違う? 11 Copyright © 2025, Oracle and/or its affiliates 項目
Rust Go C++ Java TypeScript 実行速度 非常に速い 速い 非常に速い 中〜速 中 (JS依存) メモリ安全性 高 (コンパイル時) 中 (ランタイム) 低 (手動管理) 中〜高 (GC) 中〜高 (JSエンジン) 学習コスト 高め 低 高 中 低 並行性 高 (安全) 中 (goroutine) 高 (unsafe) 中 (スレッドベース) 低 (Web依存) GCの有無 なし あり なし あり あり 主な用途例 CLI・WASM・k8s Web/APIツール 組込み・ゲーム Web/業務アプリ フロントエンド
Rustの基本と独特な特徴たち
変数を定義 • let で変数宣言 • mut をつけると値を変更できる • デフォルトはimmutable 13
Copyright © 2025, Oracle and/or its affiliates fn main() { let x = 5; // 不変(immutable)変数 let mut y = 10; // 可変(mutable)変数 println!("x = {}, y = {}", x, y); }
所有権 • Rustの変数には「所有権」が結びついている • 所有権ルールのおかげでメモリ管理は自動 • 定義した変数がスコープを抜けると、自動的にリソースも解放 14 Copyright ©
2025, Oracle and/or its affiliates 関数ブロック { let a = String::from(“hi”); // 今ココ let b = a; } { 別の処理 } ヒープ領域 “hi” aが”hi”の所有権を持つ a hi
所有権 • Rustの変数には「所有権」が結びついている • 所有権ルールのおかげでメモリ管理は自動 • 定義した変数がスコープを抜けると、自動的にリソースも解放 15 Copyright ©
2025, Oracle and/or its affiliates 関数ブロック { let a = String::from(“hi”); let b = a; // 今ココ } { 別の処理 } ヒープ領域 “hi” bに”hi”の所有権が移動 b hi aは使えなくなる = Rust では、値を持たない空の 変数は存在しない a
所有権 • Rustの変数には「所有権」が結びついている • 所有権ルールのおかげでメモリ管理は自動 • 定義した変数がスコープを抜けると、自動的にリソースも解放 16 Copyright ©
2025, Oracle and/or its affiliates 関数ブロック { let a = String::from(“hi”); let b = a; } { 別の処理 //今ココ } ヒープ領域 ヒープ領域が解放され、 bが破棄される b
所有権 : 値には持ち主がいる • 1つの変数だけが値の持ち主になれる • 3行目で所有権はs2に「移動」している • s1の所有権がs2に移ったので、もうs1は使えない 17
Copyright © 2025, Oracle and/or its affiliates fn main() { let s1 = String::from("hello"); let s2 = s1; // 所有権がs1からs2へ移動 println!("{}", s1); // コンパイルエラー }
所有権 : 所有権のコピー • clone()を使うと所有権の移動ではなく「コピー」が 発生する • ヒープのメモリコピーが行われるためコストが高い 18 Copyright
© 2025, Oracle and/or its affiliates fn main() { let s1 = String::from("hello"); let s2 = s1.clone(); // ディープコピー println!("{}", s1); // OK! }
借用 : 一時的に貸し出す仕組み • & をprefixにすると参照渡し - 「借用」と呼ぶ - 「借用」された値はあくまでも参照なので基本
的にはimmutable • 借用中でも持ち主が保持されているから、安全 19 Copyright © 2025, Oracle and/or its affiliates fn print_len(s: &String) { println!("len = {}", s.len()); } fn main() { let s = String::from("hello"); print_len(&s); // 借用(参照渡し) println!("{}", s); // OK }
借用 : 可変参照 • &mut : 可変参照 - 値そのものを借りるが、 中身を変更してもいいとい
う許可を得るための構文 • Rustは同時に複数の可変参照を禁止してデータ 競合を防ぐ • コンパイル時にチェックしてくれるのがRustの強み 20 Copyright © 2025, Oracle and/or its affiliates fn main() { let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; // コンパイルエラー }
型を定義 • Rustの型注釈は「変数名: 型」の順番 • 明示しなくても推論してくれるが、書けばもち ろん可読性の向上に寄与 21 Copyright ©
2025, Oracle and/or its affiliates let a: i32 = 42; let b: f64 = 3.14; let c: &str = "hello"; // 文字列リテラルの参照
型の一例 22 Copyright © 2025, Oracle and/or its affiliates 型
説明 例 i32 32ビット整数 let x: i32 = 5; f64 64ビット浮動小数点 let pi: f64 = 3.14; bool 真偽値 let b: bool = true; &str 文字列スライス (参照) "hello" String ヒープ上の文字列 String::from("hi")
String と &str の違い 23 Copyright © 2025, Oracle and/or
its affiliates • &str : 文字列スライス、値の所有権を持たない • String : ヒープ上の文字列、値の所有権を持つ • “hi” は &str (参照) であり、Stringとは別物 • String::from(...) を使うことでヒープ上に確保された所有権のある文字列を作る • s1は静的にプログラムに埋め込まれた読み取り専用の文字列 • s2はヒープ上に確保され、あとで変更や所有権の移動ができる let s: String = String::from("hi"); let s1 = “hi”; // &str型 (静的文字列) let s2 = String::from(“hi”); // String型 (所有権あり)
関数を定義 • 戻り値の型は -> で表現 • Rustでは関数の最後の式が返される - セミコロン (;)
がある = 値が返らない - セミコロン (;) がない = 値が返る • returnを使ってどの位置でも値を返せる - 複雑な条件がある場合はreturnを使うと 明確になる - セミコロンを忘れずに! 24 Copyright © 2025, Oracle and/or its affiliates fn add(a: i32, b: i32) -> i32 { a + b // 最後の式が返る } fn square(x: i32) -> i32 { return x * x; } fn maybe_negative(x: i32) -> i32 { if x < 0 { return 0; } x // 式として返る(正のとき) }
代表的な制御構文 if / else if / else • 条件は必ず bool
型 • 三項演算子なし • 式として値を返せる loop • 無限ループ構文 • break で脱出、continue で次のループへ • break 値; とすればループから値を返せる 25 Copyright © 2025, Oracle and/or its affiliates if x > 0 { println!("正"); } else if x < 0 { println!("負"); } else { println!("ゼロ"); } let mut count = 0; loop { count += 1; if count == 3 { break; } }
代表的な制御構文 while • 条件が false になるまで繰り返す for in • 範囲(Range)やイテレータを使って反復
• 0..3 は 0, 1, 2(終端は含まない) 26 Copyright © 2025, Oracle and/or its affiliates let mut n = 0; while n < 3 { println!("{}", n); n += 1; } for num in 0..3 { println!("{}", num); }
Rustのエラーハンドリング哲学 try/catch の概念が存在しない • エラーか成功かを値で返す • 「プログラムが途中で落ちる」より、「明示的に処理する」 ことを優先 • 結果的に、見落としによるエラーをコンパイル時に防げる
Rustの型による保証成功 • パスと失敗パスの両方を型として表現 - Result<T, E> → 成功(T)か失敗(E)のどちらか - Option<T> → 値がある(Some)か、ない(None)か • 復旧できないエラーは panic! → プロセスが即終了 • 型システムにより「必ずどちらかを処理する」ことをコンパイ ル時に強制 27 Copyright © 2025, Oracle and/or its affiliates 言語 エラーの扱い 見落としやすさ コンパイル時 検出 Java 例外 (throw/catch) 発生箇所が隠 れやすい チェック例外の み一部可能 Go error型を戻り値に 加える 無視しようと思 えばできる 型上は強制さ れない Rust Result/Option型 無視不可(未 処理だとコンパ イルエラー) 100%型で 保証
Result型の基本 • Ok() → 成功したときの値 • Err() → エラーの内容 •
関数の戻り値でエラーを表現 28 Copyright © 2025, Oracle and/or its affiliates fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("ゼロ除算です")) } else { Ok(a / b) } }
matchで結果を処理 • match式のResult(ここでは戻り値の String)がreturnのように関数から返 却 • 全てのパターンでResultの型は同じ型 (ここではString)でなければならない 29 Copyright
© 2025, Oracle and/or its affiliates fn check_number(x: i32) -> String { match x { 0 => String::from("ゼロです"), 1..=9 => String::from("1から9の間です"), _ => String::from("その他です"), } }
Option型の利用 • Some(value) → 値あり • None → 値なし(Null safety)
• match で網羅的に扱う • 「ある場合」と「ない場合」を強制的に コードに書かせる 30 Copyright © 2025, Oracle and/or its affiliates fn find_user(id: i32) -> Option<String> { if id == 1 { Some(String::from("Alice")) } else { None } } fn main() { match find_user(1) { Some(name) => println!("Hello, {}", name), None => println!("User not found"), } }
unwrapの利用とpanic! • Some → 値を返す • None → panic! で即終了
- 簡単だが、安全性は下がる panic! の位置づけ • ユーザー入力や外部要因エラーでは 使わない • プログラムのバグや復旧不能時のみ • Goのpanic()に近いが、Rustでは日 常的には避ける 31 Copyright © 2025, Oracle and/or its affiliates let s = Some("Hello").unwrap(); // "Hello" が返る let x: Option<i32> = None; let n = x.unwrap(); // panic! 発生
? 演算子の利用 ? は 「エラーや None を見つけたら即 座にその関数から返す」 という動作 •
Some → 値を取り出す • None → 関数から即返却 • Result 型でも同じ書き方が可能 ※usize: 主にメモリ上のインデックス やサイズを表すために使われる整数 型の一つ 32 Copyright © 2025, Oracle and/or its affiliates fn get_length(name: Option<&str>) -> Option<usize> { let s = name?; // Noneなら即return None Some(s.len()) }
エラーハンドリングまとめ 機能 目的 主な使い方 エラー時の動作 メリット 注意点 Result<T, E> 成功/失敗の両
方を型で表す Ok(value), Err(error) 失敗時は Err(error)を返 す エラー型を明示で き、安全 呼び出し元が必 ず処理する必要 Option<T> 値の有無を型で 表す Some(value), None 無い場合は None Null Safetyで 値がない場合を 安全に表現 None時の分岐 処理が必要 match 値の全パターンを 網羅的に処理 match x { ... } 各パターンのコー ドが実行される コンパイル時に網 羅性チェック 冗長になりがち unwrap() 値を直接取り出 す(成功前提) x.unwrap() None / Err → panic! コードが短くなる エラー時に即終 了、例外的に利 用 ? 演算子 エラー/None時 に即返す x? None または Err を呼び出し 元に返す 簡潔で安全、 panicしない 関数の戻り値が Result/Option である必要性 33 Copyright © 2025, Oracle and/or its affiliates
Rustのエコシステムと フレームワーク
Rustのエコシステム全体像 Rustの主要な開発要素 • ビルド & 依存管理 → cargo • パッケージ管理
→ crates.io - Rustではパッケージ = クレート • 豊富なクレート群(公式/OSS) • 実行環境・フレームワーク - CLI - Web - 非同期 - Cloud Native - WASM 35 Copyright © 2025, Oracle and/or its affiliates Rust開発はcargoを中心に回る Implement Build Test crates.io
cargo (パッケージマネージャ & ビルドツール) プロジェクトの作成から実行まで統合管理 $ curl https://sh.rustup.rs -sSf |
sh 36 Copyright © 2025, Oracle and/or its affiliates ビルド・依存管理・テスト $ cargo new myapp # 新規プロジェクト作成 $ cargo build # ビルド $ cargo run # 実行 $ cargo test # テスト $ cargo doc --open # ドキュメント生成 myapp/ ├── Cargo.toml └── src/ └── main.rs
Cargo.toml の役割 • Rust プロジェクトの設定ファイル • プロジェクトのメタデータ (名前・バージョン・作者)と依存クレートを管理 • TOML形式で記述
$ cargo new myapp すると… このようなCargo.tomlが出来上がる 依存の追加は [dependencies] セクションにクレート名とバージョンを書くか、cargo add コマンドを使う 37 Copyright © 2025, Oracle and/or its affiliates [package] name = "myapp" version = "0.1.0" edition = "2024" [dependencies]
依存追加の例 Cargo.toml に記述 コマンドで追加する場合 (cargo-edit のインストールが必要) Cargo.lock ファイル • 初回依存解決時に
Cargo.lock が作成され、バージョンが固定される • 依存のバージョン差異による不具合を防ぐ • ライブラリ開発ではCargo.lockは共有しないのが一般的 38 Copyright © 2025, Oracle and/or its affiliates [dependencies] serde = "1.0" reqwest = { version = "0.11", features = ["json"] } $ cargo add serde $ cargo add reqwest --features json Note : バージョン指定のルール • "1.0" → セマンティックバージョニングで互換範囲 (1.0.xまで) • "=1.0.3" → 完全一致 • ">=1.0, <2.0" → 範囲指定 • { git = "https://github.com/org/repo" } → Gitから取得 • { path = "../local_crate" } → ローカルディレクトリ から取得
crates.io - 公式パッケージレジストリ crates.io : Rustのnpm的存在 • Rust公式のパッケージ(クレート)配布サイト • https://crates.io
• 無料で公開クレートを検索・ダウンロード可能 • 利用はCargoと完全統合されており、Cargo.tomlに記述すれ ば自動取得 • クレート検索 - 名前、キーワード、カテゴリ、ダウンロード数で絞り込み • 人気ランキング - 利用実績や更新頻度の高いクレートを確認 • 詳細ページ - バージョン履歴、依存関係、README、ドキュメントリンク 39 Copyright © 2025, Oracle and/or its affiliates
よく使うクレート Rustはネイティブバイナリを生成するため、配布が簡単で高速なCLIを作りやすい 代表的なクレートを組み合わせることで、実用的なツールを短時間で構築できる • clap / structopt : コマンドライン引数解析 (structoptはclapのラッパー)
• anyhow : エラーを簡単に扱えるAPI • thiserror : カスタムエラー型の定義を簡略化 • indicatif : プログレスバー・進行状況表示 40 Copyright © 2025, Oracle and/or its affiliates CLIツールを例にしてみる
非同期処理 / Webフレームワーク 非同期ランタイム tokio : Rust非同期処理のデファクト、豊富なエコシステム async-std : Node.js風API、学習コスト低め
▪asyncを付けて非同期処理 ※ async はRustの組み込み構文なので、コンパイル自体は tokioなどのランタイムは必要ないが、実際に動かすにはランタイ ムが必要 Webフレームワーク axum : tokioベース、シンプル&型安全、モジュール化しやすい actix-web : 高性能、商用サービス採用例多数 warp : フィルターチェーン型API、柔軟なルーティング ▪axumで簡単なHTTPサーバー 41 Copyright © 2025, Oracle and/or its affiliates Rustはスレッド+非同期I/Oで効率的にリソースを利用可能 async fn fetch_data() -> String { "Hello".to_string() } use axum::{Router, routing::get}; #[tokio::main] async fn main() { let app = Router::new() .route("/", get(|| async { "Hello, Rust!" })); axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); }
#[tokio::main] ← これ何? • コード生成のための仕組み • 実行時ではなく、コンパイル時に展開される • 関数と異なり、型や構造を動的に変えることも可能 宣言的マクロ
(macro_rules!) • パターンマッチでコードを展開する • println!, vec! 手続き的マクロ • ソースコードを解析して新しいコードを生成 • #[derive(Debug)], #[tokio::main] - #[tokio::main] は非同期関数を普通のmain関数として動かせるように変換するマクロ - 裏でランタイムの初期化コードを自動生成している 42 Copyright © 2025, Oracle and/or its affiliates マクロ : コンパイル前にコードを生成する仕組み
Cloud Native と Rust Cloud Native的な目線でRustが活きる特長 • メモリ安全 + 高パフォーマンス
- C/C++並みの速度 - ガーベジコレクションなしで低レイテンシ • 単一バイナリ配布 - コンテナイメージを小さくできる (数MB〜) - 依存関係の管理が容易 • クロスコンパイルが容易 - ARM / x86 / WASMなど幅広いターゲットに対応 ▪主な関連分野とクレート 43 Copyright © 2025, Oracle and/or its affiliates 分野 クレート/プロジェクト 概要 Kubernetes操作 kube-rs Kubernetes APIとやり取 りするRustクライアント WASM実行 wasmtime / wasmer WebAssemblyランタイム バインディング bindgen C/C++との相互運用コード を自動生成 ネットワーク hyper, reqwest 高速HTTPクライアント/サー バー gRPC tonic gRPC実装(Protocol Buffers対応)
Rustを書いてみよう
Hello Rust ↓出来上がるファイル 45 Copyright © 2025, Oracle and/or its
affiliates • fn main() : エントリーポイント • println! : マクロ、文字列を標準出力へ表示する • cargo run : コンパイルして実行まで fn main() { println!("Hello, world!"); } $ cargo new myapp $ cd myapp $ cargo run Compiling myapp v0.1.0 (/home/opc/develop/rust/myapp) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s Running `target/debug/myapp` Hello, world!
cargo コマンド $ cargo check # 速い構文/型チェック $ cargo build
# デバッグビルド $ cargo build --release # 本番向け最適化 $ cargo run # ビルドして実行 $ cargo test # テスト実行 $ cargo doc --open # ドキュメント生成 46 Copyright © 2025, Oracle and/or its affiliates
Result / ? を体験してみる • ? は panic! せずに上位に返す •
main が Result を返すと、? が自然に使える • 「エラー処理」を明示的に型で扱うのがRust 47 Copyright © 2025, Oracle and/or its affiliates use std::fs; fn main() -> Result<(), std::io::Error> { let text = fs::read_to_string(“input.txt”)?; // ファイルがないとreturn Err println!("{}", text); Ok(()) }
clap でCLIを作る 依存関係を追加してみる main.rs を書き換える 48 Copyright © 2025, Oracle
and/or its affiliates clap : CLI開発用クレート、コマンドライン引数解析を行う [dependencies] clap = { version = "4", features = ["derive"] } use clap::Parser; use std::fs; #[derive(Parser, Debug)] struct Args { path: String, // ファイルパス } fn main() -> Result<(), std::io::Error> { let args = Args::parse(); let text = fs::read_to_string(&args.path)?; println!("読込ファイル: {}", args.path); println!("{}", text); Ok(()) } $ cargo run -- files/input.txt Compiling myapp v0.1.0 (/home/opc/develop/rust/myapp) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.44s Running `target/debug/myapp files/input.txt` 読み込み対象: files/input.txt Hello OCHaCafe S10 Rust 実行
ソースコード解説 • Cargo.toml の features - クレートごとに機能が定義されている - features =
["derive"] は「derive マクロ」を有効化 • #[derive(Parser)] を付けられる - 依存関係は必要な機能だけ読み込むのが基本思想 • 軽量性やコンパイル速度に寄与。 • use - モジュールやライブラリをスコープにimportするキーワード • struct - Go の struct、Java のClassに近い - Classのようにメソッドや継承は持たず、データの塊を定義 - derive(Parser) を付けると、この構造体が コマンドライン引数の 仕様になる • :: (パス演算子) - モジュールや型の中にある要素にアクセスする記号 - Javaでいう . (ドット) 49 Copyright © 2025, Oracle and/or its affiliates [dependencies] clap = { version = "4", features = ["derive"] } use clap::Parser; use std::fs; #[derive(Parser, Debug)] struct Args { path: String, // ファイルパス } fn main() -> Result<(), std::io::Error> { let args = Args::parse(); let text = fs::read_to_string(&args.path)?; println!("読込ファイル: {}", args.path); println!("{}", text); Ok(()) }
CLIツール実装チートシート before after 50 Copyright © 2025, Oracle and/or its
affiliates 1. --help を Readable に use clap::Parser; use std::fs; #[derive(Parser, Debug)] #[command(name="myapp", version, about="テキストを 表示するCLI")] struct Args { path: String, // ファイルパス } fn main() -> Result<(), std::io::Error> { let args = Args::parse(); let text = fs::read_to_string(&args.path)?; println!("読込ファイル: {}", args.path); println!("{}", text); Ok(()) } $ cargo run -- -h Running `target/debug/myapp -h` Usage: myapp <PATH> Arguments: <PATH> Options: -h, --help Print help $ cargo run -- -h Running `target/debug/myapp -h` テキストを表示するCLI Usage: myapp <PATH> Arguments: <PATH> Options: -h, --help Print help -V, --version Print version
CLIツール実装チートシート before after 51 Copyright © 2025, Oracle and/or its
affiliates 2. Error を Readable に use clap::Parser; use std::fs; use anyhow::{Context, Result}; #[derive(Parser, Debug)] #[command(name="myapp", version, about="テキストを 表示するCLI")] struct Args { path: String, // ファイルパス } fn main() -> Result<()> { let args = Args::parse(); let text = fs::read_to_string(&args.path) .with_context(|| format!("ファイルを読み込 めません: {}", args.path))?; println!("読込ファイル: {}", args.path); println!("{}", text); Ok(()) } $ cargo run -- input.text Running `target/debug/myapp input.text` Error: Os { code: 2, kind: NotFound, message: "No such file or directory" } $ cargo run -- input.text Running `target/debug/myapp input.text` Error: ファイルを読み込めません: input.text ※tomlへの追加も忘れずに
CLIツール実装チートシート before after 52 Copyright © 2025, Oracle and/or its
affiliates 3. 標準入力に対応 // 略 use std::io::{self, Read}; // 略 fn read_all(path: &str) -> Result<String> { if path == "-" { let mut s = String::new(); io::stdin().read_to_string(&mut s) .context("標準入力を読み込めません")?; Ok(s) } else { Ok(fs::read_to_string(path) .with_context(|| format!("ファイルを読 み込めません: {path}"))?) } } fn main() -> Result<()> { let args = Args::parse(); let text = read_all(&args.path)?; // 略 } $ echo "Hello OCHaCafe S10 Rust" | cargo run -- - Running `target/debug/myapp -` Error: ファイルを読み込めません: - Caused by: No such file or directory (os error 2) $ echo "Hello OCHaCafe S10 Rust" | cargo run -- - Running `target/debug/myapp -` 読込ファイル: - Hello OCHaCafe S10 Rust
CLIツール実装チートシート before after 53 Copyright © 2025, Oracle and/or its
affiliates 4. ファイルの存在有無チェック // 略 use std::path::Path; use std::fs::metadata; // 略 fn validate(path: &str) -> Result<()> { if path == "-" { return Ok(()); } let p = Path::new(path); if !p.exists() { anyhow::bail!("ファイルが存在 しません: {path}"); } let meta = metadata(p).with_context(|| format!("メタデータの取得に失敗: {path}"))?; println!("{}", format!("size: {} bytes", meta.len())); Ok(()) } // 略 fn main() -> Result<()> { let args = Args::parse(); validate(&args.path)?; // 略 } $ cargo run -- input.text Running `target/debug/myapp input.text` Error: ファイルを読み込めません: input.text Caused by: No such file or directory (os error 2) $ cargo run -- input.text Running `target/debug/myapp input.text` Error: ファイルが存在しません: input.text
CLIツール実装チートシート 実行結果 54 Copyright © 2025, Oracle and/or its affiliates
5. ファイルとして結果を出力 // 略 use std::io::Write; // 略 struct Args { path: String, #[arg(long)] output: Option<String>, } // 略 fn write_out(s: &str, to: &Option<String>) -> Result<()> { if let Some(p) = to { let mut f = std::fs::File::create(p) .with_context(|| format!("出力ファイルを作成できません: {p}"))?; f.write_all(s.as_bytes()) .with_context(|| format!("出力ファイルに書き込めません: {p}"))?; eprintln!("{}", format!("ファイルに書き出しました: {p}")); } else { println!("{s}"); } Ok(()) } fn main() -> Result<()> { // 略 write_out(&text, &args.output)?; } [opc@olcd myapp]$ cargo run -- input.txt --output out.txt Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/myapp input.txt --output out.txt` size: 14 bytes ファイルに書き出しました: out.txt [opc@olcd myapp]$ cat out.txt Hello OCHaCafe
CLIツール実装チートシート 実行結果 55 Copyright © 2025, Oracle and/or its affiliates
6. --verbose オプション // 略 use env_logger::Env; // 略 struct Args { // 略 #[arg(short, long)] verbose: bool, } // 略 fn init_logger(verbose: bool) { let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("warn")); if verbose { builder.filter_level(log::LevelFilter::Info); } let _ = builder.try_init(); } fn main() -> Result<()> { let args = Args::parse(); init_logger(args.verbose); log::info!("入力を検証しています"); validate(&args.path)?; log::info!("入力を読み込みます"); let text = read_all(&args.path)?; log::info!("結果を出力します"); write_out(&text, &args.output)?; Ok(()) } $ cargo run -- input.txt -v Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/myapp input.txt -v` [2025-08-17T19:49:38Z INFO myapp] 入力を検証しています size: 14 bytes [2025-08-17T19:49:38Z INFO myapp] 入力を読み込みます [2025-08-17T19:49:38Z INFO myapp] 結果を出力します Hello OCHaCafe
デモ: 分かりやすいエラー (エラーハンドリング) 実行結果 before 実行結果 after 56 Copyright ©
2025, Oracle and/or its affiliates 「panic! をあまり使うべきでないなぁ」を体験 $ cargo run -- --grep "(" input.txt Running `target/debug/example_error --grep '(' input.txt` thread 'main' panicked at src/main.rs:16:45: called `Result::unwrap()` on an `Err` value: Syntax( ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ regex parse error: ( ^ error: unclosed group ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace $ cargo run -- --grep "(" input.txt Running `target/debug/example_error --grep '(' input.txt` Error: 正規表現が無効です: (
デモ: 分かりやすいエラー (エラーハンドリング) • Regex::new(p) - Regex::new は 文字列から正規表現オブジェクトを作成する関数 -
戻り値は Result<Regex, regex::Error> • 正しい正規表現 → Ok(Regex) • 間違った正規表現 → Err(regex::Error) • 2. .map_err(...) - map_err は エラー変換メソッド - regex::Error を直接返すのではなく、human readableなエラーメッセージに変換 - _ で元のエラーを無視しているので、正規表現ライブラリ固有の情報は出さず、シンプルなエラーに • 3. anyhow::anyhow!(...) - anyhow! マクロは 簡単に anyhow::Error を作るためのマクロ - format! のように {} プレースホルダに値を埋め込み - エラーを anyhow::Result として自然に扱えるように 57 Copyright © 2025, Oracle and/or its affiliates 実装内容を少し補足 let re = Regex::new(p).map_err(|_| anyhow::anyhow!("正規表現が無効です: {}", p))?;
デモ: ユニットテスト テスト関係のマクロ • #[cfg(test)] - 「このモジュールはテスト時だけコンパイル」という属性 - cargo test
では有効 - cargo run では無効。 • #[test] - 「この関数はテスト関数」と印をつけるマクロ mod tests { ... } • Rust ではモジュール単位でスコープを作る • ユニットテストは通常「テスト対象のソースコードと同じファイルの中」に tests モジュールを作る use super::* • テストは通常、mod tests の中に書くので一段ネストされる • そのため、テストから元の関数を呼ぶには親モジュール(super) を参 照する必要がある 58 Copyright © 2025, Oracle and/or its affiliates #[cfg(test)] mod tests { use super::*; #[test] fn grep_matches_case_insensitive() { let src = "Alice¥nalice¥nBob¥nALICE"; let pat = Some("(?i)alice".to_string()); let out = maybe_grep(src, &pat).unwrap(); assert_eq!(out.lines().count(), 3); } #[test] fn grep_none_returns_original_text() { let src = "a¥nb¥nc"; let pat = None; let out = maybe_grep(src, &pat).unwrap(); assert_eq!(out, src); } #[test] fn invalid_regex_is_human_friendly_error() { let src = "x"; let pat = Some("(".to_string()); let err = maybe_grep(src, &pat).unwrap_err(); let msg = format!("{err}"); assert!(msg.contains("正規表現が無効です")); } }
デモ: WASM体験 Rust → WASM • wasm-pack build の結果、Rustのソースコードが WebAssembly
バイナリ (simple_wasm_bg.wasm) にコンパイル • この .wasm が実際の処理を行うネイティブに近いバイトコード wasm-bindgen によるJSラッパ生成 • simple_wasm.js や simple_wasm_bg.js は、JavaScript 側から .wasm を扱いやすくするためのブリッジになるコード - fetch または import を通じて .wasm をロード - Rust関数を JavaScript 関数として呼び出せるように変換 実行時 • ブラウザ側で import * as wasm from "./simple_wasm.js" をすると - ラッパが内部で simple_wasm_bg.wasm をロード - Rustの関数がJSの関数として使えるようになる 59 Copyright © 2025, Oracle and/or its affiliates
ご清聴ありがとうございました! Copyright © 2025, Oracle and/or its affiliates 60
None