GraphQL是一种用于API的查询语言,可以在服务端定义GraphQL Schema,客户端可以向服务端发送GraphQL请求,服务端执行GraphQL查询,并将结果作为JSON返回给客户端。
下面是一个使用golang实现GraphQL的示例,首先需要安装golang的GraphQL库github.com/graphql-go/graphql
。
第一步定义GraphQL Schema
package main
import "github.com/graphql-go/graphql"
// 定义User结构体
type User struct {
ID int
Name string
Age 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 main
import (
"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 main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func main() {
// 定义GraphQL查询
query := `
query getUser($id:Int!) {
user:getUser(id:$id) {
id
name
age
}
}
`
// 定义查询参数
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可以让客户端获取更小粒度的数据,因此很容易暴露一些敏感数据给客户端,需要在服务端实现中特别注意安全问题。