当前位置: 首页 > 工具软件 > gqlgen > 使用案例 >

gqlgen学习总结

冉俊德
2023-12-01

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
}

 

 类似资料: