Go — 搭建GraphQL 服務端

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Github提供的GraphQL介面非常全面,那麼我們該如何搭建出自己的介面呢?好在GraphQL提供了很多語言的解決方案。本文主要闡述如何用go搭建自己的GraphQL伺服器。如果瞭解GraphQL建議先閱讀GraphQL — API查詢語言 或相關資料。

graphql-go

An implementation of GraphQL in Go. Follows the official reference implementation graphql-js.

一套比較完善的架構,眾所周知go的結構體對json非常友好,所以並不需要對資料有特殊的處理,還是很方便的。開啟終端輸入命令

go get github.com/graphql-go/graphql

Object

在服務端編程中,編寫的一切都可以稱之為對象(Object)。例如一個商品(goods)的執行個體可以有商品名(name)、價格(price)、購買連結(url)三個欄位。此時商品可以很自然的被稱為一個object,查詢的語句可以寫成:

{    goods{        name        price        url    }}

如果此時我們要查詢商品和文章兩種object的資訊:

/* query 可以省去 */query{     goods{        name    }    article{        name    }}

是否你已經發覺,query像一個大的object,它有goods和article兩個欄位。除此之外,mutation也是如此:

mutation{    addGoods(input:goodsInput){        name    }}

這裡的addGoods可以看做是一個可以處理參數的對象,也就是某種意義上的函數

總之,GraphQL服務端的編程就是一個又一個的對象將形成的嵌套結構(schema)組織起來,並對外提供服務。

query&mutation

為了防止低級錯誤的發生,在當前pkg下建立一個名為query.go(隨便起)的檔案。

import (    "github.com/graphql-go/graphql"    "errors")

定義good object

type Goods struct {    ID    string `json:"id"`    Name  string `json:"name"`    Price float64`json:"price"`    Url   string `json:"url"`}var goodsType = graphql.NewObject(    graphql.ObjectConfig{        Name: "Goods",        Fields: graphql.Fields{            "id": &graphql.Field{                Type: graphql.String,            },            "name": &graphql.Field{                Type: graphql.String,            },            "price": &graphql.Field{                Type: graphql.Float,            },            "url": &graphql.Field{                Type: graphql.String,            },        },    },)var goodsListType = graphql.NewList(goodsType)

注意:數組相當於新的object類型。

定義query object

var queryType = graphql.NewObject(    graphql.ObjectConfig{        Name: "Query",        Fields: graphql.Fields{            // 無需處理參數            "goodsList": &graphql.Field{                Type:goodsListType,                // 處理結構體的回呼函數,直接返回處理完成的結構體即可                Resolve: func(p graphql.ResolveParams) (interface{}, error) {                    return result, err                },            },            // 參數是id            "goods": &graphql.Field{                Type: goodsType,                Args: graphql.FieldConfigArgument{                    "id": &graphql.ArgumentConfig{                        Type: graphql.String,                    },                },                Resolve: func(p graphql.ResolveParams) (interface{}, error) {                    // 擷取參數                    idQuery, isOK := p.Args["id"].(string)                    if isOK {                        return result, nil                    }                    err := errors.New("Field 'goods' is missing required arguments: id. ")                    return nil, err                },            },        },    },)

mutation定義基本相同,建立一個名為mutation.go的檔案:

定義input object

var goodsInputType = graphql.NewInputObject(    graphql.InputObjectConfig{        Name: "goodsInput",        Fields: graphql.InputObjectConfigFieldMap{            "name": &graphql.InputObjectFieldConfig{                Type: graphql.String,            },            "price": &graphql.InputObjectFieldConfig{                Type: graphql.Float,            },            "url": &graphql.InputObjectFieldConfig{                Type: graphql.String,            },        },    },)

定義 mutation object

var mutationType = graphql.NewObject(   graphql.ObjectConfig{      Name: "Mutation",      Fields: graphql.Fields{      "addGoods":&graphql.Field{                Type:goodsType,                Args:graphql.FieldConfigArgument{                    "input":&graphql.ArgumentConfig{                        Type:goodsInputType,                    },                },                Resolve: func(p graphql.ResolveParams) (interface{}, error) {                    input,isOk := p.Args["input"].(map[string]string)                    if !isOk{                        err := errors.New("Field 'addGoods' is missing required arguments: input. ")                        return nil,err                    }                    result := Goods{                        Name:input["name"].(string),                        Price:input["price"].(float64),                        Url:input["url"].(string),                    }                    // 處理資料                    return result,err                },            },        },    },)

然而,input類型並不能直接轉換為struct,而是一個map[string]interface{}類型,還需要進行手動轉換。

定義schema

var schema, _ = graphql.NewSchema(   graphql.SchemaConfig{      Query:    queryType,      Mutation: mutationType,   },)

至此,我們的全部的object定義完成。

提供服務

graphql-go為我們提供了一個方便的介面,封裝好的handler可以直接與go內建的http包綁定。

package apiimport "github.com/graphql-go/handler"func Register() *handler.Handler {   h := handler.New(&handler.Config{      Schema:   &schema,      Pretty:   true,      GraphiQL: true,   })   return h}
func main() {   h := api.Register()   handler := cors.Default().Handler(h)   http.Handle("/graphql", handler)   fmt.Println("The api server will run on port : ", apiPort)   http.ListenAndServe(apiPort, nil)}

開啟瀏覽器,訪問http://localhost:apiPort/graphql, 查看你自己的GraphiQL介面吧!

結束語

如果你覺得這樣的代碼談不上優雅,甚至非常醜陋,那就對了。因為我也這樣覺得,看一看隔壁python的實現方式:

import grapheneclass Query(graphene.ObjectType):  hello = graphene.String()  def resolve_hello(self, args, context, info):    return 'Hello world!'schema = graphene.Schema(query=Query)

有沒有湧來一口老血。

可能是受限與golang本身反射系統並不夠完善,沒有python各種各樣的魔術方法,沒有泛型,或者說go本身不太適合編寫架構類的代碼。在編寫的過程中,冗餘非常多,當然也可能是架構本身的問題

不可否認的是,go確實是非常不錯的一門語言,雖然開發效率無法與python媲美,但是在多並發環境下,go表現出非常出色,同時擁有與C層級的運行速度和豐富的生態。

go還年輕,其他它越來越好!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.