gqlgenを試す

以下を参考に、GraphQLサーバー開発用Goライブラリであるgqlgenを試す

gqlgenとは

  • GraphQLのSchemaベースで、GraphQLサーバー開発を進めるためのライブラリ
  • 特徴
    • schema first: GraphQLスキーマ定義言語を用いてAPI定義
    • type safe: map[string]interface{} を使わない
    • codegen: コマンドで必要なコードを自動生成して、すぐにアプリケーション構築できる
  • gqlgen公式
  • github

インストール

gqlgenをインストールする

$ go get -u github.com/99designs/gqlgen 

コマンドヘルプ

$ gqlgen -help
NAME:
   gqlgen - generate a graphql server based on schema

USAGE:
   gqlgen [global options] command [command options] [arguments...]

DESCRIPTION:
   This is a library for quickly creating strictly typed graphql servers in golang. See https://gqlgen.com/ for a getting started guide.

COMMANDS:
   generate  generate a graphql server based on schema
   init      create a new gqlgen project
   version   print the version string
   help, h   Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --verbose, -v             show logs
   --config value, -c value  the config filename
   --help, -h                show help

setup project

$ mkdir gqlgen-todos
$ cd gqlgen-todos
$ go mod init github.com/[username]/gqlgen-todos
go: creating new go.mod: module github.com/[username]/gqlgen-todos
$ tree
.
└── go.mod

create the project skeleton

$ gqlgen init
Exec "go run ./server/server.go" to start GraphQL server
$ tree
.
├── generated.go
├── go.mod
├── go.sum
├── gqlgen.yml
├── models_gen.go
├── resolver.go
├── schema.graphql
└── server
    └── server.go

gqlgen initで作成されたファイル

ファイル 説明
schema.graphql GraphQLのスキーマが書かれている。gqlgen generate を実行すると、このスキーマから 各 .go ファイルに Goコードとして記載される
generated.go schema.graphqlで記載したスキーマ情報、それに沿ったResolverやTypeの情報など、GraphQLで必要な処理が書かれている
gqlgen.yml 設定ファイル (gqlgen.ymlの設定項目)
models_gen.go schema.graphqlに記載されたもの(Type,Input,Scalar,Enumなど)に基づいたType等の Go struct が書かれている
resolver.go 各QueryやMutationを処理するためのメソッドが書かれている
server/server.go GraphQL playground用サーバー起動するためのコードが書かれている

resolver実装

自動生成されたresolver.goのTodos関数は、not impletemntedになっている.

:
func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {
  panic("not implemented")
}

ここでは、ダミーのTodoリストを返すように、変更してみる。

func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {
    return []*Todo{
        {ID: "1"},
        {ID: "2"},
        {ID: "3"},
    }, nil
}    

サーバー起動

$ go run ./server/server.go
2020/02/03 00:26:42 connect to http://localhost:8080/ for GraphQL playground

リクエス

ID取得リクエス

GraphiQL等で、Endpointを http://localhost:8080/query にセットし以下リクエストしてみる。
resolverのTodos関数で指定したTodoリストが返ってくることが確認出来る。

query {
  todos {
    id
  }
}

実行結果

f:id:kimai007:20200203002941p:plain

Text取得リクエス

現在のschema.graphqlでのTodo定義は、以下のようになっている。

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
}

試しにidフィールドではなく、resolverで値を返却しないtextフィールドを取得するようにリクエストしてみる。
空文字が入ったtextフィールドのみ返ってくることが確認できる(idフィールドは含まれていない)

query {
  todos {
    text
  }
}

実行結果

f:id:kimai007:20200203002919p:plain

フィールド追加

今後は、一度コードを生成した後、GraphQLのインタフェースを変えたい場合、どう実装していくのか

  • やること
    • schema.grpahqlを編集してフィールド追加を行い、Goのコードを再生成する
    • 今回は、Todo に comment フィールド を追加する

schema.graphqlの編集

commentフィールドを追加

type Todo {
  id: ID!
  text: String!
  done: Boolean!
  user: User!
  
  comment: String!
}

gqlgenによるGoコード再生成

追加したフィールドをGoコードに反映させたい場合、以下を実行する

$ gqlgen generate
または短縮系の
$ gqlgen

以下ファイルが一度削除されて、再度作成される

  • generated.go
  • models_gen.go

resolverのTodos関数のの実装を修正する

commentの値を追加する

func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {
    return []*Todo{
        {ID: "1", Comment: "comment1"},
        {ID: "2", Comment: "comment2"},
        {ID: "3", Comment: "comment3"},
    }, nil
}

リクエス

f:id:kimai007:20200203002857p:plain

まとめ

GraphQLサーバー開発を行う上で、shcemaからGo等のアプリケーションコードを生成してくれるライブラリを用いることは、特にshemaに変更があった時に効果を発揮するような感じがする。
また、GraphQLを追い始めた自分としては、gqlgenを使ってのコード生成を試して、GraphQLの理解が少し進んだように感じた。
Comparing Features of Other Go GraphQL Implementations — gqlgen を見るとgqlgenに似たライブラリがいくつかあるとのことで、他も時間がある時にチェックしたと思う。