中间件
在 userapi 项目中引入中间件。go项目中的中间可以处理请求之前和之后的逻辑。
1. 在 userapi/internal目录先创建 middlewares目录,并创建 user.go文件
package middlewares
import (
"github.com/zeromicro/go-zero/core/logx"
"net/http"
)
type UserMiddleware struct {
}
func NewUserMiddleware() *UserMiddleware {
return &UserMiddleware{}
}
func (*UserMiddleware) LoginAndReg(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logx.Info("execute before login and register")
next(w, r)
logx.Info("execute after login and register")
}
}
这里,就定义了一个中间件。
2. 在 userapi/internal/svc/servicecontext.go 文件中创建一个中间件实例
package svc
import (
"github.com/zeromicro/go-zero/zrpc"
"rpc-common/userclient"
"userapi/internal/middlewares"
"userapi/internal/config"
)
type ServiceContext struct {
Config config.Config
UserRpc userclient.User
UserMiddleware *middlewares.UserMiddleware // 定义中间件
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
UserMiddleware: middlewares.NewUserMiddleware(), // 创建中间件实例
}
}
3. 修改 userapi/internal/handler/routers.go 文件
在这里引入了路由中间件。
4. 修改 userapi/internal/logic/userapilogic.go文件
在该文件中,修改 Login 方法,加入一行日志。为了后面测试用。
func (l *UserLogic) Login(t *types.LoginRequest) (string, error) {
logx.Info("login executing....") // 新加入的代码
userId := 100
auth := l.svcCtx.Config.Auth
return l.getToken(auth.AccessSecret, time.Now().Unix(), auth.AccessExpire, userId)
}
5. 测试中间件
访问 login 接口后,在控制台打印日志。日志是由路由中间件打印的。
6. 全局中间件
上面引入的路由中间件是,可以针对部分路由起作用,如果想要对所有路由起作用,可以使用全局中间件。
在 userapi/internal/handler/routers.go文中,加入一行代码:
这样引入的中间件,就是全局中间件,对所有路由都会生效。
自定义错误
1. 引出问题
- 在 userapi/internal/logic/userapilogic.go 文件的 GetUser 方法加一段逻辑
- 测试
用postman 测试后,结果如图。显然,很多情况下,我们不想直接获取到这种形式的错误。更愿意拿到一个 json 格式的错误,包括错误代码,错误内容。这样更容易处理。
2. 在 userapi/internal 创建 errorx 目录,来管理错误
在 userapi/internal/errorx 目录创建一个 error.go 文件
package errorx
var ParamsError = New(1101, "parameter error")
type BizError struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
func New(code int, msg string) *BizError {
return &BizError{
Code: code,
Msg: msg,
}
}
func (e *BizError) Error() string {
return e.Msg
}
type ErrorResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
func (e *BizError) Data() *ErrorResponse {
return &ErrorResponse{
e.Code,
e.Msg,
}
}
该文件定义了错误码和错误内容。
3. 修改 userapi/internal/logic/userapilogic.go 文件
返回错误的时候,返回我们上一步自定义的错误。
4. 修改 userapi/userapi.go 文件,增加错误处理逻辑
增加了,错误处理的逻辑。
5. 测试
这样,就获取到 json 格式的错误数据。
goctl 命令
1. 源码文件生成格式
goctl api go -api userapi.api -dir ./gen
这种方式生成的代码,文件名称是所有字母全小写。有时候我们需要不同的命名格式,比如有些团队或个人喜欢驼峰命名方式,有些喜欢snake的形式
goctl api go -api userapi.api -dir ./gen -style go_zero
这种方式生成的文件名称是 snake 形式。
goctl api go -api userapi.api -dir ./gen -style goZero
这种命名方式是驼峰命名方式
2. 生成 proto 文件
goctl rpc template -o=user.proto
利用模板生成 .proto 文件,这样在开发过程中,有一个基础模块。在这个目标上进行修改,相对更方便一点。
3. 生成 rpc 服务代码
goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
之前,我们项目的代码就是靠这种方式生成的。
4. 生成 model 代码
goctl model mysql ddl -src="./*.sql" =dir="./sql/model" -c
根据数据库的 ddl 语句,生成模型代码。生成的这部分代码,可以摘取部分使用,减少工作量。
5. 生成 dockerfile
goctl docker -go hello.go
hello.go 是启动类。
6. 生成 k8s 只要清单
goctl kube deploy -name redis -namespace adhoc -image redis:6-alpine -o redis.yaml -port 6379