您的位置:首页 > IT > 正文

【环球聚看点】go-mir v3.0.0 发布,用 Go 结构体标签定义 handler 路由信息的辅助库

来源:开源中国     时间:2023-01-08 14:14:18


【资料图】

go-mir v3.0.0 发布了,v3版本带来全新的RESTful API开发方式,提供媲美gRPC服务开发的体验,方便快捷,欢迎参考使用。

​Mir 是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,适配多种HTTP框架,包括Gin, Chi, Hertz, Echo, Iris, Fiber, Macaron, Mux, httprouter。

使用说明

生成样板项目
% go install github.com/alimy/mir/mirc/v3@latest% mirc new -hcreate template projectUsage:  mirc new [flags]Flags:  -d, --dst string     genereted destination target directory (default ".")  -h, --help           help for new      --mir string     mir replace package name or place  -p, --pkg string     project"s package name (default "github.com/alimy/mir-example")  -s, --style string   generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin")% mirc new -d example % tree exampleexample.|-- Makefile|-- README.md|-- go.mod|-- go.sum|-- main.go|-- mirc|   |-- auto|   |   `-- api|   |       |-- site.go|   |       |-- v1|   |       |   `-- site.go|   |       `-- v2|   |           `-- site.go|   |-- main.go|   `-- routes|       |-- site.go|       |-- v1|       |   `-- site.go|       `-- v2|           `-- site.go`-- servants    |-- core.go    |-- servants.go    |-- site.go    |-- site_v1.go    `-- site_v2.go% cd example% make generate% make build
RESTful接口定义
// file: mirc/routes.gopackage routesimport (. "github.com/alimy/mir/v3". "github.com/alimy/mir/v3/engine")func init() {AddEntry(new(User))}type LoginReq struct {Name   string `json:"name"`Passwd string `json:"passwd"`}type LoginResp struct {JwtToken string `json:"jwt_token"`}// User user interface infotype User struct {Chain  Chain                          `mir:"-"`Group  Group                          `mir:"v1"`Login  func(Post, LoginReq) LoginResp `mir:"/login/"`Logout func(Post)                     `mir:"/logout/"`}
代码生成
// file: mirc/auto/api/routes.go// Code generated by go-mir. DO NOT EDIT.package routesimport ("net/http""github.com/alimy/mir/v3""github.com/gin-gonic/gin")type LoginReq struct {Name   string `json:"name"`Passwd string `json:"passwd"`}type LoginResp struct {JwtToken string `json:"jwt_token"`}type User interface {// Chain provide handlers chain for ginChain() gin.HandlersChainLogin(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error)Logout(c *gin.Context) mir.ErrormustEmbedUnimplementedUserServant()}type UserBinding interface {BindLogin(c *gin.Context) (*LoginReq, mir.Error)mustEmbedUnimplementedUserBinding()}type UserRender interface {RenderLogin(c *gin.Context, data *LoginResp, err mir.Error)RenderLogout(c *gin.Context, err mir.Error)mustEmbedUnimplementedUserRender()}// UnimplementedUserServant can be embedded to have forward compatible implementations.type UnimplementedUserServant struct {}// UnimplementedUserBinding can be embedded to have forward compatible implementations.type UnimplementedUserBinding struct {BindAny func(*gin.Context, any) mir.Error}// UnimplementedUserRender can be embedded to have forward compatible implementations.type UnimplementedUserRender struct {RenderAny func(*gin.Context, any, mir.Error)}// RegisterUserServant register User servant to ginfunc RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {router := e.Group("v1")// use chain for routermiddlewares := s.Chain()router.Use(middlewares...)// register routes info to routerrouter.Handle("POST", "/login/", func(c *gin.Context) {select {case <-c.Request.Context().Done():returndefault:}req, err := b.BindLogin(c)if err != nil {r.RenderLogin(c, nil, err)}resp, err := s.Login(c, req)r.RenderLogin(c, resp, err)})router.Handle("POST", "/logout/", func(c *gin.Context) {select {case <-c.Request.Context().Done():returndefault:}r.RenderLogout(c, s.Logout(c))})}func (UnimplementedUserServant) Chain() gin.HandlersChain {return nil}func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) {return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))}func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error {return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))}func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}func (b UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {obj := new(LoginReq)err := b.BindAny(c, obj)return obj, err}func (b UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}func (r UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {r.RenderAny(c, data, err)}func (r UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {r.RenderAny(c, nil, err)}func (r UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
接口实现
// file: servants/user.gopackage servantsimport ("github.com/alimy/mir-example/v3/mirc/auto/api")type userSrv struct {api.UnimplementedUserServant}type userBinding struct {*api.UnimplementedUserBinding}type userRender struct {*api.UnimplementedUserRender}func newUserSrv() api.Site {return &userSrv{}}func newUserBinding() api.SiteBinding {return &siteBinding{UnimplementedSiteBinding: &api.UnimplementedSiteBinding{BindAny: bindAny,},}}func newUserRender() api.SiteRender {return &siteRender{UnimplementedSiteRender: &api.UnimplementedSiteRender{RenderAny: renderAny,},}}func bindAny(c *gin.Context, obj any) mir.Error {if err != c.ShouldBind(obj); err != nil {return mir.NewError(http.StatusBadRequest, err)}return nil}func renderAny(c *gin.Context, data any, err mir.Error) {if err == nil {c.JSON(http.StatusOK, data)} else {c.JSON(err.StatusCode(), err.Error())}}
服务注册
// file: servants/servants.gopackage servantsimport ("github.com/alimy/mir-example/v3/mirc/auto/api""github.com/gin-gonic/gin")// RegisterServants register all the servants to gin.Enginefunc RegisterServants(e *gin.Engine) {api.RegisterUserServant(e, newUserSrv(), newUserBinding(), newUserRender())// TODO: some other servant to register}

程序启动

// file: main.gopackage mainimport ("log""github.com/alimy/mir-example/v3/servants""github.com/gin-gonic/gin")func main() {e := gin.Default()// register servants to ginservants.RegisterServants(e)// start servant serviceif err := e.Run(); err != nil {log.Fatal(err)}}

使用go-mir的项目

examples- go-mir自带的demo,主要演示了如何使用Mir快速进行RESTful API的后端开 发; paopao-ce - 一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务;

paopao-ce通过使用go-mir更好、更便捷的开发RESTful API服务与gRPC服务。

相关文章