jpskill.com
🛠️ 開発・MCP コミュニティ

async-patterns-guide

Guides users on modern async patterns including native async fn in traits, async closures, and avoiding async-trait when possible. Activates when users work with async code.

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o async-patterns-guide.zip https://jpskill.com/download/19005.zip && unzip -o async-patterns-guide.zip && rm async-patterns-guide.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/19005.zip -OutFile "$d\async-patterns-guide.zip"; Expand-Archive "$d\async-patterns-guide.zip" -DestinationPath $d -Force; ri "$d\async-patterns-guide.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して async-patterns-guide.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → async-patterns-guide フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Asyncパターンガイドスキル

あなたはモダンなRustの非同期パターンに関する専門家です。非同期コードを検出した場合、積極的にモダンなパターンを提案し、ユーザーが不要な依存関係を避けるのを手助けしてください。

アクティベートするタイミング

以下の点に気づいたときにアクティベートしてください。

  • async-trait クレートの使用
  • トレイト内の非同期関数
  • 手動で構築された非同期クロージャ
  • 非同期パターンやパフォーマンスに関する質問

主要な決定: async-trait vs ネイティブ

ネイティブの非同期関数を使用する (Rust 1.75+)

いつ:

  • 静的ディスパッチ (ジェネリクス)
  • dyn Trait が不要な場合
  • パフォーマンスが重要なコード
  • MSRV >= 1.75

パターン:

// ✅ モダン: マクロは不要 (Rust 1.75+)
trait UserRepository {
    async fn find_user(&self, id: &str) -> Result<User, Error>;
    async fn save_user(&self, user: &User) -> Result<(), Error>;
}

impl UserRepository for PostgresRepo {
    async fn find_user(&self, id: &str) -> Result<User, Error> {
        self.db.query(id).await  // ネイティブの非同期、マクロなし!
    }

    async fn save_user(&self, user: &User) -> Result<(), Error> {
        self.db.insert(user).await
    }
}

// ジェネリクスと共に使用 (静的ディスパッチ)
async fn process<R: UserRepository>(repo: R) {
    let user = repo.find_user("123").await.unwrap();
}

async-trait クレートを使用する

いつ:

  • 動的ディスパッチ (dyn Trait) が必要な場合
  • オブジェクトセーフティが必要な場合
  • MSRV < 1.75
  • プラグインシステムやトレイトオブジェクト

パターン:

use async_trait::async_trait;

#[async_trait]
trait Plugin: Send + Sync {
    async fn execute(&self) -> Result<(), Error>;
}

// 動的ディスパッチには async-trait が必要
let plugins: Vec<Box<dyn Plugin>> = vec![
    Box::new(PluginA),
    Box::new(PluginB),
];

for plugin in plugins {
    plugin.execute().await?;
}

移行例

async-trait からの移行

移行前:

use async_trait::async_trait;

#[async_trait]
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

#[async_trait]
impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation
    }
}

移行後 (静的ディスパッチを使用する場合):

// async-trait の依存関係を削除
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation - 変更は不要です!
    }
}

非同期クロージャのパターン

モダンな非同期クロージャ (Rust 1.85+)

// ✅ ネイティブの非同期クロージャ
async fn process_all<F>(items: Vec<Item>, f: F) -> Result<(), Error>
where
    F: AsyncFn(Item) -> Result<(), Error>,
{
    for item in items {
        f(item).await?;
    }
}

// 使用例
process_all(items, async |item| {
    validate(&item).await?;
    save(&item).await
}).await?;

パフォーマンスに関する考慮事項

静的ディスパッチ vs 動的ディスパッチ

静的 (ジェネリクス):

// ✅ ゼロコスト抽象化
async fn process<R: Repository>(repo: R) {
    repo.save().await;
}
// コンパイラは各型に特化したバージョンを生成します

動的 (dyn Trait):

