рдЖрдЬ рд╣рдо Golang + GraphQL рдореЗрдВ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░реЗрдВрдЧреЗредрд╣рдо рдЕрдХреНрд╕рд░ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдЧреНрд░рд╛рдлрдХрд▓рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВ: рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ, рд░реВрдмреА, рдФрд░ рдЕрдм рд╣рдорд╛рд░реЗ рд╣рд╛рде рдЧреЛрд▓рдВрдЧ рдЧреНрд░рд╛рдлрдХрд▓рд╛рдЗрди рдмрдВрдбрд▓ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рдмрд┐рдВрджреБ рдкрд░ рдкрд╣реБрдВрдЪ рдЧрдП рд╣реИрдВредрдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдЧреНрд░рд╛рдлрдХреНрдпреВрдПрд▓ рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ рдХреЗ рдлрд╛рдпрджреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ, рдХрдИ рд▓реЛрдЧ рдЗрд╕рдХреА рд╕рд░рд▓рддрд╛, рд▓рдЪреАрд▓реЗрдкрди рдФрд░ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╢рдВрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЬрдм рджреЛрдиреЛрдВ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВредGraphQL, GraphiQL рдпрд╛ GraphQL Playground рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП рдЕрдХреНрд╕рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рдФрд░ рдПрдкреАрдЖрдИ рдкреНрд░рд▓реЗрдЦрди рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕редрд╕реНрдерд╛рдиреАрдп рд╕реНрддрд░ рдкрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреНрд▓реЗрдЧреНрд░рд╛рдЙрдВрдб рдХреЛ рддреИрдирд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдЦреБрд▓реЗ рд╕реНрд░реЛрдд рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ - рдЧреНрд░рд╛рдлрд▓-рдЧреЛ рдХреЗ рд▓рд┐рдП рдЧреЛрд▓рдВрдЧ рдПрдЪрдЯреАрд╣реИрдВрдбрд▓рд░ред
рдпрд╣ рдПрдХ рдЦреЗрд▓ рдХреЗ рдореИрджрд╛рди рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИредрдЖрдЗрдП рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдПрдЧрд╛ рдХрд┐ рдЧреНрд░рд╛рдлрдХреЙрдХ рдФрд░ рдЧреЛ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдПред рдкреВрд░рд╛ рдЖрд╡реЗрджрди рдХреЛрдб рдЬреАрдердм рдкрд░ рд▓рд┐рдВрдХ рдкрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ редрд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╕рд░реНрд╡рд░ рдФрд░ рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗредfunc main() {
schema, err := graphql.NewSchema(defineSchema())
if err != nil {
log.Panic("Error when creating the graphQL schema", err)
}
h := handler.New(&handler.Config{
Schema: &schema,
Pretty: true,
GraphiQL: false,
Playground: true,
})
http.Handle("/graphql", h)
err = http.ListenAndServe(":8080", nil)
if err != nil {
log.Panic("Error when starting the http server", err)
}
}
рдХреЛрдИ рднреА рд░реЗрдЦрд╛рдВрдХрди рдмреИрдХрдПрдВрдб рдпреЛрдЬрдирд╛ рдХреЗ рд╡рд┐рд╡рд░рдг рдХреЗ рдмрд┐рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЕрдм рд╣рдо рдЗрд╕рдХреЗ рд╡рд┐рд╡рд░рдг рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗредvar User = graphql.NewObject(
graphql.ObjectConfig{
Name: "User",
Fields: graphql.Fields{
"_id": &graphql.Field{
Type: ObjectID,
},
"firstName": &graphql.Field{
Type: graphql.String,
},
"lastName": &graphql.Field{
Type: graphql.String,
},
"email": &graphql.Field{
Type: graphql.String,
},
},
},
)
var UserInput = graphql.NewInputObject(
graphql.InputObjectConfig{
Name: "UserInput",
Fields: graphql.InputObjectConfigFieldMap{
"firstName": &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
"lastName": &graphql.InputObjectFieldConfig{
Type: graphql.Int,
},
"email": &graphql.InputObjectFieldConfig{
Type: graphql.String,
},
},
},
)
func defineSchema() graphql.SchemaConfig {
return graphql.SchemaConfig{
Query: graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"users": &graphql.Field{
Name: "users",
Type: graphql.NewList(User),
Resolve: usersResolver,
},
},
}),
Mutation: graphql.NewObject(graphql.ObjectConfig{
Name: "Mutation",
Fields: graphql.Fields{
"addUser": &graphql.Field{
Name: "addUser",
Type: User,
Resolve: addUserResolver,
Args: graphql.FieldConfigArgument{
"input": &graphql.ArgumentConfig{
Type: UserInput,
},
},
},
},
})}
}
рдКрдкрд░, рд╣рдордиреЗ рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдХрд╛рд░ _id, firstName, lastName рдФрд░ рдИрдореЗрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛, рдЬрд┐рд╕реЗ рд╣рдо рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдЬрд╡рд╛рдм рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред _Id рдлрд╝реАрд▓реНрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЬреЛ рдПрдХ рдХрд╕реНрдЯрдо рдкреНрд░рдХрд╛рд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореВрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рдХрд╛рд░ MongoDB рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛, рдЬреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реИредtype InsertOneResult struct {
InsertedID interface{}
}
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд▓рд┐рдП рдЗрдирдкреБрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, UserInput рдкреНрд░рдХрд╛рд░ 3 рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝реАрд▓реНрдб рд╕реЗ рдмрдирд╛ рдерд╛ рдЬреЛ рд╣рдорд╛рд░реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдореЗрдВ _id рдлрд╝реАрд▓реНрдб рдЕрдиреБрдкрд╕реНрдерд┐рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдореЗрдВ рдЙрддреНрдкрдиреНрди рд╣реЛрдЧреАредрдореЛрдВрдЧреЛрдбрдм рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЧреЛрд▓рдВрдЧ рдореЛрдВрдЧреЛрдбрдм рдбреНрд░рд╛рдЗрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИредfunc usersCollection() *mongo.Collection {
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://mongo:27017"))
if err != nil {
log.Panic("Error when creating mongodb connection client", err)
}
collection := client.Database("testing").Collection("users")
err = client.Connect(ctx)
if err != nil {
log.Panic("Error when connecting to mongodb", err)
}
return collection
}
func usersResolver(_ graphql.ResolveParams) (interface{}, error) {
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
collection := usersCollection()
result, err := collection.Find(ctx, bson.D{})
if err != nil {
log.Print("Error when finding user", err)
return nil, err
}
defer result.Close(ctx)
var r []bson.M
err = result.All(ctx, &r)
if err != nil {
log.Print("Error when reading users from cursor", err)
}
return r, nil
}
func addUserResolver(p graphql.ResolveParams) (interface{}, error) {
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
collection := usersCollection()
id, err := collection.InsertOne(ctx, p.Args["input"])
if err != nil {
log.Print("Error when inserting user", err)
return nil, err
}
var result bson.M
err = collection.FindOne(ctx, bson.M{"_id": id.InsertedID}).Decode(&result)
if err != nil {
log.Print("Error when finding the inserted user by its id", err)
return nil, err
}
return result, nil
}
рдпрд╣рд╛рдВ рд╣рдордиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдореЛрдВрдЧреЙрдбрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдзрд┐рдЧреНрд░рд╣рдг рдФрд░ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ред рдЗрд╕ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рдмрдЬрд╛рдп, рдЖрдк рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рджреЛрдиреЛрдВ рдЧреИрд░-рд╕рдВрдмрдВрдзрдкрд░рдХ рдФрд░ рд╕рдВрдмрдВрдзрдкрд░рдХ, рдХреНрдпреЛрдВрдХрд┐ рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╣рдореЗрдВ рдбреЗрдЯрд╛рдмреЗрд╕ рдЪреБрдирдиреЗ рдореЗрдВ рд╕реАрдорд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИредрдореИрдВрдиреЗ рдЧреЙрд▓рдВрдЧ рдФрд░ рдореЛрдВрдЧреЛрдбрдм рдХреЛ рдмрдВрдбрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХрдЯрд░ рдХрдВрдкреЛрдЬрд╝ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯреА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ред рд╕рдм рдХреБрдЫ рддреИрдпрд╛рд░ рд╣реИред рдЧреЛрд▓рдВрдЧ рдореЛрдВрдЧреЛ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рд╣рдореЗрдВ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рдкреНрд░рд╢реНрдиреЛрдВ рд╕реЗ рд╡рд╛рдкрд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИредversion: '3'
services:
graphql:
image: golang
volumes:
- .:/go/src
command: /bin/bash -c "cd src && go run *.go"
ports:
- 8080:8080
mongo:
image: mongo
рдмреЗрд╢рдХ, рдпрд╣ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдлреА рд╕рд░рд▓ рдФрд░ рдХреЙрдореНрдкреИрдХреНрдЯ рдирд┐рдХрд▓рд╛ред рдФрд░ рдЗрд╕реЗ рдЖрдкрдХреА рдЕрдЧрд▓реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдирдП рдкреНрд░рдХрд╛рд░, рдЕрдиреБрд░реЛрдз рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдФрд░ рдЕрдиреНрдп рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдкреВрд░рдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдмрд╛рд░ рд╣рдордиреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреБрдЫ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛, рд╕рджрд╕реНрдпрддрд╛ред рд╢рд╛рдпрдж рдореИрдВ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЬрд╛рд░реА рд░рдЦреВрдВрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ рдпрджрд┐ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреБрдЫ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рдерд╛ рдФрд░ рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╣рдо рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред