说明
简单易用又强大的微服务golang框架。
特性
- 集成http,websocket服务。
- 丰富的中间件(请求日志、JWT认证,跨域,Recover,全局链路)
- 通过依赖注入的方式,动态加载基础组件。包括配置,日志管理器,Redis,Mysql等
- 支持基于consul,etcd的服务注册、发现、注销
- 自定义参数验证器
安装
go get -u github.com/ebar-go/ego
示例
完整的web项目请查看github.com/ebar-go/ego-demo
模块
http服务
package main import ( "fmt" "github.com/ebar-go/ego" "github.com/gin-gonic/gin" "github.com/ebar-go/ego/utils/secure" "time" ) func main() { server := ego.HttpServer() // 添加路由 server.Router.GET("/test", func(context *gin.Context) { fmt.Println("hello,world") }) // 默认启动8080 // 也可以通过传参指定端口启动,如: server.Start(8081) // 如果不传参,则读取配置文件中的 server.port配置项 secure.Panic(server.Start()) } // 支持平滑重启 func init() { // 支持停止http服务时的回调 event.Listen(event.BeforeHttpShutdown, func(ev event.Event) { // 让服务器等待3秒,等待异步业务执行结束 time.Sleep(time.Second * 3) // 关闭数据库 fmt.Println("close database") _ = app.DB().Close() }) }
websocket服务
支持与http服务共存的websocket服务
package main import ( "github.com/ebar-go/ego" "github.com/ebar-go/ego/utils/secure" "github.com/gin-gonic/gin" "github.com/ebar-go/ego/http/response" ) func main() { s := ego.HttpServer() ws := ego.WebsocketServer() s.Router.GET("/check", func(context *gin.Context) { response.WrapContext(context).Success("hello") }) s.Router.GET("/ws", func(ctx *gin.Context) { // get websocket conn conn, err := ws.UpgradeConn(ctx.Writer, ctx.Request) if err != nil { secure.Panic(err.Error()) } ws.Register(conn, func(message []byte){ if string(message) == "broadcast" {// 广播 ws.Broadcast([]byte("hello,welcome"), nil) return } ws.Send(message, conn) // 单对单发送 }) }) go ws.Start() secure.FatalError("StartHttpServer", s.Start()) }
配置
// 加载配置文件 app.Config().LoadFile("app.yaml") // 读取string配置 app.Config().GetString("someKey") // 读取int配置 app.Config().GetInt("someKey")
发起http请求
url := "http://baidu.com" request,_ := http.NewRequest(http.MethodGet, url, nil) resp, err := ego.Curl(request) fmt.Println(resp, err)
中间件
server := ego.HttpServer() // middleware must used before init router // Recover middleware server.Router.Use(middleware.Recover) // JWT middleware,make sure Config.JwtKey is not empty server.Router.Use(middleware.JWT(&jwt.StandClaims{})) // CORS middleware server.Router.Use(middleware.CORS) // RequestLog middleware server.Router.Use(middleware.RequestLog)
响应
固定格式的json输出
// 输出成功的响应数据 response.WrapContext(ctx).Success(response.Data{"hello":"world"}) // 数据错误的响应数据 response.WrapContext(ctx).Error(1001, "some error")
数据校验器
github.com/go-playground/validatorcomment
- handler里校验参数
type AuthRequest struct { // 如果是表单提交,使用form,否则获取不到数据 Email string `json:"email" validate:"required,email" comment:"邮箱"` // 验证邮箱格式 Pass string `json:"pass" binding:"required,min=6,max=10" comment:"密码"` // 验证密码,长度为6~10 } var request AuthRequest if err := ctx.ShouldBindJSON(&request); err != nil { secure.Panic(errors.New(1001, "参数错误")) }
日志
使用https://github.com/uber-go/zap实在日志组件,支持日志文件按日期自动分割。
配置如下:
server : logPath: /tmp/app.log #日志文件路径 debug: true # 是否开启debug日志
写日志
import ( "github.com/ebar-go/ego/component/log" ) // 输出:{"level_name":"info","datetime":"2020-06-03 22:52:49","file":"log/log.go:24","message":"Info","system_name":"app","system_port":8080,"context":{"hello":"world","trace_id":""}} app.Logger().Info("infoMessage", log.Context{ "hello":"world", }) app.Logger().Debug("debugMessage", log.Context{ "hello":"world", }) app.Logger().Error("errorMessage", log.Context{ "hello":"world", })
Mysql
gorm
- 配置
mysql: # mysql配置。支持多数据库,读写分离 default: # 默认连接,如果还有其他数据库要连接,换个名字即可 maxIdleConnections: 10 # 最大空闲连接数 maxOpenConnections: 40 # 最大打开连接数 maxLifeTime: 60 # 超时时间 dsn: # 连接配置,默认第一个为写库,也可以只配置一个,即读写使用一个连接 - host: 127.0.0.1 port: 32768 user: root password: mysql name: blog - host: 127.0.0.1 # 从库,读库 port: 32769 user: root password: mysql name: blog otherDB: # 其他数据库 maxIdleConnections: 10 # 最大空闲连接数 maxOpenConnections: 40 # 最大打开连接数 maxLifeTime: 60 # 超时时间 dsn: # 连接配置,默认第一个为写库,也可以只配置一个,即读写使用一个连接 - host: 127.0.0.1 port: 32768 user: root password: mysql name: blog
- 使用
// 初始化数据库,一般在init函数里,加载了配置文件之后执行 secure.Panic(app.InitDB()) // 获取默认的库连接 app.DB() // 指定库连接 app.GetDB("otherDB") // 事务 if err := app.DB().Transaction(func(tx *gorm.Db) error { // some query or update return nil }); err != nil { // return fmt.Errorf("Save failed:%v", err) }
Redis
配置如下:
redis: host: 127.0.0.1 pass: port: 6379 poolSize: 100 # 连接池大小 maxRetries: 3 # 重试次数 idleTimeout: 3 # 操作时间 cluster: # 集群(如:127.0.0.1:6379,127.0.0.1:6380)
调用:
// 连接 app.Redis().Connect() // 写入 app.Redis().Set("hello", "world", time.Second * 30) // 读取 res := app.Redis().Get("hello").String()
事件
提供快捷的事件开发模式。
- 使用
// 注册事件 event.Register("someEvent", event.Listener{ Mode: event.Sync, // 同步事件,异步事件为 event.Async Handler: func(ev event.Event) { fmt.Println(ev.Params) } }) // 更快捷的注册事件 event.Listen("someEvent", func(ev event.Event) { fmt.Println(ev.Params) }) // 触发事件 event.Trigger("someEvent", "someParam")
- 系统事件
// http服务启动前触发
event.BeforeHttpStart
// http服务启动后触发
event.AfterHttpStart
// http服务关闭前触发,平滑重启
event.BeforeHttpShutdown
// 数据库连接成功后触发
event.AfterDatabaseConnect
// 路由执行前触发
event.BeforeRoute
// 路由执行后触发
event.AfterRoute
集成Swagger,自动生成API文档。
刚开始我不喜欢让项目代码冗余太多得注释,但实际使用后,发现确实特别实用且方便。 关于swagger请参考我得文档,有详细说明,这里不再做过多描述。直接:swagger使用说明