Skip to content

Commit 2b97f4c

Browse files
authored
Merge pull request #368 from maxchagin/master
examples: adds crud example
2 parents 2800ba0 + 8a295fb commit 2b97f4c

File tree

2 files changed

+250
-0
lines changed

2 files changed

+250
-0
lines changed

examples/crud/Readme.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Go GraphQL CRUD example
2+
3+
Implementation create, read, update and delete on Go
4+
5+
To run the program, go to the directory
6+
`cd examples/crud`
7+
8+
Run the example
9+
`go run main.go`
10+
11+
## Create
12+
`http://localhost:8080/product?query=mutation+_{create(name:"Inca Kola",info:"Inca Kola is a soft drink that was created in Peru in 1935 by British immigrant Joseph Robinson Lindley using lemon verbena (wiki)",price:1.99){id,name,info,price}}`
13+
14+
## Read
15+
Get single product by id
16+
`http://localhost:8080/product?query={product(id:1){name,info,price}}`
17+
18+
Get product list
19+
`http://localhost:8080/product?query={list{id,name,info,price}}`
20+
21+
## Update
22+
`http://localhost:8080/product?query=mutation+_{update(id:1,price:3.95){id,name,info,price}}`
23+
24+
## Delete
25+
`http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}`

examples/crud/main.go

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"math/rand"
7+
"net/http"
8+
"time"
9+
10+
"github.com/graphql-go/graphql"
11+
)
12+
13+
type Product struct {
14+
ID int64 `json:"id"`
15+
Name string `json:"name"`
16+
Info string `json:"info,omitempty"`
17+
Price float64 `json:"price"`
18+
}
19+
20+
var products []Product
21+
22+
var productType = graphql.NewObject(
23+
graphql.ObjectConfig{
24+
Name: "Product",
25+
Fields: graphql.Fields{
26+
"id": &graphql.Field{
27+
Type: graphql.Int,
28+
},
29+
"name": &graphql.Field{
30+
Type: graphql.String,
31+
},
32+
"info": &graphql.Field{
33+
Type: graphql.String,
34+
},
35+
"price": &graphql.Field{
36+
Type: graphql.Float,
37+
},
38+
},
39+
},
40+
)
41+
42+
var queryType = graphql.NewObject(
43+
graphql.ObjectConfig{
44+
Name: "Query",
45+
Fields: graphql.Fields{
46+
/* Get (read) single product by id
47+
http://localhost:8080/product?query={product(id:1){name,info,price}}
48+
*/
49+
"product": &graphql.Field{
50+
Type: productType,
51+
Description: "Get product by id",
52+
Args: graphql.FieldConfigArgument{
53+
"id": &graphql.ArgumentConfig{
54+
Type: graphql.Int,
55+
},
56+
},
57+
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
58+
id, ok := p.Args["id"].(int)
59+
if ok {
60+
// Find product
61+
for _, product := range products {
62+
if int(product.ID) == id {
63+
return product, nil
64+
}
65+
}
66+
}
67+
return nil, nil
68+
},
69+
},
70+
/* Get (read) product list
71+
http://localhost:8080/product?query={list{id,name,info,price}}
72+
*/
73+
"list": &graphql.Field{
74+
Type: graphql.NewList(productType),
75+
Description: "Get product list",
76+
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
77+
return products, nil
78+
},
79+
},
80+
},
81+
})
82+
83+
var mutationType = graphql.NewObject(graphql.ObjectConfig{
84+
Name: "Mutation",
85+
Fields: graphql.Fields{
86+
/* Create new product item
87+
http://localhost:8080/product?query=mutation+_{create(name:"Inca Kola",info:"Inca Kola is a soft drink that was created in Peru in 1935 by British immigrant Joseph Robinson Lindley using lemon verbena (wiki)",price:1.99){id,name,info,price}}
88+
*/
89+
"create": &graphql.Field{
90+
Type: productType,
91+
Description: "Create new product",
92+
Args: graphql.FieldConfigArgument{
93+
"name": &graphql.ArgumentConfig{
94+
Type: graphql.NewNonNull(graphql.String),
95+
},
96+
"info": &graphql.ArgumentConfig{
97+
Type: graphql.String,
98+
},
99+
"price": &graphql.ArgumentConfig{
100+
Type: graphql.NewNonNull(graphql.Float),
101+
},
102+
},
103+
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
104+
rand.Seed(time.Now().UnixNano())
105+
product := Product{
106+
ID: int64(rand.Intn(100000)), // generate random ID
107+
Name: params.Args["name"].(string),
108+
Info: params.Args["info"].(string),
109+
Price: params.Args["price"].(float64),
110+
}
111+
products = append(products, product)
112+
return product, nil
113+
},
114+
},
115+
116+
/* Update product by id
117+
http://localhost:8080/product?query=mutation+_{update(id:1,price:3.95){id,name,info,price}}
118+
*/
119+
"update": &graphql.Field{
120+
Type: productType,
121+
Description: "Update product by id",
122+
Args: graphql.FieldConfigArgument{
123+
"id": &graphql.ArgumentConfig{
124+
Type: graphql.NewNonNull(graphql.Int),
125+
},
126+
"name": &graphql.ArgumentConfig{
127+
Type: graphql.String,
128+
},
129+
"info": &graphql.ArgumentConfig{
130+
Type: graphql.String,
131+
},
132+
"price": &graphql.ArgumentConfig{
133+
Type: graphql.Float,
134+
},
135+
},
136+
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
137+
id, _ := params.Args["id"].(int)
138+
name, nameOk := params.Args["name"].(string)
139+
info, infoOk := params.Args["info"].(string)
140+
price, priceOk := params.Args["price"].(float64)
141+
product := Product{}
142+
for i, p := range products {
143+
if int64(id) == p.ID {
144+
if nameOk {
145+
products[i].Name = name
146+
}
147+
if infoOk {
148+
products[i].Info = info
149+
}
150+
if priceOk {
151+
products[i].Price = price
152+
}
153+
product = products[i]
154+
break
155+
}
156+
}
157+
return product, nil
158+
},
159+
},
160+
161+
/* Delete product by id
162+
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
163+
*/
164+
"delete": &graphql.Field{
165+
Type: productType,
166+
Description: "Delete product by id",
167+
Args: graphql.FieldConfigArgument{
168+
"id": &graphql.ArgumentConfig{
169+
Type: graphql.NewNonNull(graphql.Int),
170+
},
171+
},
172+
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
173+
id, _ := params.Args["id"].(int)
174+
product := Product{}
175+
for i, p := range products {
176+
if int64(id) == p.ID {
177+
product = products[i]
178+
// Remove from product list
179+
products = append(products[:i], products[i+1:]...)
180+
}
181+
}
182+
183+
return product, nil
184+
},
185+
},
186+
},
187+
})
188+
189+
var schema, _ = graphql.NewSchema(
190+
graphql.SchemaConfig{
191+
Query: queryType,
192+
Mutation: mutationType,
193+
},
194+
)
195+
196+
func executeQuery(query string, schema graphql.Schema) *graphql.Result {
197+
result := graphql.Do(graphql.Params{
198+
Schema: schema,
199+
RequestString: query,
200+
})
201+
if len(result.Errors) > 0 {
202+
fmt.Printf("errors: %v", result.Errors)
203+
}
204+
return result
205+
}
206+
207+
func initProductsData(p *[]Product) {
208+
product1 := Product{ID: 1, Name: "Chicha Morada", Info: "Chicha morada is a beverage originated in the Andean regions of Perú but is actually consumed at a national level (wiki)", Price: 7.99}
209+
product2 := Product{ID: 2, Name: "Chicha de jora", Info: "Chicha de jora is a corn beer chicha prepared by germinating maize, extracting the malt sugars, boiling the wort, and fermenting it in large vessels (traditionally huge earthenware vats) for several days (wiki)", Price: 5.95}
210+
product3 := Product{ID: 3, Name: "Pisco", Info: "Pisco is a colorless or yellowish-to-amber colored brandy produced in winemaking regions of Peru and Chile (wiki)", Price: 9.95}
211+
*p = append(*p, product1, product2, product3)
212+
}
213+
214+
func main() {
215+
// Primary data initialization
216+
initProductsData(&products)
217+
218+
http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) {
219+
result := executeQuery(r.URL.Query().Get("query"), schema)
220+
json.NewEncoder(w).Encode(result)
221+
})
222+
223+
fmt.Println("Server is running on port 8080")
224+
http.ListenAndServe(":8080", nil)
225+
}

0 commit comments

Comments
 (0)