如題,今天花時間稍微了解一下GraphQL
是什麼東西。
Http
通訊協定中,有GET
、POST
、PUT
、DELETE
這些方法,從最原始的API
,到妥善運用這些方法的RestAPI
,看似前後端溝通已經沒什麼問題了,我們看一下以下這個例子
GET /books
沒看API
文件也大概看得出是要取得所有Book
的資料,其中每一個Book
是長這樣的
type Book{
id: ID!
name: String!
isbn: String!
author: String!
category: String!
similar: [Book]
}
每一筆Book
的資料都非常飽滿,但如果我今天只需要所有書籍的id
與name
,使用這種方式就浪費了許多空間與資源取得了用不到的資料。像中間similar
還需要透過資料庫做JOIN
查詢,資源浪費的問題就更嚴重。
RestAPI
主要會產生幾種問題:
API
通常是服務許多客戶,為了省麻煩,一次都是回傳所有可能需要用到的資訊,造成回傳資料肥大,造成網路資源的浪費。API
在做版本修改時,為了維護原使用者的權益,不能說動就動,維護變得困難。2015年Facebook公布了一種不同於RestAPI
的溝通方式,GraphQL
定義server
上的資料類型,在客戶端要取得資料時指定要取得的資料格式與欄位,server
就根據query
內容回傳對應的資料就好。
操作類型
Quer
y: 向後端查詢資料,以CRUD
舉例的話就是當中的C
。mutation
: 向後端做執行動作,以CRUD
舉例的話是RUD
。回到上面的例子,我只想要所有Book
的id
與name
,做以下的操作就好
query{
books{
id
name
}
}
若我只要查詢相近書籍而已,則是照下面的操作
query{
books{
id
name
similar{
id
name
}
}
}
一種Go的GraphQL
框架,可以輕鬆搭建GraphQL
服務。
先依序執行這兩個,讓套件幫忙引入架構
go get github.com/99designs/gqlgen
go run github.com/99designs/gqlgen init
會看到引入一堆東西,如下圖
.
├── go.mod
├── go.sum
├── gqlgen.yml - The gqlgen config file, knobs for controlling the generated code.
├── graph
│ ├── generated - A package that only contains the generated runtime
│ │ └── generated.go
│ ├── model - A package for all your graph models, generated or otherwise
│ │ └── models_gen.go
│ ├── resolver.go - The root graph resolver type. This file wont get regenerated
│ ├── schema.graphqls - Some schema. You can split the schema into as many graphql files as you like
│ └── schema.resolvers.go - the resolver implementation for schema.graphql
└── server.go - The entry point to your app. Customize it however you see fit
链接:https://juejin.cn/post/7098273601907851271
最主要會動到兩個檔案,其他都是由框架自動生成
schema.graphqls
: 將自己要的結構與方法定義在此,結束後從終端機輸入go get github.com/99designs/gqlgen
讓框架生成其他檔案。schema.resolvers.go
: 方法內部的實現,生成時會先由panic
告知not implemented
,要到裡面進行修改。resolver.go
: 先照著官方提供的schema.graphqls
試做一次,輸入go get github.com/99designs/gqlgen
,接著到schema.resolvers.go
看到下面兩個未定義的方法。
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
panic(fmt.Errorf("not implemented: CreateTodo - createTodo"))
}
// Todos is the resolver for the todos field.
func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
panic(fmt.Errorf("not implemented: Todos - todos"))
}
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
s := &model.Todo{
Text: input.Text,
ID: input.UserID,
}
r.todos = append(r.todos,s)
return s,nil
}
func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
return r.todos, nil
}
package graph
// This file will not be regenerated automatically.
//
// It serves as dependency injection for your app, add any dependencies you require here.
import "graphQL-test/graph/model"
type Resolver struct {
todos []*model.Todo
}
接著就能去執行server.go
了
連上 http://localhost:8080 會連接到GraphQL playground
,試著做以下輸入
mutation{
createTodo(input: {text:"What am I doing?", userId:"30"}){
id,text
}
}
query{
todos{
id,
text,
}
}
可以看到以GraphQL
概念製作的API
了,灑花
挫折感越來越重了,感覺看了好久但吸收速度超慢,也不大能自己找地方運用,果然還是該找工作增加自己的實戰經驗才行,寫完鐵人賽就要開始找工作了,讚讚
GraphQL 教學:為你迭代快速的專案 提供最適合的解決方案!
https://www.appcoda.com.tw/graphql/
GraphQL 入门看这篇就够了
https://chinese.freecodecamp.org/news/a-detailed-guide-to-graphql/
GraphQL x Go! 淺談 gqlgen 為開發帶來的便利性
https://yuanlin.dev/posts/how-i-use-graphql-in-go-with-gqlgen
Day10.Gqlgen
https://ithelp.ithome.com.tw/articles/10297700
go gqlgen使用方法
https://juejin.cn/post/7098273601907851271
99designs/gqlgen
https://github.com/99designs/gqlgen