Mir
Mir is a toolkit for register method handler to http engine router(eg: gin,echo,iris,mux,httprouter) use struct tag info.
Install / Use
/learn @alimy/MirREADME
Mir 是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,适配多种HTTP框架,包括 Gin, Chi, Hertz, Echo, Iris, Fiber, Macaron, Mux, httprouter。
<div align="center"> <a href="https://github.com/alimy/mir"> <img src="https://alimy.github.io/mir/images/mir-arc.png"> </a> </div>使用说明
- 生成样板项目
% go install github.com/alimy/mir/mirc/v5@latest
% mirc new -h
create template project
Usage:
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 example
example
.
|-- Makefile
|-- README.md
|-- go.mod
|-- go.sum
|-- main.go
|-- mirc
| |-- auto
| | `-- api
| | |-- site.go
| | |-- v1
| | | `-- site.go
| | `-- v2
| | `-- site.go
| |-- gen.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 run
- RESTful接口定义:
// file: mirc/routes/v1.go
package v1
import (
. "github.com/alimy/mir/v5"
)
type LoginReq struct {
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
JwtToken string `json:"jwt_token"`
}
// User user interface info
type User struct {
Schema `mir:"v1,chain"`
Login func(Post, LoginReq) LoginResp `mir:"login"`
Logout func(Post) `mir:"logout"`
}
- 代码生成:
// file: mirc/auto/api/routes/v1.go
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v5.2
package v1
import (
"net/http"
"github.com/alimy/mir/v5"
"github.com/gin-gonic/gin"
)
type _binding_ interface {
Bind(*gin.Context) error
}
type _render_ interface {
Render(*gin.Context)
}
type _default_ interface {
Bind(*gin.Context, any) error
Render(*gin.Context, any, error)
}
type LoginReq struct {
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
JwtToken string `json:"jwt_token"`
}
type User interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Login(*gin.Context, *LoginReq) (*LoginResp, error)
Logout(*gin.Context) error
mustEmbedUnimplementedUserServant()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "login", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
s.Render(c, resp, err)
})
router.Handle("POST", "logout", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
s.Render(c, nil, s.Logout(c))
})
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Logout(c *gin.Context) error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
- 接口实现:
// file: servants/user.go
package servants
import (
api "github.com/alimy/mir-example/v5/mirc/auto/api/v1"
"github.com/alimy/mir/v5"
"github.com/gin-gonic/gin"
)
type baseSrv struct{}
func (baseSrv) Bind(c *gin.Context, obj any) error {
if err := c.ShouldBind(obj); err != nil {
mir.NewError(http.StatusBadRequest, err)
}
return nil
}
func (baseSrv) Render(c *gin.Context, data any, err error) {
if err == nil {
c.JSON(http.StatusOK, data)
} else if code, ok := mir.HttpStatusCode(err); ok {
c.JSON(code, err.Error())
} else {
c.JSON(http.StatusInternalServer, err.Error())
}
}
type userSrv struct {
baseSrv
api.UnimplementedUserServant
// TODO: add other fields
}
func newUserSrv() api.User {
return &userSrv{}
}
- 服务注册:
// file: servants/servants.go
package servants
import (
api "github.com/alimy/mir-example/v5/mirc/auto/api/v1"
"github.com/gin-gonic/gin"
)
// RegisterServants register all the servants to gin.Engine
func RegisterServants(e *gin.Engine) {
api.RegisterUserServant(e, newUserSrv())
// TODO: some other servant to register
}
- 程序启动:
// file: main.go
package main
import (
"log"
"github.com/alimy/mir-example/v5/servants"
"github.com/gin-gonic/gin"
)
func main() {
e := gin.Default()
// register servants to gin
servants.RegisterServants(e)
// start servant service
if err := e.Run(); err != nil {
log.Fatal(err)
}
}
使用go-mir的项目
Related Skills
node-connect
338.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
338.0kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
83.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
338.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
