LoginSignup
4
3

More than 5 years have passed since last update.

Github GraphQLのクエリーに対応する構造体を作るだけでレスポンスのJSONとマッピングしてくれるGoのライブラリ「githubql」

Last updated at Posted at 2017-10-01

GoでGithub APIのGraphQLのクライアント githubql を使ってみました。

githubqlの使い方

基本的にはGraphQLのqueryやmutationに合わせたGoの構造体を定義するだけです。

まずgithubqlのページに載っているサンプルを見てみましょう。
以下のようなシンプルなqueryの場合、

query {
    viewer {
        login
        createdAt
    }
}

このように構造体を定義し、

var query struct {
    Viewer struct {
        Login     githubql.String
        CreatedAt githubql.DateTime
    }
}

client.Queryを実行すると戻り値にGithubのGraphQL APIの結果が入っています。

err := client.Query(context.Background(), &query, nil)
if err != nil {
    // Handle error.
}
fmt.Println("    Login:", query.Viewer.Login)
fmt.Println("CreatedAt:", query.Viewer.CreatedAt)

今回試すクエリー(GraphQL Explorerの場合)

GithubのGraphQL APIはこちらで簡単に実行結果を確認することができます。
https://developer.github.com/v4/explorer/

今回はGithubにあるGraphQL関連のRepositoryとその言語を5件抽出するクエリーを書きました。

query {
    search(query: "GraphQL", first: 5, type: REPOSITORY) {
      edges {
        node {
          ... on Repository {
            nameWithOwner,
            url,
            languages(first:5) {
              edges {
                node {
                  ... on Language {
                    name,
                    color
                  }
                }
              }
            }
          }
        }
      }
    }
  }

結果

{
  "data": {
    "search": {
      "edges": [
        {
          "node": {
            "nameWithOwner": "facebook/graphql",
            "url": "https://github.com/facebook/graphql",
            "languages": {
              "edges": [
                {
                  "node": {
                    "name": "Shell",
                    "color": "#89e051"
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "nameWithOwner": "graphql-go/graphql",
            "url": "https://github.com/graphql-go/graphql",
            "languages": {
              "edges": [
                {
                  "node": {
                    "name": "Go",
                    "color": "#375eab"
                  }
                }
              ]
            }
          }
        },

・・・以下省略

githubqlで書く場合

上記のクエリーをgithubqlを使ってGoで書くと以下のようになります。

Githubのトークンを使ってclientを初期化します。

src := oauth2.StaticTokenSource(
    &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
)
httpClient := oauth2.NewClient(context.Background(), src)

client := githubql.NewClient(httpClient)

続いてRepositoryとLanguageの構造体を定義します。

type Language struct {
    Name  githubql.String
    Color githubql.String
}

type Repository struct {
    NameWithOwner   githubql.String
    Url     githubql.String
    Languages struct {
        Nodes []struct {
            Language `graphql:"... on Language"`
        }
    } `graphql:"languages(first: 5)"`
}

GraphQLの引数を指定したいときは構造体にgraphql:"... on Language"のようにタグをつけます。

Searchも構造体で定義します。最初はここが分からなくて少しハマりました。先程のRepositoryの定義もSearchの中に入れ子で書けますが、今回は分けて書いてます。

var query struct {
    Search struct {
        Nodes []struct {
            Repository `graphql:"... on Repository"`
        }
    } `graphql:"search(first: 5, query: $q, type: $searchType)"`
}

Searchに渡すクエリパラメータを利用する時は、mapを作って渡します。

variables := map[string]interface{}{
    "q": githubql.String("GraphQL"),
    "searchType":  githubql.SearchTypeRepository,
}

err := client.Query(context.Background(), &query, variables)

以下が全体のソースです。

graphql-client.go
package main

import (
    "golang.org/x/oauth2"
    "os"
    "fmt"
    "context"
    "github.com/shurcooL/githubql"
)

func main() {
    src := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
    )
    httpClient := oauth2.NewClient(context.Background(), src)

    client := githubql.NewClient(httpClient)

    type Language struct {
        Name  githubql.String
        Color githubql.String
    }

    type Repository struct {
        NameWithOwner   githubql.String
        Url     githubql.String
        Languages struct {
            Nodes []struct {
                Language `graphql:"... on Language"`
            }
        } `graphql:"languages(first: 5)"`
    }

    var query struct {
        Search struct {
            Nodes []struct {
                Repository `graphql:"... on Repository"`
            }
        } `graphql:"search(first: 5, query: $q, type: $searchType)"`
    }

    variables := map[string]interface{}{
        "q": githubql.String("GraphQL"),
        "searchType":  githubql.SearchTypeRepository,
    }

    err := client.Query(context.Background(), &query, variables)
    if err != nil {
        fmt.Println(err)
    }

    for _, repo := range query.Search.Nodes {
        fmt.Println("---------")
        fmt.Println(repo.NameWithOwner)
        fmt.Println(repo.Url)
        for _, lang := range repo.Languages.Nodes {
            fmt.Println(lang.Name)
            fmt.Println(lang.Color)
        }
    }
}

実行結果

クエリーで定義した構造体に、GraphQL APIからのレスポンスのJSONがマッピングされています。

---------
facebook/graphql
https://github.com/facebook/graphql
Shell
#89e051
---------
graphql-go/graphql
https://github.com/graphql-go/graphql
Go
#375eab
---------
Youshido/GraphQL
https://github.com/Youshido/GraphQL
PHP
#4F5D95
---------
graphql-elixir/graphql
https://github.com/graphql-elixir/graphql
Elixir
#6e4a7e
Erlang
#B83998
---------
GraphQLSwift/GraphQL
https://github.com/GraphQLSwift/GraphQL
Swift
#ffac45

以上です。

参考

4
3
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
3