1.要有go.mod和go.sum这两个文件才能去执行go run github.com/99designs/gqlgen去更新generated.go和models_gen.go,在没有这两个文件的时候去执行该命令,会把generated.go文件删除
2.要执行了go mod init github.com/[username]/[project]才能生成go.mod
3.要执行了go get github.com/99designs/gqlgen才能生成go.sum
4.在generated.go里面存放了很多信息,但我们常用到的是interface接口信息,如:
type MutationResolver interface {
CreateTodo(ctx context.Context, input NewTodo) (*Todo, error)
}
在resolver.go里面去编写这些接口的实现,也就是增删改查的业务逻辑,如:
func (r *mutationResolver) CreateTodo(ctx context.Context, input NewTodo) (*Todo, error) {
newID := r.nextID
r.nextID++
newTodo := &Todo{
DatabaseID: newID,
Description: input.Text,
}
r.todos = append(r.todos, newTodo)
return newTodo, nil
}
5.gqlgen.yml的schema属性是指明schema.graphql存放的位置
schema: "*.graphql"
6.gqlgen.yml的exec.filename属性是指明generated.go存放的位置
exec:
filename: generated.go
7.gqlgen.yml的model.filename属性是指明model_gen.go存放的位置
model:
filename: models_gen.go
8.schema和struct有的字段名称可能是不匹配的,但传的值还是一样的,只是传给struct的时候改了个名称,不是直接用schema的名称,这个问题可以在gqlgen.yml里面配置解决
models:
#用于schema和struct的字段的不同名称的匹配
Todo: # Object
fields:
text:
fieldName: Description # Field
schema里面的text字段,传给struct时变成了Description
除了以上在gqlgen.xml中配置,还有一种方法也可以达到同样的效果,就是使用指令directive。在schema.graphql中编写以下代码:
directive @goField(forceResolver: Boolean, name: String) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION
type User {
id: ID!
goo:String!
name: String! @goField(name:"FullName")
}
schema里面的name字段,传给struct时变成了FullName
除了以上使用指令directive,还有第三种方法:json序列化
type Car struct {
Make string
ShortState string
LongState string `gqlgen:"state"`
Model string
Color string
OdometerReading int
}
type Car {
make: String!
model: String!
state: String!
color: String!
odometerReading: Int!
}
通过json序列化, 把schema.graphql中的LongState字段匹配到struct中的state字段
9.models_gen.go和generated.go是用go run github.com/99designs/gqlgen生成的,不用编辑
10.Resolver结构体一般包含的属性是要操作的其他结构体
11.在server.go使用NewExecutableSchema(cfg Config),可以做数据的初始化,如:
func New() Config {
c := Config{
Resolvers: &Resolver{
todos: []*Todo{
{DatabaseID: 1, Description: "A todo not to forget", Done: false},
{DatabaseID: 2, Description: "This is the most important", Done: false},
{DatabaseID: 3, Description: "Please do this or else", Done: false},
},
nextID: 3,
},
}
return c
}
type Resolver struct {
todos []*Todo
nextID int
}
12.使用了@goModel指令后,该schema无法通过命令更新到gen.go中,所以它的struct只能自定义编写,如:
type User
@goModel(model:"github.com/99designs/gqlgen/example/config.User") {
id: ID!
goo:String!
name: String! @goField(name:"FullName")
}
其实这个功能也能够在gqlgen.yml里面实现,如
models:
User:
model: github.com/99designs/gqlgen/example/config.User
13.input是输入类型,一般作为Mutation函数的参数传递,如:
input NewTodo {
text: String!
userId: String!
foo:String!
}
type Mutation {
createTodo(input: NewTodo!): Todo!
}
14.gqlgen的自定义指令一般配合着Config来使用,用来做一些数据的初始化或配置,例如,在schema.graphql中编写代码:
directive @us(id: ID!) on MUTATION | QUERY | FIELD
通过go run github.com/99designs/gqlgen命令去生成接口,在generated.go中可以看到:
type DirectiveRoot struct {
Us func(ctx context.Context, obj interface{}, next graphql.Resolver, id string) (res interface{}, err error)
}
然后就可以编写业务逻辑代码去实现这个接口
func New() Config {
//可以参照generated.go中的Config结构体来写
c := Config{
Resolvers: &resolvers{
todos: []*Todo{
{ID: 1, Text: "A todo not to forget", Done: false, owner: you},
{ID: 2, Text: "This is the most important", Done: false, owner: you},
{ID: 3, Text: "Somebody else's todo", Done: true, owner: them},
{ID: 4, Text: "Please do this or else", Done: false, owner: you},
},
lastID: 4,
},
}
c.Directives.Us = func(ctx context.Context, obj interface{}, next graphql.Resolver, id int) (interface{}, error) {
...
}
return c
}
15.绑定的字段是一个方法
type Person {
name string
}
type Car {
make: String!
model: String!
color: String!
odometerReading: Int!
owner: Person
}
type Car struct {
Make string
Model string
Color string
OwnerID *string
OdometerReading int
}
func (c *Car) Owner() (*Person) {
// get the car owner
//....
return owner
}
models:
Car:
model: github.com/my/app/models.Car
Person:
model: github.com/my/app/models.Person
Owner作为Car结构体的一个方法,返回的是*Person
16.schema.graphql绑定到匿名或嵌入式结构
type Truck {
make: String!
model: String!
state: String!
color: String!
odometerReading: Int!
is4x4: Bool!
}
type Car {
make: String!
model: String!
state: String!
color: String!
odometerReading: Int!
}
type Truck struct {
Car
Is4x4 bool
}
type Car struct {
Make string
State string
Model string
Color string
OdometerReading int
}