Skip to content

初始化路由 原创

说明

从本节课开始,我们会逐渐把项目按目标项目结构来调整。

这个节的目标如下:

  • 创建 initialize 包
  • 初始化服务
  • 初始化路由
  • 注册 api 路由

1、创建 initialize

我们在程序结构中有一个 initialize 包,这个包的作用是进行一些初始化操作。

首先,在代码根目录中创建 initialize 文件夹,再在里面创建一个 server.go 文件,填写代码如下:initialize/server.go

go
package initialize

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// 初始化
func NewServer() *gin.Engine {
	r := gin.New()
	r.Use(gin.Logger(), gin.Recovery())
	// 注册一个路由
	r.GET("/", func(c *gin.Context) {

		// 以 JSON 格式响应
		c.JSON(http.StatusOK, gin.H{
			"Data": "Hello World!",
		})
	})

	return r
}

2、初始化服务

上面只是简单的把之前在 main.go 中的代码拷贝过来,并没有做太多的解耦,为了让代码看起来更合理,我们将initialize/server.go的代码修改为如下:

go
package initialize

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// 初始化

type Engine struct {
	*gin.Engine

	Mode string
}

func NewEngine() *Engine {
	g := &Engine{}

	gin.SetMode(g.Mode)

	g.injectMiddlewares()
	g.injectRouters()

	return g
}

func (s *Engine) injectMiddlewares() {
	g := gin.New()
	defer func() {
		s.Engine = g
	}()

	if s.Mode == gin.TestMode {
		return
	}

	// 注册中间件
	g.Use(gin.Logger())
	g.Use(gin.Recovery())
}

func (s *Engine) injectRouters() {
	r := s.Engine
	// 注册一个路由
	r.GET("/", func(c *gin.Context) {

		// 以 JSON 格式响应
		c.JSON(http.StatusOK, gin.H{
			"Data": "Hello World!",
		})
	})

	s.Engine = r
}

然后将 main.go 文件改造成如下:

go
package main

import (
	"log"
	"net/http"
	"time"

	"github.com/joker-bai/hawkeye/initialize"
)

func main() {
	// 初始化

	engine := initialize.NewEngine()
	server := &http.Server{
		Addr:         ":8080",
		WriteTimeout: time.Second * 3600,
		ReadTimeout:  time.Second * 3600,
		IdleTimeout:  time.Second * 5 * 60,
		Handler:      engine,
	}

	// 运行服务
	if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		log.Fatalf("Failed to start http server, error: %s", err)
	}
}

现在我们不是直接使用 gin.Engine.Run()来启动服务,而是直接使用 net/http来启动,主要是为了定义更多的参数。

现在,我们可以重启项目,再次使用 apifox 测试,观察是否有问题。

abb177b348ae77ebc73c3714dff897d2 MD5

3、初始化路由

在之前的代码中,我们定义了 / 路由,如果整个项目都是这么一个简单的路由,其实放在任何地方都无所谓。

但是,在真实的项目中,往往有许许多多的路由,为此,我们需要将路由拆分出来,方便管理。

首先,创建 initialize/router.go文件,写入以下内容:

go
package initialize

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func (s *Engine) injectRouterGroup(router *gin.RouterGroup) {
	public := router.Group("/api")
	{
		// 注册一个路由
		public.GET("/", func(c *gin.Context) {

			// 以 JSON 格式响应
			c.JSON(http.StatusOK, gin.H{
				"Data": "Hello World!",
			})
		})
	}
}

然后将 initialize/server.go 中的injectRouters方法改造成如下:

go
func (s *Engine) injectRouters() {
	r := s.Engine

	apiRouter := r.Group("")
	s.injectRouterGroup(apiRouter)
	s.Engine = r
}

initialize/router.go文件中,我用了组的概念,并且组下面的成员都必须以 /api作为 URI 前缀,如果我们还是以http://127.0.0.1:8080/进行访问的话,会报 404,如下:

d47eaa1d58cb43c6a36654817341ed38 MD5

这时候我们应该访问http://127.0.0.1:8080/api/,如下:

e5bfb17d1fc0696defe01729f45f586f MD5

4、注册 api 路由

上面代码是直接将路由以及处理的业务都放在了 initialize/router.go 文件夹中,而在实际开发中,它们是分开的。

首先,在 internal/app/controllers/api/v1中创建helloworld.go文件,写入以下代码:

go
package v1

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

type HelloWorldController struct{}

func (s *HelloWorldController) Get(ctx *gin.Context) {
	ctx.JSON(
		http.StatusOK, gin.H{
			"Data": "Hello World",
		},
	)
}

这段代码是处理请求的业务逻辑。

然后,再在 internal/app/routers 中创建 helloworld.go 文件,写入以下内容:

go
package routers

import (
	"github.com/gin-gonic/gin"
	v1 "github.com/joker-bai/hawkeye/internal/app/controllers/api/v1"
)

type HelloWorldRouter struct{}

// Inject 实现inject接口
func (r *HelloWorldRouter) Inject(router *gin.RouterGroup) {
	hc := new(v1.HelloWorldController)
	router.GET("/hello", hc.Get)
}

这段代码主要是实现 inject 接口,注册具体的业务路由。

最后,再修改 initialize/router.go 文件中的代码,内容如下:

go
package initialize

import (
	"github.com/gin-gonic/gin"
	"github.com/joker-bai/kubemana/internal/app/routers"
)

type injector interface {
	Inject(router *gin.RouterGroup)
}

func (s *Engine) injectRouterGroup(router *gin.RouterGroup) {
	{
		for _, r := range []injector{
			new(routers.HelloWorldRouter),
		} {
			r.Inject(router.Group("/api"))
		}
	}
}

这段代码就是把业务路由加入路由组里。

5、测试一下

上面我们已经把所有代码改造完成,接下来就测试一下代码运行是否能达到预期。

启动项目过后,使用apifox进行测试,结果符合预期,如下:

c7a1726d64316bc14b8757b3dae575cd MD5

我们的请求地址变成了http://127.0.0.1:8080/api/hello。

到现在,我们整个业务流转逻辑基本完成,如下:

73d60ed171ff7e8157f193a505574abb MD5

这里还没有数据处理相关的逻辑,后续再加上。

6、代码版本

这节开发完成后,给代码打一个版本标记,如下:

go
git add .
git commit -m "初始化路由"
最近更新