ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

在 golang 中构建 GraphQL 服务器 ggenql

2021-10-02 12:32:45  阅读:233  来源: 互联网

标签:graph golang gqlgen GraphQL ggenql go input model Todo


官方文档地址 :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.gopackage和之间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

标签:graph,golang,gqlgen,GraphQL,ggenql,go,input,model,Todo
来源: https://www.cnblogs.com/brady-wang/p/15361694.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有