アプリケーションに API を実装する必要がある場合、GraphQL (GQL) を検討すると状況が一変する可能性があります。この記事では、Go で GraphQL サーバーを実装するための基本事項を説明し、ジョブに適したライブラリを選択できるようにします。
なぜ GraphQL なのか?
- GraphQL は、柔軟性、効率性、開発者に優しい機能により、最新の API 開発に強力なツールです。従来の REST API の多くの制限に対処しているため、複雑で動的なデータ インタラクションを必要とするプロジェクトに最適です。主な利点は次のとおりです。
- 過剰な取得と不足した取得を避ける: GraphQL を使用すると、クライアントは必要なデータだけを正確に要求できるため、オーバーフェッチ (取得するデータが多すぎる) やアンダーフェッチ (取得するデータが不十分) の問題が軽減されます。
- 簡素化されたエンドポイント管理: GraphQL では、さまざまなリソースに対して複数のエンドポイントが必要になることが多い REST とは異なり、単一のエンドポイントですべてのデータを提供できます。
- 柔軟かつ効率的なデータ取得: GraphQL のクエリ言語により、ネストされたデータの効率的な取得が可能になり、サーバーへの複数回の往復が不要になります。
- バージョン管理の必要性の低減: GraphQL のスキーマにより、バージョン管理を必要とせずに API を進化させることができ、下位互換性の管理が容易になります。
Go で GraphQL を実装する
Go プロジェクトの API として GraphQL を使用することを決定するときは、堅牢なコア機能を提供し、開発を高速化するライブラリを選択することが重要です。検討すべき人気のあるライブラリをいくつか紹介します。
gqlgen
- 説明: gqlgen は、型の安全性を重視した GraphQL サーバーを構築するための Go ライブラリです。GraphQL スキーマから型安全なコードを生成します。
- 長所:
-
厳密に型指定された API により、実行時エラーが削減されます。
-
リゾルバを自動的に生成し、開発をスピードアップします。
-
優れたコミュニティ サポートとドキュメント。
-
- 短所:
- コード生成の要件により、初期設定が複雑になる場合があります。
graphql-go
- 説明: graphql-go は、Go 用の低レベルの GraphQL サーバー実装です。GraphQL サーバーを構築するためのより実践的なアプローチを提供します。
- 長所:
-
シンプルでミニマル、きめ細かな制御を提供します。
-
既存の Go アプリケーションと簡単に統合できます。
-
- 短所:
- 追加の手動セットアップと定型コードが必要です。
- gqlgen に比べて型安全性が低くなります。
graph-gophers/graphql-go
- 説明: このライブラリはシンプルさとパワーのバランスを実現し、Go で GraphQL サーバーを構築する簡単な方法を提供します。
- 長所:
- 短所:
- 他のライブラリにあるいくつかの高度な機能が欠けている可能性があります。
適切なライブラリの選択
エンジニアとして、適切なライブラリを選択するには、技術仕様や製品の機能だけでなく、メンテナンス、コミュニティ サポート、ライブラリへの貢献/問題/PR のレベルも考慮する必要があります。これらの基準に基づいた私の簡単な分析を以下に示します。
gqlgen:
-
メンテナンス: 定期的に更新され、積極的にメンテナンスされています。
-
コミュニティサポート: 豊富なドキュメントとチュートリアルを備えた強力なコミュニティ。
-
貢献/問題/PR: 高いレベルの貢献と積極的な問題解決。
-
未解決の問題と既知のバグ: 定期的に更新されますが、複雑なスキーマの問題とパフォーマンスのオーバーヘッドが指摘されます。
-
オープン PR と問題の数: 約 50 件の未解決の問題と 10 件の未解決の PR。PR をマージする平均時間: 1 ~ 2 週間。
-
graphql-go:
-
メンテナンス: メンテナンスされていますが、gqlgen と比較すると更新は少なくなっています。
-
コミュニティサポート: 基本的なドキュメントを備えた小規模なコミュニティ。
-
貢献/問題/PR: 貢献度は中程度で、問題解決は遅いです。
-
未解決の問題と既知のバグ: 同時実行の問題と高度な機能のサポートが制限されています。
-
オープン PR と問題の数: 約 30 件の未解決の問題と 5 件の未解決の PR。PR をマージする平均時間: 2 ~ 4 週間。
-
graph-gophers/graphql-go:
- メンテナンス: 良好な更新頻度で積極的にメンテナンスされています。
- コミュニティサポート: 優れたドキュメントを備えた成長中のコミュニティ。
- 貢献/問題/PR: 積極的な貢献と良好な問題解決率。
- 未解決の問題と既知のバグ: メモリ リークと新しい GraphQL 機能の不完全なサポート。
- オープン PR と問題の数: 未解決の問題が約 20 件、PR が 3 件あります。PR をマージする平均時間: 1 ~ 3 週間。
結論
上記の基準に基づいて、新しいプロジェクトに最適なオプションとして gqlgen を選択しました。強力な型安全性、自動リゾルバ生成、アクティブなコミュニティ サポートにより、gqlgen は傑出した選択肢となりました。gqlgen を使用してシンプルな GraphQL サーバーを実装する方法を見てみましょう。
シンプルなGraphQLサーバーの実装 gqlgen
gqlgen を使用して基本的な GraphQL サーバーを設定するためのステップバイステップ ガイドを次に示します。
-
gqlgen をインストールします。
go get github.com/99designs/gqlgen@latest
-
プロジェクトで gqlgen を初期化します。
gqlgen init
-
確認と設定
gqlgen.yml
:必ずあなたの
gqlgen.yml
ファイルは必要なコードを生成するように適切に構成されています。構成例を次に示します。
schema:
- schema.graphqls
exec:
filename: generated/generated.go
model:
filename: generated/models_gen.go
package: generated
resolver:
layout: follow-schema
dir: graph
package: graph
-
GraphQL スキーマ (schema.graphqls) を定義します。
type Query { hello: String! } type Mutation { setMessage(message: String!): String! }
-
GraphQL サーバー コードを生成します。
gqlgen generate
-
リゾルバを実装します (graph/resolver.go):
package graph // This file will not be regenerated automatically. // // It serves as dependency injection for your app, add any dependencies you require here. type Resolver struct { Message string }
-
リゾルバを実装します (graph/schema.resolvers.go):
package graph import ( "context" "github.com/your_project/graph/generated" ) func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} } type queryResolver struct{ *Resolver } func (r *queryResolver) Hello(ctx context.Context) (string, error) { return r.Message, nil } type mutationResolver struct{ *Resolver } func (r *mutationResolver) SetMessage(ctx context.Context, message string) (string, error) { r.Message = message return r.Message, nil }
-
サーバーをセットアップします (server.go):
package main import ( "log" "net/http" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/playground" "github.com/your_project/graph" "github.com/your_project/graph/generated" ) const defaultPort = "8080" func main() { port := defaultPort srv := handler.NewDefaultServer(generated.NewExecutableSchema(generated.Config{Resolvers: &graph.Resolver{Message: "Hello, world!"}})) http.Handle("/", playground.Handler("GraphQL playground", "/query")) http.Handle("/query", srv) log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) log.Fatal(http.ListenAndServe(":"+port, nil)) }
-
サーバーを実行します:
go run server.go
完全なプロジェクト構造は次のとおりです。
your_project/
├── graph/
│ ├── resolver.go
│ └── schema.resolvers.go
├── generated/
│ ├── generated.go
│ └── models_gen.go
├── gqlgen.yml
├── schema.graphqls
└── server.go
これらの手順に従うことで、 gqlgen.yml
GraphQL サーバー コードを生成する前に構成が適切にセットアップされ、セットアップ プロセス全体が論理的かつ正しい順序で調整されます。