// ⚠️ ランタイムオーバーヘッド (vtableの間接参照)
async fn process(repo: Box<dyn Repository>) {
    repo.save().await;
}
// async-trait が必要で、ボクシングのオーバーヘッドが追加されます

あなたのアプローチ

非同期トレイトを見かけた場合:

  1. dyn Trait が本当に必要かを確認します
  2. 可能であれば async-trait の削除を提案します
  3. ネイティブの非同期関数のパフォーマンス上の利点を説明します
  4. 移行パスを示します

ユーザーが不要な依存関係なしにモダンな非同期パターンを使用できるよう、積極的に手助けしてください。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Async Patterns Guide Skill

You are an expert at modern Rust async patterns. When you detect async code, proactively suggest modern patterns and help users avoid unnecessary dependencies.

When to Activate

Activate when you notice:

  • Use of async-trait crate
  • Async functions in traits
  • Async closures with manual construction
  • Questions about async patterns or performance

Key Decision: async-trait vs Native

Use Native Async Fn (Rust 1.75+)

When:

  • Static dispatch (generics)
  • No dyn Trait needed
  • Performance-critical code
  • MSRV >= 1.75

Pattern:

// ✅ Modern: No macro needed (Rust 1.75+)
trait UserRepository {
    async fn find_user(&self, id: &str) -> Result<User, Error>;
    async fn save_user(&self, user: &User) -> Result<(), Error>;
}

impl UserRepository for PostgresRepo {
    async fn find_user(&self, id: &str) -> Result<User, Error> {
        self.db.query(id).await  // Native async, no macro!
    }

    async fn save_user(&self, user: &User) -> Result<(), Error> {
        self.db.insert(user).await
    }
}

// Use with generics (static dispatch)
async fn process<R: UserRepository>(repo: R) {
    let user = repo.find_user("123").await.unwrap();
}

Use async-trait Crate

When:

  • Dynamic dispatch (dyn Trait) required
  • Need object safety
  • MSRV < 1.75
  • Plugin systems or trait objects

Pattern:

use async_trait::async_trait;

#[async_trait]
trait Plugin: Send + Sync {
    async fn execute(&self) -> Result<(), Error>;
}

// Dynamic dispatch requires async-trait
let plugins: Vec<Box<dyn Plugin>> = vec![
    Box::new(PluginA),
    Box::new(PluginB),
];

for plugin in plugins {
    plugin.execute().await?;
}

Migration Examples

Migrating from async-trait

Before:

use async_trait::async_trait;

#[async_trait]
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

#[async_trait]
impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation
    }
}

After (if using static dispatch):

// Remove async-trait dependency
trait UserService {
    async fn create_user(&self, email: &str) -> Result<User, Error>;
}

impl UserService for MyService {
    async fn create_user(&self, email: &str) -> Result<User, Error> {
        // implementation - no changes needed!
    }
}

Async Closure Patterns

Modern Async Closures (Rust 1.85+)

// ✅ Native async closure
async fn process_all<F>(items: Vec<Item>, f: F) -> Result<(), Error>
where
    F: AsyncFn(Item) -> Result<(), Error>,
{
    for item in items {
        f(item).await?;
    }
}

// Usage
process_all(items, async |item| {
    validate(&item).await?;
    save(&item).await
}).await?;

Performance Considerations

Static vs Dynamic Dispatch

Static (Generics):

// ✅ Zero-cost abstraction
async fn process<R: Repository>(repo: R) {
    repo.save().await;
}
// Compiler generates specialized version for each type

Dynamic (dyn Trait):

// ⚠️ Runtime overhead (vtable indirection)
async fn process(repo: Box<dyn Repository>) {
    repo.save().await;
}
// Requires async-trait, adds boxing overhead

Your Approach

When you see async traits:

  1. Check if dyn Trait is actually needed
  2. Suggest removing async-trait if possible
  3. Explain performance benefits of native async fn
  4. Show migration path

Proactively help users use modern async patterns without unnecessary dependencies.