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)
以下が全体のソースです。
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
以上です。