从零开始

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 就很干净
}
  1. 还不够逼格
  2. 如果控制器多了,代码还是冗余
  3. 各个控制器代码之间,没有约束(没有接口规范)

改进

.
├── 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) {
   
})

Q.E.D.