├── .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 | } --------------------------------------------------------------------------------