GraphQL是一种用于API的查询语言,可以在服务端定义GraphQL Schema,客户端可以向服务端发送GraphQL请求,服务端执行GraphQL查询,并将结果作为JSON返回给客户端。
下面是一个使用golang实现GraphQL的示例,首先需要安装golang的GraphQL库github.com/graphql-go/graphql
。
第一步定义GraphQL Schema
package mainimport "github.com/graphql-go/graphql"// 定义User结构体
type User struct {ID intName stringAge int
}// 定义GraphQL Schema
var Schema, _ = graphql.NewSchema(graphql.SchemaConfig{Query: graphql.NewObject(graphql.ObjectConfig{Name: "Query",Fields: graphql.Fields{// 定义getUser查询,查询一个用户的信息"getUser": &graphql.Field{Type: UserObject,Args: graphql.FieldConfigArgument{"id": &graphql.ArgumentConfig{Type: graphql.Int,},},Resolve: func(p graphql.ResolveParams) (interface{}, error) {// 处理getUser查询的逻辑userID, ok := p.Args["id"].(int)if !ok {return nil, nil}var user = User{ID: userID,Name: "Tom",Age: 18,}return user, nil},},},}),
})// 定义User类型
var UserObject = graphql.NewObject(graphql.ObjectConfig{Name: "User",Fields: graphql.Fields{"id": &graphql.Field{Type: graphql.Int,},"name": &graphql.Field{Type: graphql.String,},"age": &graphql.Field{Type: graphql.Int,},},
})
以上代码中,定义了一个叫做User的类型,以及一个叫做getUser的查询,getUser查询需要一个名为id的参数,返回一个User类型的对象。
② 执行GraphQL查询
package mainimport ("encoding/json""fmt""net/http""github.com/graphql-go/graphql""github.com/graphql-go/handler"
)func main() {// 定义http请求处理函数http.Handle("/graphql", handler.New(&handler.Config{Schema: &Schema,Pretty: true,}))// 启动http服务fmt.Println("Server running on port 8080")http.ListenAndServe(":8080", nil)
}
以上代码中,使用github.com/graphql-go/handler
库创建一个http处理器,并监听8080端口。
接下来,可以使用HTTP Client来测试GraphQL查询:
package mainimport ("bytes""encoding/json""fmt""net/http"
)func main() {// 定义GraphQL查询query := `query getUser($id:Int!) {user:getUser(id:$id) {idnameage}}`// 定义查询参数params := struct {Query string `json:"query"`Variables interface{} `json:"variables"`}{Query: query,Variables: map[string]interface{}{"id": 1,},}// 将查询参数编码为JSON格式requestBody, _ := json.Marshal(params)// 发送GraphQL查询请求resp, _ := http.Post("http://localhost:8080/graphql", "application/json", bytes.NewBuffer(requestBody))// 读取查询结果var result struct {Data interface{} `json:"data"`Errors []struct {Message string `json:"message"`} `json:"errors"`}json.NewDecoder(resp.Body).Decode(&result)// 处理查询结果if len(result.Errors) > 0 {fmt.Println(result.Errors[0].Message)} else {fmt.Printf("%+v\n", result.Data)}
}
以上代码中,定义了一个叫做getUser的查询,并且将查询变量id的值设置为1。将查询参数编码为JSON格式,并通过HTTP Post发送GraphQL查询请求。最后,处理查询结果并打印到控制台。
总结:graphQL给我们带来的diff是什么?
可以给GraphQL形象地比喻成一名个人管家或者服务员。客户端向服务端发送一个需要的数据需求(就像是顾客点菜),服务端的个人管家/服务员(即GraphQL)收到需求后,帮你去找到所有数据,然后将所有数据优化打包成一个请求结果返回给客户端(即将所有的菜打包成一份菜单,客户端只需要按需取数据即可)。
下面是GraphQL的一些优点和缺点:
优点:
- 精细的数据获取:GraphQL可以精确获取客户端需要的数据,减少数据传输量和网络请求次数,提高性能。
- 灵活的数据查询:GraphQL查询语言非常灵活,支持多种查询方式,可以方便的定制查询条件,满足客户端的不同数据需求。
- 自描述性:GraphQL服务端会提供一份Schema,客户端可以根据该Schema自动生成文档或者代码,方便开发和协作。
- 适用于多平台:GraphQL不依赖具体的数据库和平台,适用于多种语言和开发框架。
缺点:
- 学习成本:相对于RESTful API,GraphQL需要更多的学习成本,包括查询语言和Schema定义等。
- 需要服务端支持:GraphQL需要服务端实现支持,需要服务端和客户端都做相应的改造,不能直接覆盖已有的API。
- 安全问题:由于GraphQL可以让客户端获取更小粒度的数据,因此很容易暴露一些敏感数据给客户端,需要在服务端实现中特别注意安全问题。