github.com/alimy/mir/v4@v4.1.0/README.md (about) 1 [](https://github.com/alimy/mir/actions/workflows/go.yml) 2 [](https://pkg.go.dev/github.com/alimy/mir/v4) 3 [](https://sourcegraph.com/github.com/alimy/mir) 4 5 <div align="center"> 6 <a href="https://github.com/alimy/mir"> 7 <img src="https://alimy.me/mir/images/mir-logo.png" alt="Logo" width="240" height="240"> 8 </a> 9 10 <h3 align="center">Mir</h3> 11 12 <p align="center"> 13 一个很酷的开发RESTful API的辅助工具 14 </p> 15 </div> 16 17 Mir 是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,适配多种HTTP框架,包括 [Gin](https://github.com/gin-gonic/gin), [Chi](https://github.com/go-chi/chi), [Hertz](https://github.com/cloudwego/hertz), [Echo](https://github.com/labstack/echo), [Iris](https://github.com/kataras/iris), [Fiber](https://github.com/gofiber/fiber), [Macaron](https://github.com/go-macaron/macaron), [Mux](https://github.com/gorilla/mux), [httprouter](https://github.com/julienschmidt/httprouter)。 18 19 <div align="center"> 20 <a href="https://github.com/alimy/mir"> 21 <img src="https://alimy.me/mir/images/mir-arc.png"> 22 </a> 23 </div> 24 25 ## 使用说明 26 * 生成样板项目 27 ```bash 28 % go install github.com/alimy/mir/mirc/v4@latest 29 % mirc new -h 30 create template project 31 32 Usage: 33 mirc new [flags] 34 35 Flags: 36 -d, --dst string genereted destination target directory (default ".") 37 -h, --help help for new 38 --mir string mir replace package name or place 39 -p, --pkg string project's package name (default "github.com/alimy/mir-example") 40 -s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin") 41 42 % mirc new -d example 43 % tree example 44 example 45 . 46 |-- Makefile 47 |-- README.md 48 |-- go.mod 49 |-- go.sum 50 |-- main.go 51 |-- mirc 52 | |-- auto 53 | | `-- api 54 | | |-- site.go 55 | | |-- v1 56 | | | `-- site.go 57 | | `-- v2 58 | | `-- site.go 59 | |-- gen.go 60 | `-- routes 61 | |-- site.go 62 | |-- v1 63 | | `-- site.go 64 | `-- v2 65 | `-- site.go 66 `-- servants 67 |-- core.go 68 |-- servants.go 69 |-- site.go 70 |-- site_v1.go 71 `-- site_v2.go 72 73 % cd example 74 % make generate 75 % make run 76 ``` 77 78 * RESTful接口定义: 79 ```go 80 // file: mirc/routes.go 81 82 package routes 83 84 import ( 85 . "github.com/alimy/mir/v4" 86 . "github.com/alimy/mir/v4/engine" 87 ) 88 89 func init() { 90 AddEntry(new(User)) 91 } 92 93 type LoginReq struct { 94 Name string `json:"name"` 95 Passwd string `json:"passwd"` 96 } 97 98 type LoginResp struct { 99 JwtToken string `json:"jwt_token"` 100 } 101 102 // User user interface info 103 type User struct { 104 Chain `mir:"-"` 105 Group `mir:"v1"` 106 Login func(Post, LoginReq) LoginResp `mir:"/login/"` 107 Logout func(Post) `mir:"/logout/"` 108 } 109 ``` 110 111 * 代码生成: 112 ```go 113 // file: mirc/auto/api/routes.go 114 115 // Code generated by go-mir. DO NOT EDIT. 116 // versions: 117 // - mir v4.0.0 118 119 package routes 120 121 import ( 122 "net/http" 123 124 "github.com/alimy/mir/v4" 125 "github.com/gin-gonic/gin" 126 ) 127 128 type _binding_ interface { 129 Bind(*gin.Context) mir.Error 130 } 131 132 type _render_ interface { 133 Render(*gin.Context) 134 } 135 136 type _default_ interface { 137 Bind(*gin.Context, any) mir.Error 138 Render(*gin.Context, any, mir.Error) 139 } 140 141 type LoginReq struct { 142 Name string `json:"name"` 143 Passwd string `json:"passwd"` 144 } 145 146 type LoginResp struct { 147 JwtToken string `json:"jwt_token"` 148 } 149 150 type User interface { 151 _default_ 152 153 // Chain provide handlers chain for gin 154 Chain() gin.HandlersChain 155 156 Login(*gin.Context, *LoginReq) (*LoginResp, mir.Error) 157 Logout(*gin.Context) mir.Error 158 159 mustEmbedUnimplementedUserServant() 160 } 161 162 // RegisterUserServant register User servant to gin 163 func RegisterUserServant(e *gin.Engine, s User) { 164 router := e.Group("v1") 165 // use chain for router 166 middlewares := s.Chain() 167 router.Use(middlewares...) 168 169 // register routes info to router 170 router.Handle("POST", "/login/", func(c *gin.Context) { 171 select { 172 case <-c.Request.Context().Done(): 173 return 174 default: 175 } 176 req := new(LoginReq) 177 if err := s.Bind(c, req); err != nil { 178 s.Render(c, nil, err) 179 return 180 } 181 resp, err := s.Login(req) 182 s.Render(c, resp, err) 183 }) 184 router.Handle("POST", "/logout/", func(c *gin.Context) { 185 select { 186 case <-c.Request.Context().Done(): 187 return 188 default: 189 } 190 191 s.Render(c, nil, s.Logout(c)) 192 }) 193 } 194 195 func (UnimplementedUserServant) Chain() gin.HandlersChain { 196 return nil 197 } 198 199 func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { 200 return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) 201 } 202 203 func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { 204 return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) 205 } 206 207 func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} 208 ``` 209 210 * 接口实现: 211 ```go 212 // file: servants/user.go 213 214 package servants 215 216 import ( 217 "github.com/alimy/mir-example/v4/mirc/auto/api" 218 "github.com/alimy/mir/v4" 219 "github.com/gin-gonic/gin" 220 ) 221 222 type baseSrv struct{} 223 224 func (baseSrv) Bind(c *gin.Context, obj any) mir.Error { 225 if err := c.ShouldBind(obj); err != nil { 226 mir.NewError(http.StatusBadRequest, err) 227 } 228 return nil 229 } 230 231 func (baseSrv) Render(c *gin.Context, data any, err mir.Error) { 232 if err == nil { 233 c.JSON(http.StatusOK, data) 234 } else { 235 c.JSON(err.StatusCode(), err.Error()) 236 } 237 } 238 239 type userSrv struct { 240 baseSrv 241 242 api.UnimplementedUserServant 243 } 244 245 func newUserSrv() api.Site { 246 return &userSrv{} 247 } 248 ``` 249 250 * 服务注册: 251 ```go 252 // file: servants/servants.go 253 254 package servants 255 256 import ( 257 "github.com/alimy/mir-example/v4/mirc/auto/api" 258 "github.com/gin-gonic/gin" 259 ) 260 261 // RegisterServants register all the servants to gin.Engine 262 func RegisterServants(e *gin.Engine) { 263 api.RegisterUserServant(e, newUserSrv()) 264 265 // TODO: some other servant to register 266 } 267 ``` 268 269 * 程序启动: 270 ```go 271 // file: main.go 272 273 package main 274 275 import ( 276 "log" 277 278 "github.com/alimy/mir-example/v4/servants" 279 "github.com/gin-gonic/gin" 280 ) 281 282 func main() { 283 e := gin.Default() 284 285 // register servants to gin 286 servants.RegisterServants(e) 287 288 // start servant service 289 if err := e.Run(); err != nil { 290 log.Fatal(err) 291 } 292 } 293 ``` 294 295 ### 使用[go-mir](https://github.com/alimy/mir)的项目 296 * [examples](examples) - 本项目自带的demo,主要演示了如何使用[Mir](https://github.com/alimy/mir)快速进行RESTful API的后端开发。 297 * [paopao-ce](https://github.com/rocboss/paopao-ce/tree/dev) - 一个清新文艺的微社区,提供类似Twiter/微博的推文分享服务。