Go-zero入门使用 | 青训营
介绍
go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。
它的优点有:
- 轻松获得支撑千万日活服务的稳定性
- 内建级联超时控制、限流、自适应熔断、自适应降载等微服务治理能力,无需配置和额外代码
- 微服务治理中间件可无缝集成到其它现有框架使用
- 极简的 API 描述,一键生成各端代码
- 自动校验客户端请求参数合法性
- 大量微服务治理和并发工具包
安装
goctl
goctl 是 go-zero 的内置脚手架,是提升开发效率的一大利器,可以一键生成代码、文档、部署 k8s yaml、dockerfile 等。
按照官方声明,直接在命令行输入如下:
-
如果 go 版本在
1.16以前,则使用如下命令安装:go get -u github.com/zeromicro/go-zero/tools/goctl@latest -
如果 go 版本在
1.16及以后,则使用如下命令安装:go install github.com/zeromicro/go-zero/tools/goctl@latest
安装完成后,可输入如下命令验证是否成功:
goctl --version
go-zero
下载go-zero的包直接在项目文件下的命令行中输入:
go get -u github.com/zeromicro/go-zero@latest
简单使用
快速生成默认的api服务:
我们可以通过goctl快速生成默认的api服务,只需要在工作目录下命令行输入:
goctl api new greet
cd greet
go mod init
go mod tidy
go run greet.go -f etc/greet-api.yaml
这样我们就简单的快速生成了api服务,默认监听8888端口号(可以在etc/greet-api.yaml下修改配置),这时我们可以通过curl请求:
curl -i http://localhost:8888/from/you
命令行中会输出:
同时,我们也可以通过使用的编译器插件一键生成服务api:
然后更新go.mod包依赖关系即可。
整个服务目录结构如下所示:
├── etc
│ └── greet-api.yaml // 配置文件
├── go.mod // mod文件
├── greet.api // api描述文件
├── greet.go // main函数入口
└── internal
├── config
│ └── config.go // 配置声明type
├── handler // 路由及handler转发
│ ├── greethandler.go
│ └── routes.go
├── logic // 业务逻辑
│ └── greetlogic.go
├── middleware // 中间件文件
│ └── greetmiddleware.go
├── svc // logic所依赖的资源池
│ └── servicecontext.go
└── types // request、response的struct,根据api自动生成,不建议编辑
└── types.go
根据api生成服务
此外,我们还可以自己写一个api文件,然后通过goctl根据api文件生成相应的代码。
首先,我们在目录下新建一个order.api:
syntax = "v1"
info(
title: "订单api"
desc: "通过订单的id返回对应的订单信息"
author: "Tom"
email: "123456@qq.com"
version: "v1"
)
type request {
OrderId int64 `json:"order_id"`
}
type response {
OrderId int64 `json:"order_id"` //订单id
GoodsName string `json:"goods_name"` //商品名称
}
@server(
jwt: Auth
group: template
)
//定义了一个服务叫order-api
service order-api {
//获取接口的名字叫获取用户信息
@doc "获取订单信息"
//对应的hanlder即controller是orderInfo
@handler orderInfo
//请求方法是post,路径是/order/order_id,参数是request,返回值是response
post /order/info (request) returns (response)
//可以继续定义多个api
}
然后再命令行下输入:
goctl api go -api *.api -dir ./ --style=goZero
这样我们就根据api文件生成了对应的api项目。
同时goland的插件也支持一键生成模板api:
syntax = "v1"
info(
title: "type title here"
desc: "type desc here"
author: "type author here"
email: "type email here"
version: "type version here"
)
type request {
// TODO: add members here and delete this comment
}
type response {
// TODO: add members here and delete this comment
}
@server(
jwt: Auth
group: template
)
service template {
@handler handlerName // TODO: replace handler name and delete this comment
get /users/id/:userId (request) returns (response)
}
修改完相应的代码后,我们右键该api文件自动生成api项目代码:
项目的目录如下:
其中,我们首先查看服务下的所有路由,路径在/internal/handler/routes.go:
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/order/info",
Handler: orderInfoHandler(serverCtx),
},
},
)
}
func orderInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := logic.NewOrderInfoLogic(r.Context(), svcCtx)
resp, err := l.OrderInfo(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
我们根据业务逻辑的需要,修改/internal/logic/orderinfologic.go文件:
func (l *OrderInfoLogic) OrderInfo(req *types.Request) (resp *types.Response, err error) {
orderId := req.OrderId
resp = new(types.Response)
if orderId == 1 {
resp.GoodsName = "手机"
} else {
resp.GoodsName = "电脑"
}
resp.OrderId = orderId
return
}
这样,我们就简单是实现了一个通过订单id查询订单信息的接口,自此一个简单的api服务完成。
下面我们通过curl对我们的api服务进行测试:
首先,启动order.go文件,然后我们在命令行中输入:
curl -X POST -H "Content-Type: application/json" http://localhost:8888/order/info -d "{"order_id": 1}"
需要注意,命令行中curl的命令参数中,设置josn格式参数中的""需要前面加上\,否则会报错。