golang-graphql
gqlgen または graphql-go を使用して Golang で GraphQL API を実装します。GraphQL サーバーの構築、スキーマ設計、リゾルバーの作成、サブスクリプションの処理、または既存の Go HTTP サービスへの GraphQL 統合時に適用されます。コードベースが `github.com/99designs/gqlgen` や `github.com/graph-gophers/graphql-go` をインポートしている場合にも適用されます。
description の原文を見る
Implements GraphQL APIs in Golang using gqlgen or graphql-go. Apply when building GraphQL servers, designing schemas, writing resolvers, handling subscriptions, or integrating GraphQL with existing Go HTTP services. Also apply when the codebase imports `github.com/99designs/gqlgen` or `github.com/graph-gophers/graphql-go`.
SKILL.md 本文
ペルソナ: あなたは Go GraphQL エンジニアです。スキーマを意図的に設計し、N+1 を防ぐためにデータベースアクセスをバッチ処理し、クエリ複雑性制限を本番環境では必須として扱います。
モード:
- ビルドモード — 新しいスキーマ、リゾルバ、またはサーバーセットアップを生成する場合: スキルの逐次的な指示に従います。既存のリゾルバパターンと命名規則を grep で検索するためにバックグラウンドエージェントを起動してから新しいコードを生成してください。
- レビューモード — GraphQL コードベースまたはプルリクエストを監査する場合: サブエージェントを使用して N+1 リゾルバパターン、欠落している複雑性制限、グローバル DataLoader、本番環境での introspection を並列にスキャンしながらビジネスロジックを読み込みます。
コミュニティデフォルト。
samber/cc-skills-golang@golang-graphqlスキルを明示的に置き換える企業スキルが優先されます。
Go GraphQL ベストプラクティス
両方の主要なライブラリはスキーマファーストです: SDL (.graphql ファイル) を書き、Go リゾルバをバインドします。プロジェクトサイズとチームの好みに基づいて選択します。
このスキルは網羅的ではありません。最新の API シグネチャについては、各ライブラリの公式ドキュメントとコード例を参照してください。Context7 は検出プラットフォームとして役立ちます。
ライブラリの選択
| ライブラリ | アプローチ | 型安全性 | ビルドステップ | 最適用途 |
|---|---|---|---|---|
github.com/99designs/gqlgen | コード生成 | コンパイル時 | go generate | 大規模スキーマ、Federation、厳密な型 |
github.com/graph-gophers/graphql-go | リフレクション | パース時 | なし | 小〜中規模スキーマ、高速反復 |
github.com/graphql-go/graphql | コードファースト | ランタイム | なし | 回避 — 冗長、SDL なし |
gqlgen を選ぶ場合: Apollo Federation が必須、スキーマが大規模 (100+ 型)、またはチームが生成されたスタブとゼロリフレクションオーバーヘッドを希望する場合。
graph-gophers を選ぶ場合: スキーマが小〜中規模、ビルドパイプラインはシンプルにすべき、または動的スキーマが必要な場合。
各ライブラリの詳細については、gqlgen リファレンス および graphql-go リファレンス を参照してください。
スキーマ設計
# ✓ Good — 明示的な null 許容性; 不透明な識別子の ID スカラー
type User {
id: ID!
email: String! # non-null: サーバーは常にこれを返すことができます
bio: String # nullable: 未設定の場合があります
posts(first: Int = 10, after: String): PostConnection!
}
# ✗ Bad — Int ID は実装詳細をリーク、クライアントキャッシングが壊れます
type Post {
id: Int!
}
Null 許容性ルール: サーバーが 常に 値を返せる場合のみ、フィールドを ! でマークします。非 null フィールドのリゾルバエラーは親オブジェクトを null にし、カスケード障害を引き起こします。null 許容フィールドはフィールド自体のみ null にします。
ページネーション: リストフィールドには Relay カーソル接続 (Connection/Edge/PageInfo) を使用します。大規模データセットではオフセットページネーションを回避します — カーソルは同時実行書き込みの下で安定しています。
ミューテーション: 結果をエンベロープタイプでラップして、クライアントが GraphQL errors 配列を汚染せずにビジネスエラーと部分的な結果を受け取るようにします:
type CreateUserPayload {
user: User
errors: [UserError!]!
}
リゾルバパターン
リゾルバは薄く保ちます — GraphQL 入力をドメイン呼び出しに変換し、ドメイン応答を GraphQL 出力に変換します。
// ✓ Good — リゾルバはサービスレイヤーにデリゲート
func (r *mutationResolver) CreateUser(ctx context.Context, input model.CreateUserInput) (*model.CreateUserPayload, error) {
user, err := r.userService.Create(ctx, input.Email, input.Name)
if err != nil {
return nil, formatError(err)
}
return &model.CreateUserPayload{User: toGQLUser(user)}, nil
}
// ✗ Bad — リゾルバに SQL が含まれる、関心の分離がない
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
row := r.db.QueryRowContext(ctx, "SELECT * FROM users WHERE id = $1", id)
// ...
}
すべてのフィールドに対する 1 つのモノリシックリゾルバではなく、型ごとのリゾルバストラクト (userResolver, postResolver) を使用します。
N+1 防止 (DataLoader)
各 User.posts リゾルバはユーザーごと 1 つの SQL クエリを実行します — バッチ処理なしで n ユーザーに対して O(n) DB 呼び出し。DataLoader は、フィールドごとのロードを 1 つのバッチクエリに統合することでこれを解決します。
重要なルール: DataLoader は HTTP ミドルウェア内でリクエストごとに作成する必要があります。グローバルに作成してはいけません。 グローバル DataLoader はリクエスト間でキャッシュします — 古いデータ、潜在的なクロスユーザーデータリーク。
// ✓ Good — ミドルウェアのリクエストごとの DataLoader
func DataLoaderMiddleware(db *sql.DB, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
loaders := &Loaders{
PostsByUserID: newPostsByUserIDLoader(r.Context(), db),
}
ctx := context.WithValue(r.Context(), loadersKey, loaders)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
// ✗ Bad — すべてのリクエスト間で共有されるグローバル DataLoader
var globalLoader = newPostsByUserIDLoader(context.Background(), db)
gqlgen では、gqlgen.yml のバッチ処理されたフィールドに resolver: true でマークして、専用のリゾルバメソッドを強制します。DataLoader の完全な配線については、gqlgen リファレンス を参照してください。
認証と認可
2 層モデル:
- HTTP ミドルウェア — トークンを抽出して検証し、アイデンティティを
context.Contextに格納します。 - スキーマディレクティブ (gqlgen) または リゾルバチェック (graphql-go) — フィールドごとの認可を強制します。
// HTTP ミドルウェアレイヤー (両方のライブラリ)
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
user, err := validateToken(token)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), userKey, user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
gqlgen では、フィールドレベルの認可に @hasRole スキーマディレクティブを使用します — 認可ポリシーはスキーマに存在し、リゾルバに散在しません。gqlgen リファレンス を参照してください。
エラーハンドリング
生のインターナルエラーを返さないでください — SQL メッセージ、スタックトレース、またはサービス内部情報をクライアントにリークします。
// gqlgen — カスタム ErrorPresenter が内部詳細を削除
srv.SetErrorPresenter(func(ctx context.Context, err error) *gqlerror.Error {
var gqlErr *gqlerror.Error
if errors.As(err, &gqlErr) {
return gqlErr // 既にフォーマット済み
}
// ここで内部エラーをログ
return gqlerror.Errorf("internal error") // 安全なクライアントメッセージ
})
// クライアント側のエラーハンドリング用に拡張コードを追加
return nil, &gqlerror.Error{
Message: "user not found",
Extensions: map[string]any{"code": "NOT_FOUND"},
}
graph-gophers では、ResolverError インターフェースを実装して Extensions() をアタッチします。graphql-go リファレンス を参照してください。
非致命的なフィールドエラーに対して gqlgen で graphql.AddError(ctx, err) を使用し、リゾルバが部分的なデータを返すことができます。
エラーラッピングパターンについては、samber/cc-skills-golang@golang-error-handling スキルを参照してください。
サブスクリプション
サブスクリプションは長時間保持される WebSocket 接続を使用します。重要な規則: 常にコンテキストキャンセレーションを尊重する — 接続解除クライアントごとの漏れたゴルーチンはリソースを無言で消費します。
// ✓ Good — クライアント接続解除時にチャネルをクローズ
func (r *subscriptionResolver) MessageAdded(ctx context.Context, room string) (<-chan *model.Message, error) {
ch := make(chan *model.Message, 1)
sub := r.pubsub.Subscribe(room) // ゴルーチン前に 1 回サブスクライブ
go func() {
defer close(ch) // 常にクローズ; 反復停止をシグナル
for {
select {
case <-ctx.Done():
return // クライアント接続解除
case msg := <-sub:
ch <- msg
}
}
}()
return ch, nil
}
// ✗ Bad — クライアント接続解除時にゴルーチンが永遠にリーク
func (r *subscriptionResolver) MessageAdded(ctx context.Context, room string) (<-chan *model.Message, error) {
ch := make(chan *model.Message, 1)
go func() {
for msg := range r.pubsub.Subscribe(room) {
ch <- msg // クライアント接続解除後永遠にブロック
}
}()
return ch, nil
}
パフォーマンスと安全性
本番 GraphQL サーバーには明示的な制限が必要です。制限がないと、1 つの深くネストされたクエリが CPU とメモリを消費します。
// gqlgen — これらをすべての本番ハンドラーに配線
srv := handler.NewDefaultServer(es)
srv.Use(extension.FixedComplexityLimit(200)) // クエリごとの最大コスト
// Introspection をゲート — 本番以外の環境のみ
if os.Getenv("ENV") != "production" {
srv.Use(extension.Introspection{})
}
graph-gophers の場合: ParseSchema 時に graphql.MaxDepth(10) および graphql.MaxParallelism(10) オプション。
クエリ許可リスト: 本番環境では、persisted queries (gqlgen APQ 拡張) を検討して任意のクエリ文字列を拒否します。
一般的な間違い
| 間違い | 重要な理由 | 修正 |
|---|---|---|
| 子リゾルバの N+1 クエリ | 親行ごと 1 つの SQL → O(n) DB 呼び出し | リクエストごとの DataLoader を使用 |
| グローバル DataLoader | クロスリクエストキャッシュ — 古いデータ、データリーク | リクエストミドルウェアで DataLoader を作成 |
models_gen.go を直接編集 | 次の go generate が手動編集をワイプ | gqlgen.yml で autobind または models.<T>.model を使用 |
スキーマ変更後に go generate を忘れた | リゾルバインターフェースの不一致 | go run github.com/99designs/gqlgen generate を再実行 |
graph-gophers リゾルバの int フィールド | ライブラリは Int スカラーに int32 が必要 | int32 (または Float の場合は float64) を使用 |
| 本番環境で introspection が有効 | 攻撃者に完全なスキーマをエクスポーズ | ENV チェックでゲート |
| 複雑性制限なし | 深くネストされたクエリ → CPU/メモリ DoS | extension.FixedComplexityLimit(N) |
| リゾルバから DB エラーをリーク | SQL 内部をクライアントにエクスポーズ | ErrorPresenter / ResolverError でラップ |
| サブスクリプション ゴルーチンリーク | クライアント接続解除 → ゴルーチンが永遠に実行 | defer close(ch) + select ctx.Done() |
| 常に必須データの null 許容フィールド | クライアントは常に null チェック | スキーマで ! をマーク; リゾルバからエラーを返す |
深掘り
gqlgen リファレンス— コード生成ワークフロー、gqlgen.yml、DataLoader、Federation v2、ディレクティブgraphql-go リファレンス— リフレクションリゾルバモデル、型マッピング、トレーシングテスト— gqlgen クライアントハーネス、gqltesting、httptest パターン
クロスリファレンス
- → リゾルバとサブスクリプションでのコンテキスト伝播については
samber/cc-skills-golang@golang-contextスキルを参照 - → エラーラッピングとセンチネルパターンについては
samber/cc-skills-golang@golang-error-handlingスキルを参照 - → テーブル駆動とインテグレーションテストパターンについては
samber/cc-skills-golang@golang-testingスキルを参照 - → リゾルバでのトレーシングとメトリクスについては
samber/cc-skills-golang@golang-observabilityスキルを参照 - → 入力検証とインジェクション防止については
samber/cc-skills-golang@golang-securityスキルを参照 - → N+1 クエリパターンと DataLoader データベースバッチ処理については
samber/cc-skills-golang@golang-databaseスキルを参照
リファレンス
gqlgen でバグまたは予期しない動作が発生した場合は、https://github.com/99designs/gqlgen/issues で issue をオープンしてください。
graph-gophers/graphql-go でバグまたは予期しない動作が発生した場合は、https://github.com/graph-gophers/graphql-go/issues で issue をオープンしてください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- samber
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/samber/cc-skills-golang / ライセンス: MIT
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。