Graphql Go основан на практиках Golang.

GraphQL
Graphql Go основан на практиках Golang.

GraphQL

GraphQL — это и язык запросов для API, и среда выполнения, которая удовлетворяет вашим запросам данных. GraphQL предоставляет полное и простое для понимания описание данных в вашем API, позволяя клиентам получать именно те данные, которые им нужны, без какой-либо избыточности, упрощая развитие API с течением времени, и может использоваться для создания мощных инструментов разработчика. .

При разработке серверов на основе узлов технология GraphQL является более зрелой и широко используемой. Как высокопроизводительный современный язык, Golang также имеет высокий уровень использования при разработке веб-серверов, и он действительно ароматен при совместном использовании.

в соответствии сКод официального сайта GraphQLнайти вgraphql-go: реализация GraphQL на Go/Golang.
Эта библиотека также инкапсулируетgraphql-go-handler: ПО промежуточного слоя, которое обрабатывает запросы GraphQL через HTTP-запросы.

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/graphql-go/graphql"
)

func main() {
	// Schema
	fields := graphql.Fields{
		"hello": &graphql.Field{
			Type: graphql.String,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return "world", nil
			},
		},
	}
	rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
	schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
	schema, err := graphql.NewSchema(schemaConfig)
	if err != nil {
		log.Fatalf("failed to create new schema, error: %v", err)
	}

	// Query
	query := `
		{
			hello
		}
	`
	params := graphql.Params{Schema: schema, RequestString: query}
	r := graphql.Do(params)
	if len(r.Errors) > 0 {
		log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors)
	}
	rJSON, _ := json.Marshal(r)
	fmt.Printf("%s \n", rJSON) // {“data”:{“hello”:”world”}}
}

Давайте начнем

goВерсия, рекомендуемая после 1.12, по созданному проекту должна иметьgo.modУправление пакетами зависимостей,поговорим о го модеЗдесь не объясняется.

Согласно приведенному выше примеру, вам нужно иметьSchema,QueryПосле совместного синтаксического анализа для создания объекта документа запроса используйте средство запроса для анализа объекта документа запроса.

первый шаг

Обычно рекомендуемый синтаксис SDL.graphqlфайл, более строгая типизация требует написания кода, подобного следующему.

// schemaQuery 查询函数路由
var schemaQuery= graphql.NewObject(graphql.ObjectConfig{
	Name:        graphql.DirectiveLocationQuery,
	Description: "查询函数",
	Fields: graphql.Fields{
		// 简单输出字符串
		"hello": &graphql.Field{
			Type:        graphql.String, // 返回类型
			Description: "输出 world",     // 解释说明
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				// 根据查询处理函数方法进行返回对应类型的数据值
				return "word", nil
			},
		},
		// 参数直接输出
		"echo": &graphql.Field{
			Type:        graphql.String, // 返回类型
			Description: "参数直接输出",       // 解释说明
			Args: graphql.FieldConfigArgument{ // 参数接收
				"toEcho": &graphql.ArgumentConfig{
					Type: graphql.NewNonNull(graphql.String),  // 接收参数类型,表示非空字符串
				},
			},
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				// 根据查询处理函数方法进行返回对应类型的数据值
				return p.Args["toEcho"].(string), nil
			},
		},
	},
})

второй шаг

Состав документа схемы

// Schema
var Schema graphql.Schema
Schema, _ = graphql.NewSchema(graphql.SchemaConfig{
	Query:    schemaQuery, // 查询函数Schema
	Mutation: schemaMutation, // 如果有提交函数Schema
})

третий шаг

Получить параметры и выполнить функцию запроса, соответствующую схеме

// ExecuteQuery GraphQL查询器
func ExecuteQuery(params *graphql.Params) *graphql.Result {
	params.Schema = schema
	return graphql.Do(*params)
}

четвертый шаг

Разобрать параметры в записи маршрута и использовать запрос

// 请求入口
http.HandleFunc("/graphql", func(res http.ResponseWriter, req *http.Request) {
	// JSON格式输出,状态200
	res.Header().Add("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	// 解析请求参数,得到Query、Variables、OperationName三个参数
	opts := ParseRequestOptions(req)  // 需要自己写函数处理得到参数
	// 进行graphql查询Query
	result := ExecuteQuery(&graphql.Params{  // 使用查询
		RequestString:  opts.Query,
		VariableValues: opts.Variables,
		OperationName:  opts.OperationName,
		Context:        req.Context(),
	})
	// 错误输出
	if len(result.Errors) > 0 {
		log.Printf("errors: %v", result.Errors)
	}
	// map转json序列化
	buff, _ := json.Marshal(result)
	_, _ = res.Write(buff)
})

Примерно завершено через четыре вышеуказанных шага, прост в использованииgraphqlВыполнение интерфейсных операций.

поле выбора запроса

соответствоватьgraphqlДизайн заключается в том, чтобы выводить информацию, соответствующую полю, в соответствии с соответствующим полем запроса, а не запрашивать все поля, которые нужно вернуть в соответствии с полем.
Это нужно делать после получения полей в запросеSQLПолевой запрос.
Более проблематично получить поля, которые отправляют запрос, и вы можете справиться с обходом самостоятельно.SelectionSetполучить.

В соответствии с кратким изложением большинства проблем ниже представлены два метода функционального анализа и сбора данных.

// SelectionFieldNames 查询选择字段
func SelectionFieldNames(fieldASTs []*ast.Field) []string{
	fieldNames := make([]string, 0)
	for _, field := range fieldASTs {
		selections := field.SelectionSet.Selections
		for _, selection := range selections {
			fieldNames = append(fieldNames, selection.(*ast.Field).Name.Value)
		}
	}
	return fieldNames
}

// selectedFieldsFromSelections 提交查询的字段列表
func selectedFieldsFromSelections(params graphql.ResolveParams, selections []ast.Selection) (selected map[string]interface{}, err error) {
	selected = map[string]interface{}{}
	for _, s := range selections {
		switch s := s.(type) {
		case *ast.Field:
			if s.SelectionSet == nil {
				selected[s.Name.Value] = true
			} else {
				selected[s.Name.Value], err = selectedFieldsFromSelections(params, s.SelectionSet.Selections)
				if err != nil {
					return
				}
			}
		case *ast.FragmentSpread:
			n := s.Name.Value
			frag, ok := params.Info.Fragments[n]
			if !ok {
				err = fmt.Errorf("getSelectedFields: no fragment found with name %v", n)
				return
			}
			selected[s.Name.Value], err = selectedFieldsFromSelections(params, frag.GetSelectionSet().Selections)
			if err != nil {
				return
			}
		default:
			err = fmt.Errorf("getSelectedFields: found unexpected selection type %v", s)
			return
		}
	}
	return
}

Наконец

пройти черезgraphql-goЭта библиотека реализует запросы GraphQl, используяtype,input,enumМетод параметра реализует операции CRUD. Внедрение микросервисовrestfulиgraphqlДва способа разработки, два дополняют друг друга, такие как: загрузка, веб-сокет и другой смешанный режим интерфейса.
Образец кода:GitHub

Пример средыgo:1.13,редакторvscode
Реализация официального сайта GraphQLJavaScriptиспользованиеtypescriptПишите строго типизированный код.
Если вы не знаете грамматику, рекомендуется сначала прочитать ееJavaScriptБазовая запись файла SDL.

示例目录文件说明

обучение не по теме

Golang

JavaScript

Java