Claude Codeを使いこなすためのRust入門【第2回】つまずきやすいポイントOption・Result・async
はじめに:今日のテーマは「もしも」への備え
前回は、Rust でいちばん大事な「所有権」と「借用」をお話ししました。「持ち主はひとり」「貸すときは `&`」でした。
さて、今回のテーマはこちらです。
`Option`(オプション)
`Result`(リザルト)
`async`(エイシンク)/ `await`(アウェイト)
これらは、「もしも、うまくいかなかったらどうする?」という「備え」の仕組みです。
そして、ここは Claude Code が作るプログラムの中で特にわかりにくい場所でもあります。だからこそ、あなたが少しだけ知っておくと、開発がぐっと安定します。
なぜこの知識が必要なのか
Claude Code は賢いですが、ときどき「とりあえず動けばいい」というようなコードを書きます。
その代表が、これから出てくる `unwrap()`(アンラップ)というものです。
これは便利な一方で、ある条件がそろうとアプリが突然クラッシュ(強制終了)する原因になります。
つまり、あなたがこの仕組みを知らないと、「テストでは動いたのに、本番で急に落ちる」というトラブルに気づけません。
逆に言えば、ポイントを知っているだけで、「ここ、危ない書き方になってない?」と Claude Code にひとこと言えるようになります。
それだけで、あなたのアプリはぐっと壊れにくくなります。
基本概念(1):Option 〜「あるかも、ないかも」を表す箱〜
まず `Option` です。これは、「中身があるかもしれないし、ないかもしれない箱」だと思ってください。
身近な例で言うと、郵便受けです。朝、郵便受けをのぞくと、手紙が入っていることもあれば、空っぽのこともありますよね。
Rust では、この「あるかないか分からない状態」を、`Option` という箱で表します。中身は2種類です。
`Some(値)` … 中身がある(手紙が入っている)
`None` … 中身がない(空っぽ)
コードで見てみましょう。
fn find_user(id: i32) -> Option<String> {
if id == 1 {
Some(String::from("田中さん")) // 見つかった
} else {
None // 見つからなかった
}
}このコードは「IDで利用者を探す」関数です。ID が `1` なら「田中さん」が見つかったので `Some` で包んで返します。それ以外なら、見つからなかったので `None` を返します。
ポイントは、「見つからないかもしれない」ことを、型(かた)で正直に表していることです。
Rust は「もしかしたら空っぽかもよ」と最初から教えてくれるので、うっかり空っぽのものを使ってアプリが壊れる、という事故を防げるのです。
基本概念(2):Result 〜「成功か、失敗か」を表す箱〜
次に `Result` です。`Option` が「あるか、ないか」だったのに対し、
`Result` は「成功したか、失敗したかを表す箱」です。
例えるなら、試験の結果通知です。封筒を開けると「合格」か「不合格」、どちらかが入っています。
`Result` の中身も2種類です。
`Ok(値)` … 成功(合格。中に成功した結果が入っている)
`Err(理由)` … 失敗(不合格。中に失敗の理由が入っている)
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("0では割れません")) // 失敗
} else {
Ok(a / b) // 成功
}
}このコードは「割り算をする」関数です。割る数が `0` だと計算できないので、`Err` に理由を入れて返します。それ以外なら、ちゃんと計算して `Ok` で結果を包んで返します。
`Option` との違いは、失敗したときに「なぜ失敗したか」も一緒に渡せることです。ファイルの読み込みやネット通信など、「失敗の理由を知りたい」場面で大活躍します。反対に、失敗することが普通で、特に理由を知る必要がないような場合は、`Option`を用います。
ここが要注意:unwrap と panic
さて、いよいよ Claude Code が間違えやすいポイントです。
`Option` や `Result` は箱に包まれているので、中身を取り出すにはひと手間かかります。
その「ひと手間」を一気に省略する魔法が、`unwrap()`(アンラップ)です。名前のとおり「包み(wrap)をむく(un)」という意味です。
let result = divide(10, 0);
let answer = result.unwrap(); // 危険!この `unwrap()` は、中身があれば取り出してくれます。便利です。
でも、もし中身が `None` や `Err`(つまり失敗)だったら?
そのとき Rust は、なんとアプリを強制終了させます。この強制終了のことをpanic(パニック)と呼びます。
つまり `unwrap()` は、「中身が必ずあると信じて、もし無かったらアプリごと爆発する」という、かなり強気な書き方なのです。
Claude Code は、手早く動くコードを作ろうとして、この `unwrap()` をあちこちに置いてしまうことがあります。お試しなら問題ないかもしれませんが、本番のアプリでは多用しないように注意しましょう。
安全な取り出し方:match
では、どうすれば安全なのでしょうか。
おすすめは `match`(マッチ)という仕組みです。「もし中身がこうなら、こうする」を、ていねいに場合分けします。
let result = divide(10, 0);
match result {
Ok(answer) => println!("答えは {}", answer), // 成功したとき
Err(reason) => println!("エラー: {}", reason), // 失敗したとき
}このコードは、割り算の結果を場合分けして処理しています。
・`Ok` だったら(成功)、答えを表示します。
・`Err` だったら(失敗)、その理由を表示します。
`unwrap()` と違って、失敗してもアプリは爆発しません。ちゃんと「エラーが出ましたよ」と教えてくれるだけです。これが、人にやさしいエラー処理です。
便利な近道:? 演算子
毎回 `match` を書くのは、正直ちょっと面倒です。そこで Rust には、`?`(クエスチョンマーク)という便利な近道があります。
fn calc() -> Result<i32, String> {
let answer = divide(10, 2)?; // 成功なら中身を取り出す
Ok(answer + 1)
}`divide(10, 2)?` の最後についている `?` がポイントです。この `?` は、こう動きます。
成功(`Ok`)なら → 中身を取り出して、次に進む
失敗(`Err`)なら → そこで処理をやめて、エラーを呼び出し元に返す
つまり `?` は、「成功したら進む、失敗したら安全に引き返す」という、かしこい近道なのです。
`unwrap()` のようにアプリを爆発させず、失敗をきちんと外へ伝えてくれます。Claude Code のコードに `?` が出てきたら、「お、安全な書き方だな」と思ってOKです。
基本概念(3):async / await 〜「待ち時間」を上手に使う仕組み〜
最後は `async`(アシンク)と `await`(アウェイト)です。
これは、「時間のかかる作業を、待っている間に他のこともやる」仕組みです。
カフェで例えましょう。
あなたがコーヒーを注文します。
注文を取る店員さんは、あなたのコーヒーができるのをただ突っ立って待ったりしません。
その間に、次のお客さんの注文を取りますよね。
`async` は、まさにこれです。ネット通信やファイル読み込みなど「待ち時間が発生する作業」のとき、待っている間にパソコンが他の仕事を進められるようにします。
async fn get_data() -> String {
let data = fetch_from_web().await; // ここで待つ
data
}`async fn` は「これは待ち時間がある関数ですよ」という宣言です。
そして `.await` が「ここで待ち時間が発生します」という合図です。ただし、ただ突っ立って待つのではなく、待っている間は他の処理に道をゆずります。
初心者のうちは、ここまで理解できれば十分です。「`async` と `await` はセットで、待ち時間を上手に使うためのもの」と覚えておけば大丈夫です。
Claude Codeがasyncで間違えやすいこと
`async` まわりは、Claude Code でもエラーが出やすい場所です。よくあるのは、こんなエラーです。
`await` の付け忘れ
`async` ではない普通の関数の中で `.await` を使ってしまう
動かすための土台(ランタイムと呼ばれます)の設定が足りない
エラーメッセージに `await`、`async`、`Future` といった単語が出てきたら、「これは待ち時間まわりの話だな」と気づければ十分です。
細かい設定は、Claude Code にお願いすれば直してくれます。
AIへの指示例
では、今回も大事な「AI への頼み方」です。
(1) unwrap を見つけたとき
悪い例
エラーが出ないようにして
良い例
このコードに `unwrap()` が使われています。
失敗したときにアプリが落ちないよう、`match` か `?` を使った
安全なエラー処理に書き換えてください。
(2) エラー処理を頼むとき
悪い例
ちゃんとエラー処理して
良い例
この関数で失敗が起きる可能性がある箇所を教えてください。
その上で、`Result` 型を使い、失敗の理由が分かるように
エラー処理を追加してください。
(3)async で困ったとき
悪い例
動かない、直して
良い例
`await` まわりでエラーが出ています。
どこで待ち時間が発生しているのかを説明した上で、
正しく `await` を付けて修正してください。
共通するコツは、前回と同じです。エラーをそのまま貼る、専門用語を使う、直す方向を示す。この3つで、Claude Code の精度は大きく変わります。
まとめ
今回は、Claude Code が間違えやすい3つのポイントを見てきました。
Option:中身があるかも、ないかもの箱(`Some` / `None`)
Result:成功か失敗かの箱(`Ok` / `Err`)
unwrap:便利だけど、失敗するとアプリが爆発(panic)する危険な近道
match:ていねいに場合分けする、安全な取り出し方
? 演算子:成功なら進む、失敗なら安全に引き返すかしこい近道
async / await:待ち時間を上手に使う仕組み。セットで覚える
全部を完璧に理解する必要はありません。大事なのは、「あ、ここ `unwrap` 使ってるな、危ないかも」、「これは待ち時間まわりの話だな」と気づけること。
そして、Claude Code に「安全なエラー処理に直して」とお願いできることです。
Rust の「もしもへの備え」は、最初は回りくどく感じます。でもそれは、あなたのアプリを守るための優しさです。
仕組みを少し知っているだけで、その優しさを味方にできます。「Claude Code となら、壊れにくいアプリも作れそう」。そう思っていただけたら、うれしいです。
次回はいよいよ最終回。`Cargo` や依存ライブラリ、そしてセキュリティといった「実際に開発を進めるための道具」についてお話しします。
今回の連載について、ChatGPT(5.5)に全体構成とファクトチェックと表紙画像生成を、Claude Cowork(Opus 4.8)に原稿作成を、それぞれ担当してもらいました。最後に、私が加筆・修正しています。
