从零开始
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.New()
r.Handle("GET", "/", func(c *gin.Context) {
c.JSONP(200, gin.H{"result": "success"})
})
r.Run()
}
隐藏功与名
├── classes
│ └── index.go
├── cmd
│ └── main.go
├── go.mod
└── go.sum
package main
import (
"github.com/gin-gonic/gin"
"src/classes"
)
func main() {
r := gin.New()
classes.NewIndexClass(r).Build() //就一句话
r.Run()
}
package classes
import "github.com/gin-gonic/gin"
type IndexClass struct {
*gin.Engine //这玩意就是 gin.New() 创建出来的
// 嵌套, 好比继承,但并不是继承。go 并不是纯面向对象语言,别想太多
}
func NewIndexClass(e *gin.Engine) *IndexClass { // 所谓的构造函数
return &IndexClass{Engine: e} // 需要赋值,因为是指针
}
func (this *IndexClass) GetIndex() gin.HandlerFunc { // 这就是我们的业务方法,函数名随便了
return func(c *gin.Context) {
c.JSON(200, gin.H{
"result": "index ok", // 换行别忘记 逗号
})
}
}
func (this IndexClass) Build() {
this.Handle("GET", "/", this.GetIndex()) //我们把内容隐藏在这里了,main 就很干净
}
- 还不够逼格
- 如果控制器多了,代码还是冗余
- 各个控制器代码之间,没有约束(没有接口规范)
改进
.
├── classes
│ ├── index.go
│ └── user.go
├── cmd
│ └── main.go
├── go.mod
├── go.sum
└── goft
├── Goft.go
└── IClass.go
package main
import (
"github.com/gin-gonic/gin"
"src/classes"
"src/goft"
)
func main() {
r := gin.New()
goft.Ignite().Mount(classes.NewIndexClass(), classes.NewUserClass()).Launch()
r.Run()
}
package goft
import "github.com/gin-gonic/gin"
type Goft struct {
*gin.Engine //我们把 engin放到主类里
}
func Ignite() *Goft { //这就是所谓的构造函数
return &Goft{Engine: gin.New()}
}
func (this *Goft) Launch() { //最终启动函数,不用run,没有逼格
this.Run(":8080") // 这块套接字,暂时先写死
}
func (this *Goft) Mount(classes ...IClass) *Goft { //返回自己是为了链式调用
for _, class := range classes {
class.Build(this) //这一步是关键。 这样在mian里面就不需要调用了
}
return this
}
package goft
type IClass interface {
Build(goft *Goft) // 参数和方法名必须一致
}
package classes
import (
"github.com/gin-gonic/gin"
"src/goft"
)
type IndexClass struct {
}
func NewIndexClass() *IndexClass { // 所谓的构造函数
return &IndexClass{} // 需要赋值,因为是指针
}
func (this *IndexClass) GetIndex() gin.HandlerFunc { // 这就是我们的业务方法,函数名随便了
return func(c *gin.Context) {
c.JSON(200, gin.H{
"result": "index ok", // 换行别忘记 逗号
})
}
}
func (this IndexClass) Build(goft *goft.Goft) {
goft.Handle("GET", "/", this.GetIndex()) //我们把内容隐藏在这里了,main 就很干净
}
package classes
import (
"github.com/gin-gonic/gin"
"src/goft"
)
type UserClass struct {
//*gin.Engine 去掉了,业务控制器 不应该和 服务类 有强关联, 否则耦合太高了
}
func NewUserClass() *UserClass {
return &UserClass{}
}
func (this *UserClass) GetUser() gin.HandlerFunc {
return func(c *gin.Context) {
c.JSON(200, gin.H{
"result": "user ok",
})
}
}
func (this *UserClass) Build(goft *goft.Goft) { // 这个参数是关键,我们把goft传进来
goft.Handle("GET", "/user", this.GetUser())
}
把路由挂载到group
我们知道GIN 里面可以自定义Group 分组
譬如,原来是/user 这种路径,加入代码后,可以编程/v1/users,方便进行API版本的设定
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.New()
//mygin.NewCtr(r).MountCtr(Controllers.NewUserController(), Controllers.NewInfoController()).RunCtr()
g := r.Group("v1")
g.Handle("GET", "/test", func(c *gin.Context) {
c.JSON(200, "test xxxxxxxx")
})
r.Run(":8080")
}
改造
package mygin
import "github.com/gin-gonic/gin"
type Ctr struct {
*gin.Engine
g *gin.RouterGroup
}
func NewCtr() *Ctr {
return &Ctr{Engine: gin.New()}
}
func (this *Ctr) RunCtr() {
this.Run(":8080")
}
func (this *Ctr) Handle(httpMethod, relativePath string, handlers ...gin.HandlerFunc) *Ctr {
this.g.Handle(httpMethod, relativePath, handlers...)
return this
}
func (this *Ctr) MountCtr(group string, ictrs ...Ictr) *Ctr {
this.G = this.Group(group)
for _, ctr := range ictrs {
ctr.Build(this)
}
return this
}
精酿中间件
//我们知道,gin官方代码是支持中间件的。譬如如下代码
r := gin.New()
r.Use(func(c *gin.Context) {
})