These steps cover writing and running your application:
- From your Terminal or console application, create a new directory called ~/projects/go-programming-cookbook/chapter12/graphql and navigate to this directory.
- Run this command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter12/graphql
You should see a file called go.mod that contains the following:
module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter12/graphql
- Copy the tests from ~/projects/go-programming-cookbook-original/chapter12/graphql, or use this as an exercise to write some of your own code!
- Create and navigate to the cards directory.
- Create a file called card.go with the following content:
package cards
// Card represents a standard playing
// card
type Card struct {
Value string
Suit string
}
var cards []Card
func init() {
cards = []Card{
{"A", "Spades"}, {"2", "Spades"}, {"3", "Spades"},
{"4", "Spades"}, {"5", "Spades"}, {"6", "Spades"},
{"7", "Spades"}, {"8", "Spades"}, {"9", "Spades"},
{"10", "Spades"}, {"J", "Spades"}, {"Q", "Spades"},
{"K", "Spades"},
{"A", "Hearts"}, {"2", "Hearts"}, {"3", "Hearts"},
{"4", "Hearts"}, {"5", "Hearts"}, {"6", "Hearts"},
{"7", "Hearts"}, {"8", "Hearts"}, {"9", "Hearts"},
{"10", "Hearts"}, {"J", "Hearts"}, {"Q", "Hearts"},
{"K", "Hearts"},
{"A", "Clubs"}, {"2", "Clubs"}, {"3", "Clubs"},
{"4", "Clubs"}, {"5", "Clubs"}, {"6", "Clubs"},
{"7", "Clubs"}, {"8", "Clubs"}, {"9", "Clubs"},
{"10", "Clubs"}, {"J", "Clubs"}, {"Q", "Clubs"},
{"K", "Clubs"},
{"A", "Diamonds"}, {"2", "Diamonds"}, {"3",
"Diamonds"},
{"4", "Diamonds"}, {"5", "Diamonds"}, {"6",
"Diamonds"},
{"7", "Diamonds"}, {"8", "Diamonds"}, {"9",
"Diamonds"},
{"10", "Diamonds"}, {"J", "Diamonds"}, {"Q",
"Diamonds"},
{"K", "Diamonds"},
}
}
- Create a file called type.go with the following content:
package cards
import "github.com/graphql-go/graphql"
// CardType returns our card graphql object
func CardType() *graphql.Object {
cardType := graphql.NewObject(graphql.ObjectConfig{
Name: "Card",
Description: "A Playing Card",
Fields: graphql.Fields{
"value": &graphql.Field{
Type: graphql.String,
Description: "Ace through King",
Resolve: func(p graphql.ResolveParams)
(interface{}, error) {
if card, ok := p.Source.(Card); ok {
return card.Value, nil
}
return nil, nil
},
},
"suit": &graphql.Field{
Type: graphql.String,
Description: "Hearts, Diamonds, Clubs, Spades",
Resolve: func(p graphql.ResolveParams)
(interface{}, error) {
if card, ok := p.Source.(Card); ok {
return card.Suit, nil
}
return nil, nil
},
},
},
})
return cardType
}
- Create a file called resolve.go with the following content:
package cards
import (
"strings"
"github.com/graphql-go/graphql"
)
// Resolve handles filtering cards
// by suit and value
func Resolve(p graphql.ResolveParams) (interface{}, error) {
finalCards := []Card{}
suit, suitOK := p.Args["suit"].(string)
suit = strings.ToLower(suit)
value, valueOK := p.Args["value"].(string)
value = strings.ToLower(value)
for _, card := range cards {
if suitOK && suit != strings.ToLower(card.Suit) {
continue
}
if valueOK && value != strings.ToLower(card.Value) {
continue
}
finalCards = append(finalCards, card)
}
return finalCards, nil
}
- Create a file called schema.go with the following content:
package cards
import "github.com/graphql-go/graphql"
// Setup prepares and returns our card
// schema
func Setup() (graphql.Schema, error) {
cardType := CardType()
// Schema
fields := graphql.Fields{
"cards": &graphql.Field{
Type: graphql.NewList(cardType),
Args: graphql.FieldConfigArgument{
"suit": &graphql.ArgumentConfig{
Description: "Filter cards by card suit
(hearts, clubs, diamonds, spades)",
Type: graphql.String,
},
"value": &graphql.ArgumentConfig{
Description: "Filter cards by card
value (A-K)",
Type: graphql.String,
},
},
Resolve: Resolve,
},
}
rootQuery := graphql.ObjectConfig{Name: "RootQuery",
Fields: fields}
schemaConfig := graphql.SchemaConfig{Query:
graphql.NewObject(rootQuery)}
schema, err := graphql.NewSchema(schemaConfig)
return schema, err
}
- Navigate back to the graphql directory.
- Create a new directory named example and navigate to it.
- Create a file named main.go with the following content:
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/PacktPublishing/
Go-Programming-Cookbook-Second-Edition/
chapter12/graphql/cards"
"github.com/graphql-go/graphql"
)
func main() {
// grab our schema
schema, err := cards.Setup()
if err != nil {
panic(err)
}
// Query
query := `
{
cards(value: "A"){
value
suit
}
}`
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, err := json.MarshalIndent(r, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s ", rJSON)
}
- Run go run main.go.
- You may also run the following command:
$ go build
$ ./example
You should see the following output:
$ go run main.go
{
"data": {
"cards": [
{
"suit": "Spades",
"value": "A"
},
{
"suit": "Hearts",
"value": "A"
},
{
"suit": "Clubs",
"value": "A"
},
{
"suit": "Diamonds",
"value": "A"
}
]
}
}
- Test some additional queries, such as the following:
- cards(suit: "Spades")
- cards(value: "3", suit:"Diamonds")
- The go.mod file may be updated, and the go.sum file should now be present in the top-level recipe directory.
- If you have copied or written your own tests, go up one directory and run go test. Ensure that all the tests pass.