官方文檔地址 :https://gqlgen.com/getting-started/
本教程將帶您完成使用 gqlgen 構建 GraphQL 服務器的過程,該服務器可以:
- 返回待辦事項列表
- 創建新的待辦事項
- 在待辦事項完成時標記它們
您可以在此處找到本教程的完成代碼
設置項目
為您的項目創建一個目錄,並將其初始化為 Go Module:
$ mkdir gqlgen-todos
$ cd gqlgen-todos $ go mod init github.com/[username]/gqlgen-todos $ go get github.com/99designs/gqlgen
構建服務器
創建項目骨架
$ go run github.com/99designs/gqlgen init
這將創建我們建議的包布局。如果需要,您可以在 gqlgen.yml 中修改這些路徑。
├── 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
定義您的架構
gqlgen 是一個模式優先的庫——在編寫代碼之前,你使用 GraphQL模式定義語言來描述你的 API 。默認情況下,這會進入一個名為的文件, schema.graphql
但您可以根據需要將其分解為多個不同的文件。
為我們生成的模式是:
type Todo { id: ID! text: String! done: Boolean! user: User! } type User { id: ID! name: String! } type Query { todos: [Todo!]! } input NewTodo { text: String! userId: String! } type Mutation { createTodo(input: NewTodo!): Todo! }
實現解析器
執行時,gqlgen 的generate
命令將模式文件 ( graph/schema.graphqls
) 與模型進行比較graph/model/*
,並且,只要可能,它將直接綁定到模型。這已經在init
運行時完成了。我們將在本教程的后面編輯模式,但現在,讓我們看看已經生成的內容。
如果我們看一看,graph/schema.resolvers.go
我們將看到 gqlgen 無法匹配它們的所有時間。對我們來說是兩次:
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { panic(fmt.Errorf("not implemented")) } func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) { panic(fmt.Errorf("not implemented")) }
我們只需要實現這兩個方法來讓我們的服務器工作:
首先我們需要一個地方來跟蹤我們的狀態,讓我們把它放在graph/resolver.go
. 該graph/resolver.go
文件是我們聲明應用程序依賴項的地方,例如我們的數據庫。server.go
當我們創建圖形時,它會被初始化一次。
type Resolver struct{ todos []*model.Todo }
回到graph/schema.resolvers.go
,讓我們實現那些自動生成的解析器函數的主體。對於CreateTodo
,我們將使用math.rand
隨機生成的 ID 簡單地返回一個待辦事項,並將其存儲在內存中的待辦事項列表中——在實際應用中,您可能會使用數據庫或其他一些后端服務。
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { todo := &model.Todo{ Text: input.Text, ID: fmt.Sprintf("T%d", rand.Int()), User: &model.User{ID: input.UserID, Name: "user " + input.UserID}, } r.todos = append(r.todos, todo) return todo, nil } func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) { return r.todos, nil }
運行服務器
我們現在有一個工作服務器,可以啟動它:
go run server.go
在瀏覽器中打開 http://localhost:8080。以下是一些要嘗試的查詢,從創建待辦事項開始:
mutation createTodo { createTodo(input: { text: "todo", userId: "1" }) { user { id } text done } }
然后查詢它:
query findTodos { todos { text done user { name } } }
不要急切地獲取用戶
這個例子很棒,但在現實世界中獲取大多數對象的成本很高。我們不想在待辦事項上加載用戶,除非用戶確實要求它。所以讓我們用Todo
更真實的東西替換生成的模型。
創建一個名為的新文件 graph/model/todo.go
package model type Todo struct { ID string `json:"id"` Text string `json:"text"` Done bool `json:"done"` UserID string `json:"user"` }
筆記
默認情況下,gqlgen 將使用模型目錄中與名稱匹配的任何模型,這可以在
gqlgen.yml
.
並運行go run github.com/99designs/gqlgen generate
。
現在,如果我們查看,graph/schema.resolvers.go
我們可以看到一個新的解析器,讓我們實現它並修復CreateTodo
.
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { todo := &model.Todo{ Text: input.Text, ID: fmt.Sprintf("T%d", rand.Int()), UserID: input.UserID, // fix this line } r.todos = append(r.todos, todo) return todo, nil } func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User, error) { return &model.User{ID: obj.UserID, Name: "user " + obj.UserID}, nil }
收尾工作
在我們的resolver.go
,package
和之間import
,添加以下行:
//go:generate go run github.com/99designs/gqlgen
這個神奇的注釋告訴go generate
我們要重新生成代碼時要運行的命令。要在整個項目中遞歸運行 go generate,請使用以下命令:
go generate ./...
失敗 執行 go get github.com/99designs/gqlgen/cmd@v0.14.0