
Olá pessoal! Existem muitos artigos sobre o GraphQL no Habr, mas, depois de analisá-los, descobri que todos eles ignoram uma linguagem maravilhosa como o Go. Hoje vou tentar corrigir esse mal-entendido. Para fazer isso, escreveremos uma API on Go usando o GraphQL. 
Em poucas palavras: GraphQL é uma linguagem de consulta para a criação de uma API que descreve de que forma solicitar e retornar dados (informações mais detalhadas sobre o recurso oficial graphql.imtqy.com e o hub )
Você pode argumentar que GraphQL ou REST é melhor aqui.
Teremos a API clássica: CRUD (criar, ler, atualizar, excluir) adicionar, receber, editar e excluir produtos na loja online.
No lado do servidor, usaremos a pronta implementação do GraphQL graphql-go
Primeiro você precisa baixar o graphql-go, isso pode ser feito com o comando
go get github.com/graphql-go/graphql 
A seguir, descrevemos a estrutura do produto (de forma simplificada)
 type Product struct { ID int64 `json:"id"` Name string `json:"name"` Info string `json:"info,omitempty"` Price float64 `json:"price"` } 
ID - identificador exclusivo, Name - nome, Info - informações sobre o produto, Price - preço
A primeira coisa a fazer é chamar o método Do , que aceita um esquema de dados e consulta parâmetros como parâmetros de entrada. E ele retornará os dados resultantes para nós (para posterior transmissão ao cliente)
 result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) 
Código completo func executeQuery(query string, schema graphql.Schema) *graphql.Result { result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) if len(result.Errors) > 0 { fmt.Printf("errors: %v", result.Errors) } return result } func main() { http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query().Get("query"), schema) json.NewEncoder(w).Encode(result) }) http.ListenAndServe(":8080", nil) } 
 Schema - Schema dados, RequestString - valor do parâmetro string de consulta, no nosso caso, valor da query
Esquema
Um esquema aceita dois tipos de dados raiz: Query - dados imutáveis, Mutation - dados mutáveis
 var schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }, ) 
Consulta
Query é usada para ler (e apenas ler) dados. Usando Query especificamos quais dados o servidor deve retornar.
Escreveremos uma implementação do tipo de dados Query , no nosso caso, conterá campos com informações sobre um único produto (produto) e uma lista de mercadorias (lista)
 var queryType = graphql.NewObject( graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{  "product": &graphql.Field{ Type: productType, Description: "Get product by id",  
O tipo queryType contém o Name e os Fields necessários, bem como a Description opcional (usada para a documentação)
Por sua vez, o campo Fields também contém o campo Type obrigatório e os campos Args , Resolve e Description opcionais
Args (argumentos)
Argumentos - uma lista de parâmetros transferidos do cliente para o servidor e afetando o resultado dos dados retornados. Os argumentos estão vinculados a um campo específico. E os argumentos podem ser passados na Query e na Mutation .
 ?query={product(id:1){name,info,price}} 
Nesse caso, o argumento id para o campo do product com o valor 1 indica que é necessário retornar o produto com o identificador especificado.
Para a list argumentos são omitidos, mas em um aplicativo real, pode ser, por exemplo: limit e offset .
Resolução (reconhecimento)
Toda a lógica de trabalhar com dados (por exemplo, consultas de banco de dados, processamento e filtragem) está nos reconhecedores, são eles que retornam os dados que serão transmitidos ao cliente como resposta à solicitação.
Tipo
O GraphQL usa seu sistema de tipos para descrever dados. Você pode usar os tipos básicos String , Int , Float , Boolean e seus próprios (personalizados). Para o nosso exemplo, precisaremos de um Product personalizado, que descreva todas as propriedades do produto
 var productType = graphql.NewObject( graphql.ObjectConfig{ Name: "Product", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "info": &graphql.Field{ Type: graphql.String, }, "price": &graphql.Field{ Type: graphql.Float, }, }, }, ) 
Para cada campo, o tipo de base é especificado, neste caso, graphql.String , graphql.Float , graphql.Float .
O número de campos aninhados não é limitado, portanto, você pode implementar um sistema gráfico de qualquer nível.
Mutação
Mutações são esses dados mutáveis, que incluem: adição, edição e exclusão. Caso contrário, as mutações são muito semelhantes às consultas regulares: elas também Args argumentos de Args e retornam dados de Resolve como resposta à consulta.
Vamos escrever mutações para nossos produtos.  var mutationType = graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{  "create": &graphql.Field{ Type: productType, Description: "Create new product", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String),  
 Tudo semelhante ao queryType . Existe apenas um pequeno tipo de recurso graphql.NewNonNull(graphql.Int) , que indica que esse campo não pode estar vazio (semelhante a NOT NULL no MySQL)
Só isso. Agora, temos uma API Go CRUD simples para trabalhar com mercadorias. Não usamos o banco de dados para este exemplo, mas vimos como criar um modelo de dados e manipulá-los usando mutações.
Exemplos
Se você baixou a fonte através do
 go get github.com/graphql-go/graphql 
basta ir ao diretório com um exemplo
 cd examples/crud 
e execute o aplicativo
 go run main.go 
Você pode usar as seguintes consultas:
Obtendo produto por ID
http://localhost:8080/product?query={product(id:1){name,info,price}}
Obtendo uma lista de produtos
http://localhost:8080/product?query={list{id,name,info,price}}
Adicionar novo produto
http://localhost:8080/product?query=mutation+_{create(name:"Tequila",info:"Strong alcoholic beverage",price:999){id,name,info,price}}
Edição do produto
http://localhost:8080/product?query=mutation+_{update(id:1,price:195){id,name,info,price}}
Removendo um Produto por ID
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
Se você usa o REST, preste atenção ao GraphQL como uma possível alternativa. Sim, à primeira vista, parece mais difícil, mas vale a pena começar e em alguns dias você dominará essa tecnologia. Pelo menos será útil.