<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rust Tech</title>
	<atom:link href="https://rust-tech.nkhn37.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://rust-tech.nkhn37.net</link>
	<description>Rustプログラミング学習サイト</description>
	<lastBuildDate>Sun, 05 Jul 2026 04:21:16 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.1</generator>

<image>
	<url>https://rust-tech.nkhn37.net/wp-content/uploads/2025/06/cropped-lion-preasure-clear-32x32.png</url>
	<title>Rust Tech</title>
	<link>https://rust-tech.nkhn37.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【Rust】reqwest の基本と使い方を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-reqwest-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-reqwest-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Sat, 04 Jul 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[reqwest]]></category>
		<category><![CDATA[async]]></category>
		<category><![CDATA[await]]></category>
		<category><![CDATA[blocking]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[serde]]></category>
		<category><![CDATA[tokio]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=2177</guid>

					<description><![CDATA[Rust で HTTP 通信を行うためのクレートである reqwest の基本的な使い方について、初心者にも分かりやすく解説します。 reqwest クレートの概要 reqwest とは reqwest は、Rust で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust で HTTP 通信を行うためのクレートである <span class="jinr-d--text-color d--marker1 d--bold"><code>reqwest</code> の基本的な使い方</span>について、初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold"><code>reqwest</code> クレートの概要</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>reqwest</code> とは</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>reqwest</code></span> は、Rust で HTTP 通信を行うための代表的なクレートです。GET や POST などの HTTP リクエストを簡潔なコードで記述でき、JSON の送受信、認証ヘッダーの付与、タイムアウト設定なども柔軟に対応しています。</p>



<p class="wp-block-paragraph">Rust の標準ライブラリには、HTTP クライアント機能は含まれていないため、Web API との通信が必要な場面では、<code>reqwest</code> がデファクトスタンダードとして広く使用されています。</p>



<p class="wp-block-paragraph">この記事では、<span class="jinr-d--text-color d--marker1 d--bold"><code>reqwest</code> の基本的な使い方</span>を紹介します。</p>



<h3 class="wp-block-heading jinr-heading d--bold">非同期モードと同期モード</h3>



<p class="wp-block-paragraph"><code>reqwest</code> には、非同期モードと同期モードの 2 種類があります。<code>reqwest</code> は、非同期処理ランタイムの <code>tokio</code> をベースに構築されており、デフォルトは非同期モードです。</p>



<ul class="wp-block-list jinr-list">
<li>非同期モード（デフォルト）：<code>async</code> / <code>await</code> を使用して非同期でリクエストを送信します。非同期処理ランタイムである <code>tokio</code> が必要です。</li>



<li>同期モード：<code>reqwest::blocking</code> モジュールを使うことで、通常の同期コードとして HTTP リクエストを書くことができます。使用する場合には、blocking feature を有効にする必要があります。</li>
</ul>



<p class="wp-block-paragraph">この記事では、実務上よく使われる非同期モードを中心に解説します。同期モード（<code>reqwest::blocking</code>）については、後半で簡単に触れます。 </p>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold"><code>reqwest</code> を使用した HTTP 通信の基本</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>reqwest</code> の導入方法</h3>



<p class="wp-block-paragraph"><code>reqwest</code> は、他のクレートと同様に <code>cargo add</code> または <code>Cargo.toml</code> に追記することで利用できます。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>cargo add</code> で追加する場合</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cargo add reqwest --features json,query
cargo add tokio --features full</pre>



<h4 class="wp-block-heading jinr-heading d--bold"><code>Cargo.toml</code> に追記する場合</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[dependencies]
reqwest = { version = "0.13", features = ["json", "query"] }
tokio = { version = "1", features = ["full"] }</pre>



<h4 class="wp-block-heading jinr-heading d--bold">feature について</h4>



<p class="wp-block-paragraph"><code>reqwest</code> の json feature を有効にすることで、<code>json</code> メソッドが使えるようになります。これにより、リクエストボディへの JSON 埋め込みや、レスポンスの JSON デシリアライズを簡単に行うことができます。JSON を扱う場合には、必ず指定するようにしましょう。また、以降で使用する <code>query</code> メソッドも使えるように query feature も有効にします。</p>



<p class="wp-block-paragraph"><code>tokio</code> の full feature は、<code>tokio</code> が提供するすべての機能を有効にしておきます。</p>



<p class="wp-block-paragraph">導入時には crates.io の <a href="https://crates.io/crates/reqwest" target="_blank" rel="noreferrer noopener">reqwest</a> や <a href="https://crates.io/crates/tokio" target="_blank" rel="noreferrer noopener">tokio</a> のページを確認してください。なお、実際にインストールされたバージョンは <code>Cargo.lock</code> ファイルで確認できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">クレートや依存関係の基本については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-crates-basics/" target="_blank" rel="noreferrer noopener">クレート（バイナリ／ライブラリ）と依存関係の管理を分かりやすく解説</a></p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">テスト用サービス httpbin.org</h3>



<h4 class="wp-block-heading jinr-heading d--bold">HTTP リクエストとレスポンスをテストする</h4>



<p class="wp-block-paragraph">HTTP リクエストとレスポンスのテストをするためには、API を提供するサーバーが必要になります。今回は「<a href="https://httpbin.org/" target="_blank" rel="noreferrer noopener">httpbin.org</a>」を使用します。</p>



<p class="wp-block-paragraph">httpbin.org は、HTTP リクエストとレスポンスのテストに使用される人気のオンラインサービスで、開発者が HTTP リクエストを送信し、レスポンスを確認することができます。</p>



<p class="wp-block-paragraph">httpbin.org は、WebAPI 開発や HTTP クライアントのライブラリ、フレームワークのテストなどに広く使用されています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">Docker 環境の利用</h4>



<p class="wp-block-paragraph">httpbin.org は、通信タイミングによってサービスが不安定なことがあります。httpbin.org のサービスは、Docker 環境が用意されているため、Docker 環境が手元にある場合には、以下のコマンドでローカル実行してテストする方が安定的に動作の確認が可能です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">docker run --rm -p 8080:80 kennethreitz/httpbin</pre>



<p class="wp-block-paragraph">上記コマンドを実行すると「<code>kennethreitz/httpbin</code>」というコンテナ環境をインストールし、起動します。<code>--rm</code>&nbsp;オプションは、終了時にコンテナを削除するコマンドで、<code>-p 8080:80</code>&nbsp;はポートの接続設定です。ローカル環境からは&nbsp;<code>8080</code>&nbsp;ポートを使用してコンテナにアクセスします。</p>



<p class="wp-block-paragraph">なお、httpbin.org にアクセスする場合は、https で SSL可能ですが、ローカルの Docker 環境は SSL 通信は対応していないので http でアクセスする必要があります。</p>



<p class="wp-block-paragraph">以降のサンプルコードでは、<code>https://httpbin.org</code> への URL を記載しています。ローカルの Docker 環境を使う場合は <code>http://localhost:8080</code> に切り替えて試してください。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">Docker インストールや使い方は以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://tech.nkhn37.net/docker-desktop-for-windows-install/" target="_blank" rel="noreferrer noopener">Docker Desktop for Windowsのインストール方法</a></li>



<li><a href="https://tech.nkhn37.net/docker-container-python/" target="_blank" rel="noreferrer noopener">Dockerイメージを取得してコンテナを作成・動作させる方法</a></li>
</ul>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">各 HTTP メソッドでリクエストを送信する<br>（<code>GET</code> / <code>POST</code>/ <code>PUT</code> / <code>DELETE</code>）</h3>



<h4 class="wp-block-heading jinr-heading d--bold">基本的な使い方の流れ</h4>



<p class="wp-block-paragraph"><code>reqwest</code> を用いて HTTP 通信をする際の基本的な流れは以下の通りです。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--simple-box1  "><div class="c--simple-box-inner">
<ol class="wp-block-list jinr-list">
<li><code>ClientBuilder</code> を生成して、タイムアウトなどの通信の設定をする。</li>



<li><code>ClientBuilder</code> から <code>Client</code> を生成する。</li>



<li><code>RequestBuilder</code> を生成し、パラメータなどの設定をする。</li>



<li>リクエストを送信 (<code>send</code>) し、レスポンスを取得する。</li>



<li>取得したレスポンスからヘッダーやボディなど必要な情報を取り出す。</li>
</ol>
</div></div></section>



<p class="wp-block-paragraph">以降では、上記の流れで各 HTTP メソッドを使用する例を順番に紹介します。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>GET</code> リクエストでレスポンスを取得する</h4>



<h5 class="wp-block-heading jinr-heading d--bold">基本的な使い方</h5>



<p class="wp-block-paragraph">基本的な <code>GET</code> リクエストを送ってレスポンスを取得する例から見ていきましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // httpbin.org から取得する
    let url = "https://httpbin.org/get";
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = "http://localhost:8080/get";

    // ClientBuilder でタイムアウトなどを設定する
    let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));

    // ClientBuilder から Client を作成する
    let client = client_builder.build()?;

    // RequestBuilder を作成する
    let request_builder = client.get(url);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // ステータスコードを取得する
    let status = response.status();
    println!("ステータスコード:\n{status}\n");

    // レスポンスボディを文字列として取得する
    let text = response.text().await?;
    println!("応答の文字列形式:\n{text}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

応答の文字列形式:
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49b680-6c650d0050fcf1c707d6e742"
  }, 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "https://httpbin.org/get"
}</pre>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>#[tokio::main]</code></span> は、<code>main</code> 関数を非同期関数として実行するためのものです。<code>reqwest</code> の非同期モードでは、<code>tokio</code> のランタイムが必要なため、この指定が必要です。</p>



<p class="wp-block-paragraph">まず、<code>reqwest::Client::builder()</code> で <code>ClientBuilder</code> を生成し、<code>timeout()</code> で通信タイムアウトを設定しています。</p>



<p class="wp-block-paragraph">次に、<code>client.get(url)</code> で、<code>RequestBuilder</code> を生成し、<code>send().await</code> でリクエストを送信します。このとき、<span class="jinr-d--text-color d--marker1 d--bold"><code>await</code></span> で非同期処理の完了を待ち、<code>?</code> 演算子でエラーを呼び出し元に伝播しています。</p>



<p class="wp-block-paragraph">レスポンスからは、<code>status()</code> でステータスコードを取得でき、ボディの文字列を取得する際には、<code>text().await</code> を使用します。<code>text()</code> は非同期処理のため、<code>await</code> が必要な点に注意してください。</p>



<h5 class="wp-block-heading jinr-heading d--bold">クエリパラメータを指定する</h5>



<p class="wp-block-paragraph">GET リクエストを送る際に、検索の条件となるクエリパラメータを指定する場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>query</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    ...(Client 作成までは同様なので省略)...

    // RequestBuilder を作成する
    // query() でクエリパラメータを付与することができる
    let queries = [("key1", "value1"), ("key2", "value2")];
    let request_builder = client.get(url).query(&amp;queries);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    ...(ステータスコード表示とボディの表示は同様なので省略)...
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

応答の文字列形式:
{
  "args": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49b7d7-169234f062f0d8bb46cea5c2"
  }, 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "https://httpbin.org/get?key1=value1&amp;key2=value2"
}</pre>



<p class="wp-block-paragraph">query メソッドにキーと値を持った配列を渡すことで、クエリパラメータを設定できます。具体的な URL としては、<code>https://httpbin.org/get?key1=value1&amp;key2=value2</code> のように送信されることになります。</p>



<h5 class="wp-block-heading jinr-heading d--bold">ヘッダーを扱う</h5>



<p class="wp-block-paragraph">リクエストの際にはヘッダー情報を指定する場合や、レスポンスのヘッダーを確認することがよくあります。ヘッダーの扱いについても以下で確認しましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    ...(Client 作成までは同様なので省略)...

    // RequestBuilder を作成する
    // header() でリクエストヘッダーを付与することができる
    // API キーを送信する場合によく使われる例
    let request_builder = client.get(url).header("X-API-Key", "sample-api-key");

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // ステータスコードを取得する
    let status = response.status();
    println!("ステータスコード:\n{status}\n");

    // ヘッダーを取得する
    let headers = response.headers();
    println!("ヘッダー:\n{headers:?}\n");

    // ヘッダーから特定の項目だけを取り出す例
    // ヘッダーは HeaderMap 型で取得されるので、get() メソッドで取り出す
    // 値の型は HeaderValue なので、文字列に変換する必要がある
    let content_type = headers
        .get("content-type")
        .ok_or("content-type ヘッダーが見つかりません")?
        .to_str()?;
    println!("content-type ヘッダー: {content_type}\n");

    // レスポンスボディを文字列として取得する
    let text = response.text().await?;
    println!("応答の文字列形式:\n{text}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

ヘッダー:
{"date": "Sun, 05 Jul 2026 02:06:48 GMT", "content-type": "application/json", "content-length": "257", "server": "gunicorn/19.9.0", "access-control-allow-origin": "*", "access-control-allow-credentials": "true"}

content-type ヘッダー: application/json

応答の文字列形式:
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49bc38-646f78d43467315669dd0b4a", 
    "X-Api-Key": "sample-api-key"
  }, 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "https://httpbin.org/get"
}</pre>



<p class="wp-block-paragraph">リクエストのヘッダーに固有のヘッダを付与したい場合には、<code>RequestBuilder</code> で、<code>header</code> メソッドを使用します。例の「<code>header("X-API-Key", "sample-api-key")</code>」のような指定は、外部サービスの REST API を使用する際に固有の認証キーを使う際によく利用されます。</p>



<p class="wp-block-paragraph">レスポンスのヘッダー情報は、<code>headers</code> メソッドで全体を取得できます。ヘッダーは、<code>HeaderMap</code> 型であり、特定の項目を取り出す際は、<code>get()</code> でアクセスします。取得される値は <code>HeaderValue</code> 型のため、最後に <code>to_str</code> で文字列に変換します。</p>



<h5 class="wp-block-heading jinr-heading d--bold">JSON レスポンスを構造体にデシリアライズする</h5>



<p class="wp-block-paragraph">Web API では JSON 形式のレスポンスを受け取るケースが多くあります。<code>reqwest</code> では <code>serde</code> と組み合わせることで、JSON レスポンスを構造体に直接デシリアライズできます。デシリアライズするためには <code>serde</code> が必要です。<code>cargo add</code>で追加しておいてください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cargo add serde --features derive</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::Deserialize;
use std::collections::HashMap;
use std::error::Error;
use std::time::Duration;

// url と headers だけを保持する構造体
#[derive(Debug, Deserialize)]
struct HttpBinResponse {
    url: String,
    headers: HashMap&lt;String, String>,
}

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    ...(Client 作成までは同様なので省略)...

    // RequestBuilder を作成する
    let request_builder = client.get(url);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // json() で構造体にデシリアライズする
    let data: HttpBinResponse = response.json().await?;

    // url と headers を取り出す
    println!("url: {}", data.url);
    println!("headers: {:?}", data.headers);

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
url: https://httpbin.org/get
headers: {"X-Amzn-Trace-Id": "Root=1-6a498cbb-25fe1cde73cbb10827f0d817", "Accept": "*/*", "Host": "httpbin.org"}</pre>



<p class="wp-block-paragraph"><code>json().await</code> で、レスポンスボディを指定した型に直接デシリアライズできます。受け取る変数には「<code>let data: HttpBinResponse</code>」のように型を明示する必要があります。また、JSON で取り込む構造体は、<code>#[derive(Deserialize)]</code>を付けて定義する必要があります。</p>



<p class="wp-block-paragraph">JSON のフィールドと構造体のフィールドが一致しない場合や、型が合わない場合にはエラーとなります。存在しない場合があるフィールドは <code>Option&lt;T&gt;</code> にしておくと安全です。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">serde を使った JSON の扱いについては「<a href="https://rust-tech.nkhn37.net/rust-serde-json-basic/" target="_blank" rel="noreferrer noopener">serde で JSON を扱う基本を分かりやすく解説</a>」を参考にしてください。</p>
</div>
		</div></section>



<h4 class="wp-block-heading jinr-heading d--bold">POST リクエストで JSON を送信する</h4>



<p class="wp-block-paragraph">JSON データを含めて POST リクエストを送信する例を見てみましょう。POST でデータを登録する場合には、対象サービスのエンドポイントが用意されます。</p>



<p class="wp-block-paragraph">今回は、<code>https://httpbin.org/anything/users</code> というエンドポイントがユーザー登録のためのエンドポイントとして例を紹介します。なお、httpbin.org で <code>/anything</code> や <code>/anything/&lt;任意パス></code> は、HTTPメソッドを問わず、リクエスト内容をそのまま返却するようなエンドポイントです。今回は、<code>users</code> というユーザー登録のエンドポイント例の代替として使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

use serde::Serialize;

// リクエストボディとして送信するデータ
// user_id はサーバー側で採番される想定とする
#[derive(Serialize)]
struct User {
    name: String,
    age: u32,
}

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // httpbin.org へ送信する
    // ユーザー登録エンドポイントを呼び出す
    let url = "https://httpbin.org/anything/users";
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = "http://localhost:8080/anything/users";

    // ClientBuilder でタイムアウトなどを設定する
    let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));

    // ClientBuilder から Client を作成する
    let client = client_builder.build()?;

    // 送信するデータ
    let user = User {
        name: "Taro".to_string(),
        age: 30,
    };

    // RequestBuilder を作成する
    // json() でリクエストボディを JSON として送信する
    let request_builder = client.post(url).json(&amp;user);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // ステータスコードを取得する
    let status = response.status();
    println!("ステータスコード:\n{status}\n");

    // レスポンスボディを文字列として取得する
    let text = response.text().await?;
    println!("応答の文字列形式:\n{text}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

応答の文字列形式:
{
  "args": {}, 
  "data": "{\"name\":\"Taro\",\"age\":30}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "24", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49c912-2d1d37541f89dcbd32a31524"
  }, 
  "json": {
    "age": 30, 
    "name": "Taro"
  }, 
  "method": "POST", 
  "origin": "xxx.xxx.xx.xxx", 
  "url": "https://httpbin.org/anything/users"
}</pre>



<p class="wp-block-paragraph"><code>client.post(url)</code> で POST リクエストの <code>RequestBuilder</code> を作成し、<code>json(&amp;user)</code> で送信したい構造体のデータを設定します。</p>



<p class="wp-block-paragraph">送信するデータの構造体には <code>#[derive(Serialize)]</code> を付与しておく必要があります。なお、<code>json()</code> は内部で <code>Content-Type: application/json</code> ヘッダーも自動付与してくれます。</p>



<h4 class="wp-block-heading jinr-heading d--bold">PUT リクエストでデータを更新する</h4>



<p class="wp-block-paragraph">PUT リクエストについても考えましょう。今回の例では、既に <code>user_id</code> が POST により登録されており、<code>https://httpbin.org/anything/users/u1001</code> というユーザー ID のエンドポイントを PUT で呼び出すと考えます。</p>



<p class="wp-block-paragraph">REST API では、このようにエンドポイントで対象となる ID をパスパラメータとして指定できるように作られることが一般的です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

use serde::Serialize;

// リクエストボディとして送信するデータ
// user_id は URL のパスパラメータで指定するため、ボディには含めない
#[derive(Serialize)]
struct User {
    name: String,
    age: u32,
}

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // 更新対象の user_id
    let user_id = "u1001";

    // httpbin.org へ送信する
    // user_id をパスパラメータとして URL に含める
    let url = format!("https://httpbin.org/anything/users/{user_id}");
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = format!("http://localhost:8080/anything/users/{user_id}");

    ...(Client 作成までは同様なので省略)...

    // 更新後のデータ
    let user = User {
        name: "Miki".to_string(),
        age: 25,
    };

    // RequestBuilder を作成する
    // put() で PUT リクエストを送信する
    let request_builder = client.put(url).json(&amp;user);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // ステータスコードを取得する
    let status = response.status();
    println!("ステータスコード:\n{status}\n");

    // レスポンスボディを文字列として取得する
    let text = response.text().await?;
    println!("応答の文字列形式:\n{text}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

応答の文字列形式:
{
  "args": {}, 
  "data": "{\"name\":\"Miki\",\"age\":25}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "24", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49c11f-39b3368462de6e1f2244052c"
  }, 
  "json": {
    "age": 25, 
    "name": "Miki"
  }, 
  "method": "PUT", 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "https://httpbin.org/anything/users/u1001"
}</pre>



<p class="wp-block-paragraph">対象とする ID 情報は、例のように <code>format!</code> を用いて埋め込むのが簡単です。それ以降の処理の流れは、<code>post</code> が <code>put</code> に変わるだけで同様の流れとなります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">DELETE リクエストでデータを削除する</h4>



<p class="wp-block-paragraph">DELETE リクエストも、PUT と同様に <code>https://httpbin.org/anything/users/u1001</code> に対して DELETE のリクエストを送信する例を考えます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // 削除対象の user_id
    let user_id = "u1001";

    // httpbin.org へ送信する
    // user_id をパスパラメータとして URL に含める
    let url = format!("https://httpbin.org/anything/users/{user_id}");
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = format!("http://localhost:8080/anything/users/{user_id}");

    ...(Client 作成までは同様なので省略)...

    // RequestBuilder を作成する
    // delete() で DELETE リクエストを送信する
    let request_builder = client.delete(url);

    // レスポンスを取得する
    let response = request_builder.send().await?;

    // ステータスコードを取得する
    let status = response.status();
    println!("ステータスコード:\n{status}\n");

    // レスポンスボディを文字列として取得する
    let text = response.text().await?;
    println!("応答の文字列形式:\n{text}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード:
200 OK

応答の文字列形式:
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-6a49c102-51e1f4260751237d2a3ea3c7"
  }, 
  "json": null, 
  "method": "DELETE", 
  "origin": "xxx.xxx.xxx.xxx", 
  "url": "https://httpbin.org/anything/users/u1001"
}</pre>



