📝

Go言語でGraphQLのサーバを立てる

2023/08/12に公開

概要

GraphQLを初めて触ることになった。勉強のためにサーバを立ててみる。

gqlgen

GoでGraphQLを使うのに一番有名なのはgqlgenということで、gqlgenから入れる。
https://gqlgen.com/getting-started/
※個人的にはGraphQL-goもいいと思ったけど会社がgqlgenだったのと、GraphQL-goは自動生成以外のドキュメントがほぼなさそうなので。

あれ?こっちはStar多いな?

あれ、こっちはStar多いな?
https://github.com/graph-gophers/graphql-go

これじゃないGraphQL-goを見ていたのだが・・・Star数800くらいの・・・でもこれはいいかもな・・・
でも今回は会社に合わせてgqlgenです。

gplgen導入

インストール

go mod init example
printf '// +build tools\npackage tools\nimport (_ "github.com/99designs/gqlgen"\n _ "github.com/99designs/gqlgen/graphql/introspection")' | gofmt > tools.go
go mod tidy
go run github.com/99designs/gqlgen init
go mod tidy
go run server.go

できたもの

.
├── README.md
├── go.mod
├── go.sum
├── gqlgen.yml
├── graph
│   ├── generated.go
│   ├── model
│   │   └── models_gen.go
│   ├── resolver.go
│   ├── schema.graphqls
│   └── schema.resolvers.go
├── server.go
└── tools.go

詳細

ディレクトリ・ファイル 説明
gqlgen.yml 設定ファイル、生成されたコードを制御するためのボタン。
generated 生成されたランタイムのみを含むパッケージ
model 生成されたかどうかにかかわらず、すべてのグラフモデルのパッケージ。schema.graphsから自動生成される?
resolver.go ルート グラフ リゾルバー タイプ。 このファイルは再生成されない
schema.graphs いくつかのスキーマ。スキーマはgraphqlファイルに分割できる。
schema.resovers.go schema.graphql のリゾルバー実装
server.go アプリへのエントリポイント。 必要に応じてカスタマイズする。

スキーマ定義

gqlgen はスキーマ優先のライブラリ。
コードを記述する前に、GraphQLスキーマ定義言語を使用して API を記述する。
デフォルトでは schema.graphqls に保存されるが、必要な数の異なるファイルに分割できる。

GraphQLスキーマ定義言語(GraphQLクエリ言語)については長くなったので以下に切り出した。
https://zenn.dev/tofucode/articles/218b271e8b8704

リゾルバ実装

リゾルバ構造体定義

graph/resolver.go
type Resolver struct{
	todos []*model.Todo
}

リゾルバ実装(POSTされたTODOをメモリ上に保存するコード)

graph/schema.resolvers.go
// POST todo
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
  todo := &model.Todo{
	  Text: input.Text,
	  ID:   fmt.Sprintf("T%d", rand.Intn(100)),
	  User: &model.User{ID: input.UserID, Name: "user " + input.UserID},
  }
  r.todos = append(r.todos, todo)
  return todo, nil
}

// GET todo
func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
	return r.todos, nil
}

実行

go mod tidy
go run server.go

動作確認

ブラウザで http://localhost:8080/ にアクセスすると超綺麗なGUIが現れた!

左の枠にTODO追加リクエストとなる構造体を入れる。

▶︎ ボタンを押すと右に結果が返ってくる。

何回かりTODOを追加した後で取得リクエストを実行するとちゃんと出てくる。

感想

gqlgenのstartサンプルに何個もあべこべな記述が見つかる。
大丈夫なのか・・不信感が募る。
PR作った。
https://github.com/99designs/gqlgen/pull/2756
discordでも言った
https://discord.com/channels/831012771810377778/831012771810377781/1139783831575076914
初OSSコミット。返事来るのかなこれ

今後

今回はgqlgenを触ったが、gqlgen周りは以下のも触りたい。

pkg 説明 リンク
99designs/gqlgen GraphQLサーバ用ライブラリ https://github.com/99designs/gqlgen
Yamashou/gqlgenc 上記のプラグイン https://github.com/Yamashou/gqlgenc
go-chi/chi ルーティング https://github.com/go-chi/chi
graph-gophers/dataloader GraphQL用データローダー。SQLクエリたくさん発行(N+1問題)を解決する。 https://github.com/graph-gophers/dataloader

参考(H.Saki)
https://zenn.dev/hsaki/books/golang-graphql/viewer/dataloader#dataloaderとは
vektah/gqlparser/v2 gqlgen用のパーサー https://github.com/vektah/gqlparser
GitHubで編集を提案

Discussion