graphql GO学习

参考graphql-go-example

设计API参数列表

type User {
  id: ID
  email: String!
  post(id: ID!): Post
  posts: [Post!]!
  follower(id: ID!): User
  followers: [User!]!
  followee(id: ID!): User
  followees: [User!]!
}
type Post {
  id: ID
  user: User!
  title: String!
  body: String!
  comment(id: ID!): Comment
  comments: [Comment!]!
}

type Comment {
  id: ID
  user: User!
  post: Post!
  title: String
  body: String!
}

 [Type]!或者[Type!]或者[Type!]!(请仔细看这里!的位置),它们的含义分别为:

  • 列表本身为必填项,但其内部元素可以为空
  • 列表本身可以为空,但是其内部元素为必填
  • 列表本身和内部元素均为必填

转换为go的实现(User为例)

 

var UserType = graphql.NewObject(graphql.ObjectConfig{
   Name: "User",
   Fields: graphql.Fields{
      "id": &graphql.Field{
         Type: graphql.NewNonNull(graphql.ID),
         Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            if user, ok := p.Source.(*User); ok == true {
               return user.ID, nil
            }
            return nil, nil
         },
      },
      "email": &graphql.Field{
         Type: graphql.NewNonNull(graphql.String),
         Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            if user, ok := p.Source.(*User); ok == true {
               return user.Email, nil
            }
            return nil, nil
         },
      },
   },
})

func init() {
   UserType.AddFieldConfig("post", &graphql.Field{
      Type: PostType,
      Args: graphql.FieldConfigArgument{
         "id": &graphql.ArgumentConfig{
            Description: "Post ID",
            Type:        graphql.NewNonNull(graphql.ID),
         },
      },
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
               return nil, err
            }
            return GetPostByIDAndUser(id, user.ID)
         }
         return nil, nil
      },
   })
   UserType.AddFieldConfig("posts", &graphql.Field{
      Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(PostType))),
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            return GetPostsForUser(user.ID)
         }
         return []Post{}, nil
      },
   })
   UserType.AddFieldConfig("follower", &graphql.Field{
      Type: UserType,
      Args: graphql.FieldConfigArgument{
         "id": &graphql.ArgumentConfig{
            Description: "Follower ID",
            Type:        graphql.NewNonNull(graphql.ID),
         },
      },
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
               return nil, err
            }
            return GetFollowerByIDAndUser(id, user.ID)
         }
         return nil, nil
      },
   })
   UserType.AddFieldConfig("followers", &graphql.Field{
      Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(UserType))),
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            return GetFollowersForUser(user.ID)
         }
         return []User{}, nil
      },
   })
   UserType.AddFieldConfig("followee", &graphql.Field{
      Type: UserType,
      Args: graphql.FieldConfigArgument{
         "id": &graphql.ArgumentConfig{
            Description: "Followee ID",
            Type:        graphql.NewNonNull(graphql.ID),
         },
      },
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
               return nil, err
            }
            return GetFolloweeByIDAndUser(id, user.ID)
         }
         return nil, nil
      },
   })
   UserType.AddFieldConfig("followees", &graphql.Field{
      Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(UserType))),
      Resolve: func(p graphql.ResolveParams) (interface{}, error) {
         if user, ok := p.Source.(*User); ok == true {
            return GetFolloweesForUser(user.ID)
         }
         return []User{}, nil
      },
   })
}

API查询 

graphql设计模式有三种查询类型

  • query(查询):当获取数据时,应当选取Query类型
  • mutation(更改):当尝试修改数据时,应当使用mutation类型
  • subscription(订阅):当希望数据更改时,可以进行消息推送,使用subscription类型

query和mutation设计如下:

type Query {
  user(id: ID!): User
}

type Mutation {
  createUser(email: String!): User
  removeUser(id: ID!): Boolean
  follow(follower: ID!, followee: ID!): Boolean
  unfollow(follower: ID!, followee: ID!): Boolean
  createPost(user: ID!, title: String!, body: String!): Post
  removePost(id: ID!): Boolean
  createComment(user: ID!, post: ID!, title: String!, body: String!): Comment
  removeComment(id: ID!): Boolean
}

 转换为go的实现

var QueryType = graphql.NewObject(graphql.ObjectConfig{
   Name: "Query",
   Fields: graphql.Fields{
      "user": &graphql.Field{
         Type: UserType,
         Args: graphql.FieldConfigArgument{
            "id": &graphql.ArgumentConfig{
               Description: "User ID",
               Type:        graphql.NewNonNull(graphql.ID),
            },
         },
         Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
               return nil, err
            }
            return GetUserByID(id)
         },
      },
   },
})
var MutationType = graphql.NewObject(graphql.ObjectConfig{
   Name: "Mutation",
   Fields: graphql.Fields{
      "createUser": &graphql.Field{
         Type: UserType,
         Args: graphql.FieldConfigArgument{
            "email": &graphql.ArgumentConfig{
               Description: "New User Email",
               Type:        graphql.NewNonNull(graphql.String),
            },
         },
         Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            email := p.Args["email"].(string)
            user := &User{
               Email: email,
            }
            err := InsertUser(user)
            return user, err
         },
      },
      "removeUser": &graphql.Field{
         Type: graphql.Boolean,
         Args: graphql.FieldConfigArgument{
            "id": &graphql.ArgumentConfig{
               Description: "User ID to remove",
               Type:        graphql.NewNonNull(graphql.ID),
            },
         },
         Resolve: func(p graphql.ResolveParams) (interface{}, error) {
            i := p.Args["id"].(string)
            id, err := strconv.Atoi(i)
            if err != nil {
               return nil, err
            }
            err = RemoveUserByID(id)
            return (err == nil), err
         },
      },    
    },
})

 接口的启用也很简单

func main() {
   schema, err := graphql.NewSchema(graphql.SchemaConfig{
      Query:    QueryType,
      Mutation: MutationType,
   })
   if err != nil {
      log.Fatal(err)
   }

   http.Handle("/graphql", handler(schema))
   log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil))
}
func handler(schema graphql.Schema) http.HandlerFunc {
   return func(w http.ResponseWriter, r *http.Request) {
      query, err := ioutil.ReadAll(r.Body)
      if err != nil {
         http.Error(w, err.Error(), http.StatusBadRequest)
         return
      }
      result := graphql.Do(graphql.Params{
         Schema:        schema,
         RequestString: string(query),
      })
      w.Header().Set("Content-Type", "application/json")
      w.WriteHeader(http.StatusOK)
      json.NewEncoder(w).Encode(result)
   }
}

请求实例

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值