Développement Rust avec Claude Code
Découvrez développement Rust avec Claude Code. Conseils pratiques et exemples de code inclus.
Rust開発でClaude Codeが活躍する場面
Rustは所有権、ライフタイム、トレイトなど独自の概念が多く、学習コストの高い言語です。Claude Codeはこれらの概念を正確に理解し、コンパイルが通るコードを高い精度で生成できます。特にエラーハンドリングや非同期処理の定型パターンで威力を発揮します。
CLIツールの開発
> clapを使ったCLIツールを作成して。
> JSONファイルを読み込んでCSVに変換する機能で。
> プログレスバーとエラーハンドリングも実装して。
// src/main.rs
use clap::Parser;
use anyhow::{Context, Result};
use indicatif::{ProgressBar, ProgressStyle};
use serde_json::Value;
use std::fs;
use std::io::Write;
#[derive(Parser, Debug)]
#[command(name = "json2csv", about = "Convert JSON to CSV")]
struct Args {
/// Input JSON file path
#[arg(short, long)]
input: String,
/// Output CSV file path
#[arg(short, long)]
output: String,
/// Fields to extract (comma-separated)
#[arg(short, long)]
fields: Option<String>,
}
fn main() -> Result<()> {
let args = Args::parse();
let content = fs::read_to_string(&args.input)
.context(format!("Failed to read file: {}", args.input))?;
let data: Vec<Value> = serde_json::from_str(&content)
.context("Failed to parse JSON")?;
if data.is_empty() {
println!("No data found in the JSON file.");
return Ok(());
}
// フィールドの決定
let fields: Vec<String> = match &args.fields {
Some(f) => f.split(',').map(|s| s.trim().to_string()).collect(),
None => {
if let Some(obj) = data[0].as_object() {
obj.keys().cloned().collect()
} else {
anyhow::bail!("JSON array elements must be objects");
}
}
};
let pb = ProgressBar::new(data.len() as u64);
pb.set_style(
ProgressStyle::with_template(
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})"
)?
.progress_chars("=>-"),
);
let mut output = fs::File::create(&args.output)
.context(format!("Failed to create output file: {}", args.output))?;
// Header
writeln!(output, "{}", fields.join(","))?;
// データ行
for item in &data {
let row: Vec<String> = fields.iter().map(|field| {
match item.get(field) {
Some(Value::String(s)) => format!("\"{}\"", s.replace('"', "\"\"")),
Some(v) => v.to_string(),
None => String::new(),
}
}).collect();
writeln!(output, "{}", row.join(","))?;
pb.inc(1);
}
pb.finish_with_message("Done");
println!("Converted {} records to {}", data.len(), args.output);
Ok(())
}
# Cargo.toml
[package]
name = "json2csv"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4", features = ["derive"] }
serde_json = "1"
anyhow = "1"
indicatif = "0.17"
Web APIの開発(Axum)
> Axumを使ったREST APIを作成して。
> CRUD操作、バリデーション、エラーハンドリングを実装して。
// src/main.rs
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
routing::{get, post, put, delete},
Json, Router,
};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
struct Task {
id: Uuid,
title: String,
description: Option<String>,
completed: bool,
created_at: chrono::NaiveDateTime,
}
#[derive(Debug, Deserialize)]
struct CreateTask {
title: String,
description: Option<String>,
}
#[derive(Debug, Deserialize)]
struct UpdateTask {
title: Option<String>,
description: Option<String>,
completed: Option<bool>,
}
#[derive(Clone)]
struct AppState {
db: PgPool,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let db = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
sqlx::migrate!().run(&db).await?;
let state = AppState { db };
let app = Router::new()
.route("/api/tasks", get(list_tasks).post(create_task))
.route("/api/tasks/:id", get(get_task).put(update_task).delete(delete_task))
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
println!("Server running on http://localhost:3000");
axum::serve(listener, app).await?;
Ok(())
}
async fn list_tasks(State(state): State<AppState>) -> impl IntoResponse {
let tasks = sqlx::query_as::<_, Task>("SELECT * FROM tasks ORDER BY created_at DESC")
.fetch_all(&state.db)
.await;
match tasks {
Ok(tasks) => Json(tasks).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
async fn create_task(
State(state): State<AppState>,
Json(input): Json<CreateTask>,
) -> impl IntoResponse {
if input.title.trim().is_empty() {
return (StatusCode::BAD_REQUEST, "Title is required").into_response();
}
let task = sqlx::query_as::<_, Task>(
"INSERT INTO tasks (id, title, description) VALUES ($1, $2, $3) RETURNING *"
)
.bind(Uuid::new_v4())
.bind(&input.title)
.bind(&input.description)
.fetch_one(&state.db)
.await;
match task {
Ok(task) => (StatusCode::CREATED, Json(task)).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
async fn get_task(
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> impl IntoResponse {
let task = sqlx::query_as::<_, Task>("SELECT * FROM tasks WHERE id = $1")
.bind(id)
.fetch_optional(&state.db)
.await;
match task {
Ok(Some(task)) => Json(task).into_response(),
Ok(None) => StatusCode::NOT_FOUND.into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
async fn update_task(
State(state): State<AppState>,
Path(id): Path<Uuid>,
Json(input): Json<UpdateTask>,
) -> impl IntoResponse {
let task = sqlx::query_as::<_, Task>(
"UPDATE tasks SET title = COALESCE($2, title), description = COALESCE($3, description), completed = COALESCE($4, completed) WHERE id = $1 RETURNING *"
)
.bind(id)
.bind(&input.title)
.bind(&input.description)
.bind(input.completed)
.fetch_optional(&state.db)
.await;
match task {
Ok(Some(task)) => Json(task).into_response(),
Ok(None) => StatusCode::NOT_FOUND.into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
async fn delete_task(
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> impl IntoResponse {
let result = sqlx::query("DELETE FROM tasks WHERE id = $1")
.bind(id)
.execute(&state.db)
.await;
match result {
Ok(r) if r.rows_affected() > 0 => StatusCode::NO_CONTENT.into_response(),
Ok(_) => StatusCode::NOT_FOUND.into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(),
}
}
エラーハンドリングのパターン
Claude Codeに依頼する際、Rustらしいエラーハンドリングを指示できます。
> カスタムエラー型をthiserrorで定義して。
> APIレスポンスへの変換も実装して。
use axum::{http::StatusCode, response::IntoResponse, Json};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Not found: {0}")]
NotFound(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Database error: {0}")]
Database(#[from] sqlx::Error),
#[error("Internal error: {0}")]
Internal(#[from] anyhow::Error),
}
impl IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
let (status, message) = match &self {
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
AppError::Database(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Database error".into()),
AppError::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal error".into()),
};
(status, Json(serde_json::json!({ "error": message }))).into_response()
}
}
Summary
Claude Codeを使えば、Rustの所有権やライフタイムを正しく扱ったコードを効率的に生成できます。CLIツール、Web API、エラーハンドリングなど、Rust特有のパターンに精通しているため、コンパイルエラーとの戦いを大幅に減らせます。他の言語との比較はClaude Code vs GitHub Copilotを参照してください。効率的な使い方は生産性を3倍にするTipsで紹介しています。
Claude Codeの詳細はAnthropic公式ドキュメントをご覧ください。Rustの学習にはThe Rust Programming Languageが最適です。
PDF gratuit : aide-mémoire Claude Code en 5 minutes
Laissez simplement votre e-mail et nous vous enverrons immédiatement l'aide-mémoire A4 en PDF.
Nous traitons vos données avec soin et n'envoyons jamais de spam.
À propos de l'auteur
Masa
Ingénieur passionné par Claude Code. Il gère claudecode-lab.com, un média tech en 10 langues avec plus de 2 000 pages.
Articles similaires
7 vérifications avant de publier chaque jour un article multilingue sur Claude Code
Une checklist pratique pour publier des articles multilingues sur Claude Code chaque jour sans oublier une langue, casser les CTA ou laisser l’ancien contenu en production.
Codex Automations : confier l'analyse, les articles et le deploiement a l'IA
Guide pratique pour utiliser Codex Automations dans une operation de contenu orientee monetisation.
Claude Code × GCP Cloud Functions Guide Complet | Développement Serverless Ultra-Rapide
Optimisez GCP Cloud Functions avec Claude Code. Implémentez des triggers HTTP/Pub/Sub/Firestore, des tests locaux et l'automatisation des déploiements avec des exemples de code réels de l'expérience de Masa.