github.com/bewolv/gqlgen@v0.10.12/docs/content/getting-started.md (about)

     1  ---
     2  linkTitle: Getting Started
     3  title: Building GraphQL servers in golang
     4  description: Get started building type-safe GraphQL servers in Golang using gqlgen  
     5  menu: main
     6  weight: -7
     7  ---
     8  
     9  This tutorial will take you through the process of building a GraphQL server with gqlgen that can:
    10  
    11   - Return a list of todos
    12   - Create new todos
    13   - Mark off todos as they are completed
    14  
    15  You can find the finished code for this tutorial [here](https://github.com/vektah/gqlgen-tutorials/tree/master/gettingstarted)
    16  
    17  > Note
    18  >
    19  > This tutorial uses Go Modules and requires Go 1.11+.  If you want to use this tutorial without Go Modules, take a look at our [Getting Started Using dep]({{< ref "getting-started-dep.md" >}}) guide instead.
    20  
    21  ## Setup Project
    22  
    23  Create a directory for your project, and initialise it as a Go Module:
    24  
    25  ```sh
    26  $ mkdir gqlgen-todos
    27  $ cd gqlgen-todos
    28  $ go mod init github.com/[username]/gqlgen-todos
    29  ```
    30  
    31  ## Building the server
    32  
    33  ### Define the schema
    34  
    35  gqlgen is a schema-first library — before writing code, you describe your API using the GraphQL 
    36  [Schema Definition Language](http://graphql.org/learn/schema/). This usually goes into a file called `schema.graphql`. A basic example as follows will be generated by the `init` command:
    37  
    38  ```graphql
    39  type Todo {
    40    id: ID!
    41    text: String!
    42    done: Boolean!
    43    user: User!
    44  }
    45  
    46  type User {
    47    id: ID!
    48    name: String!
    49  }
    50  
    51  type Query {
    52    todos: [Todo!]!
    53  }
    54  
    55  input NewTodo {
    56    text: String!
    57    userId: String!
    58  }
    59  
    60  type Mutation {
    61    createTodo(input: NewTodo!): Todo!
    62  }
    63  ```
    64  
    65  ### Create the project skeleton
    66  
    67  ```bash
    68  $ go run github.com/bewolv/gqlgen init
    69  ```
    70  
    71  This has created an empty skeleton with all files you need:
    72  
    73   - `gqlgen.yml` — The gqlgen config file, knobs for controlling the generated code.
    74   - `generated.go` — The GraphQL execution runtime, the bulk of the generated code.
    75   - `models_gen.go` — Generated models required to build the graph. Often you will override these with your own models. Still very useful for input types.
    76   - `resolver.go` — This is where your application code lives. `generated.go` will call into this to get the data the user has requested. 
    77   - `server/server.go` — This is a minimal entry point that sets up an `http.Handler` to the generated GraphQL server.
    78   
    79  ### Create the database models
    80  
    81  The generated model for Todo isn't right, it has a user embeded in it but we only want to fetch it if the user actually requested it. So instead lets make a new model in `todo.go`:
    82  
    83  ```go
    84  package gqlgen_todos
    85  
    86  type Todo struct {
    87  	ID     string
    88  	Text   string
    89  	Done   bool
    90  	UserID string
    91  }
    92  ```
    93  
    94  Next tell gqlgen to use this new struct by adding it to `gqlgen.yml`:
    95  
    96  ```yaml
    97  models:
    98    Todo:
    99      model: github.com/[username]/gqlgen-todos.Todo
   100  ```
   101  
   102  Regenerate by running:
   103  
   104  ```bash
   105  $ go run github.com/bewolv/gqlgen -v
   106  ```
   107  
   108  > Note
   109  >
   110  > The verbose flag `-v` is here to show what gqlgen is doing. It has looked at all the fields on the model and found matching methods for all of them, except user. For user it has added a resolver to the interface you need to implement. *This is the magic that makes gqlgen work so well!*
   111  
   112  ### Implement the resolvers
   113  
   114  The generated runtime has defined an interface for all the missing resolvers that we need to provide. Lets take a look in `generated.go`:
   115  
   116  ```go
   117  func NewExecutableSchema(cfg Config) graphql.ExecutableSchema {}
   118  	// ...
   119  }
   120  
   121  type Config struct {
   122  	Resolvers  ResolverRoot
   123  	// ...
   124  }
   125  
   126  type ResolverRoot interface {
   127  	Mutation() MutationResolver
   128  	Query() QueryResolver
   129  	Todo() TodoResolver
   130  }
   131  
   132  type MutationResolver interface {
   133  	CreateTodo(ctx context.Context, input NewTodo) (*Todo, error)
   134  }
   135  type QueryResolver interface {
   136  	Todos(ctx context.Context) ([]Todo, error)
   137  }
   138  type TodoResolver interface {
   139  	User(ctx context.Context, obj *Todo) (*User, error)
   140  }
   141  ```
   142  
   143  Notice the `TodoResolver.User` method? Thats gqlgen saying "I dont know how to get a User from a Todo, you tell me.".
   144  Its worked out how to build everything else for us.
   145  
   146  For any missing models (like `NewTodo`) gqlgen will generate a go struct. This is usually only used for input types and 
   147  one-off return values. Most of the time your types will be coming from the database, or an API client so binding is
   148  better than generating.
   149  
   150  ### Write the resolvers
   151  
   152  This is a work in progress, we have a way to generate resolver stubs, but it cannot currently update existing code. We can force it to run again by deleting `resolver.go` and re-running gqlgen:
   153  
   154  ```bash
   155  $ rm resolver.go
   156  $ go run github.com/bewolv/gqlgen
   157  ```
   158  
   159  Now we just need to fill in the `not implemented` parts.  Update `resolver.go`
   160  
   161  ```go
   162  package gqlgen_todos
   163  
   164  import (
   165  	context "context"
   166  	"fmt"
   167  	"math/rand"
   168  )
   169  
   170  type Resolver struct {
   171  	todos []*Todo
   172  }
   173  
   174  func (r *Resolver) Mutation() MutationResolver {
   175  	return &mutationResolver{r}
   176  }
   177  func (r *Resolver) Query() QueryResolver {
   178  	return &queryResolver{r}
   179  }
   180  func (r *Resolver) Todo() TodoResolver {
   181  	return &todoResolver{r}
   182  }
   183  
   184  type mutationResolver struct{ *Resolver }
   185  
   186  func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) {
   187  	todo := &Todo{
   188  		Text:   input.Text,
   189  		ID:     fmt.Sprintf("T%d", rand.Int()),
   190  		UserID: input.UserID,
   191  	}
   192  	r.todos = append(r.todos, todo)
   193  	return todo, nil
   194  }
   195  
   196  type queryResolver struct{ *Resolver }
   197  
   198  func (r *queryResolver) Todos(ctx context.Context) ([]*Todo, error) {
   199  	return r.todos, nil
   200  }
   201  
   202  type todoResolver struct{ *Resolver }
   203  
   204  func (r *todoResolver) User(ctx context.Context, obj *Todo) (*User, error) {
   205  	return &User{ID: obj.UserID, Name: "user " + obj.UserID}, nil
   206  }
   207  
   208  ```
   209  
   210  We now have a working server, to start it:
   211  ```bash
   212  go run server/server.go
   213  ```
   214  
   215  then open http://localhost:8080 in a browser. here are some queries to try:
   216  ```graphql
   217  mutation createTodo {
   218    createTodo(input:{text:"todo", userId:"1"}) {
   219      user {
   220        id
   221      }
   222      text
   223      done
   224    }
   225  }
   226  
   227  query findTodos {
   228    	todos {
   229        text
   230        done
   231        user {
   232          name
   233        }
   234      }
   235  }
   236  ```
   237  
   238  ## Finishing touches
   239  
   240  At the top of our `resolver.go`, between `package` and `import`, add the following line:
   241  
   242  ```go
   243  //go:generate go run github.com/bewolv/gqlgen
   244  ```
   245  
   246  This magic comment tells `go generate` what command to run when we want to regenerate our code.  To run go generate recursively over your entire project, use this command:
   247  
   248  ```go
   249  go generate ./...
   250  ```