├── .gitignore
├── README.md
├── graphiql.html
├── lessons
├── 01-hello-go.es.md
└── 01-hello-go.md
├── main.go
└── schema.graphql
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/go,linux,macos,windows
3 |
4 | ### Go ###
5 | # Binaries for programs and plugins
6 | *.exe
7 | *.dll
8 | *.so
9 | *.dylib
10 |
11 | # Test binary, build with `go test -c`
12 | *.test
13 |
14 | # Output of the go coverage tool, specifically when used with LiteIDE
15 | *.out
16 |
17 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
18 | .glide/
19 |
20 | ### Linux ###
21 | *~
22 |
23 | # temporary files which can be created if a process still has a handle open of a deleted file
24 | .fuse_hidden*
25 |
26 | # KDE directory preferences
27 | .directory
28 |
29 | # Linux trash folder which might appear on any partition or disk
30 | .Trash-*
31 |
32 | # .nfs files are created when an open file is removed but is still being accessed
33 | .nfs*
34 |
35 | ### macOS ###
36 | *.DS_Store
37 | .AppleDouble
38 | .LSOverride
39 |
40 | # Icon must end with two \r
41 | Icon
42 |
43 | # Thumbnails
44 | ._*
45 |
46 | # Files that might appear in the root of a volume
47 | .DocumentRevisions-V100
48 | .fseventsd
49 | .Spotlight-V100
50 | .TemporaryItems
51 | .Trashes
52 | .VolumeIcon.icns
53 | .com.apple.timemachine.donotpresent
54 |
55 | # Directories potentially created on remote AFP share
56 | .AppleDB
57 | .AppleDesktop
58 | Network Trash Folder
59 | Temporary Items
60 | .apdisk
61 |
62 | ### Windows ###
63 | # Windows thumbnail cache files
64 | Thumbs.db
65 | ehthumbs.db
66 | ehthumbs_vista.db
67 |
68 | # Folder config file
69 | Desktop.ini
70 |
71 | # Recycle Bin used on file shares
72 | $RECYCLE.BIN/
73 |
74 | # Windows Installer files
75 | *.cab
76 | *.msi
77 | *.msm
78 | *.msp
79 |
80 | # Windows shortcuts
81 | *.lnk
82 |
83 | # End of https://www.gitignore.io/api/go,linux,macos,windows
84 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GraphQL Go Introduction
2 |
3 | >This introduction was stopped give that the graphql-go api was going through some [changes](https://github.com/neelance/graphql-go/issues/88) that make it easier to get started and really simple. As soon as is updated i will use it from scratch
4 |
5 | This repo is a small introduction where i will try to explain how to create a graphql server in go with [graphql-go](https://github.com/neelance/graphql-go) by [neelance](https://github.com/neelance), i hope that anybody that's looking into graphql and go could benefit from this.
6 |
7 | Before you start make sure you have go installed, and have graphql-go installed as well by running `go get github.com/neelance/graphql-go`
8 |
9 | You can start here at [hello-go](https://github.com/lpalmes/graphql-go-introduction/blob/master/lessons/01-hello-go.md)
10 |
11 | I will try my best to have each lesson in english as well as spanish (my native language), if find something unclear, missing or badly explanied, whatever it is, please send an issue, pull request, or scream it through your window and i will attend your call for help.
12 | ___
13 |
14 | # Introduccion a GraphQL Go
15 | Este repositorio es una pequeña introduccion donde voy a intentar explicar como crear un servidor graphql en go usando [graphql-go](https://github.com/neelance/graphql-go) de [neelance](https://github.com/neelance), espero que cualquier intentando usar graphql y go pueda usar esta guia para empezar.
16 |
17 | Antes de empezar asegurate que tenes go instalado y que tenes graphql-go instalado tambien, sino podes instalarlo mediante `go get github.com/neelance/graphql-go`
18 |
19 | Podes empezar aca en [hola-go](https://github.com/lpalmes/graphql-go-introduction/blob/master/lessons/01-hello-go.es.md)
20 |
21 | Voy a intentar tener cada leccion en ingles y en español, si encuentran algo confuso, faltante o mal explicado, lo que sea, porfavor manda un issue, pull request, o gritalo a todo pulmon en tu departamento a eso de las 4 de la mañana, y voy a intentar responder inmediatamente.
22 |
--------------------------------------------------------------------------------
/graphiql.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Loading...
12 |
34 |
35 |
--------------------------------------------------------------------------------
/lessons/01-hello-go.es.md:
--------------------------------------------------------------------------------
1 | # Hola GraphQL-Go!
2 |
3 |
4 | Si sabes un poco sobre graphql podes empezar tranquilamente, sino voy a intentar explicarlo mientras avanzemos.
5 |
6 | ## Este es nuestro schema
7 |
8 | ```
9 | schema {
10 | query: Query
11 | }
12 |
13 | type Query {
14 | hello: String!
15 | }
16 | ```
17 |
18 | Aca el [schema](http://graphql.org/learn/schema/#the-query-and-mutation-types) define el comienzo de los queries y las mutations, por ahora solamente vamos a usar Query.
19 | Voy a intentar traducir este texto de [graphql.org](http://graphql.org).
20 | >Cada servicio de GraphQL tiene un objeto tipo Query y puede tener o no un objeto tipo Mutation. Estos tipos de objetos son lo mismo que objetos regulares, pero en este caso son especiales por que definen la entrada a cada query de GraphQL.
21 |
22 | El objeto Query aca tiene una sola propiedad, `hello: String!` la cual vamos a utilizar cuando usemos nuestro servidor graphql.
23 |
24 | Todos las propiedades de Query deben ser resueltas por nosotros. Por eso vamos a usar un `struct` para declarar un `Resolver`
25 |
26 | Este va a ser el struct principal que vamos a usar para resolver todos los Query y Mutations que tengamos.
27 | ```go
28 | type Resolver struct {}
29 | ```
30 |
31 | Y esta funcion va a resolver nuestro `hello: String!`.
32 |
33 | ```go
34 | func (r *Resolver) Hello() string {
35 | return "world"
36 | }
37 | ```
38 | Fijate que nuestra funcion esta exportada al tener la primera letra en mayuscula, y ademas devuelve un `string` por que declaramos `hello` de tipo `String!`, el `!` declara que hello no debe ser null, por eso podemos devolver un `string` en vez de un `*string`
39 |
40 | Esto es todo lo que vamos a necesitar! ᕕ( ᐛ )ᕗ
41 |
42 | Se puede ver que en `main.go` tenemos
43 | ``` go
44 | schemaFile, err := ioutil.ReadFile("schema.graphql")
45 | schema, err = graphql.ParseSchema(string(schemaFile), &Resolver{})
46 | ```
47 | para leer nuestro archivo `schema.graphql` que va a convertirlo en un struct tipo `graphqlSchema`. Le tenemos que pasar nuestro `Resolver struct` para que resuelva los queries como `Hello()` en este caso.
48 |
49 | Despues solamente se lo pasamos a nuestra funcion `http.Handle()` y eso es todo
50 | ```go
51 | http.Handle("/graphql", &relay.Handler{Schema: schema})
52 | ```
53 |
54 | Tene en cuenta que si cambias la direccion de nuestro `Handle` tambien tenes que cambiarla en el archivo `graphiql.html` para que apunte al servidor apropiadamente
55 |
56 |
57 | Ahora si corres `go run main.go` vas a poder ver que nuestro servidor esta funcionando en `http://localhost:8080` y vamos a poder usar graphiql
58 |
59 | Solamente copia esto en el panel izquierdo y dale click a la flecha de arriba (mac: `cmd + enter` windows: `ctrl + enter` si estas muy apurado)
60 | ```
61 | {
62 | hello
63 | }
64 | ```
65 | Este es nuestro primer query, y si a la derecha hay algo como esto, parece que todo anduvo perfectamente.
66 | ```
67 | {
68 | "data": {
69 | "hello": "world"
70 | }
71 | }
72 | ```
--------------------------------------------------------------------------------
/lessons/01-hello-go.md:
--------------------------------------------------------------------------------
1 | # Hello GraphQL-Go!
2 |
3 | If you know a bit about graphql you are in good shape to start, if you don't i will try to explain everything down the road.
4 |
5 | ## Here it is a quick rundown of the schema.
6 |
7 | ```graphql
8 | schema {
9 | query: Query
10 | }
11 |
12 | type Query {
13 | hello: String!
14 | }
15 | ```
16 |
17 | Here the [schema](http://graphql.org/learn/schema/#the-query-and-mutation-types) defines the start of the graphql queries and mutations, we will only use Query for now.
18 | This bit below is from [graphql.org](http://graphql.org)
19 | >Every GraphQL service has a query type and may or may not have a mutation type. These types are the same as a regular object type, but they are special because they define the entry point of every GraphQL query.
20 |
21 | The Query object here only contains one field, `hello: String!` which we will be able to use when working with our graphql server.
22 |
23 | All of these Query fields should be resolved by us. So we use a `struct` to declare a main Resolver
24 |
25 | This will be the main Resolver that we will use
26 | ```go
27 | type Resolver struct {}
28 | ```
29 |
30 | And this func will resolve our `hello: String!`.
31 |
32 | ```go
33 | func (r *Resolver) Hello() string {
34 | return "world"
35 | }
36 | ```
37 | Notice that our func is exported by having the first letter beign uppercased, and our `func` returns a `string` because we declared `hello` to be a `String!`, The `!` declares that hello should not be null, so that's why we are able to return a `string` rather than a `*string`
38 |
39 | That's everything that we will need! ᕕ( ᐛ )ᕗ
40 |
41 | You can see in `main.go` that we also have
42 | ``` go
43 | schemaFile, err := ioutil.ReadFile("schema.graphql")
44 | schema, err = graphql.ParseSchema(string(schemaFile), &Resolver{})
45 | ```
46 | to read our `schema.graphql` file and then convert it to a `graphql.Schema` type. We have to pass our `Resolver struct` so it can use our resolvers like `Hello()` in this case
47 |
48 | Then we just pass it to a `http.Handle()` function and that's it
49 | ```go
50 | http.Handle("/graphql", &relay.Handler{Schema: schema})
51 | ```
52 |
53 | Keep in mind if you change the path you should change your path in graphiql.html script given that it points to your graphql handler
54 |
55 | Now if you `go run main.go` you will be able to see that our server runs and if we go to `http://localhost:8080` you will be able to use graphiql
56 |
57 | Just paste this into the left panel and click the play arrow at the top left (`cmd + enter` is faster for those who have to pickup their pet from the hair salon in 5 min)
58 | ```graphql
59 | {
60 | hello
61 | }
62 | ```
63 | This is the first query, and if you something like this at the right, all went pretty pretty good.
64 | ```
65 | {
66 | "data": {
67 | "hello": "world"
68 | }
69 | }
70 | ```
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "io/ioutil"
8 |
9 | "fmt"
10 |
11 | "github.com/neelance/graphql-go"
12 | "github.com/neelance/graphql-go/relay"
13 | )
14 |
15 | // This will be use by our handler at /graphql
16 | var schema *graphql.Schema
17 |
18 | // This function runs at the start of the program
19 | func init() {
20 |
21 | // We get the schema from the file, rather than having the schema inline here
22 | // I think will lead to better organizaiton of our own code
23 | schemaFile, err := ioutil.ReadFile("schema.graphql")
24 | if err != nil {
25 | // We will panic if we don't find the schema.graphql file in our server
26 | panic(err)
27 | }
28 |
29 | // We will use graphql-go library to parse our schema from "schema.graphql"
30 | // and the resolver is our struct that should fullfill everything in the Query
31 | // from our schema
32 | schema, err = graphql.ParseSchema(string(schemaFile), &Resolver{})
33 | if err != nil {
34 | panic(err)
35 | }
36 | }
37 |
38 | func main() {
39 | // We will start a small server that reads our "graphiql.html" file and
40 | // responds with it, so we are able to have our own graphiql
41 | http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
42 | page, err := ioutil.ReadFile("graphiql.html")
43 | if err != nil {
44 | log.Fatal(err)
45 | }
46 | w.Write(page)
47 | }))
48 |
49 | // This is where our graphql server is handled, we declare "/graphql" as the route
50 | // where all our graphql requests will be directed to
51 | http.Handle("/graphql", &relay.Handler{Schema: schema})
52 |
53 | // We start the server by using ListenAndServe and we log if we have any error, hope not!
54 | fmt.Println("Listening at http://localhost:8080")
55 | log.Fatal(http.ListenAndServe(":8080", nil))
56 | }
57 |
58 | // Resolver struct is the main resolver wich we will use to fullfill
59 | // queries and mutations that our schema.graphql defines
60 | type Resolver struct{}
61 |
62 | // Hello function resolves to hello: String! in the Query object in our schema.graphql
63 | func (r *Resolver) Hello() string {
64 | return "world"
65 | }
66 |
--------------------------------------------------------------------------------
/schema.graphql:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | }
4 |
5 | type Query {
6 | hello: String!
7 | }
--------------------------------------------------------------------------------