4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GraphQL、gqlgen を使って サーバ を立てる

Last updated at Posted at 2022-10-14

記事を書こうと思ったきっかけ

インターン先で GraphQL が使われているので実際に手元で動かしてみようと思ったのがきっかけです。
本家のチュートリアルや、参考になった記事の内容をもとに構成されています。
この記事は Go Conference mini 2022 Autumn IN Sendai の発表でも使われています。

この記事に書かれていること

gqlgen を使ったサーバの立て方

Client 側の詳しい説明

GraphQL とは

image.png

  • Facebook が作った OSS
  • API のために作られたクエリ言語
  • 既存のデータに対するクエリを実行するランタイム

Client 側

↓ のスライドをご覧ください。GraphQL のメリット・デメリットも書いてあります。

gqlgen とは

image.png

  • gqlgen はGraphQLサーバを簡単に構築するためのGoライブラリです。
  • gqlgen はスキーマファーストのアプローチに基づいています
  • gqlgen は型の安全性を優先します
  • gqlgen はCodegenを可能にします

とりあえず作って試してみよう

サーバを立てる

https://github.com/99designs/gqlgen

1. 作業するディレクトリ作成、初期化

mkdir gqlgen-server

cd gqlgen-server

go mod init gqlgen-server

2. github.com/99designs/gqlgentools.go に追加

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

go mod tidy

3. gqlgen の設定を初期化し、モデルを生成

go run github.com/99designs/gqlgen init

4. gqlgen サーバ起動

go run server.go

これでサーバを起動しました。
↓ のようなアウトプットになれば成功!
image.png
http://localhost:8080/ にアクセスすると ↓ のような Client 画面に飛ぶかと思います。
ここでは GraphQL のリクエストである、querymutation を書いて、リクエストを投げることができます。
image.png

ディレクトリ構成

├── go.mod
├── go.sum
├── gqlgen.yml               - gqlgen の設定ファイル。生成されたコードを制御する
├── graph
│   ├── generated            - 生成されたランタイムのみが含まれるパッケージ
│   │   └── generated.go
│   ├── model                - すべての graph model 用のパッケージ
│   │   └── models_gen.go
│   ├── resolver.go          - root graph resolver タイプ。このファイルは再生成されない
│   ├── schema.graphqls      - スキーマが書かれているファイル。好きなようにいじって大丈夫
│   └── schema.resolvers.go  - schema.graphql の resolver 実装。
└── server.go                - エントリーポイント。カスタマイズできる

実践パート

ファイルを見てみよう

↓ のようなスキーマが生成されているはず。

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

type User {
  id: ID!
  name: String!
}

type Query {
  todos: [Todo!]!
}

input NewTodo {
  text: String!
  userId: String!
}

type Mutation {
  createTodo(input: NewTodo!): Todo!
}

変更するファイル

graph/resolver.go
type Resolver struct{
    // ↓ の一行を追加 
	todos []*model.Todo
}

正常に import できていない packege があるかもしれないので、エラーが出たら確認してみてください。

↓ のように変更する
自動生成されたリゾルバ関数の本体を実装。
CreateTodoについては、math.randパッケージを使用して、ランダムに生成されたIDを持つTodoを返し、それをインメモリのTodoリストに格納。

graph/schema.resolvers.go
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.Int()),
		User: &model.User{ID: input.UserID, Name: "user " + input.UserID},
	}
	r.todos = append(r.todos, todo)
	return todo, nil
}

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

これでサーバにリクエストを送る準備完了。

再度サーバを起動する

go run server.go

todo 作成

http://localhost:8080/ ここで request を書く

request

mutation createTodo {
  createTodo(input: { text: "todo", userId: "3" }) {
    user {
      id
    }
    text
    done
  }
}

response

{
  "data": {
    "createTodo": {
      "user": {
        "id": "3"
      },
      "text": "todo",
      "done": false
    }
  }
}

todo 取得

http://localhost:8080/ ここで request を書く

request

query findTodos {
  todos {
    id
    text
    done
    user {
      name
    	id
    }
  }
}

response

{
  "data": {
    "todos": [
      {
        "id": "T5577006791947779410",
        "text": "todo",
        "done": false,
        "user": {
          "name": "user 3",
          "id": "3"
        }
      }
    ]
  }
}

以上!!

終わりに

初めて qiita の記事を書いてみました。自分の知識整理のためにもなり勉強になりました!この調子でアウトプットしていけたらいいなと思います。
また、この記事が皆様の役に立つことを祈っています。

博多行きたい。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?