天天看點

graphql學習(二)

昨天完成了hello world,今天接着做getAll和getOne,主要是學習傳參和參數處理.

建立models目錄,增加article.go檔案,内容如下:

package models

import "errors"

type Article struct {
    ID      int    `json:"id"`
    Title   string `json:"title"`
    Content string `json:"content"`
}

// For this demo, we're storing the article list in memory
var articleList = []Article{
    Article{ID: 1, Title: "Article 1,文章1", Content: "Article 1 body,中國加油"},
    Article{ID: 2, Title: "Article 2,文章2", Content: "Article 2 body,武漢加油"},
}

// Return a list of all the articles
func GetAllArticles() []Article {
    return articleList
}

// Get article
func GetArticleByID(id int) (*Article, error) {
    for _, a := range articleList {
        if a.ID == id {
            return &a, nil
        }
    }
    return nil, errors.New("Article not found")
}           

很簡單,定義了Article結構體,然後初始化了一個slice,裡面有兩篇文章.定義了兩個函數,一個是傳回全部的文章,一個是根據id查找單篇文章.

接下來,建立schema目錄,增加article.go檔案:

package schema

import (
    "errors"
    "graphqldemo/models"

    "github.com/graphql-go/graphql"
)

// 定義查詢對象的字段,支援嵌套
var articleType = graphql.NewObject(graphql.ObjectConfig{
    Name:        "Article",
    Description: "Article Model",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Type: graphql.Int,
        },
        "title": &graphql.Field{
            Type: graphql.String,
        },
        "content": &graphql.Field{
            Type: graphql.String,
        },
    },
})

// 處理查詢請求,擷取文章清單
var queryArticles = graphql.Field{
    Name:        "QueryArticles",
    Description: "Query Article List",
    Type:        graphql.NewList(articleType),
    // 無需處理參數
    // Resolve是一個處理請求的函數,具體處理邏輯可在此進行
    Resolve: func(p graphql.ResolveParams) (result interface{}, err error) {
        // 調用Article的models裡面的方法查詢資料
        result = models.GetAllArticles()

        return result, nil
    },
}

// 查詢單篇文章
var queryArticle = graphql.Field{
    Name:        "QueryArticle",
    Description: "Query Article",
    Type:        articleType,
    // Args是定義在GraphQL查詢中支援的查詢字段,
    // 可自行随意定義,如加上limit,start這類
    Args: graphql.FieldConfigArgument{
        "id": &graphql.ArgumentConfig{
            Type: graphql.Int,
        },
    },
    // Resolve是一個處理請求的函數,具體處理邏輯可在此進行
    Resolve: func(p graphql.ResolveParams) (result interface{}, err error) {
        // Args裡面定義的字段在p.Args裡面,對應的取出來
        // 因為是interface{}的值,需要類型轉換
        id, ok := p.Args["id"].(int)
        if !ok {
            return nil, errors.New("missing required arguments: id. ")
        }

        result, err = models.GetArticleByID(id)

        // 調用Hello這個model裡面的Query方法查詢資料
        return result, err
    },
}

// 定義根查詢節點及各種查詢
var rootQuery = graphql.NewObject(graphql.ObjectConfig{
    Name:        "RootQuery",
    Description: "Root Query",
    Fields: graphql.Fields{
        "articles": &queryArticles,  //分别對應前面定義的query
        "article":  &queryArticle,
    },
})

// 定義Schema用于http handler處理
var Schema, _ = graphql.NewSchema(graphql.SchemaConfig{
    Query:    rootQuery,
    Mutation: nil,
})           

這個檔案把昨天main.go裡的很多關于graphql的有關内容,都移到這裡.

這裡的兩個query,分别對應了傳回所有文章和單篇文章,特别是單篇文章處理,增加了Args部分,同時增加了Resolve對于如何擷取參數内容.

現在的main.go就變成了這樣:

package main

import (
    "fmt"
    "graphqldemo/schema"
    "net/http"

    "github.com/graphql-go/handler"
)

// main
func main() {
    h := Register()
    http.Handle("/graphql", h)
    fmt.Println("Now server is running on port 8080")
    http.ListenAndServe(":8080", nil)
}

// 初始化handler
func Register() *handler.Handler {
    h := handler.New(&handler.Config{
        Schema:   &schema.Schema,
        Pretty:   true,
        GraphiQL: true,
    })
    return h
}           

編譯執行後,打開浏覽器,

graphql學習(二)

注意左側的傳參格式,還有最右側的Docs.

graphql的優勢之一來了,再也不用操心swagger了.

到現在為止,我們的目錄結構如下:

graphql學習(二)

除了使用浏覽器,我們還可以使用postman來調試:

graphql學習(二)