<p class="wp-block-paragraph"><code>DELETE</code> の場合は、対象が識別できればいいので、エンドポイントを指定して <code>delete</code> メソッドを呼び出しているだけになります。プログラムの構成としては、<code>PUT</code> と同様です。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--heading-iconbox1 ">
			<div class="a--heading-iconbox-title">
			<div class="a--iconbox-title-icon"><i class="jif jin-ifont-caution" aria-hidden="true"></i></div>
			<div class="a--iconbox-title-text">注意点</div>
			</div>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">上記はあくまで、想定の API の呼び出し例です。実際には、各 HTTP メソッドでの呼び出し方は各サービスの仕様に依存します。対象とする API の仕様をしっかりと確認して使い方を考えるようにしてください。</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">エラー情報に対処する</h3>



<p class="wp-block-paragraph">各 HTTP メソッドの使い方を見てきました。これまでの例は、成功ステータスの例のみでしたが、実開発では、エラーステータスコードの場合、適切な処理が必要です。<code>4xx</code>、<code>5xx</code> 番はエラーとして扱いますが、これまで紹介したメソッドは、レスポンスが返ってくれば <code>4xx</code> や <code>5xx</code> でも <code>Ok</code> 扱いとなります。</p>



<p class="wp-block-paragraph">そのため、エラーステータスを判断して処理をしたい場合は、レスポンスの <span class="jinr-d--text-color d--marker1 d--bold"><code>error_for_status</code></span> メソッドを使用します。このメソッドは、<code>4xx</code>、<code>5xx</code> の場合に、<code>Err</code> を返すため、<code>?</code> 演算子と組み合わせるなど状況に応じて適切にエラー処理ができます。</p>



<p class="wp-block-paragraph">httpbin.org には、特定のエラーコードを返却するエンドポイントが用意されているので、今回は、ステータスコード <code>400</code>  が返ってくる場合の対処例を紹介します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // httpbin.org から取得する
    let url = "https://httpbin.org/status/400";
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = "http://localhost:8080/status/400";

    // ClientBuilder でタイムアウトなどを設定する
    let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));

    // ClientBuilder から Client を作成する
    let client = client_builder.build()?;

    // ケース1: HTTP レベルのエラー(ステータスコードが 4xx や 5xx)
    // 通信自体は成功しているため、send() は Ok(Response) を返す
    let response = client.get(url).send().await?;
    println!("ステータスコード: {}\n", response.status());

    // error_for_status() を使うと、4xx・5xx のステータスコードを Err に変換できる
    match response.error_for_status() {
        Ok(response) => println!("成功として扱われました: {}", response.status()),
        Err(error) => println!("error_for_status() でエラーになりました: {error}"),
    }
    println!();

    // ケース2: 通信レベルのエラー
    // 存在しないホスト名のため、DNS 解決に失敗して send() 自体が Err を返す
    let invalid_url = "https://this-host-does-not-exist.com";
    match client.get(invalid_url).send().await {
        Ok(response) => println!("ステータスコード: {}", response.status()),
        Err(error) => println!("send() でエラーになりました: {error}"),
    }

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
ステータスコード: 400 Bad Request

