之前接触过Java的Swagger,非常简单易用,但是Golang中一直没有合适的Swagger实现。现在比较流行的方案是使用注释实现,需要手动写注释,总感觉不是特别方便,所以就自己实现了个该工具。坑是挖了很久,刚学go的时候挖的,之后无奈搬砖去写java,一直没机会填坑,最近又重新写go了,所以回来慢慢填坑。
ginhelper
支持的功能:
- 整合gin的参数绑定与路由设置
- 非注释自动生成swagger
为了自动绑定参数和生成路由,需要先了解下面几个概念:
- GroupRouter 路由组
type GroupRouter struct {
Path string // 路由组的根路径,与Gin的Group一样,定义一组接口的公共路径
Name string // 路由组的名称
Routes []*Route // 路由组中的具体路由
}
定义一组相关的路由
- Router 路由
type Route struct {
Param Parameter // 接口的参数实现
Path string // 接口的路径
Method string // 接口的方法
Handlers []gin.HandlerFunc // 接口的额外处理函数
}
- 参数绑定
为了成功绑定参数,并降低代码的重复度,需要参数实现Parameter
接口:
type Parameter interface {
Bind(c *gin.Context, p Parameter) (err error) //绑定参数
Handler(c *gin.Context) (data Data, err error) //执行具体业务
Result(c *gin.Context, data Data, err error) //结果返回
}
为了避免不必要的重复实现接口,可以使用结构体嵌入,比如使用内置的BaseParam
嵌入。
包内包含两种初始化方法:不需要Swagger的func New() *Helper
,和自动生成swagger的func NewWithSwagger(swaggerInfo *SwaggerInfo, r GinRouter) *Helper
示例:
// 定义一个Group
var testGroup = &ginhelper.GroupRouter{
Path: "test",
Name: "Mytest",
Routes: []*ginhelper.Route{
{
Param: new(testBodyParam),
Path: "/hello/:id",
Method: "POST",
}},
}
type FooStruct struct {
FooA string `binding:"required" `
FooB *bool `binding:"required"`
}
// 接口的参数
type testBodyParam struct {
ginhelper.BaseParam `json:"-"`
Foo string `binding:"required"`
FooName string `json:"fName" binding:"required"`
FooInt int `binding:"required"`
FooIgnore string `json:"-"`
FooStruct
FooStruct2 FooStruct
FooStruct3 *FooStruct
}
func (param *testBodyParam) Handler(c *gin.Context) (data ginhelper.Data, err error) {
return param, nil
}
func Example() {
router := gin.Default()
r := router.Group("api")
// 如果不需要swagger,可以使用New初始化
h := ginhelper.NewWithSwagger(&ginhelper.SwaggerInfo{
Description: "swagger test page",
Title: "Swagger Test Page",
Version: "0.0.1",
ContactInfoProps: ginhelper.ContactInfoProps{
Name: "zzj",
URL: "https://zzj.cool",
Email: "[email protected]",
},
}, r)
h.Add(testGroup, r)
_ = router.Run(":8888")
}
如果开启了swagger的话,访问http://127.0.0.1:8888/api/swagger
即可。
性能测试:
直接使用Gin和使用ginhelper生成的接口,两者性能差别不大:
go test -bench=. -benchmem -run=none
goos: linux
goarch: amd64
pkg: github.com/zzjcool/ginhelper
cpu: AMD Ryzen 5 3400G with Radeon Vega Graphics
BenchmarkHelp-8 236252 4836 ns/op 2258 B/op 38 allocs/op
BenchmarkNorm-8 254684 4765 ns/op 2258 B/op 38 allocs/op
PASS
ok github.com/zzjcool/ginhelper 2.466s