iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
Software Development

你知道Go是什麼嗎?系列 第 27

Day27 - GraphQL - Golang

  • 分享至 

  • xImage
  •  

如題,今天花時間稍微了解一下GraphQL是什麼東西。

API的發展

Http通訊協定中,有GETPOSTPUTDELETE這些方法,從最原始的API,到妥善運用這些方法的RestAPI,看似前後端溝通已經沒什麼問題了,我們看一下以下這個例子

GET /books
沒看API文件也大概看得出是要取得所有Book的資料,其中每一個Book是長這樣的

type Book{
    id:       ID!
    name:     String!
    isbn:     String!
    author:   String!
    category: String!
    similar:  [Book]
}

每一筆Book的資料都非常飽滿,但如果我今天只需要所有書籍的idname,使用這種方式就浪費了許多空間與資源取得了用不到的資料。像中間similar還需要透過資料庫做JOIN查詢,資源浪費的問題就更嚴重。

RestAPI主要會產生幾種問題:

  • 回傳的資料有些是不需要的:大型API通常是服務許多客戶,為了省麻煩,一次都是回傳所有可能需要用到的資訊,造成回傳資料肥大,造成網路資源的浪費。
  • 修改需求十分麻煩:前後端必須一起修改,其中一邊動了另一邊也要跟著動,修改成本拉高。
  • 版本控制不易:公開API在做版本修改時,為了維護原使用者的權益,不能說動就動,維護變得困難。

GraphQL

2015年Facebook公布了一種不同於RestAPI的溝通方式,GraphQL定義server上的資料類型,在客戶端要取得資料時指定要取得的資料格式與欄位,server就根據query內容回傳對應的資料就好。

操作類型

  • Query: 向後端查詢資料,以CRUD舉例的話就是當中的C
  • mutation: 向後端做執行動作,以CRUD舉例的話是RUD

回到上面的例子,我只想要所有Bookidname,做以下的操作就好

query{
    books{
        id
        name
    }
}

若我只要查詢相近書籍而已,則是照下面的操作

query{
    books{
        id
        name
        similar{
            id
            name
        }
    }
}

透過Go實現GraphQL概念

gqlgen

一種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
}

修正resolver.go

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


上一篇
Day26 - gRPC - Golang
下一篇
Day28 - Test(上) - Golang
系列文
你知道Go是什麼嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言