error_for_status() でエラーになりました: HTTP status client error (400 Bad Request) for url (https://httpbin.org/status/400)

send() でエラーになりました: error sending request for url (https://this-host-does-not-exist.com/)</pre>



<p class="wp-block-paragraph">ケース1 は、通信は通っているものの適切なリクエストの仕方ではなかったため、<code>400</code> 番のレスポンスがあった場合です。一方で、ケース2 の方は、そもそも通信レベルのエラーの場合です。例では存在しない URL へアクセスしようとして通信が返ってきません。この時は、<code>send</code> の時点で <code>Err</code> が返ってきます。どちらのケースのエラーであるのかを判断できるようにコーディングするようにしましょう。</p>



<h3 class="wp-block-heading jinr-heading d--bold">汎用メソッド <code>request</code> を使用する</h3>



<p class="wp-block-paragraph">これまで、<code>get</code>、<code>post</code>、<code>put</code>、<code>delete</code> と各 HTTP メソッドごとの専用メソッドを使ってきました。<code>reqwest</code> には、HTTP メソッドを動的に指定できる <span class="jinr-d--text-color d--marker1 d--bold"><code>request</code></span> という汎用メソッドも用意されています。 </p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

use reqwest::Method;

#[tokio::main]
async fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // ClientBuilder でタイムアウトなどを設定する
    let client_builder = reqwest::Client::builder().timeout(Duration::from_secs(10));

    // ClientBuilder から Client を作成する
    let client = client_builder.build()?;

    // 対象の user_id
    let user_id = "u1001";

    // request() を使うと、get()・post()・put()・delete() のような専用メソッドの代わりに、
    // Method を指定して同じ内容のリクエストを送信できる
    let requests = [
        (
            "GET",
            Method::GET,
            "https://httpbin.org/anything/users".to_string(),
        ),
        (
            "POST",
            Method::POST,
            "https://httpbin.org/anything/users".to_string(),
        ),
        (
            "PUT",
            Method::PUT,
            format!("https://httpbin.org/anything/users/{user_id}"),
        ),
        (
            "DELETE",
            Method::DELETE,
            format!("https://httpbin.org/anything/users/{user_id}"),
        ),
    ];

    for (label, method, url) in requests {
        // RequestBuilder を作成する
        let request_builder = client.request(method, url);

        // レスポンスを取得する
        let response = request_builder.send().await?;

        // ステータスコードを取得する
        let status = response.status();
        println!("[{label}] {status}");
    }

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[GET] 200 OK
[POST] 200 OK
[PUT] 200 OK
[DELETE] 200 OK</pre>



<p class="wp-block-paragraph"><code>request</code> では、例えば、<code>GET</code> であれば、<code>client.request(Method::GET, url)</code> のように <code>reqwest::Method</code> 型を指定することで HTTP メソッドを切り替えます。<code>client.get()</code> などの個別メソッドは、内部的にはこの <code>client.request()</code> を呼び出すラッパーになっています。</p>



<p class="wp-block-paragraph">呼び出されるメソッドが明確な場合は、各専用メソッドを用いる方が可読性の観点で優れています。一方で、ライブラリなどで動的に呼び出すメソッドを変更したい場合には、<code>request</code> を使って実装するのがおすすめです。</p>



<h3 class="wp-block-heading jinr-heading d--bold">同期通信 <code>reqwest::blocking</code></h3>



<p class="wp-block-paragraph">この記事の冒頭で説明した通り、reqwest は、非同期モードがデフォルトになっています。同期的に使用したい場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>reqwest::blocking</code></span> を使用します。 blocking はデフォルトでは無効なので「<code>cargo add reqwest --features json,query,blocking</code>」のように blocking feature を有効にするようにしてください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::error::Error;
use std::time::Duration;

// blocking::Client を使うと、async/await を使わずに同期的に通信できる
// tokio::main は不要で、通常の fn main で実行できる
fn main() -> Result&lt;(), Box&lt;dyn Error>> {
    // httpbin.org から取得する
    let url = "https://httpbin.org/get";
    // Docker を使用する場合は、以下のように URL を変更してください
    // let url = "http://localhost:8080/get";

    // ClientBuilder でタイムアウトなどを設定する
    let client_builder = reqwest::blocking::Client::builder().timeout(Duration::from_secs(10));

    // ClientBuilder から Client を作成する
    let client = client_builder.build()?;

    // 同じ Client で複数回リクエストを送る
    for count in 1..=3 {
        // RequestBuilder を作成する
        let request_builder = client.get(url);

        // レスポンスを取得する(await が不要)
        let response = request_builder.send()?;

        // ステータスコードを取得する
        let status = response.status();
        println!("{count}回目 ステータスコード: {status}");
    }

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
1回目 ステータスコード: 200 OK
2回目 ステータスコード: 200 OK
3回目 ステータスコード: 200 OK</pre>



<p class="wp-block-paragraph">非同期との違いは、まず、main 関数が同期関数となっている点です。<code>#[tokio::main]</code> の付いた関数の中で <code>reqwest::blocking</code> を使うと実行時に <code>panic</code> となるので、非同期との併用は不可である点は注意してください。</p>



<p class="wp-block-paragraph">また、使い方では、<code>ClientBuilder</code> 生成で <code>reqwest::<span class="jinr-d--text-color d--marker1 d--bold">blocking</span>::Client::builder()</code> を使用する点が異なります。それ以外の使い方はほとんど同様ですが、同期実行であるため、<code>send</code> の際に <code>await</code> は不要となります。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust で HTTP 通信を行うためのクレートである <span class="jinr-d--text-color d--marker1 d--bold"><code>reqwest</code> の基本的な使い方</span>について、解説しました。</p>



<p class="wp-block-paragraph"><code>GET</code>・<code>POST</code>・<code>PUT</code>・<code>DELETE</code> といった基本的な HTTP メソッドの使い方から、クエリパラメータやヘッダーの指定、JSON のシリアライズ・デシリアライズ、エラー処理の考え方まで、実務でよく使う内容を中心に紹介しました。</p>



<p class="wp-block-paragraph">また、汎用メソッドの <code>request</code> や、同期的に扱える <code>reqwest::blocking</code> についても紹介しました。基本の使い方をしっかり押さえておくことで、外部 API との連携など、様々な場面で活用できるようになります。ぜひ、基本的な使い方を理解してください。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>reqwest</code> の公式ドキュメントは以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://crates.io/crates/reqwest" target="_blank" rel="noreferrer noopener">crates.io のページ</a></li>



<li><a href="https://docs.rs/reqwest/latest/reqwest/" target="_blank" rel="noreferrer noopener">ドキュメント</a></li>
</ul>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては <a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-libraries/reqwest-basic" target="_blank" rel="noreferrer noopener">GitHub</a> にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-reqwest-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust】serde で JSON を扱う基本を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-serde-json-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-serde-json-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Fri, 26 Jun 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[serde]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[serde_json]]></category>
		<category><![CDATA[シリアライズ]]></category>
		<category><![CDATA[デシリアライズ]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=2143</guid>

					<description><![CDATA[Rust で serde を用いて JSON を扱う方法について、初心者にも分かりやすく解説します。 serde クレートの概要 serde とは Web API のレスポンスや設定ファイルなど、開発現場では、JSON  [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust で <span class="jinr-d--text-color d--marker1 d--bold"><code>serde</code> を用いて JSON を扱う方法</span>について、初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold"><code>serde</code> クレートの概要</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>serde</code> とは</h3>



<p class="wp-block-paragraph">Web API のレスポンスや設定ファイルなど、開発現場では、JSON 形式のデータを扱うことが多くあります。プログラム内の型のデータを JSON のような文字列形式に変換することを「<span class="jinr-d--text-color d--marker1 d--bold">シリアライズ（serialize）</span>」、逆に JSON 文字列を型のデータに変換することを「<span class="jinr-d--text-color d--marker1 d--bold">デシリアライズ（deserialize）</span>」と言います。</p>



<p class="wp-block-paragraph">Rust では、このシリアライズ・デシリアライズで <span class="jinr-d--text-color d--marker1 d--bold"><code>serde</code></span> （サード、サーディと読みます）というクレートを使用します。この記事では、<code>serde</code> を使った JSON の基本的な扱い方について紹介します。</p>



<p class="wp-block-paragraph">この記事で理解してもらいたい内容は以下の通りです。</p>



<ul class="wp-block-list jinr-list">
<li><code>serde</code> は、シリアライズ・デシリアライズの共通の仕組みを提供する。</li>



<li>JSON を扱うには <code>serde_json</code> と組み合わせて使う。</li>



<li><code>#[derive(Serialize)]</code> で型をJSONに変換でき、<code>#[derive(Deserialize)]</code> で JSON を型に変換できる。</li>



<li>ネストした型や、<code>Vec&lt;T&gt;</code>、<code>Option&lt;T&gt;</code> などを含む型もそのまま扱える。</li>
</ul>



<p class="wp-block-paragraph">以降では、上記について例を用いつつ紹介していきます。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>serde</code> と <code>serde_json</code></h3>



<p class="wp-block-paragraph"><code>serde</code> 本体は、<span class="jinr-d--text-color d--marker1 d--bold">特定のデータ形式（フォーマット）に依存しない共通の仕組み</span>です。そのため、serde 自体には、「JSON に変換する」「JSON から変換する」といった具体的な処理はありません。</p>



<p class="wp-block-paragraph">実際に、JSON を扱うためには、JSON フォーマットに対応した <span class="jinr-d--text-color d--marker1 d--bold"><code>serde_json</code></span> というクレートを組み合わせて使用します。このクレートは、serde の仕組みを利用して、JSON フォーマットの読み書きを実装しています。</p>



<p class="wp-block-paragraph">このように <code>serde</code> は形式に依存しない設計になっているおかげで、JSON 以外にも YAML (<code>serde_yaml</code>) や TOML (<code>toml</code>) など、各フォーマットに対応するクレートを使って同じ書き方で使用することができます。この記事では、最もよく使われる JSON を例に紹介します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">この記事では、基本となる構造体の型 (<code>struct</code>) を中心に解説しますが、<code>serde</code> は、列挙型 (<code>enum</code>) も扱うことができます。</p>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold"><code>serde</code> を使用した JSON 操作の基本</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>serde</code> の導入方法</h3>



<p class="wp-block-paragraph"><code>serde</code> と <code>serde_json</code> は、他のクレートと同様に <code>cargo add</code> または <code>Cargo.toml</code> に追記することで利用できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--heading-iconbox1 ">
			<div class="a--heading-iconbox-title">
			<div class="a--iconbox-title-icon"><i class="jif jin-ifont-caution" aria-hidden="true"></i></div>
			<div class="a--iconbox-title-text">注意点</div>
			</div>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">#[derive(Serialize, Deserialize)] というマクロを使用するためには、serde の derive フィーチャーの有効化が必要である点に注意が必要です。導入時には必ず指定するようにしましょう。</p>
</div>
		</div></section>



<h4 class="wp-block-heading jinr-heading d--bold"><code>cargo add</code> で追加する場合</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cargo add serde --features derive
cargo add serde_json</pre>



<h4 class="wp-block-heading jinr-heading d--bold"><code>Cargo.toml</code> に追記する場合</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"</pre>



<p class="wp-block-paragraph">例では、メジャーバージョンとして <code>"1"</code> を指定しています。これにより、互換性のある範囲で最新のバージョンが使用されます。もちろん特定のバージョンを指定しても構いません。</p>



<p class="wp-block-paragraph">導入時には crates.io の <a href="https://crates.io/crates/serde" target="_blank" rel="noreferrer noopener">serde</a> や <a href="https://crates.io/crates/serde_json" target="_blank" rel="noreferrer noopener">serde_json</a> のページを確認してください。なお、実際にインストールされたバージョンは <code>Cargo.lock</code> ファイルで確認できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">クレートや依存関係の基本については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-crates-basics/" target="_blank" rel="noreferrer noopener">クレート（バイナリ／ライブラリ）と依存関係の管理を分かりやすく解説</a></p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">型を JSON に変換する（<code>Serialize</code>）</h3>



<h4 class="wp-block-heading jinr-heading d--bold">基本的な方法</h4>



<p class="wp-block-paragraph">構造体 (<code>struct</code>) を JSON 文字列に変換する<span class="jinr-d--text-color d--marker1 d--bold">シリアライズ (<code>Serialize</code>)</span> から見ていきましょう。対象の型に <span class="jinr-d--text-color d--marker1 d--bold"><code>#[derive(Serialize)]</code></span> を付与し、<span class="jinr-d--text-color d--marker1 d--bold"><code>serde_json::to_string</code></span> 関数を使用することで、JSON 形式の文字列に変換することができます。</p>



<p class="wp-block-paragraph">以下の例では、<code>User</code> という型を定義し、JSON 文字列に変換しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::Serialize;

// 構造体を定義し、Serialize トレイトを derive することで
// 構造体を JSON にシリアライズできるようにする
#[derive(Serialize, Debug)]
struct User {
    name: String,
    age: u32,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user = User {
        name: String::from("Alice"),
        age: 30,
    };

    // 構造体を JSON 文字列に変換（シリアライズ）
    let json = serde_json::to_string(&amp;user)?;
    println!("{json}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"name":"Alice","age":30}</pre>



<p class="wp-block-paragraph">定義した型に対して <code>#[derive(Serialize)]</code> を付けておくことで、<code>serde_json::to_string</code> にわたすだけで JSON 文字列に変換できていることが分かります。</p>



<p class="wp-block-paragraph">なお、<code>serde_json::to_string</code> は変換に失敗する可能性があることから、戻り値は <code>Result</code> 型となります。今回の例では、<code>?</code> 演算子を使ってエラー (<code>serde_json::Error</code>) を上位へ伝播しています。もちろん <code>match</code> を用いて処理する方法も適切ですので設計に応じて検討しましょう。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">エラー処理の基本については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-error-handling-basic/" target="_blank" rel="noreferrer noopener">エラー処理の基本を分かりやすく解説</a></p>
</div>
		</div></section>



<h4 class="wp-block-heading jinr-heading d--bold">改行やインデントを入れて整形する方法</h4>



<p class="wp-block-paragraph">改行やインデントを入れて整形した、人間が読みやすい形式の JSON 文字列にしたい場合は、<span class="jinr-d--text-color d--marker1 d--bold"><code>serde_json::to_string_pretty</code></span> を使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::Serialize;

#[derive(Serialize, Debug)]
struct User {
    name: String,
    age: u32,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user = User {
        name: String::from("Alice"),
        age: 30,
    };

    // 読みやすいように改行・インデント付きの JSON 文字列に変換する
    let json = serde_json::to_string_pretty(&amp;user)?;
    println!("{json}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{
  "name": "Alice",
  "age": 30
}</pre>



<p class="wp-block-paragraph">設定ファイルの出力やデバッグ時など、見やすさを重視したい場合には、<code>serde_json::to_string_pretty</code> を使用するのが便利です。</p>



<h3 class="wp-block-heading jinr-heading d--bold">JSON を型に変換する（<code>Deserialize</code>）</h3>



<p class="wp-block-paragraph">次に、JSON 文字列を構造体 (<code>struct</code>) に変換する<span class="jinr-d--text-color d--marker1 d--bold">デシリアライズ (<code>Deserialize</code>)</span> を見ていきましょう。対象の型に <span class="jinr-d--text-color d--marker1 d--bold"><code>#[derive(Deserialize)]</code></span> を付与し、<span class="jinr-d--text-color d--marker1 d--bold"><code>serde_json::from_str</code></span> 関数を使用することで、JSON 形式の文字列から構造体に変換することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::Deserialize;

// 構造体を定義し、Deserialize トレイトを derive することで
// JSON 文字列を構造体にデシリアライズできるようにする
#[derive(Deserialize, Debug)]
struct User {
    name: String,
    age: u32,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let json = r#"{"name":"Alice","age":30}"#;

    // JSON 文字列を構造体に変換（デシリアライズ）
    let user: User = serde_json::from_str(json)?;
    println!("{user:?}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
User { name: "Alice", age: 30 }</pre>



<p class="wp-block-paragraph">定義した型 (<code>User</code>)に対して <code>#[derive(Deserialize)]</code> を付けておき、<code>serde_json::from_str</code> に JSON 文字列を渡せば <code>User</code> 構造体に変換できます。なお、「<code>let user: User</code>」 のように変換先の型注釈を明示している点に注意してください。<code>serde_json::from_str</code> は様々な型に変換できる関数のため、どの型に変換するのかを伝える必要があります。</p>



<p class="wp-block-paragraph">また、<code>serde_json::from_str</code> も変換に失敗する可能性があることから、戻り値は <code>Result</code> 型となります。例えば、フィールドが一致しない場合や、型が合わない場合にエラーとなります。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">JSON 文字列を <code>r#"…"#</code> という形式で記載しています。これは raw 文字列リテラル と呼ばれる書き方です。文字列中のダブルクォート（<code>"</code>）をエスケープせずにそのまま書けるため、JSON のように <code>"</code> を含む文字列を扱う際に便利です。</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Serialize</code> と <code>Deserialize</code> を同時に使用する</h3>



<p class="wp-block-paragraph">実際の開発では、ある型に対してシリアライズとデシリアライズを両方行えるようにするケースがほとんどです。その場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>#[derive(Serialize, Deserialize)]</code></span> のように両方をまとめて指定します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::{Deserialize, Serialize};

// Serialize と Deserialize の両方を derive することで
// シリアライズとデシリアライズの両方に対応できる
#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    age: u32,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user = User {
        name: String::from("Alice"),
        age: 30,
    };

    // 構造体を JSON 文字列に変換（シリアライズ）
    let json = serde_json::to_string(&amp;user)?;
    println!("{json}");

    // JSON 文字列を構造体に変換（デシリアライズ）
    let deserialized_user: User = serde_json::from_str(&amp;json)?;
    println!("{deserialized_user:?}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"name":"Alice","age":30}
User { name: "Alice", age: 30 }</pre>



<p class="wp-block-paragraph">以降では、いくつかよく使用するパターンを紹介します。その際には、<code>#[derive(Serialize, Deserialize)]</code> のように両方を付けた形で紹介していきます。</p>



<h2 class="wp-block-heading jinr-heading d--bold">よく使用するパターン</h2>



<h3 class="wp-block-heading jinr-heading d--bold">ネストした型を含む場合</h3>



<p class="wp-block-paragraph">型を定義する際に、構造体のフィールドに別の構造体を持たせることはよくあります。このような場合に、シリアライズ・デシリアライズをする場合には両方に <code>#[derive(Serialize, Deserialize)]</code> を付けて定義しておく必要があることに注意してください。</p>



<p class="wp-block-paragraph">以下の例では、<code>User</code> 構造体のフィールドとして <code>Address</code> 構造体を持っています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Address {
    city: String,
    zip: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    address: Address,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user = User {
        name: String::from("Alice"),
        address: Address {
            city: String::from("Tokyo"),
            zip: String::from("100-0001"),
        },
    };

    // 構造体を JSON 文字列に変換（シリアライズ）
    let json = serde_json::to_string_pretty(&amp;user)?;
    println!("{json}");

    // JSON 文字列を構造体に変換（デシリアライズ）
    let deserialized_user: User = serde_json::from_str(&amp;json)?;
    println!("{deserialized_user:?}");

    Ok(())
}
</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{
  "name": "Alice",
  "address": {
    "city": "Tokyo",
    "zip": "100-0001"
  }
}
User { name: "Alice", address: Address { city: "Tokyo", zip: "100-0001" } }</pre>



<p class="wp-block-paragraph">例のようにネストした構造体を含めて JSON 文字列に変換できていることが分かります。また、デシリアライズでも、ネストした JSON をそのまま <code>User</code> 構造体に変換できています。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Vec&lt;T&gt;</code> や配列のフィールドを含む場合</h3>



<p class="wp-block-paragraph">複数の値を持つコレクションである <code>Vec&lt;T&gt;</code> についても特別な対応をすることなく、そのまま扱うことが可能です。<code>Vec&lt;T&gt;</code> は JSON の配列に対応します。</p>



<p class="wp-block-paragraph">以下の例では、先ほどの例における <code>Address</code> を <code>Vec&lt;Address&gt;</code> として表現しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Address {
    city: String,
    zip: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    addresses: Vec&lt;Address>,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user = User {
        name: String::from("Alice"),
        addresses: vec![
            Address {
                city: String::from("Tokyo"),
                zip: String::from("100-0001"),
            },
            Address {
                city: String::from("Osaka"),
                zip: String::from("530-0001"),
            },
        ],
    };

    // 構造体を JSON 文字列に変換（シリアライズ）
    let json = serde_json::to_string_pretty(&amp;user)?;
    println!("{json}");

    // JSON 文字列を構造体に変換（デシリアライズ）
    let deserialized_user: User = serde_json::from_str(&amp;json)?;
    println!("{deserialized_user:?}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{
  "name": "Alice",
  "addresses": [
    {
      "city": "Tokyo",
      "zip": "100-0001"
    },
    {
      "city": "Osaka",
      "zip": "530-0001"
    }
  ]
}
User { name: "Alice", addresses: [Address { city: "Tokyo", zip: "100-0001" }, Address { city: "Osaka", zip: "530-0001" }] }</pre>



<p class="wp-block-paragraph"><code>Vec&lt;Address&gt;</code> が JSON の配列として表現されていることが分かります。例は、作成した構造体に対してですが、<code>Vec&lt;i32&gt;</code> や <code>Vec&lt;String&gt;</code> のように基本的な型の場合も同様です。</p>



<p class="wp-block-paragraph">なお、<code>[T; N]</code> のような固定長配列も同様に扱えますが、デシリアライズ時に要素数が一致しないとエラーになります。実用上は要素数を柔軟に扱える <code>Vec&lt;T&gt;</code> を使うことがほとんどです。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Option&lt;T&gt;</code> のフィールドを含む場合</h3>



<p class="wp-block-paragraph">値が存在する場合と存在しない場合がある場合には、<code>Option&lt;T&gt;</code> を使用します。<code>serde</code> では、<code>Option&lt;T&gt;</code> も自然に扱うことができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    email: Option&lt;String>,
}

fn main() -> Result&lt;(), serde_json::Error> {
    let user1 = User {
        name: String::from("Alice"),
        email: Some(String::from("alice@example.com")),
    };
    let user2 = User {
        name: String::from("Bob"),
        email: None,
    };

    // 構造体を JSON 文字列に変換（シリアライズ）
    let json1 = serde_json::to_string(&amp;user1)?;
    let json2 = serde_json::to_string(&amp;user2)?;
    println!("{json1}");
    println!("{json2}");

    // JSON 文字列を構造体に変換（デシリアライズ）
    let deserialized_user1: User = serde_json::from_str(&amp;json1)?;
    let deserialized_user2: User = serde_json::from_str(&amp;json2)?;
    println!("{deserialized_user1:?}");
    println!("{deserialized_user2:?}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"name":"Alice","email":"alice@example.com"}
{"name":"Bob","email":null}
User { name: "Alice", email: Some("alice@example.com") }
User { name: "Bob", email: None }</pre>



<p class="wp-block-paragraph"><code>Option&lt;T&gt;</code> を使用する場合、<code>None</code> は <code>null</code> として JSON 文字列に出力されます。デシリアライズの場合は、JSON 文字列に当該キーが存在しないか、<code>null</code> であれば <code>None</code> に、値があれば <code>Some(値)</code> という形に変換されます。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>null</code> を出力せずキー自体を出力したくない場合</h4>



<p class="wp-block-paragraph"><code>Option</code> 型の値が <code>None</code> の際に、<code>null</code> を出力するのではなく、キー自体を出力したくないような場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>#[serde(skip_serializing_if = "Option::is_none")]</code></span> を対象のフィールドに付与します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">...(省略)...

#[derive(Serialize, Deserialize, Debug)]
struct User {
    name: String,
    // None の場合はキーごと出力しない
    #[serde(skip_serializing_if = "Option::is_none")]
    email: Option&lt;String>,
}
...(省略)...</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"name":"Alice","email":"alice@example.com"}
{"name":"Bob"}
User { name: "Alice", email: Some("alice@example.com") }
User { name: "Bob", email: None }</pre>



<p class="wp-block-paragraph">例の結果のようにキー自体が出力されなくなったことが分かります。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">上記のような出力制御のための属性は、構造体自体やフィールドなどに付与することができます。詳細は公式ページの<a href="https://serde.rs/attributes.html#attributes" target="_blank" rel="noreferrer noopener">こちら</a>を参照してください。</p>
</div>
		</div></section>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust で <span class="jinr-d--text-color d--marker1 d--bold"><code>serde</code> を用いて JSON を扱う方法</span>について解説しました。<code>serde</code> の入門として最低限理解してほしい内容を中心に説明し、よくある使用例なども紹介しました。</p>



<p class="wp-block-paragraph"><code>serde</code> は、外部 API との通信や設定ファイルの読み書きなど、様々な場面で利用される非常に重要なクレートで、Rust の学習時に代表例としてよく出てくるものです。今回紹介した基本をしっかりと押さえておくことで今後の様々なクレートの活用にもつながります。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>serde</code> の公式ドキュメントは以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://serde.rs/" target="_blank" rel="noreferrer noopener"><code>serde</code> 公式ページ</a></li>



<li><a href="https://crates.io/crates/serde" target="_blank" rel="noreferrer noopener">crates.io のページ</a></li>
</ul>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-libraries/serde-json-basic" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-serde-json-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】HashSet 型の基本について分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-hashset-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-hashset-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Thu, 18 Jun 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[HashSet]]></category>
		<category><![CDATA[コレクション]]></category>
		<category><![CDATA[集合演算]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=2087</guid>

					<description><![CDATA[Rust で重複しない要素の集合を管理するための HashSet 型の基本を初心者にも分かりやすく解説します。 HashSet&#60;T&#62; 型 Rust には、同じ型のデータをまとめて管理するための「コレクション（ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust で重複しない要素の集合を管理するための <span class="jinr-d--text-color d--marker1 d--bold"><code>HashSet</code></span> 型の基本を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold"><code>HashSet&lt;T&gt;</code> 型</h2>



<p class="wp-block-paragraph">Rust には、同じ型のデータをまとめて管理するための「<span class="jinr-d--text-color d--marker1 d--bold">コレクション（Collections）</span>」が用意されています。コレクションは、実行中に要素数を変更できる柔軟なデータ構造です。</p>



<p class="wp-block-paragraph">この記事では、コレクション型の代表例である&nbsp;<code>HashSet&lt;T&gt;</code>&nbsp;型について解説します。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashSet&lt;T&gt;</code> 型とは</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>HashSet&lt;T&gt;</code> 型</span>は重複しない値の集合を管理するためのコレクション型です。</p>



<p class="wp-block-paragraph"><code>HashSet</code> には、次のような特徴があります。</p>



<ul class="wp-block-list jinr-list">
<li>重複した要素を保持できない</li>



<li>要素の順序は保証されない</li>



<li>要素の検索が高速</li>
</ul>



<p class="wp-block-paragraph">例えば、「ユーザーIDの重複チェック」「タグ一覧の管理」「特定の値の存在確認」などの目的のためにデータの集合として利用できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">その他の代表的なコレクションである <code>Vec</code> や <code>HashMap</code> については、以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://rust-tech.nkhn37.net/rust-vec-basic/" target="_blank" rel="noreferrer noopener">Vec 型の基本について分かりやすく解説</a></li>



<li><a href="https://rust-tech.nkhn37.net/rust-hashmap-basic/" target="_blank" rel="noreferrer noopener">HashMap 型の基本について分かりやすく解説</a></li>
</ul>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashSet</code> の生成方法</h3>



<h4 class="wp-block-heading jinr-heading d--bold">HashSet を使う準備</h4>



<p class="wp-block-paragraph">HashSet は標準ライブラリの <span class="jinr-d--text-color d--marker1 d--bold"><code>std::collections</code></span> モジュールで提供されています。利用するには以下のようにインポートします。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;</pre>



<p class="wp-block-paragraph">以降で紹介する各プログラムでも先頭でインポートしています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">関連関数&nbsp;<code>HashSet::new()</code>&nbsp;を使用する</h4>



<p class="wp-block-paragraph"><code>HashSet</code> を生成する最も基本的な方法は、<span class="jinr-d--text-color d--marker1 d--bold"><code>new</code></span> メソッドを使用する方法です。値を追加するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>insert</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    // HashSet を生成する
    let mut set = HashSet::new();

    // 値を追加する
    set.insert(String::from("Alice"));
    set.insert(String::from("Bob"));
    set.insert(String::from("Charlie"));

    println!("{:?}", set);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"Alice", "Charlie", "Bob"}</pre>



<p class="wp-block-paragraph">なお、<code>HashSet</code> は要素の追加順序を保証しません。そのため、実行により表示順序が異なる場合があります。以降の例についても同様です。</p>



<h4 class="wp-block-heading jinr-heading d--bold">配列から <code>HashSet</code> を生成する</h4>



<p class="wp-block-paragraph"><code>HashSet</code> は配列から生成することも可能です。<code>into_iter().collect()</code> を使うことで配列から <code>HashSet</code> を生成できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    // 配列から HashSet を生成する
    let set: HashSet&lt;_> = [1, 2, 3, 4].into_iter().collect();

    println!("生成された HashSet : {set:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
生成された HashSet : {3, 1, 4, 2}</pre>



<h4 class="wp-block-heading jinr-heading d--bold"><code>Vec</code> から <code>HashSet</code> を生成する</h4>



<p class="wp-block-paragraph">配列同様に <code>Vec</code> から <code>HashSet</code> を生成することもできます。なお、重複した値が <code>Vec</code> に含まれている場合は、自動的に除かれます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let numbers = vec![1, 2, 2, 3, 3, 4];

    // Vec から HashSet を生成する（重複は自動で除かれる）
    let set: HashSet&lt;_> = numbers.into_iter().collect();

    println!("元の Vec : [1, 2, 2, 3, 3, 4]");
    println!("生成された HashSet : {set:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
元の Vec : [1, 2, 2, 3, 3, 4]
生成された HashSet : {1, 2, 4, 3}</pre>



<p class="wp-block-paragraph">上記のように、重複していた <code>2</code> と <code>3</code> は除かれてユニークな要素のみ保持できていることが確認できます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【参考】<code>HashSet</code> から <code>Vec</code> に変換する</strong></p>



<p class="wp-block-paragraph">逆に <code>HashSet</code> から <code>Vec</code> に変換することも可能です。<code>HashSet</code> は順序を持たないため、必要に応じて <code>sort</code> で並び替えることもできます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set: HashSet&lt;_> = [3, 1, 4, 2].into_iter().collect();

    // HashSet から Vec に変換する
    let mut numbers: Vec&lt;_> = set.into_iter().collect();

    // HashSet は順序を持たないため、見やすいように並べ替える
    numbers.sort();

    println!("変換後の Vec : {numbers:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
変換後の Vec : [1, 2, 3, 4]</pre>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashSet</code> の操作（要素の取得・追加・削除など）</h3>



<p class="wp-block-paragraph"><code>HashSet</code> 型では、要素の取得・追加・削除などの各種メソッドが用意されています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">要素の取得</h4>



<p class="wp-block-paragraph"><code>HashSet</code> の要素値を取得するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>get</code></span>&nbsp;メソッドにより取得する値を指定します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));

    // 要素を取得する
    let alice = names.get("Alice");
    match alice {
        Some(name) => println!("取得できた要素 : {name}"),
        None => println!("要素が見つかりませんでした。"),
    }

    let charlie = names.get("Charlie");
    match charlie {
        Some(name) => println!("取得できた要素 : {name}"),
        None => println!("Charlie は存在しません。"),
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
取得できた要素 : Alice
Charlie は存在しません。</pre>



<p class="wp-block-paragraph"><code>get</code>&nbsp;は、<code>Option&lt;&amp;T&gt;</code>&nbsp;型 を返却するため、<code>match</code>&nbsp;を使って値の有無を確認して安全に処理することが可能です。指定した値が存在しない場合には、<code>None</code>&nbsp;となります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">要素の追加</h4>



<p class="wp-block-paragraph">新しい要素の追加や更新には、<span class="jinr-d--text-color d--marker1 d--bold"><code>insert</code></span>&nbsp;メソッドを使用します。例のように、既に同じ値が存在する場合は、追加されず <code>HashSet</code> の内容は変化しません。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    println!("追加前 : {names:?}");

    // 要素を追加する
    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));

    println!("追加後 : {names:?}");

    // 同じ値を追加しても重複しない
    names.insert(String::from("Alice"));

    println!("同じ値を再追加した後 : {names:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
追加前 : {}
追加後 : {"Alice", "Bob"}
同じ値を再追加した後 : {"Alice", "Bob"}</pre>



<h4 class="wp-block-heading jinr-heading d--bold">要素の削除</h4>



<p class="wp-block-paragraph">要素を削除する場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>remove</code></span>&nbsp;メソッドを使用します。存在しない値を削除しようとしても何も起こりません。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));
    names.insert(String::from("Charlie"));

    println!("削除前 : {names:?}");

    // 要素を削除する
    names.remove("Alice");

    println!("Alice 削除後 : {names:?}");

    // 存在しない要素を削除しても変化しない
    names.remove("Dave");

    println!("Dave 削除後（変化なし） : {names:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
削除前 : {"Bob", "Charlie", "Alice"}
Alice 削除後 : {"Bob", "Charlie"}
Dave 削除後（変化なし） : {"Bob", "Charlie"}</pre>



<h4 class="wp-block-heading jinr-heading d--bold">要素数の取得</h4>



<p class="wp-block-paragraph"><code>HashSet</code> に含まれる要素数を取得するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>len</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    let len = names.len();
    println!("初期状態の要素数 : {len}");

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));

    let len = names.len();
    println!("追加後の要素数 : {len}");

    names.remove("Alice");

    let len = names.len();
    println!("削除後の要素数 : {len}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
初期状態の要素数 : 0
追加後の要素数 : 2
削除後の要素数 : 1</pre>



<h4 class="wp-block-heading jinr-heading d--bold">要素の存在確認</h4>



<p class="wp-block-paragraph"><code>HashSet</code> に指定した値が存在するかどうかを確認するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>contains</code></span> メソッドを使用します。指定値が存在するかは <code>bool</code> 型の返却値として確認できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));

    // 要素の存在を確認する
    let contains_alice = names.contains("Alice");
    let contains_charlie = names.contains("Charlie");
    println!("Alice は存在するか : {contains_alice}");
    println!("Charlie は存在するか : {contains_charlie}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Alice は存在するか : true
Charlie は存在するか : false</pre>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">繰り返し処理（<code>for</code>）での利用方法</h2>



<p class="wp-block-paragraph"><code>HashSet</code>&nbsp;は複数の要素を管理するため、<code>for</code> を利用した繰り返し処理を行うことがよくあります。Rust の繰り返しでは、イテレータを取得して動作します。</p>



<h3 class="wp-block-heading jinr-heading d--bold">参照のみの繰り返し処理</h3>



<p class="wp-block-paragraph"><code>HashSet</code> の要素を 1 つずつ取り出して参照するだけの繰り返しの場合には、以下のように不変参照 (<code>&amp;</code>) を使って <code>for</code> を使用します。ループ後も元の <code>HashSet</code> を引き続き利用できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));
    names.insert(String::from("Charlie"));

    // 所有権を移動せず、参照としてループする
    for name in &amp;names {
        println!("名前 : {name}");
    }

    // ループ後も names を使える
    println!("ループ後の要素数 : {}", names.len());
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
名前 : Charlie
名前 : Bob
名前 : Alice
ループ後の要素数 : 3</pre>



<p class="wp-block-paragraph">なお、<code>HashSet</code> は要素がキーなので、要素を直接変更するという考え方が基本的にありません。そのため、<code>HashMap</code> ではあった値を変更を伴う繰り返し (<code>iter_mut</code>) はありません。</p>



<h3 class="wp-block-heading jinr-heading d--bold">所有権を移動する繰り返し処理</h3>



<p class="wp-block-paragraph"><code>HashSet</code>&nbsp;の所有権を移動して繰り返し処理をする場合には、以下のように&nbsp;<code>in</code>&nbsp;の部分に&nbsp;<code>HashSet</code>&nbsp;の変数を直接指定します。所有権を移動する繰り返し処理をした場合には、繰り返し後には変数を使うことができなくなる点に注意が必要です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let mut names = HashSet::new();

    names.insert(String::from("Alice"));
    names.insert(String::from("Bob"));
    names.insert(String::from("Charlie"));

    // 所有権を移動してループする
    for name in names {
        println!("名前 : {name}");
    }

    // 所有権が移動したため、ここで names は使えない
    // println!("{:?}", names); // コンパイルエラー
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
名前 : Charlie
名前 : Bob
名前 : Alice</pre>



<p class="wp-block-paragraph">この方法は、ループ後に元の&nbsp;<code>HashSet</code>&nbsp;を使わない場合や、大きいサイズの&nbsp;<code>HashSet</code>&nbsp;であるためループ終了にあわせてメモリ解放したい場合などに利用できます。</p>



<h2 class="wp-block-heading jinr-heading d--bold">集合演算と包含関係の判定</h2>



<h3 class="wp-block-heading jinr-heading d--bold">集合演算</h3>



<p class="wp-block-paragraph"><code>HashSet</code> には、数学の集合演算に対応した各種メソッドが用意されています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">積集合</h4>



<p class="wp-block-paragraph">積集合を計算するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>intersection</code></span> メソッドを使用します。積集合では、両方の集合に含まれる要素を取得できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = [1, 2, 3, 4].into_iter().collect();
    let set_b: HashSet&lt;_> = [3, 4, 5, 6].into_iter().collect();

    // 積集合（両方に含まれる要素）
    let intersection: HashSet&lt;_> = set_a.intersection(&amp;set_b).copied().collect();

    println!("A: {set_a:?}");
    println!("B: {set_b:?}");
    println!("A ∩ B: {intersection:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A: {3, 4, 2, 1}
B: {3, 4, 5, 6}
A ∩ B: {4, 3}</pre>



<p class="wp-block-paragraph"><code>intersection</code> などの集合演算メソッドは、元の集合の要素への参照を返すイテレータになっています。例の <code>i32</code> のように <code>Copy</code> トレイトを実装している場合は、<code>copied()</code> を呼ぶことで参照 (<code>&amp;i32</code>) を値 (<code>i32</code>) にコピーし、<code>collect</code> により <code>HashSet&lt;i32&gt;</code> として集約できます。</p>



<p class="wp-block-paragraph">なお、所有権を持つ <code>String</code> のような <code>Copy</code> トレイトを実装していない型の場合は、<code>cloned()</code> を使用するか、参照のままの <code>HashSet&lt;&amp;String&gt;</code> として扱うことになります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">和集合</h4>



<p class="wp-block-paragraph">和集合を計算するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>union</code></span> メソッドを使用します。和集合では、どちらかの集合に含まれる要素が取得され、重複要素は自動で除かれます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = [1, 2, 3].into_iter().collect();
    let set_b: HashSet&lt;_> = [3, 4, 5].into_iter().collect();

    // 和集合（どちらかに含まれる要素）
    let union: HashSet&lt;_> = set_a.union(&amp;set_b).copied().collect();

    println!("A: {set_a:?}");
    println!("B: {set_b:?}");
    println!("A ∪ B: {union:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A: {1, 2, 3}
B: {3, 4, 5}
A ∪ B: {1, 3, 5, 2, 4}</pre>



<h4 class="wp-block-heading jinr-heading d--bold">差集合</h4>



<p class="wp-block-paragraph">差集合を計算するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>difference</code></span>メソッドを使用します。差集合の場合は、順序が重要になり、以下の例で <code>A - B</code> の場合は、<code>A</code> にのみ含まれる要素を取得できます。一方で、<code>B - A</code> の場合は、<code>B</code> にのみ含まれる要素を取得できます。 </p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = [1, 2, 3, 4].into_iter().collect();
    let set_b: HashSet&lt;_> = [3, 4, 5].into_iter().collect();

    // 差集合（A にだけ含まれる要素）
    let difference_a_b: HashSet&lt;_> = set_a.difference(&amp;set_b).copied().collect();

    // 差集合（B にだけ含まれる要素）
    let difference_b_a: HashSet&lt;_> = set_b.difference(&amp;set_a).copied().collect();

    println!("A: {set_a:?}");
    println!("B: {set_b:?}");
    println!("A - B: {difference_a_b:?}");
    println!("B - A: {difference_b_a:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A: {4, 2, 1, 3}
B: {3, 4, 5}
A - B: {1, 2}
B - A: {5}</pre>



<h4 class="wp-block-heading jinr-heading d--bold">排他的論理和</h4>



<p class="wp-block-paragraph">排他的論理和を計算するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>symmetric_difference</code></span> メソッドを使用します。排他的論理和では、どちらか一方にのみ含まれる要素を取得します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = [1, 2, 3, 4].into_iter().collect();
    let set_b: HashSet&lt;_> = [3, 4, 5, 6].into_iter().collect();

    // 排他的論理和（片方にだけ含まれる要素）
    let symmetric_difference: HashSet&lt;_> = set_a.symmetric_difference(&amp;set_b).copied().collect();

    println!("A: {set_a:?}");
    println!("B: {set_b:?}");
    println!("A △ B: {symmetric_difference:?}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A: {1, 4, 3, 2}
B: {4, 5, 6, 3}
A △ B: {6, 1, 2, 5}</pre>



<h3 class="wp-block-heading jinr-heading d--bold">集合の包含関係の判定方法</h3>



<p class="wp-block-paragraph"><code>HashSet</code> には、集合同士の包含関係を判定するメソッドも各種用意されています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">集合が等しいかどうかの判定</h4>



<p class="wp-block-paragraph">集合が等しいかを判定するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>==</code></span> 演算子を使用します。要素の順序は関係ありません。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = ["Alice", "Bob", "Charlie"].into_iter().collect();
    let set_b: HashSet&lt;_> = ["Charlie", "Alice", "Bob"].into_iter().collect();
    let set_c: HashSet&lt;_> = ["Alice", "Bob"].into_iter().collect();

    // 集合が等しいか判定する
    let eq_ab = set_a == set_b;
    let eq_ac = set_a == set_c;
    println!("A と B は等しいか : {eq_ab}");
    println!("A と C は等しいか : {eq_ac}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A と B は等しいか : true
A と C は等しいか : false</pre>



<p class="wp-block-paragraph"><code>set_a</code> と <code>set_b</code> は順序は異なっていますが、含まれる要素が同じため <code>true</code> となります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">上位集合の判定</h4>



<p class="wp-block-paragraph">ある集合が別の集合の全要素を含む場合を<span class="jinr-d--text-color d--marker1 d--bold">上位集合</span>と言います。上位集合かどうかを判定するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>is_superset</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let all_members: HashSet&lt;_> = ["Alice", "Bob", "Charlie"].into_iter().collect();
    let team_a: HashSet&lt;_> = ["Alice", "Bob"].into_iter().collect();

    // 上位集合かどうかを判定する
    let is_superset_all = all_members.is_superset(&amp;team_a);
    let is_superset_team = team_a.is_superset(&amp;all_members);
    println!("all_members は team_a の上位集合か : {is_superset_all}");
    println!("team_a は all_members の上位集合か : {is_superset_team}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
all_members は team_a の上位集合か : true
team_a は all_members の上位集合か : false</pre>



<h4 class="wp-block-heading jinr-heading d--bold">部分集合の判定</h4>



<p class="wp-block-paragraph">ある集合が別の集合に完全に含まれる場合を<span class="jinr-d--text-color d--marker1 d--bold">部分集合</span>と言います。部分集合かどうかを判定するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>is_subset</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let all_members: HashSet&lt;_> = ["Alice", "Bob", "Charlie"].into_iter().collect();
    let team_a: HashSet&lt;_> = ["Alice", "Bob"].into_iter().collect();

    // 部分集合かどうかを判定する
    let is_subset_team = team_a.is_subset(&amp;all_members);
    let is_subset_all = all_members.is_subset(&amp;team_a);
    println!("team_a は all_members の部分集合か : {is_subset_team}");
    println!("all_members は team_a の部分集合か : {is_subset_all}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
team_a は all_members の部分集合か : true
all_members は team_a の部分集合か : false</pre>



<h4 class="wp-block-heading jinr-heading d--bold">共通要素の有無の判定</h4>



<p class="wp-block-paragraph">2 つの集合に共通する要素が存在しないかどうかを判定するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>is_disjoint</code></span> メソッドを使います。共通要素がなければ <code>true</code>、1 つでもあれば <code>false</code> が返ります。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let set_a: HashSet&lt;_> = [1, 2, 3].into_iter().collect();
    let set_b: HashSet&lt;_> = [4, 5, 6].into_iter().collect();
    let set_c: HashSet&lt;_> = [3, 7, 8].into_iter().collect();

    // 共通要素がないかどうかを判定する
    let is_disjoint_ab = set_a.is_disjoint(&amp;set_b);
    let is_disjoint_ac = set_a.is_disjoint(&amp;set_c);
    println!("A と B に共通要素はない : {is_disjoint_ab}");
    println!("A と C に共通要素はない : {is_disjoint_ac}");
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
A と B に共通要素はない : true
A と C に共通要素はない : false</pre>



<p class="wp-block-paragraph"><code>intersection</code> を使って確認することも可能ですが、単純に共通要素の有無だけを確認したい場合は、<code>is_disjoint</code> を使うと簡潔に記載できます。</p>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust で重複しない要素の集合を管理するための <span class="jinr-d--text-color d--marker1 d--bold"><code>HashSet</code></span> 型の基本を解説しました。</p>



<p class="wp-block-paragraph"><code>HashSet</code> は、重複しない要素の集合を管理するためのコレクション型です。要素の追加・削除、存在確認といった基本操作に加えて、積集合・和集合・差集合などの集合演算や包含関係判定などについて紹介しました。</p>



<p class="wp-block-paragraph">重複削除や高速な存在確認が必要な場面では、<code>Vec</code> や <code>HashMap</code> の代わりに <code>HashSet</code> の利用を検討してみてください。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/hashset-basic" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-hashset-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】HashMap 型の基本について分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-hashmap-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-hashmap-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[HashMap]]></category>
		<category><![CDATA[コレクション]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1092</guid>

					<description><![CDATA[Rust でデータをキーと値のペアで管理するための HashMap 型の基本を初心者にも分かりやすく解説します。 HashMap&#60;K, V&#62; 型 Rust には、同じ型のデータをまとめて管理するための「コレク [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust でデータをキーと値のペアで管理するための <span class="jinr-d--text-color d--marker1 d--bold"><code>HashMap</code> 型</span>の基本を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold"><code>HashMap&lt;K, V&gt;</code> 型</h2>



<p class="wp-block-paragraph">Rust には、同じ型のデータをまとめて管理するための「<span class="jinr-d--text-color d--marker1 d--bold">コレクション（Collections）</span>」が用意されています。コレクションは、実行中に要素数を変更できる柔軟なデータ構造です。</p>



<p class="wp-block-paragraph">この記事では、コレクション型の代表例である <span class="jinr-d--text-color d--marker1 d--bold"><code>HashMap&lt;K, V&gt;</code></span> 型について解説します。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashMap&lt;K, V&gt;</code> 型とは</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>HashMap&lt;K, V&gt;</code> 型</span>は、キー（Key）と値（Value）のペアでデータを管理するためのコレクション型です。</p>



<p class="wp-block-paragraph"><code>Vec&lt;T&gt;</code> 型がインデックスで要素にアクセスするのに対して、<code>HashMap</code> はキーを使って値を取得します。コレクション型は、内部でヒープ領域を利用してデータを管理するため、プログラム実行時のデータ長の変更や大きなサイズのデータの扱いに適します。</p>



<p class="wp-block-paragraph">例えば、「ユーザー ID からユーザー名を取得する」「商品 ID から価格を取得する」というような場合を扱う際のデータ管理に非常に適しています。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">その他の代表的なコレクションである <code>Vec</code> や <code>HashSet</code> については、以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://rust-tech.nkhn37.net/rust-vec-basic/" target="_blank" rel="noreferrer noopener">Vec 型の基本について分かりやすく解説</a></li>



<li><a href="https://rust-tech.nkhn37.net/rust-hashset-basic/" target="_blank" rel="noreferrer noopener">HashSet 型の基本について分かりやすく解説</a></li>
</ul>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashMap</code> の生成方法</h3>



<h4 class="wp-block-heading jinr-heading d--bold"><code>HashMap</code> を使う準備</h4>



<p class="wp-block-paragraph"><code>HashMap</code> は標準ライブラリの <span class="jinr-d--text-color d--marker1 d--bold"><code>std::collections</code></span> モジュールで提供されています。利用するには以下のようにインポートします。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;</pre>



<p class="wp-block-paragraph">以降で紹介する各プログラムでも先頭でインポートをしています。</p>



<h4 class="wp-block-heading jinr-heading d--bold">関連関数&nbsp;<code>HashMap::new()</code>&nbsp;を使用する</h4>



<p class="wp-block-paragraph">HashMap 型を生成する最も基本的な方法は、<span class="jinr-d--text-color d--marker1 d--bold"><code>new</code></span> メソッドを使用する方法です。キーや値を追加するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>insert</code></span> メソッドを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    // HashMap を生成する
    let mut scores = HashMap::new();

    // キー、値を追加する
    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);

    println!("{:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"Alice": 80, "Bob": 100}</pre>



<p class="wp-block-paragraph">なお、<code>HashMap</code> は要素の順序を保証しません。そのため、実行により表示順序が異なる場合があります。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>collect</code> メソッドを使用する</h4>



<p class="wp-block-paragraph"><code>HashMap</code> は、イテレータから <span class="jinr-d--text-color d--marker1 d--bold"><code>collect</code></span> メソッドを使用して生成することも可能です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let keys = vec![String::from("Alice"), String::from("Bob")];
    let values = vec![80, 10];

    let scores: HashMap&lt;String, i32> = keys.into_iter().zip(values.into_iter()).collect();

    println!("{:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
{"Alice": 80, "Bob": 10}</pre>



<p class="wp-block-paragraph">上記例では、<code>keys</code> と <code>values</code> という <code>Vec</code> 型の変数を用意し、<code>zip</code> によりペアを生成して <code>collect</code> により <code>HashMap</code> 型に集約しています。<code>collect</code> メソッドは任意のコレクションにまとめることができるため、型注釈をつけるようにしてください。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>collect</code> については、イテレータの消費メソッドに関する以下記事で紹介しているので参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-iterator-consuming-adapters/" target="_blank" rel="noreferrer noopener">Iteratorの消費アダプタ（sum・fold・collect など）を分かりやすく解説</a></p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>HashMap</code>&nbsp;要素の取得・追加・更新・削除</h3>



<h4 class="wp-block-heading jinr-heading d--bold">要素の取得</h4>



<p class="wp-block-paragraph"><code>HashMap</code> の要素値を取得するには、<span class="jinr-d--text-color d--marker1 d--bold"><code>get</code></span> メソッドによりキーを指定します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    // Alice のスコアを追加
    scores.insert(String::from("Alice"), 80);

    // Alice のスコアを取得
    let alice_score = scores.get("Alice");
    match alice_score {
        Some(score) => println!("Alice のスコア : {}", score),
        None => println!("Alice のスコアが見つかりませんでした。"),
    }

    // Bob のスコアを取得（存在しないキー）
    let bob_score = scores.get("Bob");
    match bob_score {
        Some(score) => println!("Bob のスコア : {}", score),
        None => println!("Bob のスコアが見つかりませんでした。"),
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Alice のスコア : 80
Bob のスコアが見つかりませんでした。</pre>



<p class="wp-block-paragraph"><code>get</code> は、<code>Option&lt;&amp;V&gt;</code> 型 を返却するため、<code>match</code> を使って値の有無を確認して安全に処理することが可能です。キーが存在しない場合には、<code>None</code> となります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">要素の追加・更新</h4>



<p class="wp-block-paragraph">新しい要素の追加や更新には、<span class="jinr-d--text-color d--marker1 d--bold"><code>insert</code></span> メソッドを使用します。例のように、同じキーに対して <code>insert</code> を実行すると更新となる点に注意してください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    println!("初期状態 : {:?}", scores);

    // スコアを追加する
    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);

    println!("追加後 : {:?}", scores);

    // Alice のスコアを更新する（上書き）
    scores.insert(String::from("Alice"), 95);

    println!("更新後 : {:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
初期状態 : {}
追加後 : {"Bob": 100, "Alice": 80}
更新後 : {"Bob": 100, "Alice": 95}</pre>



<p class="wp-block-paragraph">なお、<code>String</code> のような所有権を持つ型の場合、変数を使用している場合は、<code>insert</code> 時に所有権が移動し、元の変数は使えなくなるので注意しましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">let name = String::from("Alice");

scores.insert(name, 80);

// 所有権が移動するためエラーとなる。
// println!("{name}");</pre>



<h4 class="wp-block-heading jinr-heading d--bold">要素の削除</h4>



<p class="wp-block-paragraph">要素を削除する場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>remove</code></span> メソッドを使用します。存在しないキーを削除しても何も起こりません。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);
    scores.insert(String::from("Charlie"), 70);

    println!("削除前 : {:?}", scores);

    // キーを指定して削除する
    scores.remove("Alice");

    println!("Alice 削除後 : {:?}", scores);

    // 存在しないキーを削除しても何も起きない
    scores.remove("Dave");

    println!("Dave 削除後（変化なし） : {:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
削除前 : {"Bob": 100, "Charlie": 70, "Alice": 80}
Alice 削除後 : {"Bob": 100, "Charlie": 70}
Dave 削除後（変化なし） : {"Bob": 100, "Charlie": 70}</pre>



<h4 class="wp-block-heading jinr-heading d--bold">存在しない場合のみ値を追加する場合（Entry API）</h4>



<p class="wp-block-paragraph"><code>HashMap</code> にキーが存在しない場合にのみ値を追加したい場合は、Entry API を使用するのが便利です。<span class="jinr-d--text-color d--marker1 d--bold"><code>entry</code></span> により対象を取得し、<span class="jinr-d--text-color d--marker1 d--bold"><code>or_insert</code></span> で値を追加することで、存在しない場合にのみ値を追加することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Alice"), 80);

    println!("初期状態 : {:?}", scores);

    // Alice はすでに存在するので更新されない
    scores.entry(String::from("Alice")).or_insert(0);

    // Bob は存在しないので追加される
    scores.entry(String::from("Bob")).or_insert(100);

    println!("or_insert 後 : {:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
初期状態 : {"Alice": 80}
or_insert 後 : {"Bob": 100, "Alice": 80}</pre>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">繰り返し処理（<code>for</code>）での利用方法</h2>



<p class="wp-block-paragraph"><code>HashMap</code>&nbsp;は複数の要素を管理するため、<code>for</code> を利用した繰り返し処理を行うことがよくあります。Rust の繰り返しでは、イテレータを取得して動作します。</p>



<h3 class="wp-block-heading jinr-heading d--bold">参照のみの繰り返し処理</h3>



<p class="wp-block-paragraph"><code>HashMap</code> の要素を 1 つずつ取り出して参照するだけの繰り返しの場合には、以下のように不変参照 (<code>&amp;</code>) を使って <code>for</code> を使用します。ループ後も元の <code>HashMap</code> を引き続き利用できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);
    scores.insert(String::from("Charlie"), 70);

    // 所有権を移動せず参照としてループする
    for (name, score) in &amp;scores {
        println!("{name} のスコア : {score}");
    }

    // ループ後も scores を使用できる
    println!("ループ後のエントリ数 : {}", scores.len());
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Bob のスコア : 100
Alice のスコア : 80
Charlie のスコア : 70
ループ後のエントリ数 : 3</pre>



<p class="wp-block-paragraph">キーと値は、<code>(name, score)</code> にそれぞれ 1 要素ずつ取り出して繰り返し処理が進みます。</p>



<h3 class="wp-block-heading jinr-heading d--bold">値の変更を伴う繰り返し処理</h3>



<p class="wp-block-paragraph"><code>HashMap</code> の要素を繰り返しの中で変更する場合には、以下のように可変参照 (<code>&amp;mut</code>) を使って <code>for</code> を使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);
    scores.insert(String::from("Charlie"), 70);

    println!("更新前 : {:?}", scores);

    // 可変参照でループし、全員のスコアに 10 を加算する
    for (_name, score) in &amp;mut scores {
        *score += 10;
    }

    println!("更新後 : {:?}", scores);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
更新前 : {"Alice": 80, "Bob": 100, "Charlie": 70}
更新後 : {"Alice": 90, "Bob": 110, "Charlie": 80}</pre>



<p class="wp-block-paragraph">値を変更する場合には、<code>*score</code> のように参照を外して変更することが可能です。</p>



<h3 class="wp-block-heading jinr-heading d--bold">所有権の移動を伴う繰り返し処理</h3>



<p class="wp-block-paragraph"><code>HashMap</code> の所有権を移動して繰り返し処理をする場合には、以下のように <code>in</code> の部分に <code>HashMap</code> の変数を直接指定します。所有権を移動する繰り返し処理をした場合には、繰り返し後には変数を使うことができなくなる点に注意が必要です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Alice"), 80);
    scores.insert(String::from("Bob"), 100);
    scores.insert(String::from("Charlie"), 70);

    // 所有権を移動させてループする
    for (name, score) in scores {
        println!("{name} のスコア : {score}");
    }

    // 所有権が移動したため、ループ後は scores を使用できない
    // println!("{:?}", scores); // コンパイルエラー
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Charlie のスコア : 70
Bob のスコア : 100
Alice のスコア : 80</pre>



<p class="wp-block-paragraph">この方法は、ループ後に元の <code>HashMap</code> を使わない場合や、大きいサイズの <code>HashMap</code> であるためループ終了にあわせてメモリ解放したい場合などに利用できます。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust でデータをキーと値のペアで管理するための <span class="jinr-d--text-color d--marker1 d--bold"><code>HashMap</code> 型</span>の基本を解説しました。</p>



<p class="wp-block-paragraph"><code>HashMap&lt;K, V&gt;</code> 型は、キーと値のペアでデータを管理するためのコレクション型です。ユーザー ID とユーザー名、商品 ID と価格など、対応関係を持つデータを効率的に管理できます。</p>



<p class="wp-block-paragraph">この記事では、<code>HashMap</code> の生成方法から要素の取得・追加・更新・削除、Entry API を利用した値の追加方法、<code>for</code> を使った繰り返し処理まで紹介しました。</p>



<p class="wp-block-paragraph"><code>HashMap</code> は Rust のプログラムで非常によく利用されるコレクション型です。<code>Vec</code> 型とあわせて使う機会も多いため、この記事で紹介した基本操作をしっかり身につけておきましょう。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/hashmap-basic" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-hashmap-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】Iteratorの消費アダプタ（sum・fold・collect など）を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-iterator-consuming-adapters/</link>
					<comments>https://rust-tech.nkhn37.net/rust-iterator-consuming-adapters/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Fri, 03 Apr 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[fold]]></category>
		<category><![CDATA[イテレータ]]></category>
		<category><![CDATA[イテレータアダプタ]]></category>
		<category><![CDATA[消費アダプタ]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1891</guid>

					<description><![CDATA[Rust の イテレータ（Iterator）に用意されている消費アダプタの基本を初心者にも分かりやすく解説します。 イテレータの消費とは イテレータ（Iterator）とは、値の列を生成する値で、要素を順番に取り出すこと [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust の イテレータ（Iterator）に用意されている<span class="jinr-d--text-color d--marker1 d--bold">消費アダプタの基本</span>を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">イテレータの消費とは</h2>



<p class="wp-block-paragraph">イテレータ（Iterator）とは、値の列を生成する値で、要素を順番に取り出すことができる仕組みです。イテレータの基本やイテレータアダプタについて理解が不十分な方は、以下にまとめていますので参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://rust-tech.nkhn37.net/rust-iterator-basic/" target="_blank" rel="noreferrer noopener">イテレータ（Iterator）の基本を分かりやすく解説</a></li>



<li><a href="https://rust-tech.nkhn37.net/rust-iterator-adapters/" target="_blank" rel="noreferrer noopener">Iterator のアダプタ（map・filter など）を分かりやすく解説</a></li>
</ul>



<p class="wp-block-paragraph">上記では、イテレータの基本とアダプタを使って別のイテレータを作る方法を紹介しました。</p>



<p class="wp-block-paragraph">イテレータは、<code>next</code> を使って順に値を取り出すことができます。<code>next</code> を繰り返し呼び出すことで、イテレータの要素を最後まで（または途中まで）使い切ることを「消費」と言います。イテレータを消費しつつ、最終的な計算結果を得るメソッドを「<span class="jinr-d--text-color d--marker1 d--bold">消費アダプタ（consuming adapter）</span>」と言います。</p>



<p class="wp-block-paragraph">この記事では、代表的な消費アダプタを紹介しつつ、<span class="jinr-d--text-color d--marker1 d--bold">イテレータを消費する方法</span>を紹介します。</p>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">代表的な消費アダプタ</h2>



<p class="wp-block-paragraph">以降では、よく使用される代表的な消費アダプタを紹介していきます。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>collect</code>：コレクションに集約する</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>collect</code></span> は、イテレータの要素をコレクションにまとめることができる消費アダプタです。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>Vec</code> への集約</h4>



<p class="wp-block-paragraph">以下は、<code>numbers</code> を 2 倍した数値列を <code>Vec</code> に集約する例です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    // map を適用したイテレータを collect して新しい Vec に集約
    let result_vec: Vec&lt;_> = numbers.iter().map(|x| x * 2).collect();

    // 結果を表示
    println!("{:?}", result_vec);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[2, 4, 6, 8, 10]</pre>



<p class="wp-block-paragraph">例で「<code>numbers.iter().map(|x| x * 2)</code>」は、map というイテレータアダプタを使い、各要素を 2 倍したイテレータを返します。この段階では、<code>x * 2</code> の計算は適用されていません。その後、<code>collect</code> という消費アダプタが適用されることで計算が実行されて <code>Vec</code> の <code>result_vec</code> にまとめられます。</p>



<p class="wp-block-paragraph">なお、collect は、任意のコレクションにまとめることができるため「<code>result_vec: Vec&lt;i32&gt;</code>」という型注釈をつけるか、「<code>collect::&lt;Vec&lt;_&gt;&gt;()</code>&nbsp;」のようにどの型に変換するかを明示する必要があります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">その他のコレクションへの集約</h4>



<p class="wp-block-paragraph">上記で <code>Vec</code> への集約を紹介しましたが、任意のコレクションにまとめられると説明しました。1 例として <code>HashSet</code> に集約する例を見ておきましょう。</p>



<p class="wp-block-paragraph">以下は、<code>numbers</code> の 値を 2 倍にした後、<code>HashSet</code> に集約しています。<code>HashSet</code> を用いると、重複を取り除いた集合として扱うことができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use std::collections::HashSet;

fn main() {
    let numbers = vec![1, 2, 3, 1, 2, 5];

    // HashSet を使用して、重複を排除したコレクションに集約
    let result_set: HashSet&lt;_> = numbers.iter().map(|x| x * 2).collect();

    // 結果を表示
    println!("{:?}", result_set);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果例】※ HashSet は順序保証がされないため、順序は実行により異なります
{4, 2, 6, 10}</pre>



<p class="wp-block-paragraph">型注釈で「<code>: HashSet&lt;_&gt;</code>」を付けることで、<code>HashSet</code> に集約できます。このように、<code>collect</code> は変換先のコレクションの型によって結果が変わることが特徴的です。</p>



<p class="wp-block-paragraph">省略しますが、同様に <code>HashMap</code> などのその他コレクションも同様に扱うことができます。</p>



<h4 class="wp-block-heading jinr-heading d--bold">無限のシーケンスの場合</h4>



<p class="wp-block-paragraph">イテレータの強力な特徴は、無限のデータシーケンスも扱うことができる点です。ただし、<code>collect</code> を使用する場合には、注意が必要です。以下のように <code>take</code> や <code>take_while</code> などで、データの範囲を制限して適用をする必要があります。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // 無限の数値列を生成するイテレータ
    let infinite_numbers = 1..;

    // 無限の数値列から最初の 5 個を collect して Vec に集約
    let result_vec: Vec&lt;_> = infinite_numbers.take(5).collect();

    // 結果を表示
    println!("{:?}", result_vec);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[1, 2, 3, 4, 5]</pre>



<p class="wp-block-paragraph">例では「<code>1..</code>」により、<code>RangeFrom&lt;i32&gt;</code> のイテレータを生成しています。このイテレータは 1 から順番に数値を取り出せますが、末尾が決まっていません。そのため、<code>take</code> により先頭 5 個を取り出すイテレータアダプタを適用してから <code>collect</code> を適用しています。</p>



<p class="wp-block-paragraph">無限のデータシーケンスの場合は、消費アダプタの使用には注意が必要です。以降で紹介する消費アダプタについても同様に無限に続くイテレータの場合は注意して使用してください。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>count</code>：件数を取得する</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>count</code></span> は、イテレータの要素数を取得する消費アダプタです。<code>count</code> はイテレータを消費し、要素を最後まで走査することで件数を返します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    // count() メソッドを使用して、イテレータの要素数を数える
    let count = numbers.iter().count();

    // 結果を表示
    println!("{}", count);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
5</pre>



<h3 class="wp-block-heading jinr-heading d--bold"><code>sum</code> / <code>product</code>：数値の合計や積を計算する</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>sum</code></span> は要素の合計、<span class="jinr-d--text-color d--marker1 d--bold"><code>product</code></span> は要素の積を計算するための消費アダプタです。これらは、数値を集約したいときに便利です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = [1, 2, 3, 4, 5];

    let sum: i32 = numbers.iter().sum();
    let product: i32 = numbers.iter().product();

    println!("sum: {}", sum);
    println!("product: {}", product);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
sum: 15
product: 120</pre>



<p class="wp-block-paragraph"><code>sum</code> や <code>product</code> は、戻り値の型をコンパイラが決められないため、基本的には型注釈が必要になります（例「<code>sum : i32</code>」）。ただし、関数の戻り値型などから型が明らかな場合は、型推論により型注釈を省略できることもあります。なお、<code>sum</code> は数値型に対してのみ使用可能です。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>max</code> / <code>min</code>：最大値や最小値を取得する</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>max</code></span> と <span class="jinr-d--text-color d--marker1 d--bold"><code>min</code></span> は、それぞれ最大値・最小値を取得するための消費アダプタです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = [3, 2, 5, 1, 4];

    // 最大値と最小値を求める
    let max = numbers.iter().max();
    let min = numbers.iter().min();

    // 結果を表示
    println!("max: {:?}", max);
    println!("min: {:?}", min);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
max: Some(5)
min: Some(1)</pre>



<p class="wp-block-paragraph"><code>max</code> と <code>min</code> については、戻り値が <code>Option</code> 型になる点に注意してください。これは、イテレータが空の場合は、最大値や最小値を返せないためです。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【補足：比較方法を指定する】</strong></p>



<p class="wp-block-paragraph"><code>max_by</code> や <code>min_by</code> を使用すると、比較方法を自分で指定することができます。また、<code>max_by_key</code> や <code>min_by_key</code> を使うと、キーを指定して比較することも可能です。</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>fold</code> / <code>rfold</code>：畳み込み計算を行う</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>fold</code></span> や <span class="jinr-d--text-color d--marker1 d--bold"><code>rfold</code></span> は、イテレータの要素を順番に取り出しながら 1 つの値にまとめるための消費アダプタです。<code>fold</code> は前から、<code>rfold</code> は後ろから計算する点に違いがあります。</p>



<p class="wp-block-paragraph">基本的な構文は以下のような形となります。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">iterator.fold(初期値, |累積値, 要素| 処理)</pre>



<ul class="wp-block-list jinr-list">
<li>初期値：最初に累積する値</li>



<li>累積値：これまでの計算結果</li>



<li>要素：イテレータから取り出した要素</li>
</ul>



<p class="wp-block-paragraph">以降では、簡単な合計の例で <code>fold</code> と <code>rfold</code> の使い方を見てみましょう。なお、合計を例にするだけで、<code>fold</code> / <code>rfold</code> では任意の処理ができる点が非常に強力です。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>fold</code>（前から畳み込む）</h4>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>fold</code></span> は、イテレータの要素を前から順に処理しながら、1 つにまとめます。</p>



<h5 class="wp-block-heading jinr-heading d--bold">合計 (<code>sum</code>) を <code>fold</code> で計算する例</h5>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    // fold を使用して、イテレータの要素の合計を求める
    let sum = numbers.iter().fold(0, |acc, x| acc + x);

    // 結果を表示
    println!("sum: {}", sum);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
sum: 15</pre>



<p class="wp-block-paragraph">例では、「初期値: <code>0</code>」「<code>0 + 1 = 1</code>」「<code>1 + 2 = 3</code>」…「<code>10 + 5 = 15</code>」のように計算が繰り返し進んで 1 つの合計結果にまとまります。この例から、分かるように上記で紹介した <code>sum</code> や <code>product</code> などは、<code>fold</code> でも実現することができます。</p>



<h5 class="wp-block-heading jinr-heading d--bold">任意の処理を定義可能</h5>



<p class="wp-block-paragraph">上記では分かりやすいように合計の例を紹介しましたが、<code>fold</code> は任意の処理を定義できます。以下は、文字列を連結する例です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let words = vec!["Hello", " ", "Rust", "!"];

    // fold を使用して、イテレータの要素を連結する
    let concatenated = words.iter().fold(String::new(), |acc, word| acc + word);

    // 結果を表示
    println!("{}", concatenated);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Hello Rust!</pre>



<p class="wp-block-paragraph">このように、<code>fold</code> は文字列の結合などにも使えます。<code>fold</code> や後述する <code>rfold</code> は要素をどのように 1 つの値へまとめるかを柔軟に定義できる点が大きな特徴です。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>rfold</code>（後ろから畳み込む）</h4>



<p class="wp-block-paragraph">rfold は、fold と同じように値を 1 つにまとめますが、後ろから順に処理する点が異なります。数値計算だと計算順序が分かりにくいため、文字列結合で比較してみましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let words = vec!["a", "b", "c", "d"];

    // fold を使用して、前から順に要素を結合する
    let forward = words.iter().fold(String::new(), |acc, word| acc + word);

    // rfold を使用して、逆順に要素を結合する
    let backward = words.iter().rfold(String::new(), |acc, word| acc + word);

    // 結果を表示
    println!("forward: {}", forward);
    println!("backward: {}", backward);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
fold: abcd
rfold: dcba</pre>



<p class="wp-block-paragraph">例のように、<code>fold</code> では <code>"abcd"</code> のような順になりますが、<code>rfold</code> では、<code>"dcba"</code> のように処理の順序が逆になっています。数値計算などでも、処理の順序が変わる点は同様です。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【補足：エラー処理付きの畳み込み】</strong></p>



<p class="wp-block-paragraph"><code>try_fold</code> や <code>try_rfold</code> を使用すると途中でエラーが発生した場合に処理を中断することができます。</p>
</div>
		</div></section>



<h2 class="wp-block-heading jinr-heading d--bold">その他の便利な消費アダプタ</h2>



<h3 class="wp-block-heading jinr-heading d--bold">その他の消費アダプタ一覧</h3>



<p class="wp-block-paragraph">上記で紹介した消費アダプタの他にも多くの消費アダプタがありますが、ここでは、代表的なものを一覧で簡単に紹介します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>消費アダプタ</th><th>概要</th></tr></thead><tbody><tr><td><code>any</code> / <code>all</code></td><td>条件を満たす要素の有無を判定する。</td></tr><tr><td><code>position</code> / <code>rposition</code></td><td>条件の要素を満たす要素の位置を返す。</td></tr><tr><td><code>nth</code> / <code>nth_back</code></td><td><code>n</code> 番目の要素を取得する。<code>nth(0)</code> は <code>next()</code> と同じ。</td></tr><tr><td><code>last</code></td><td>最後の要素を取得する。</td></tr><tr><td><code>find</code> / <code>rfind</code> / <code>find_map</code></td><td>条件に一致する要素を検索する。</td></tr><tr><td><code>partition</code></td><td>条件に応じて 2 つに分割する。</td></tr><tr><td><code>for_each</code> / <code>try_for_each</code></td><td>各要素に処理を適用する。</td></tr></tbody></table></figure>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust の イテレータ（Iterator）に<span class="jinr-d--text-color d--marker1 d--bold">消費アダプタの基本</span>について解説しました。</p>



<p class="wp-block-paragraph">イテレータは <code>next</code> を使って順番に値を取り出す仕組みであり、その要素を最後まで、または途中まで使うことを「消費」と言います。消費アダプタは、そのイテレータを消費しながら最終的な結果を得るためのメソッドです。</p>



<p class="wp-block-paragraph">この記事では、代表的な消費アダプタとして、次のようなものを紹介しました。</p>



<ul class="wp-block-list jinr-list">
<li><code>collect</code>：コレクションにまとめる</li>



<li><code>count</code>：件数を取得する</li>



<li><code>sum</code> / <code>product</code>：合計や積を計算する</li>



<li><code>max</code> / <code>min</code>：最大値や最小値を取得する</li>



<li><code>fold</code> / <code>rfold</code>：任意の処理で 1 つの値にまとめる</li>
</ul>



<p class="wp-block-paragraph">まずは <code>collect</code>、<code>count</code>、<code>sum</code> などの基本的な消費アダプタに慣れてもらい、そのうえで <code>fold</code> を理解すると、イテレータの仕組みをより深く理解できるようになります。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/iterator-consuming-adapters" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-iterator-consuming-adapters/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】Iterator のアダプタ（map・filter など）を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-iterator-adapters/</link>
					<comments>https://rust-tech.nkhn37.net/rust-iterator-adapters/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[filter_map]]></category>
		<category><![CDATA[flat_map]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[イテレータ]]></category>
		<category><![CDATA[イテレータアダプタ]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1886</guid>

					<description><![CDATA[Rust の イテレータ（Iterator）に用意されているイテレータアダプタの基本を初心者にも分かりやすく解説します。 イテレータアダプタとは イテレータ（Iterator）とは、値の列を生成する値で、要素を順番に取り [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust の イテレータ（Iterator）に用意されている<span class="jinr-d--text-color d--marker1 d--bold">イテレータアダプタの基本</span>を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">イテレータアダプタとは</h2>



<p class="wp-block-paragraph">イテレータ（Iterator）とは、値の列を生成する値で、要素を順番に取り出すことができる仕組みです。イテレータの基本は「<a href="https://rust-tech.nkhn37.net/rust-iterator-basic/" target="_blank" rel="noreferrer noopener">イテレータ（Iterator）の基本を分かりやすく解説</a>」を参考にしてください。この記事で、基本となる <code>next</code> や <code>into_iter</code> などについて解説しています。</p>



<p class="wp-block-paragraph">イテレータには、要素を順番に取り出すだけでなく、要素を変換したり、条件に合うものだけを残したりする便利なメソッドが多数用意されています。これらを<span class="jinr-d--text-color d--marker1 d--bold">イテレータアダプタ</span>と言います。イテレータアダプタは、既存のイテレータをもとに、新しいイテレータを作り出します。</p>



<p class="wp-block-paragraph">イテレータアダプタの重要な点は、その場ですぐに最終結果を作るのではなく、新しいイテレータを返すという点です。この仕組みは「遅延評価」と呼ばれ、要素が実際に取り出されるときに初めて処理が実行されます。そのため、必要な分だけ効率よく処理を行うことができます。</p>



<p class="wp-block-paragraph">また、イテレータアダプタには、変換などの処理内容を指定するためにクロージャをよく使用します。なお、クロージャの代わりに通常関数を渡すことも可能ですが、外部変数を利用できる点からクロージャがよく使用されます。</p>



<p class="wp-block-paragraph">この記事では、代表的なイテレータアダプタを紹介しつつ、イテレータアダプタの基本的な使い方を紹介していきます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">クロージャの基本については「<a href="https://rust-tech.nkhn37.net/rust-closure-basic/" target="_blank" rel="noreferrer noopener">クロージャの基本と使い方を分かりやすく解説</a>」を参考にしてください。</p>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">代表的なイテレータアダプタ</h2>



<p class="wp-block-paragraph">ここでは、基本としてよく使用するイテレータアダプタである <code>map</code> と <code>filter</code> を中心に使い方を見ていきましょう。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>map</code>：各要素に処理を適用し、別の値に変換する</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>map</code></span> は、イテレータの各要素に対して指定した処理を適用し、その結果となるイテレータに変換するアダプタです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // 元データのベクタを作成
    let numbers = vec![1, 2, 3];

    // map を使用し、各要素を2倍にしたイテレータを作成
    // (この時点ではまだ計算されない)
    let doubled_iter = numbers.iter().map(|x| x * 2);

    // イテレータをベクタに収集 (ここで初めて計算が行われる)
    let result: Vec&lt;_> = doubled_iter.collect();

    // 結果を表示
    println!("{:?}", result);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[2, 4, 6]</pre>



<p class="wp-block-paragraph"><code>map</code> では、引数にクロージャ（または関数）を受け取りイテレータを返却します。上記で <code>doubled_iter</code> はイテレータです。この時点では、各要素を 2 倍にするという計算はまだされていません。<code>collect</code> や <code>for</code> 文で要素を取り出すときに、初めて計算が実行されます。これが「遅延評価」です。</p>



<p class="wp-block-paragraph"><code>result</code> 変数に束縛する際に使用している <code>collect</code> という処理は、イテレータの要素をコレクションにまとめるメソッドです。<code>collect</code> は戻り値の型が一意には決まりません。例えば、<code>Ve</code>c や <code>HashSet</code> などのさまざまなコレクションに変換できるためです。このため「<code>let result: Vec&lt;_&gt;</code>」のように型注釈をつけるか、<code>collect::&lt;Vec&lt;_&gt;&gt;()</code> のように、どの型に変換するかを明示する必要があります</p>



<p class="wp-block-paragraph">なお、上記では <code>map</code> によるイテレータ生成から、<code>collect</code> による遅延評価での処理という流れを理解してもらうために丁寧に文を分けて記載しましたが、以下のように「<code>.</code>（ドット）」で処理を連結させることで簡潔に記載も可能です。以降では、この形式で紹介していきます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // 元データのベクタを作成
    let numbers = vec![1, 2, 3];

    // map を使用し、各要素を2倍にした結果を取得する
    let result: Vec&lt;_> = numbers.iter().map(|x| x * 2).collect();

    // 結果を表示
    println!("{:?}", result);
}</pre>



<h3 class="wp-block-heading jinr-heading d--bold"><code>filter</code>：条件に一致する要素だけを残す</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>filter</code></span> は、イテレータの各要素に対して条件による判定をし、条件に一致する要素だけを残したイテレータに変換するアダプタです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // filter を使用し、偶数のみを残す
    let even_numbers: Vec&lt;_> = numbers.iter().filter(|x| **x % 2 == 0).collect();

    // 結果を表示
    println!("{:?}", even_numbers);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[2, 4, 6, 8, 10]</pre>



<p class="wp-block-paragraph"><code>filter</code> では、クロージャが <code>true</code> を返した要素のみ残り、<code>false</code> の要素は除外されます。</p>



<p class="wp-block-paragraph">例では、<code>iter()</code> を使用しているため要素は参照として扱われます。また、<code>filter</code> は要素をクロージャに渡して条件判定を行うため、この例では <code>**x</code> のように参照を外して値を取り出しています。（参照が重なっているため、2 回参照を外しています。）</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>map</code> と <code>filter</code> を組み合わせて使う</h3>



<p class="wp-block-paragraph">イテレータアダプタは、「<code>.</code>（ドット）」でつなげることで複数の処理を連続して適用することで本領を発揮します。以下は、<code>filter</code> で偶数のみ残し、さらに <code>map</code> で 2 倍する例です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // filter と map を組み合わせて、偶数の2倍を計算する
    let even_doubles: Vec&lt;_> = numbers
        .iter()
        .filter(|x| **x % 2 == 0)
        .map(|x| x * 2)
        .collect();

    // 結果を表示
    println!("{:?}", even_doubles);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[4, 8, 12, 16, 20]</pre>



<p class="wp-block-paragraph">このように、イテレータアダプタを組み合わせて、データの処理を上から順に記述していくことで、可読性が高いコードを記述できることが特徴です。</p>



<h2 class="wp-block-heading jinr-heading d--bold">その他の便利なイテレータアダプタ</h2>



<p class="wp-block-paragraph"><code>map</code> と <code>filter</code> はイテレータアダプタとして中心的なものです。他にも多くのイテレータアダプタがありますが、ここではよく使われるものをいくつか紹介します。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>filter_map</code>：変換を行い、成功（<code>Option</code> の <code>Some</code>）のみを残す</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>filter_map</code></span> は、変換と絞り込みを同時に行うことができるアダプタで、変換を行い成功した値のみを残すことができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let values = vec!["10", "abc", "20", "def", "30"];

    // filter_map を使用して、文字列を整数に変換し、成功したものだけを収集する
    let numbers: Vec&lt;_> = values
        .iter()
        .filter_map(|s| s.parse::&lt;i32>().ok())
        .collect();

    // 結果を表示
    println!("{:?}", numbers);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[10, 20, 30]</pre>



<p class="wp-block-paragraph">この例では、文字列の <code>Vec</code> を整数に変換しています。指定したクロージャは、整数に変換できた場合は、<code>Option</code> 型の <code>Some(v)</code> を返し、変換できなかった場合は <code>None</code> を返します。</p>



<p class="wp-block-paragraph">結果を見ると分かるように <code>filter_map</code> は、変換結果が <code>Some(v)</code> であれば中の値 <code>v</code> を結果に残し、<code>None</code> の場合はその値を除外します。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>flat_map</code>：各要素を複数の要素に展開し、1 つの列としてつなげる</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>flat_map</code></span> は、各要素を複数の要素に展開し、1 つの列としてつなげるアダプタです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let numbers = vec![1, 2, 3];

    let result: Vec&lt;_> = numbers.iter().flat_map(|x| vec![*x, *x * 10]).collect();

    // 結果を表示
    println!("{:?}", result);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
[1, 10, 2, 20, 3, 30]</pre>



<p class="wp-block-paragraph">この例で、指定したクロージャは与えられたイテレータの要素の値に対して、値と 10 倍の値のペアを生成しています。<code>[1, 2, 3]</code> がクロージャにより <code>[[1, 10], [2, 20], [3, 30]]</code> に展開され、<code>flat_map</code> により <code>[1, 10, 2, 20, 3, 30]</code> に 1 つの列につなげられているイメージを持ってもらうと分かりやすいかと思います。</p>



<h3 class="wp-block-heading jinr-heading d--bold">その他のイテレータアダプタ一覧</h3>



<p class="wp-block-paragraph">上記で紹介したイテレータアダプタの他にも多くのイテレータアダプタがありますが、ここでは、代表的なものを一覧で簡単に紹介します。</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>イテレータアダプタ</th><th>概要</th></tr></thead><tbody><tr><td><code>flatten</code></td><td>ネストした構造を平坦化する</td></tr><tr><td><code>take</code></td><td>先頭から指定した数だけ取得する</td></tr><tr><td><code>take_while</code></td><td>条件を満たす間だけ先頭から取得する</td></tr><tr><td><code>skip</code></td><td>先頭から指定した数だけをスキップする</td></tr><tr><td><code>skip_while</code></td><td>条件を満たす間だけ先頭からスキップする</td></tr><tr><td><code>enumerate</code></td><td>インデックス付きで取得する</td></tr><tr><td><code>zip</code></td><td>複数のイテレータを組み合わせて取得する（短い方にあわせて終了する）</td></tr></tbody></table></figure>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust の イテレータに用意されている<span class="jinr-d--text-color d--marker1 d--bold">イテレータアダプタの基本</span>について解説しました。</p>



<p class="wp-block-paragraph">イテレータアダプタは、既存のイテレータから新しいイテレータを作る仕組みです。代表的なイテレータアダプタである <code>map</code> と <code>filter</code> を用いて基本的な使い方を紹介しています。また、その他のイテレータアダプタについても簡単に紹介しました。</p>



<p class="wp-block-paragraph">イテレータアダプタは、組み合わせて使用することで、処理の流れを非常に分かりやすく記述することができます。まずは、<code>map</code> と <code>filter</code> でしっかりと理解してもらうことが重要です。その上で、<code>filter_map</code> や <code>flat_map</code> などのさまざまなアダプタも徐々に使えるようになっていってください。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/iterator-adapters" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section>


<p class="wp-block-paragraph"></p>
<div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-iterator-adapters/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】イテレータ（Iterator）の基本を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-iterator-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-iterator-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[IntoIterator]]></category>
		<category><![CDATA[Iterator]]></category>
		<category><![CDATA[トレイト]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1884</guid>

					<description><![CDATA[Rust におけるイテレータ（Iterator）の基本を初心者にも分かりやすく解説します。 イテレータとは イテレータ（Iterator）は、値の列を生成する値で、要素を順番に取り出すことができる仕組みです。Rust で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">イテレータ（Iterator）</span>の基本を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">イテレータとは</h2>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold">イテレータ（Iterator）</span>は、値の列を生成する値で、要素を順番に取り出すことができる仕組みです。Rust では、文字列や <code>Vec</code> などから要素を取り出して処理するイテレータが用意されています。他にも、様々な場面でイテレータの仕組みが利用されています。</p>



<p class="wp-block-paragraph">Rust の <code>for</code> 文はイテレータにとって自然に扱える構文となっており、シンプルなプログラム例は以下のようなものです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let v = vec![1, 2, 3];

    for x in v {
        println!("{}", x);
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
1
2
3</pre>



<p class="wp-block-paragraph">Rust では、このような繰り返し処理の多くがイテレータを使って実装されており、Rust における重要な仕組みです。Rust のイテレータは、具体的には、<code>Iterator</code> トレイトや <code>IntoIterator</code> トレイトにより表現されています。</p>



<p class="wp-block-paragraph">この記事では、<span class="jinr-d--text-color d--marker1 d--bold">Rust のイテレータ（Iterator）の基本</span>を解説します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">この記事では、トレイトに関する基本知識が必要です。トレイトについては「<a href="https://rust-tech.nkhn37.net/rust-trait-basic/" target="_blank" rel="noreferrer noopener">トレイトの基本を分かりやすく解説</a>」を参考にしてください。</p>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">イテレータの基本</h2>



<p class="wp-block-paragraph">イテレータを実現する中心的なトレイトは、<span class="jinr-d--text-color d--marker1 d--bold"><code>Iterator</code></span> トレイトと <span class="jinr-d--text-color d--marker1 d--bold"><code>IntoIterator</code></span> トレイトです。ここでは、それぞれの概要について紹介します。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Iterator</code> トレイト</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>Iterator</code></span> トレイトは、以下のように定義されています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">pub trait Iterator {
    type Item;

    // Required method
    fn next(&amp;mut self) -> Option&lt;Self::Item>;

    ...(他のメソッドは省略)...
}</pre>



<p class="wp-block-paragraph"><code>Item</code> という取り出す要素の型と <code>next</code> メソッドを持ちます。独自の型に <code>Iterator</code> トレイトを実装する際には <code>next</code> メソッドは必須のメソッドになります。他にもトレイトで定義されているメソッドはありますが、明確に定義しない場合はデフォルト実装が使用されます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>Iterator</code> トレイトの詳細については、公式ドキュメントの<a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html" target="_blank" rel="noreferrer noopener">こちら</a>を参照してください。</p>
</div>
		</div></section>



<h4 class="wp-block-heading jinr-heading d--bold"><code>next</code> メソッド</h4>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>next</code></span> メソッドは、イテレータの中心となる重要なメソッドです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let v = vec![1, 2, 3];
    let mut iter = v.iter();

    println!("{:?}", iter.next()); // Some(1)
    println!("{:?}", iter.next()); // Some(2)
    println!("{:?}", iter.next()); // Some(3)
    println!("{:?}", iter.next()); // None
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Some(1)
Some(2)
Some(3)
None</pre>



<p class="wp-block-paragraph"><code>iter</code> メソッドは、対象のイテレータを取得します。（<code>iter</code> については後ほど説明します。）</p>



<p class="wp-block-paragraph">イテレータにおける <code>next</code> メソッドは、順に要素を取り出し、値 <code>x</code> がある場合は、<code>Option</code> 型の <code>Some(x)</code> を返却します。要素を取り出し続け、取り出す要素がなくなったら最後に <code>None</code> を返却します。 イテレータは、<code>Option</code> 型を使って処理の終了を表現していることがポイントです。</p>



<p class="wp-block-paragraph"><code>v</code> は、イミュータブル（変更不可）ですが、<code>iter</code> は <code>mut</code> を付けてミュータブル（変更可能）にしています。これは、<code>next()</code> メソッドがイテレータ自身の状態を更新するためであり、イテレータは <code>mut</code> で宣言する必要があります。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>IntoIterator</code> トレイト</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>IntoIterator</code></span> トレイトは、イテレータを生成できる型を表すトレイトで、以下のように定義されています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator&lt;Item = Self::Item>;

    // Required method
    fn into_iter(self) -> Self::IntoIter;
}</pre>



<p class="wp-block-paragraph"><code>IntoIterator</code> を実装している型は、<code>into_iter</code> メソッドによってイテレータに変換することができます。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>IntoIterator</code> トレイトの詳細については、公式ドキュメントの<a href="https://doc.rust-lang.org/std/iter/trait.IntoIterator.html" target="_blank" rel="noreferrer noopener">こちら</a>を参照してください。</p>
</div>
		</div></section>



<h4 class="wp-block-heading jinr-heading d--bold"><code>into_iter</code> メソッド</h4>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>into_iter</code></span> メソッドは、値や参照からイテレータを生成するメソッドです。<code>into_iter()</code> で理解しておくべきことは以下の通りです。対象 <code>v</code> に対してそれぞれ呼ばれる実装が変わります。</p>



<ul class="wp-block-list jinr-list">
<li><code>(&amp;v).into_iter()</code>：不変参照のイテレータを生成する</li>



<li><code>(&amp;mut v).into_iter()</code>：可変参照のイテレータを生成する</li>



<li><code>v.into_iter()</code>：所有権を移動するイテレータを生成する</li>
</ul>



<p class="wp-block-paragraph">以下の例を見てみましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let v1 = vec![1, 2, 3];

    // 不変参照のイテレータを作成
    for x in (&amp;v1).into_iter() {
        println!("{}", x);
    }

    let mut v2 = vec![4, 5, 6];

    // 可変参照のイテレータを作成
    for x in (&amp;mut v2).into_iter() {
        *x += 1; // 各要素に1を加える
        println!("{}", x);
    }

    let v3 = vec![7, 8, 9];

    // 所有権を移動するイテレータを作成
    for x in v3.into_iter() {
        println!("{}", x);
    }

    // v3は所有権が移動したため、ここで使用できない
    // println!("{:?}", v3); // コンパイルエラー
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
1
2
3
5
6
7
7
8
9</pre>



<p class="wp-block-paragraph">このように、<code>into_iter()</code> は同じ名前のメソッドであっても、値に対して呼ぶのか、参照に対して呼ぶのかで返すイテレータの型が異なります。この違いは、<code>IntoIterator</code> が「値」「不変参照」「可変参照」のそれぞれに対して実装されていることによるものです。そのため、要素の型も <code>T</code> / <code>&amp;T</code> / <code>&amp;mut T</code> のように変化します。なお、<code>T</code> は型パラメータです。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>for</code> 文と <code>Iterator</code> の関係</h3>



<p class="wp-block-paragraph">Rust の <code>for</code> 文は、<span class="jinr-d--text-color d--marker1 d--bold"><code>IntoIterator</code> トレイトを実装している型</span>に対して使用できます。つまり、<code>for</code> 文は内部的に <code>into_iter()</code> を呼び出し、イテレータとして要素を取り出しています。</p>



<p class="wp-block-paragraph"><code>for</code> 文で繰り返し処理を実装する場合は、明示的に <code>into_iter()</code> を書かなくても、以下のように不変参照で繰り返し処理を行うことができます。なお、可変参照や所有権移動の場合も同様に考えることができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">for x in &amp;v {
    println!("{}", x);
}</pre>



<p class="wp-block-paragraph">これは、内部的には、概ね次のような処理が行われていると考えることができます。<br></p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let v = vec![1, 2, 3];

    let mut iter = (&amp;v).into_iter();

    while let Some(x) = iter.next() {
        println!("{}", x);
    }
}</pre>



<p class="wp-block-paragraph">つまり、「<code>for x in &amp;v</code>」は、<code>(&amp;v).into_iter()</code> を使ってイテレータを生成し、<code>next()</code> で要素を順番に取り出して処理をしているというイメージです。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox1 ">
			<i class="jif jin-ifont-v2bulb" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">ここで示したコードは概念的な説明であり、Rust の内部実装が必ずしもこの通りであることを示すものではない点に注意してください。</p>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>for</code> 文の基本については「<a href="https://rust-tech.nkhn37.net/rust-for-while-loop-basic/" target="_blank" rel="noreferrer noopener">繰り返し処理（for, while, loop）を分かりやすく解説</a>」を参考にしてください。</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold">コレクションにおける <code>iter</code> や <code>iter_mut</code> メソッド</h3>



<p class="wp-block-paragraph"><code>Vec</code> などのコレクションでは、<code>Iterator</code> を返すメソッドとして、<span class="jinr-d--text-color d--marker1 d--bold"><code>iter</code></span> メソッドや <span class="jinr-d--text-color d--marker1 d--bold"><code>iter_mut</code></span> メソッドが提供されています。名称の通り、<code>iter</code> メソッドは不変参照のイテレータを、<code>iter_mut</code> メソッドは、可変参照のイテレータを返却します。</p>



<p class="wp-block-paragraph">以下の例で見てみましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    let mut v = vec![1, 2, 3];

    // iter メソッドで不変参照のイテレータを返却
    for x in v.iter() {
        println!("{}", x);

        // 不変参照なので、以下のように値を変更することはできない
        // *x += 1;
    }

    // iter_mut メソッドで可変参照のイテレータを返却
    for x in v.iter_mut() {
        *x += 1;
        println!("{}", x);
    }
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
1
2
3
2
3
4</pre>



<p class="wp-block-paragraph">例えば、<code>iter</code> を使用すると要素への不変参照を順番に取り出すことができます。不変参照なので、値を変更しようとするとコンパイルエラーとなります。一方で、<code>iter_mut</code> を使用すると要素への可変参照を取得できるため、要素の値を書き換えることができます。</p>



<h4 class="wp-block-heading jinr-heading d--bold">ポイント</h4>



<p class="wp-block-paragraph">多くのコレクションでは以下のような対応関係があります。</p>



<ul class="wp-block-list jinr-list">
<li><code>v.iter()</code> は <code>(&amp;v).into_iter()</code> に対応</li>



<li><code>v.iter_mut()</code> は <code>(&amp;mut v).into_iter()</code> に対応</li>
</ul>



<p class="wp-block-paragraph">つまり、<code>iter</code> や <code>iter_mut</code> は、参照に対する <code>into_iter()</code> をより分かりやすく使うためのメソッドと考えることができます。ただし、誤解しやすいポイントですが、<code>iter</code> や <code>iter_mut</code> は、<code>Iterator</code> トレイトや <code>IntoIterator</code> トレイトで定義されているメソッドではありません。</p>



<p class="wp-block-paragraph">これらは、Rust の標準ライブラリにおいて、コレクションがイテレータを生成するための便利なメソッドとして提供しているものです。そのため、必ずしも上記対応が保証されているわけではありませんので注意してください。</p>



<p class="wp-block-paragraph"><code>Iterator</code> トレイトの必須メソッドとされている <code>next</code> や <code>IntoIterator</code> トレイトの必須メソッドとされている <code>into_iter</code> とは位置づけが異なることを理解しておきましょう。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">イテレータ（Iterator）</span>の基本を解説しました。</p>



<p class="wp-block-paragraph">イテレータは、値の列を生成する値で、要素を順番に取り出すことができる仕組みで <code>for</code> 文などの繰り返し処理で利用されます。</p>



<p class="wp-block-paragraph">イテレータの中心となるのが、<code>Iterator</code> トレイトと <code>IntoIterator</code> トレイトです。この記事では、それぞれの必須メソッドである <code>next</code> や <code>into_iter</code> メソッドの役割について説明しました。また、<code>for</code> 文との関係や、Rust のコレクションで提供される <code>iter</code>、<code>iter_mut</code> といったメソッドについても紹介しました。</p>



<p class="wp-block-paragraph">イテレータは、Rust のデータ処理の中心的な仕組みです。基本の考え方をしっかりと理解しておきましょう。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/iterator-basic" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section><div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-iterator-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】クロージャの型とトレイト（Fn / FnMut / FnOnce）</title>
		<link>https://rust-tech.nkhn37.net/rust-closure-fn-traits/</link>
					<comments>https://rust-tech.nkhn37.net/rust-closure-fn-traits/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Fri, 06 Mar 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[Fn]]></category>
		<category><![CDATA[FnMut]]></category>
		<category><![CDATA[FnOnce]]></category>
		<category><![CDATA[キャプチャ]]></category>
		<category><![CDATA[クロージャ]]></category>
		<category><![CDATA[トレイト]]></category>
		<category><![CDATA[所有権]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1843</guid>

					<description><![CDATA[Rust におけるクロージャ（Closure）の型とトレイト（Fn / FnMut / FnOnce）について初心者にも分かりやすく解説します。 Rust のクロージャの型とトレイト Rust におけるクロージャ（Clo [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）の型とトレイト（Fn / FnMut / FnOnce）</span>について初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">Rust のクロージャの型とトレイト</h2>



<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）</span>とは、「<strong>その場で定義できる無名の関数</strong>のようなもの」のことです。クロージャの使い方の基本については「<a href="https://rust-tech.nkhn37.net/rust-closure-basic/" target="_blank" rel="noreferrer noopener">クロージャの基本と使い方を分かりやすく解説</a>」を参考にしてください。</p>



<p class="wp-block-paragraph">この記事では、基本からは一段深く、<span class="jinr-d--text-color d--marker1 d--bold">クロージャの「型」と「トレイト」</span>について踏み込んで紹介します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">以降の内容の理解には型やトレイトの基本的な知識が必要です。基本的な内容については、以下を参考にしてください。</p>



<ul class="wp-block-list jinr-list">
<li><a href="https://rust-tech.nkhn37.net/rust-basic-types/" target="_blank" rel="noreferrer noopener">基本型を分かりやすく解説（スカラー型と複合型）</a></li>



<li><a href="https://rust-tech.nkhn37.net/rust-structs-basic/" target="_blank" rel="noreferrer noopener">構造体の使い方を分かりやすく解説</a></li>



<li><a href="https://rust-tech.nkhn37.net/rust-trait-basic/" target="_blank" rel="noreferrer noopener">トレイトの基本を分かりやすく解説</a></li>
</ul>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">クロージャの型</h2>



<p class="wp-block-paragraph">まずは、クロージャーの本質について確認してみましょう。結論から述べると<span class="jinr-d--text-color d--marker1 d--bold">クロージャは、コンパイラが生成する固有の型</span>です。</p>



<p class="wp-block-paragraph">記事冒頭で「その場で定義できる無名の関数<span class="jinr-d--text-color d--marker1 d--bold">のようなもの</span>」と説明しましたが、実際には「関数」ではありません。ここではその違いを具体的なコードで確認します。</p>



<h3 class="wp-block-heading jinr-heading d--bold">関数の型とクロージャの型は異なる</h3>



<p class="wp-block-paragraph">Rust のクロージャは、以下のように使用することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // クロージャで使用する外部変数
    let base = 1;

    // クロージャーを定義
    let add_one_closure = |x| x + base;
    println!("クロージャーを呼び出す: {}", add_one_closure(5));
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
クロージャーを呼び出す: 6</pre>



<p class="wp-block-paragraph">この例では、<code>base</code> という外部変数をキャプチャしています。これにより <code>add_one_closure</code> は引数 <code>x</code> に与えられた値に <code>base</code> の値を加算する機能を提供します。</p>



<p class="wp-block-paragraph">では、このクロージャが関数として扱えるかを試してみましょう。以下の <code>call_function</code> は関数を引数として受け取り呼び出すだけの関数です。比較のために <code>add_one</code> という通常の関数を用意しています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 関数を引数として受け取り、呼び出す関数
fn call_function(f: fn(i32) -> i32, x: i32) -> i32 {
    f(x)
}

// 1を加算する通常の関数
fn add_one(x: i32) -> i32 {
    x + 1
}

fn main() {
    // クロージャで使用する外部変数
    let base = 1;

    // クロージャーを定義
    let add_one_closure = |x| x + base;
    println!("クロージャーを呼び出す: {}", add_one_closure(5));

    // 通常の関数を呼び出す
    println!(
        "通常の関数を call_function 経由で呼び出す: {}",
        call_function(add_one, 5)
    );

    // クロージャーを call_function に渡す。（これはエラーとなる）
    // println!(
    //     "クロージャーを call_function 経由で呼び出す: {}",
    //     call_function(add_one_closure, 5)
    // );
}</pre>



<p class="wp-block-paragraph">例の <code>call_function</code> は、「<code>fn(i32) -&gt; i32</code>」という型を受け取ります。この型は、<span class="jinr-d--text-color d--marker1 d--bold">関数ポインタ型</span>と呼ばれ、「<code>i32</code> 型を受け取り <code>i32</code> 型の結果を返す」ことを意味しています。</p>



<p class="wp-block-paragraph">通常関数の <code>add_one</code> も、クロージャである <code>add_one_closure</code> も「<code>i32</code> 型を受け取り <code>i32</code> 型の結果を返す」という形式に一致しています。しかし、例でコメントアウトしているクロージャー <code>add_one_closure</code> を <code>call_function</code> に渡している部分はコンパイルエラーとなります。</p>



<p class="wp-block-paragraph">理由はシンプルで、クロージャーの型は「<code>fn(i32) -&gt; i32</code>」ではないためです。この結果から分かりますが、<span class="jinr-d--text-color d--marker1 d--bold">クロージャは、コンパイラが生成する固有の型</span>となっています。</p>



<h3 class="wp-block-heading jinr-heading d--bold">トレイト境界でクロージャと関数を同様に扱う</h3>



<p class="wp-block-paragraph">上記で、通常関数とクロージャは型が異なることが分かりました。しかし、関数にクロージャを渡して実行したいケースは非常に多くあります。関数とクロージャーを同じように扱う方法はないのでしょうか？もちろんあります。ポイントとなるのが <span class="jinr-d--text-color d--marker1 d--bold"><code>Fn</code> トレイト</span>です。</p>



<p class="wp-block-paragraph">次の例のようにトレイト境界を用いた <code>call_function</code> を使用すれば、通常関数もクロージャも両方受け取ることができるようになります。<code>Fn</code> トレイトについては詳細は後述しますので、一旦ここでは、このようにすることで対応できると理解していただければと思います</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// クロージャも引数として受け取ることができる関数
fn call_function_closure&lt;F>(f: F, x: i32) -> i32
where
    F: Fn(i32) -> i32,
{
    f(x)
}

// 1を加算する通常の関数
fn add_one(x: i32) -> i32 {
    x + 1
}

fn main() {
    // クロージャで使用する外部変数
    let base = 1;

    // クロージャーを定義
    let add_one_closure = |x| x + base;
    println!("クロージャーを呼び出す: {}", add_one_closure(5));

    // 通常の関数を呼び出す
    println!(
        "通常の関数を call_function 経由で呼び出す: {}",
        call_function_closure(add_one, 5)
    );

    // クロージャーを call_function_closure に渡す
    println!(
        "クロージャーを call_function_closure 経由で呼び出す: {}",
        call_function_closure(add_one_closure, 5)
    );
}</pre>



<p class="wp-block-paragraph">このようにすることで「通常の関数」と「クロージャ」をどちらも同じように扱うことができます。これは、通常の関数もクロージャも、<code>Fn</code> トレイトを通じて扱うことができるためです。</p>



<p class="wp-block-paragraph">実は、クロージャは、常に同じトレイトを実装するわけではありません。外部変数のキャプチャ方法（不変参照、可変参照、所有権移動）によって実装されるトレイトが変わります。以降では、クロージャのトレイトについて説明していきます。</p>



<h2 class="wp-block-heading jinr-heading d--bold">クロージャのトレイト（<code>Fn</code> / <code>FnMut</code> / <code>FnOnce</code>）</h2>



<p class="wp-block-paragraph">Rust では、この違いを表現するために、以下の 3 つのトレイトが用意されています。</p>



<ul class="wp-block-list jinr-list">
<li><span class="jinr-d--text-color d--marker1 d--bold"><code>Fn</code></span>：不変参照</li>



<li><span class="jinr-d--text-color d--marker1 d--bold"><code>FnMut</code></span>：可変参照</li>



<li><span class="jinr-d--text-color d--marker1 d--bold"><code>FnOnce</code></span>：所有権の移動</li>
</ul>



<p class="wp-block-paragraph">これらは、<span class="jinr-d--text-color d--marker1 d--bold">クロージャが外部の変数をどのように扱うか</span>によって使い分けられます。以降では、クロージャのトレイトの違いについて詳しく見ていきます。</p>



<p class="wp-block-paragraph">クロージャの基本記事「<a href="https://rust-tech.nkhn37.net/rust-closure-basic/" target="_blank" rel="noreferrer noopener">クロージャの基本と使い方を分かりやすく解説</a>」で紹介しているクロージャのキャプチャ方法は、この各トレイトに相当しています。基本記事で使用したコードを再掲しながら確認してみましょう。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Fn</code> トレイト（不変参照）</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>Fn</code> トレイト</span>は、外部の変数を変更せずに利用するクロージャに対して実装されるトレイトです。つまり、キャプチャした変数を「読み取るだけ」の 場合に <code>Fn</code> が実装されます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 不変参照でのキャプチャ例
    let x = 10;
    // x は不変参照でキャプチャされる
    let f = |y| x + y;

    // クロージャの呼び出し
    println!("f(5) = {}", f(5));
    // xはまだ使用可能
    println!("x = {}", x);
}</pre>



<p class="wp-block-paragraph">例では、<code>x</code> をクロージャの中で参照しているだけで変更していません。そのため、このクロージャは <code>Fn</code> トレイトを実装します。<code>Fn</code> のクロージャは、状態を変更しないため何度でも安全に呼び出すことができます。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>FnMut</code> トレイト（可変参照）</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>FnMut</code> トレイト</span>は、キャプチャした変数を「変更する」クロージャに対して実装されるトレイトです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 可変参照でのキャプチャ例
    let mut count = 0;
    println!("count before: {}", count);
    // countは可変参照でキャプチャされる
    let mut g = || count += 1;

    // クロージャを呼び出すとcountが変更される
    g();
    // countは変更されている
    println!("count after: {}", count);
}</pre>



<p class="wp-block-paragraph">例では、クロージャの中で <code>count</code> を変更しています。そのため、このクロージャは <code>FnMut</code> トレイトを実装します。</p>



<p class="wp-block-paragraph"><code>FnMut</code> のクロージャは、キャプチャした変数を変更する可能性があります。そのため、呼び出し時には、クロージャ自身が変更される可能性があるため、クロージャを変数に束縛するには「<code>let mut g</code>」のように <code>mut</code> をつける必要があります。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>FnOnce</code> トレイト（所有権の移動）</h3>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>FnOnce</code> トレイト</span>は、「キャプチャした値の所有権を消費する」クロージャに対して実装されるトレイトです。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== move による所有権の移動でのキャプチャ例
    let s = String::from("Hello");
    // s は move で所有権がクロージャに移動される
    let h = move || println!("{s} World!");

    // 実行時に s は消費されて使用できなくなる
    h();
    // sはmoveで所有権が移動されているため以降は使用できない
    // println!("{s}"); // コンパイルエラー
}</pre>



<p class="wp-block-paragraph">例では、<code>move</code> を使用して <code>s</code> の所有権をクロージャに移動しています。このような場合、クロージャはキャプチャした値を消費する可能性があるため、1 回しか安全に呼び出すことができません。そのため、このようなクロージャは <code>FnOnce</code> トレイトを実装します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【<code>move</code> について】</strong></p>



<p class="wp-block-paragraph">例では、明示的に <code>move</code> を付与して実装していますが、Rust はコンパイラがクロージャの使われ方で判断するため、<code>move</code> の指定がなくても <code>FnOnce</code> となる場合があります。代表的な例は、以下のようにクロージャの中で <code>drop()</code> を使用するような場合です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">let s = String::from("Hello");
let h = || drop(s);</pre>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>Fn</code> / <code>FnMut</code> / <code>FnOnce</code> の関係性</h3>



<p class="wp-block-paragraph">上記で紹介したトレイトは、次のような関係になっています。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Fn ⊂ FnMut ⊂ FnOnce</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" width="448" height="449" src="https://rust-tech.nkhn37.net/wp-content/uploads/2026/03/image.png" alt="Fn / FnMut / FnOnce の関係性" class="wp-image-1857" style="aspect-ratio:0.9978047578513507;width:256px;height:auto" srcset="https://rust-tech.nkhn37.net/wp-content/uploads/2026/03/image.png 448w, https://rust-tech.nkhn37.net/wp-content/uploads/2026/03/image-300x300.png 300w, https://rust-tech.nkhn37.net/wp-content/uploads/2026/03/image-150x150.png 150w, https://rust-tech.nkhn37.net/wp-content/uploads/2026/03/image-320x320.png 320w" sizes="(max-width: 448px) 100vw, 448px" /><figcaption class="wp-element-caption">Fn / FnMut / FnOnce の関係性</figcaption></figure>
</div>


<p class="wp-block-paragraph">上記図は「<code>Fn</code> は <code>FnMut</code> のサブトレイト」「<code>FnMut</code> は <code>FnOnce</code> のサブトレイト」という意味を表しています。つまり、<code>Fn</code> を実装するクロージャは <code>FnMut</code> としても扱うことができ、<code>FnMut</code> を実装するクロージャは <code>FnOnce</code> としてもあつかえるという関係になっています。</p>



<p class="wp-block-paragraph">記事の前半で <code>Fn</code> をトレイト境界に持つ関数の例を紹介しましたが、この <code>call_function</code> は、<code>FnMut</code> のクロージャを受け取ることができません。一方で、<code>FnMut</code> をトレイト境界に持つ関数は、<code>Fn</code> トレイトのクロージャを受け取ることが可能となります。</p>



<p class="wp-block-paragraph">ここまでで紹介してきたように、Rust では、クロージャの振る舞いに応じて <code>Fn</code> / <code>FnMut</code> / <code>FnOnce</code> のトレイトが自動的に決定されます。このような仕組みとなっていることをしっかり理解していただければと思います。</p>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）の型とトレイト（<code>Fn</code> / <code>FnMut</code> / <code>FnOnce</code>）</span>について解説しました。</p>



<p class="wp-block-paragraph">クロージャは、通常の関数とは異なり、コンパイラが生成する固有の型です。一方で、トレイト境界を使うことで通常の関数と同じように扱うことができます。</p>



<p class="wp-block-paragraph">また、クロージャは、キャプチャする外部変数の扱い方に応じて、<code>Fn</code> / <code>FnMut</code> / <code>FnOnce</code> のいずれかのトレイトを実装します。これらの違いを理解しておくことで、クロージャを引数として受け取る関数や所有権が関わるコードをより正確に理解して実装ができるようになります。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては&nbsp;<a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/closure-traits" target="_blank" rel="noreferrer noopener">GitHub</a>&nbsp;にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section><div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-closure-fn-traits/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust入門】クロージャの基本と使い方を分かりやすく解説</title>
		<link>https://rust-tech.nkhn37.net/rust-closure-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-closure-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Fri, 20 Feb 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[Rust入門]]></category>
		<category><![CDATA[move]]></category>
		<category><![CDATA[キャプチャ]]></category>
		<category><![CDATA[クロージャ]]></category>
		<category><![CDATA[借用]]></category>
		<category><![CDATA[型推論]]></category>
		<category><![CDATA[所有権]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1783</guid>

					<description><![CDATA[Rust におけるクロージャ（Closure）の基本を初心者にも分かりやすく解説します。 クロージャ（Closure）とは Rust におけるクロージャ（Closure）とは、「その場で定義できる無名の関数のようなもの」 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）</span>の基本を初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold">クロージャ（Closure）とは</h2>



<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）</span>とは、「<strong>その場で定義できる無名の関数</strong>のようなもの」のことです。</p>



<p class="wp-block-paragraph">通常の <code>fn</code> で定義する関数との大きな違いは、外部のスコープにある変数を利用できることです。この「外側の変数を取り込んで使う」ことを「<strong>キャプチャ（capture）</strong>」と呼びます。</p>



<p class="wp-block-paragraph">共通的な変数をクロージャの中に取り込んでおくことで、他の可変な値と組み合わせながら、柔軟で再利用可能な処理を定義することができます。</p>



<p class="wp-block-paragraph">この記事では、<span class="jinr-d--text-color d--marker1 d--bold">Rust におけるクロージャの基本的な使い方や考え方</span>について紹介します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【無名関数とクロージャ】</strong></p>



<p class="wp-block-paragraph">厳密には、クロージャという言葉は「<strong>外部の変数をキャプチャした関数</strong>」のことを言います。しかし、Rust では、外部の変数をキャプチャしていない場合でも、すべてクロージャと呼びます。</p>



<p class="wp-block-paragraph">Python などの他の言語では、「無名関数」と「クロージャ」を分けて説明されることがあります。一方で、Rust コミュニティでは「無名関数」という用語はほとんど使われず、一貫してクロージャという言葉で説明がされる点を覚えておくとよいでしょう。</p>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">クロージャの基本<br></h2>



<h3 class="wp-block-heading jinr-heading d--bold">クロージャの基本的な使い方</h3>



<p class="wp-block-paragraph">基本的なクロージャの使い方を紹介します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">|引数1, 引数2, ...| 式</pre>



<p class="wp-block-paragraph">クロージャの構文は非常にシンプルです。上記のように <code>||</code> 内に引数を列挙し、クロージャの返却値となる式をその後に記載します。引数なしのクロージャー (<code>|| 式</code>) でも問題ありません。</p>



<p class="wp-block-paragraph">また、複数の文を書く場合は、以下のように <code>{}</code> のブロックを使用します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">|引数1, 引数2, ...| {
    文;
    ...;
    式
}</pre>



<p class="wp-block-paragraph">最後の式は、クロージャの戻り値になります。最後に <code>;</code> (セミコロン) をつけると戻り値は <code>()</code> となります。</p>



<p class="wp-block-paragraph">それでは、簡単な具体例で確認してみましょう。</p>



<h4 class="wp-block-heading jinr-heading d--bold">単一式の例</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 単一の式のクロージャ例
    let add = |a, b| a + b;
    println!("add(2, 3) = {}", add(2, 3));
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
add(2, 3) = 5</pre>



<p class="wp-block-paragraph">この例では、変数 <code>a</code> と <code>b</code> を受け取り <code>a + b</code> という単一の式を計算するクロージャを定義して <code>add</code> という変数名に束縛しています。<code>a + b</code> がクロージャの戻り値になります。</p>



<p class="wp-block-paragraph">クロージャを使用する時には「<code>add(2, 3)</code>」のように使用します。もちろん、<code>add(4, 5)</code>、 &#8230;のように任意の引数での再利用が可能です。</p>



<p class="wp-block-paragraph">単一の式の場合であれば、<code>{}</code> を使用しなくても上記のように簡潔に書くことができます。</p>



<h4 class="wp-block-heading jinr-heading d--bold">引数なしの例</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 引数なしのクロージャ例
    let greet = || "Hello, Rust!";
    println!("greet() = {}", greet());
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
greet() = Hello, Rust!</pre>



<p class="wp-block-paragraph">クロージャは、引数がなくても使用できます。引数がない場合、|| のように何も書かずに定義します。この例では、<code>"Hello, Rust!"</code> という文字列リテラルがそのまま戻り値になります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">ブロック形式の例</h4>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== ブロック形式のクロージャ例
    let multiply = |a, b| {
        println!("calculating {a} * {b} ...");
        // 最後の式がクロージャの戻り値になる
        a * b
    };
    println!("multiply(3, 5) = {}", multiply(3, 5));
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
calculating 3 * 5 ...
multiply(3, 5) = 15</pre>



<p class="wp-block-paragraph">複数の文を実行したい場合には、<code>{}</code> ブロックを使用します。例では、計算前に <code>println!</code> でメッセージを表示し、その後に <code>a * b</code> を評価しています。</p>



<p class="wp-block-paragraph">Rust では、ブロックの最後の式が戻り値になるというルールがあります。そのため、<code>a * b</code> に <code>;</code> (セミコロン) をつけないことが重要です。<code>;</code> を付けた場合の返却値は <code>()</code> となります。</p>



<h4 class="wp-block-heading jinr-heading d--bold">外側の変数をキャプチャする例</h4>



<p class="wp-block-paragraph">ここまでの例は、関数とほぼ同じような使い方でした。しかし、クロージャの本質は「外側の変数を利用できること」です。以下の例で、外側の変数をキャプチャする例を見てみましょう。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 外側の変数をキャプチャするクロージャ例
    let base = 10;

    let add_to_base = |x| base + x;
    println!("add_to_base(5) = {}", add_to_base(5));
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
add_to_base(5) = 15</pre>



<p class="wp-block-paragraph">この例では、<code>base</code> という変数をクロージャの外側で定義しています。<code>add_to_base</code> は、引数 <code>x</code> だけを受け取っていますが、計算で <code>base</code> も利用しています。このように <code>add_to_base</code> を用意しておくと、様々な <code>x</code> に対して <code>base</code> を足した結果を再利用して計算できます。</p>



<p class="wp-block-paragraph">あたかも add_to_base が base 変数を捕捉した状態で使いまわせるため「キャプチャする」という表現が使われています。</p>



<p class="wp-block-paragraph">このように、外側のスコープにある変数を取り込んで使用することができるのがクロージャの本質です。ここまでの例を振り返るとクロージャーは次のような特徴があることが分かります。</p>



<ul class="wp-block-list jinr-list">
<li>関数のように振る舞う</li>



<li><code>fn</code> を使わなくても、その場で定義することができる</li>



<li>外側の変数を利用することができる（キャプチャできる）</li>
</ul>



<p class="wp-block-paragraph">つまり、単なる無名関数というだけではなく、定義された環境設定ごと関数を扱える仕組みであることがクロージャの本当の価値です。</p>



<h3 class="wp-block-heading jinr-heading d--bold">クロージャの型注釈と型推論</h3>



<h4 class="wp-block-heading jinr-heading d--bold">引数の型注釈</h4>



<p class="wp-block-paragraph">クロージャーは型推論がされるため、基本的には型注釈を入れる必要はありません。以下のように型注釈を入れたクロージャも使うことができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 単一の式のクロージャ例 (型注釈あり)
    let subtract = |a: i32, b: i32| a - b;
    println!("subtract(5, 2) = {}", subtract(5, 2));
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
subtract(5, 2) = 3</pre>



<p class="wp-block-paragraph">例のように <code>a: i32, b: i32</code> といった形で型注釈を書くことができます。なお、戻り値については、<code>let subtract = |a: i32, b: i32| -&gt; i32 { a - b };</code> のように書くことも可能ですが、引数の型が決まれば、戻り値の型は式から自動推論できるため、通常は記載しません。</p>



<h4 class="wp-block-heading jinr-heading d--bold">クロージャの型推論</h4>



<p class="wp-block-paragraph">クロージャは型推論をすると記載しましたが、どこで型が確定するかというと「<span class="jinr-d--text-color d--marker1 d--bold">最初にクロージャが使用されたときの型</span>」で確定となります。そのため、先ほどの例で一度 <code>add(2, 3)</code> と使用した<span class="jinr-d--text-color d--marker1">後に</span>以下のように、<code>floating-point</code> で使用しようとするとコンパイルエラーとなります。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">println!("add(1.0, 2.0) = {}", add(1.0, 2.0));</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【エラー例】
error[E0308]: arguments to this function are incorrect
  --> rust-basic\closure-basic\examples\closure_basic.rs:28:36
   |
28 |     println!("add(1.0, 2.0) = {}", add(1.0, 2.0));
   |                                    ^^^ ---  --- expected integer, found floating-point number
   |                                        |
   |                                        expected integer, found floating-point number</pre>



<h2 class="wp-block-heading jinr-heading d--bold">クロージャのキャプチャの方法</h2>



<p class="wp-block-paragraph">ここでは、クロージャのキャプチャについて少し詳しく見てみましょう。キャプチャとは、クロージャが外側のスコープにある変数を取り込んで利用することでした。</p>



<p class="wp-block-paragraph">Rust のクロージャでは、外側の変数をどのように扱うかに応じて、キャプチャ方法をコンパイラが自動で選択します。主なキャプチャの方法には以下の 3 種類です。</p>



<ol class="wp-block-list jinr-list">
<li>不変参照でのキャプチャ</li>



<li>可変参照でのキャプチャ</li>



<li><code>move</code> による所有権の移動でのキャプチャ</li>
</ol>



<h3 class="wp-block-heading jinr-heading d--bold">不変参照でのキャプチャ</h3>



<p class="wp-block-paragraph">外側の変数を「読み取るだけ」であればクロージャは、変数を不変参照でキャプチャします。この場合、外側の変数は所有権を失わないため、クロージャ呼び出し後も引き続き利用できます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 不変参照でのキャプチャ例
    let x = 10;
    // x は不変参照でキャプチャされる
    let f = |y| x + y;

    // クロージャの呼び出し
    println!("f(5) = {}", f(5));
    // xはまだ使用可能
    println!("x = {}", x);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
f(5) = 15
x = 10</pre>



<p class="wp-block-paragraph">例のクロージャでは、<code>x</code> を不変参照しているだけで変更していません。そのため、クロージャを呼び出した後でも <code>x</code> は使用できます。</p>



<h3 class="wp-block-heading jinr-heading d--bold">可変参照でのキャプチャ</h3>



<p class="wp-block-paragraph">クロージャの中で外側の変数を変更する場合、クロージャはその変数を可変参照でキャプチャします。以下は、<code>count</code> 変数をクロージャ内部でカウントアップしているような例です。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== 可変参照でのキャプチャ例
    let mut count = 0;
    println!("count before: {}", count);
    // countは可変参照でキャプチャされる
    let mut g = || count += 1;

    // クロージャを呼び出すとcountが変更される
    g();
    // countは変更されている
    println!("count after: {}", count);
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
count before: 0
count after: 1</pre>



<p class="wp-block-paragraph">可変参照でキャプチャする場合は、外側の変数は <code>let mut</code> により、変更可能（ミュータブル）な変数として定義する必要があります。また、クロージャを変数（上記例では <code>g</code>）に束縛する場合は、<code>g</code> についても <code>let mut</code> で変更可能な形で定義する必要があります。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>move</code> による所有権の移動でのキャプチャ</h3>



<p class="wp-block-paragraph">これまでの例では、外側の変数は参照としてキャプチャされていました。以下のようにクロージャの定義の前に <span class="jinr-d--text-color d--marker1 d--bold"><code>move</code></span> をつけることで、外側の変数は所有権ごとクロージャに移動します。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fn main() {
    // ===== move による所有権の移動でのキャプチャ例
    let s = String::from("Hello");
    // s は move で所有権がクロージャに移動される
    let h = move || println!("{s} World!");

    // 実行時に s は消費されて使用できなくなる
    h();
    // sはmoveで所有権が移動されているため以降は使用できない
    // println!("{s}"); // コンパイルエラー
}
</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Hello World!</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【move 後のコメントアウト部分を外した場合のコンパイルエラー 一部抜粋】
error[E0382]: borrow of moved value: `s`
  --> rust-basic\closure-basic\examples\closure_capture.rs:31:16
   |
24 |     let s = String::from("Hello");
   |         - move occurs because `s` has type `String`, which does not implement the `Copy` trait
25 |     // s は move で所有権がクロージャに移動される
26 |     let h = move || println!("{s} World!");
   |             -------            - variable moved due to use in closure
   |             |
   |             value moved into closure here
...
31 |     println!("{s}"); // コンパイルエラー
   |                ^ value borrowed here after move</pre>



<p class="wp-block-paragraph">例のように、<code>move</code> を付けた時点で変数 <code>s</code> の所有権はクロージャに移動します。そのため、以降外側のスコープでは <code>s</code> は使用できません。使用しようとするとコンパイルエラーとなります。（例でコメントアウトしている部分を外して試してみてください。）</p>



<p class="wp-block-paragraph"><code>move</code> は、外側の値の所有権をクロージャ側に移して、クロージャがその値を保持できるようにしたい場合に使います。（例：スレッドに渡す、関数の外へ変数を持ち出す など）</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">所有権の基本については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-ownership-borrowing-basic/" target="_blank" rel="noreferrer noopener">所有権と借用の基本を分かりやすく解説</a></p>
</div>
		</div></section>



<div id="nkhn3-3777167215" class="nkhn3--2 nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold">クロージャの型とトレイト</h2>



<p class="wp-block-paragraph">クロージャの基本的な使い方を紹介してきました。記事の冒頭で、クロージャは「その場で定義できる無名の関数<span class="jinr-d--text-color d--marker1 d--bold">のようなもの</span>」という少し曖昧な表現をしました。これは、クロージャの型やトレイトをより理解すると、関数とは異なるということが分かるためです。</p>



<p class="wp-block-paragraph">少し詳細な内容になるため、クロージャの型とトレイトについては「<a href="https://rust-tech.nkhn37.net/rust-closure-fn-traits/" target="_blank" rel="noreferrer noopener">クロージャの型とトレイト（Fn / FnMut / FnOnce）</a>」でまとめていますので参考にしてください。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust における<span class="jinr-d--text-color d--marker1 d--bold">クロージャ（Closure）</span>の基本を解説しました。</p>



<p class="wp-block-paragraph">クロージャは 「 <code>|引数1, 引数2, …| 式</code>」の形式で、その場で定義できる無名の関数のような仕組みです。ブロック形式の場合は、最後の式が戻り値になります。また、型注釈は必要に応じて記載できますが、多くの場合は型推論に任せることができます。</p>



<p class="wp-block-paragraph">さらに、クロージャの本質である「キャプチャ」について、不変参照・可変参照・<code>move</code> による所有権移動の 3 パターンを紹介しました。特に <code>move</code> を使うと、外側の値の所有権がクロージャに移動し、以降は外側のスコープでは利用できなくなる点が重要です。</p>



<p class="wp-block-paragraph">クロージャは、その場で処理を定義できる非常に便利な機能で、Rust ではさまざまな場面で利用されます。まずは、基本的な書き方とキャプチャの考え方をしっかり押さえておきましょう。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては <a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-basic/closure-basic" target="_blank" rel="noreferrer noopener">GitHub</a> にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section><div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-closure-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>【Rust】anyhow で複数のエラーをまとめて扱う方法</title>
		<link>https://rust-tech.nkhn37.net/rust-anyhow-basic/</link>
					<comments>https://rust-tech.nkhn37.net/rust-anyhow-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Fri, 06 Feb 2026 20:00:00 +0000</pubDate>
				<category><![CDATA[anyhow]]></category>
		<category><![CDATA[? 演算子]]></category>
		<category><![CDATA[bail!]]></category>
		<category><![CDATA[context]]></category>
		<category><![CDATA[thiserror]]></category>
		<category><![CDATA[エラー処理]]></category>
		<guid isPermaLink="false">https://rust-tech.nkhn37.net/?p=1697</guid>

					<description><![CDATA[Rust で anyhow を用いて複数のエラーをまとめて扱う方法について、初心者にも分かりやすく解説します。 anyhow クレートの概要 anyhow とは Rust のエラー処理では、Result&#60;T, E&#038; [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Rust で <span class="jinr-d--text-color d--marker1 d--bold"><code>anyhow</code> を用いて複数のエラーをまとめて扱う方法</span>について、初心者にも分かりやすく解説します。</p>



<h2 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> クレートの概要</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> とは</h3>



<p class="wp-block-paragraph">Rust のエラー処理では、<code>Result&lt;T, E&gt;</code> 型を使用して「成功（<code>Ok</code>）」か「失敗（<code>Err</code>）」かを表現するのが基本となります。この時、<code>E</code> は、エラーを表す型の型パラメータです。</p>



<p class="wp-block-paragraph">エラーの型は、各種外部のクレートなど様々な機能でも個別に用意されており、扱うエラー型は多岐に渡るため、すべてのエラー型を意識して厳密にエラーに対する処理を実装していくことは、多くの負担がかかってしまいます。</p>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>anyhow</code></span> は、こうした「<span class="jinr-d--text-color d--marker1 d--bold">複数のエラーをまとめて扱いたい</span>」場面で非常に便利なクレートです。<code>anyhow::Error</code> という汎用的なエラー型を用いることで、アプリケーション側のエラー処理を簡潔に表現して扱うことができます。</p>



<h3 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> の特徴（複数のエラーをまとめて扱う）</h3>



<p class="wp-block-paragraph"><code>anyhow</code> を使用する<span class="jinr-d--text-color d--marker1 d--bold">最大のメリットは、エラー型を 1 つに統一できること</span>です。</p>



<p class="wp-block-paragraph">通常、Rust の <code>?</code> 演算子は、エラーが一致 または 変換できる場合（<code>From</code> トレイトによる変換が可能な場合）にしか使用することができません。そのため、複数のエラー型が混ざる処理では、エラー変換を自前で実装したり、独自エラー型にまとめる必要性が出てきます。</p>



<p class="wp-block-paragraph"><code>anyhow</code> を使用すると以下のような書き方ができるようになります。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--simple-box1  "><div class="c--simple-box-inner">
<ul class="wp-block-list jinr-list">
<li>関数の戻り値を <code>anyhow::Result&lt;T&gt;</code> ※にする。</li>



<li>エラー型の種類を意識せずに <code>?</code> で上位の呼び出し元に伝播することができる。</li>
</ul>
</div></div></section>



<p class="wp-block-paragraph">なお、<code>anyhow</code> はエラーを握りつぶすためのものではありません。後ほど説明するようにエラーに追加の文脈情報（コンテキスト）を付与することで、原因調査をしやすくするための仕組みも提供します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【※ <code>anyhow::Result&lt;T&gt;</code> について】</strong></p>



<p class="wp-block-paragraph"><code>anyhow::Result&lt;T&gt;</code> は、<code>Result&lt;T, anyhow::Error&gt;</code> の型エイリアスです。<code>anyhow::Error</code> を毎回書く必要がなく、<code>use</code> で <code>anyhow::Result</code> をスコープに取り込めば、以下のように非常に簡潔に記載ができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::Result;

fn run() -> Result&lt;()> {
    Ok()
}</pre>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> の位置づけ（<code>Result&lt;T, E&gt;</code> や <code>thiserror</code> との関係性）</h3>



<p class="wp-block-paragraph">Rust のエラー処理では、基本的に <code>Result&lt;T, E&gt;</code> 型を利用してエラーを処理します。この <code>E</code> は、エラーのためのジェネリックな型パラメータで、任意の型を使用することができます。</p>



<p class="wp-block-paragraph"><code>anyhow</code> を使用するということは、<code>E</code> に <code>anyhow::Error</code> を採用する設計を意味します。とにかくエラー型を統一して扱いたい場合には、<code>anyhow</code> は非常に向いています。</p>



<p class="wp-block-paragraph">一方で、<code>thiserror</code> という独自エラー型を設計するクレートも非常によく使用されます。これは、自身で <code>MyError</code> 型を定義し、<code>Result&lt;T, MyError&gt;</code> のようにエラーの種類を明確に表現したい場合に向いています。クレートの位置づけを整理すると以下の通りです。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--simple-box1  "><div class="c--simple-box-inner">
<ul class="wp-block-list jinr-list">
<li><code>thiserror</code>：独自のエラー型を簡単に定義する。</li>



<li><code>anyhow</code>：様々なエラー型をまとめて取り扱うことができる。</li>
</ul>
</div></div></section>



<p class="wp-block-paragraph">一般的には、ライブラリ側では&nbsp;<code>thiserror</code>、アプリケーション側では&nbsp;<code>anyhow</code>&nbsp;が使われることが多いです。ライブラリが用意している独自エラー型を、アプリケーション側が受け取った際には <code>anyhow::Error</code> に変換・統一して扱うという構成です。もちろん、独自エラーの情報を消してしまうわけではなく、元の独自エラーの情報を保持しつつ、<code>anyhow::Error</code> に統一します。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">エラー処理の基本や <code>thiserror</code> については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-error-handling-basic/" target="_blank" rel="noreferrer noopener">エラー処理の基本を分かりやすく解説</a></p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-thiserror-error-types/" target="_blank" rel="noreferrer noopener">thiserrorにより独自のエラー型を実装する方法</a></p>
</div>
		</div></section>



<div id="nkhn3-973853240" class="nkhn3- nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="4670569211"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div><h2 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> の基本</h2>



<h3 class="wp-block-heading jinr-heading d--bold"><code>anyhow</code> の導入方法</h3>



<p class="wp-block-paragraph"><code>anyhow</code> は、他クレートと同様に <code>cargo add</code> または <code>Cargo.toml</code> に追記することで利用できるようになります。</p>



<p class="wp-block-paragraph"><strong>【<code>cargo add</code> で追加する場合】</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cargo add anyhow</pre>



<p class="wp-block-paragraph"><strong>【<code>Cargo.toml</code> に追記する場合】</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[dependencies]
anyhow = "1.0.101"</pre>



<p class="wp-block-paragraph">例での記載バージョンは、記事執筆・更新時点での最新バージョンで記載しているため、導入時には crates.io の <a href="https://crates.io/crates/anyhow" target="_blank" rel="noreferrer noopener"><code>anyhow</code> のページ</a>を確認して指定してください。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph">クレートや依存関係の基本については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-crates-basics/" target="_blank" rel="noreferrer noopener">クレート（バイナリ／ライブラリ）と依存関係の管理を分かりやすく解説</a></p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>?</code> で複数のエラーをまとめて扱う基本的な使い方</h3>



<p class="wp-block-paragraph"><code>anyhow</code> を利用する最も大きなメリットの 1 つは、ライブラリなどの複数のエラーをまとめて扱うことができることです。代表的な使い方として <code>?</code> 演算子により、<code>From</code> トレイトによる変換を通じて、外部エラーを <code>anyhow::Error</code> に変換して扱う方法を紹介します。</p>



<p class="wp-block-paragraph">以下は、<code>input_file.txt</code> を読み込む際に、ファイルが存在しない場面と思ってください。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::Result;
use std::fs;

fn main() -> Result&lt;()> {
    let path = "input_file.txt";

    // エラーを anyhow::Error に変換して返す
    let content = fs::read_to_string(path)?;

    println!("{content}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Error: 指定されたファイルが見つかりません。 (os error 2)
error: process didn't exit successfully: `D:\RustProject\rust-tech-sample-source\target\debug\examples\anyhow_basic.exe` (exit code: 1)  </pre>



<p class="wp-block-paragraph">例では、<code>fs::read_to_string</code> によって <code>std::io::Error</code> が発生しています。通常であれば、このエラー型にあわせて処理を実装する必要があります。</p>



<p class="wp-block-paragraph">しかし、<code>main</code> 関数の戻り値は <code>anyhow::Result&lt;()&gt;</code>（= <code>Result&lt;(), anyhow::Error&gt;</code>）としているため、自動的に <code>anyhow::Error</code> に変換され、? 演算子により上位へ返却されます。このように、エラー型を意識せずに <code>?</code> を使えることが、<code>anyhow</code> を使用する大きなメリットです。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox5 ">
			<i class="jif jin-ifont-v2speaker" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><strong>【<code>anyhow::Error</code> に自動変換できる条件】</strong></p>



<p class="wp-block-paragraph"><code>?</code> 演算子によって自動的に <code>anyhow::Error</code> に変換して伝播できるかどうかは、返却されるエラー型により決まります。自動変換のためには、呼び出し先のエラーは以下を満たす必要があります。</p>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--simple-box1  "><div class="c--simple-box-inner">
<ul class="wp-block-list jinr-list">
<li><code>std::error::Error</code> を実装している</li>



<li><code>Send + Sync + 'static</code> のトレイト境界を満たす</li>
</ul>
</div></div></section>



<p class="wp-block-paragraph">標準ライブラリのエラー型は、多くの場合で上記制約を満たすのであまり意識する必要なく使えることがほとんどです。</p>



<p class="wp-block-paragraph">また、 <code>thiserror</code> により作成した独自エラー型も <code>String</code> のような所有型・スレッドセーフな型で構成していれば、通常は自然に制約を満たします。ただし <code>&amp;str</code> などの参照含む場合などでは条件を満たせない場合があります。</p>
</div>
		</div></section>



<h3 class="wp-block-heading jinr-heading d--bold"><code>context</code> / <code>with_context</code> で文脈情報（コンテキスト）を追加する</h3>



<p class="wp-block-paragraph">? を使用したエラー伝播は非常に簡潔で便利ですが、そのままではどの処理で失敗したのかが分かりづらくなってしまう場合があります。このような場合に便利なのが、<code>Context</code> トレイトが提供する <span class="jinr-d--text-color d--marker1 d--bold"><code>context</code></span> および <span class="jinr-d--text-color d--marker1 d--bold"><code>with_context</code></span> です。</p>



<p class="wp-block-paragraph">これらを使うことで、エラー発生時に追加の文脈情報（コンテキスト）を付与することができ、原因調査をしやすくなります。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>context</code> で固定のメッセージを追加する</h4>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>context</code></span> を使用することで以下のように固定のメッセージを追加することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::{Context, Result};
use std::fs;

fn main() -> Result&lt;()> {
    let path = "input_file.txt";

    // コンテキスト情報を追加してエラーを返す
    let content =
        fs::read_to_string(path).context("[main] テキストファイルの読み込みに失敗しました。")?;

    println!("{content}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Error: [main] テキストファイルの読み込みに失敗しました。

Caused by:
    指定されたファイルが見つかりません。 (os error 2)
error: process didn't exit successfully: `D:\RustProject\rust-tech-sample-source\target\debug\examples\anyhow_context.exe` (exit code: 1)</pre>



<p class="wp-block-paragraph">例のように <code>context</code> を使用すると、元のエラーに対して固定のメッセージを追加することができます。実行結果を見ると、最初に追加したメッセージが表示されており、その下の「Caused by:」以下に元のエラーが保持されていることが分かります。</p>



<p class="wp-block-paragraph">このように、<code>anyhow</code> は元のエラー情報を失うことなく、追加の文脈情報（コンテキスト）を積み重ねて保持することができます。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>with_context</code> で動的にメッセージを生成して追加する</h4>



<p class="wp-block-paragraph"><code>context</code> は固定メッセージを追加する方法でしたが、<span class="jinr-d--text-color d--marker1 d--bold"><code>with_context</code></span> を使用すると、以下のように動的にメッセージを生成して追加することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::{Context, Result};
use std::fs;

fn main() -> Result&lt;()> {
    let path = "input_file.txt";

    // クロージャーを使って動的にコンテキスト情報を追加してエラーを返す
    let content = fs::read_to_string(path)
        .with_context(|| format!("[main] テキストファイルの読み込みに失敗しました。path={path}"))?;

    println!("{content}");

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Error: [main] テキストファイルの読み込みに失敗しました。path=input_file.txt

Caused by:
    指定されたファイルが見つかりません。 (os error 2)
error: process didn't exit successfully: `D:\RustProject\rust-tech-sample-source\target\debug\examples\anyhow_with_context.exe` (exit code: 1)</pre>



<p class="wp-block-paragraph"><code>with_context</code> は、クロージャーを受け取り、エラーが発生した場合にのみ処理を実行します。そのため、例のように <code>format!</code> マクロを使って変数を埋め込んだ動的なメッセージを生成したい場合などに向いています。</p>



<p class="wp-block-paragraph"><code>context</code> と <code>with_context</code> は似ていますが、使い分けは以下のように整理できます。</p>



<ul class="wp-block-list jinr-list">
<li><code>context</code>：固定のメッセージを追加したい場合</li>



<li><code>with_context</code>：エラー発生時に処理を行い、動的なメッセージを生成したい場合</li>
</ul>



<h3 class="wp-block-heading jinr-heading d--bold"><code>anyhow!</code> / <code>bail!</code> マクロで自分でエラーを作る</h3>



<p class="wp-block-paragraph">これまでは、下位の処理が返却するエラーを ? 演算子で伝播する例を見てきました。一方で、アプリケーション側の条件チェックなどにより自分でエラーを生成したい場合もよくあります。</p>



<p class="wp-block-paragraph">このような場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>anyhow!</code></span> マクロや <span class="jinr-d--text-color d--marker1 d--bold"><code>bail!</code></span> マクロの使用が便利です。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>anyhow!</code> マクロで <code>anyhow::Error</code> を生成する</h4>



<p class="wp-block-paragraph"><span class="jinr-d--text-color d--marker1 d--bold"><code>anyhow!</code></span> マクロを使用することで以下のように <code>anyhow::Error</code> を生成することができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::{Result, anyhow};

fn main() -> Result&lt;()> {
    let path = "";

    if path.is_empty() {
        // エラーを生成する
        let err = anyhow!("[main] パスが空です。");

        // エラーを返却する
        return Err(err);
    }

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Error: [main] パスが空です。
error: process didn't exit successfully: `D:\RustProject\rust-tech-sample-source\target\debug\examples\anyhow_anyhow_macro.exe` (exit code: 1)</pre>



<p class="wp-block-paragraph">例のように、<code>anyhow!</code> マクロにより <code>anyhow::Error</code> 型の値を生成することができ、変数に代入して扱うことができます。これにより、ログ出力などの追加の処理をしてから「<code>return Err(err)</code>」のように返却するといったことが可能になります。</p>



<h4 class="wp-block-heading jinr-heading d--bold"><code>bail!</code> マクロで <code>anyhow::Error</code> を生成し、即時返却する</h4>



<p class="wp-block-paragraph"><code>anyhow!</code> マクロでは一度変数に代入して扱いましたが、場合によってはエラー発生時に即時に <code>return</code> すればいい場合があります。このような場合には、<span class="jinr-d--text-color d--marker1 d--bold"><code>bail!</code></span> マクロを使用することでコードがより簡潔に書くことができます。</p>



<pre class="EnlighterJSRAW" data-enlighter-language="rust" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">use anyhow::{Result, bail};

fn main() -> Result&lt;()> {
    let path = "";

    if path.is_empty() {
        // エラーを生成して、即時に返却する
        bail!("[main] パスが空です。");
    }

    Ok(())
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="false" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">【実行結果】
Error: [main] パスが空です。
error: process didn't exit successfully: `D:\RustProject\rust-tech-sample-source\target\debug\examples\anyhow_bail_macro.exe` (exit code: 1)</pre>



<p class="wp-block-paragraph">例のように <code>bail!</code> マクロは <code>anyhow::Error</code> を生成し、その場で <code>Err</code> を返却しています。そのため、<code>return</code> の記載も必要なくなり非常に簡潔にコードを各ことができます。</p>



<h2 class="wp-block-heading jinr-heading d--bold">まとめ</h2>



<p class="wp-block-paragraph">Rust で <span class="jinr-d--text-color d--marker1 d--bold"><code>anyhow</code> を用いて複数のエラーをまとめて扱う方法</span>について解説しました。</p>



<p class="wp-block-paragraph"><code>anyhow</code> を使用することでアプリケーション側ではエラー型を 1 つに統一し、<code>?</code> 演算子によるエラー伝播を簡潔に記述できます。</p>



<p class="wp-block-paragraph">また、<code>context</code> / <code>with_context</code> を使用することでエラーに追加の文脈情報（コンテキスト）を追加することで原因調査もしやすくなります。さらに、<code>anyhow!</code> や <code>bail!</code> といったマクロを使うことで、自分でエラー生成をして扱うことも簡単です。</p>



<p class="wp-block-paragraph"><code>anyhow</code> は、エラー型を厳密にするためのクレートではなく、アプリケーション側でのエラー運用をしやすくしてくれるクレートです。ライブラリ側では、<code>thiserror</code> による独自エラー型を設計し、アプリケーション側では <code>anyhow</code> を使って統一的にエラーを扱うという使い分けをすると非常に効率的に開発を進められると思います。</p>



<p class="wp-block-paragraph">ぜひ、<code>anyhow</code> の使い方の基本をしっかりと覚えてもらえたらと思います。</p>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>anyhow</code> のドキュメントは<a href="https://docs.rs/anyhow/latest/anyhow/" target="_blank" rel="noreferrer noopener">こちら</a>を参考にしてください。</p>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-iconbox b--jinr-block b--jinr-iconbox"><div class="d--simple-iconbox6 ">
			<i class="jif jin-ifont-v2books" aria-hidden="true"></i>
			<div class="a--jinr-iconbox">
<p class="wp-block-paragraph"><code>thiserror</code> については以下を参考にしてください。</p>



<p class="wp-block-paragraph"><a href="https://rust-tech.nkhn37.net/rust-thiserror-error-types/" target="_blank" rel="noreferrer noopener">thiserrorにより独自のエラー型を実装する方法</a></p>
</div>
		</div></section>



<section class="wp-block-jinr-blocks-simplebox b--jinr-block-container"><div class="b--jinr-block b--jinr-box d--heading-box8  "><div class="a--simple-box-title d--bold">ソースコード</div><div class="c--simple-box-inner">
<p class="wp-block-paragraph">上記で紹介しているソースコードについては <a href="https://github.com/nkhn37/rust-tech-sample-source/tree/main/rust-libraries/anyhow-basic" target="_blank" rel="noreferrer noopener">GitHub</a> にて公開しています。参考にしていただければと思います。</p>
</div></div></section>


<section class="b--jinr-block b--jinr-blogcard d--blogcard-hover-up d--blogcard-style1 d--blogcard-mysite t--round "><div class="a--blogcard-label ef">あわせて読みたい</div><a class="o--blogcard-link t--round" href="https://rust-tech.nkhn37.net/rust-programming-basics/"><div class="c--blogcard-image"><img decoding="async" class="a--blogcard-img-src" width="128" height="72" src="https://rust-tech.nkhn37.net/wp-content/uploads/2025/08/77e7c51961993fb9cb96c02a2311436d-320x180.jpg" alt="Rust プログラミング入門" /></div><div class="a--blogcard-title d--bold">Rust プログラミング入門</div></a></section><div id="nkhn3-2767822496" class="nkhn3-multiplex nkhn3-entity-placement" style="margin-left: auto;margin-right: auto;text-align: center;"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9478001176347002"
     crossorigin="anonymous"></script>
<ins class="adsbygoogle"
     style="display:block"
     data-ad-format="autorelaxed"
     data-ad-client="ca-pub-9478001176347002"
     data-ad-slot="8958649655"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script></div>]]></content:encoded>
					
					<wfw:commentRss>https://rust-tech.nkhn37.net/rust-anyhow-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Disk: Enhanced  を使用したページ キャッシュ

Served from: rust-tech.nkhn37.net @ 2026-07-18 06:07:26 by W3 Total Cache
-->