来源:开源中国 时间: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)}}
paopao-ce通过使用go-mir更好、更便捷的开发RESTful API服务与gRPC服务。
海量数据同步首选 SeaTunnel Zeta 引擎正式发布!
微软将 ChatGPT 技术整合到 Bing 中,以挑战谷歌
2022 网络浏览器市场份额:Edge 增长缓慢、Chrome 地位无法撼动