Skip to content

HTTP 服务

如果使用的是 gooze-cli 或者 gen api... 指令生成的代码,那么已经自动实现了 http 服务

此时,只需要确保 main.go 中匿名导入了即可

但是,就算你自行实现,也需要按照 gooze 的要求来

实现

一定要知道的内容

gooze 中启动一个 http 服务,必须要做一件事

通过实现接口 gooze.IService 注册你要启动的服务

  1. 注册服务
go
// 参数必须是一个或多个实现了 IService 接口的对象
gooze.RegisterService(&HttpServer{})

要求:每个对象都必须实现 OnStart() error 方法

  1. 接口实现
go
type HttpServer struct {
    *gooze.IServer
}

func (self *HttpServer) OnStart() (err error) { // 必须实现的方法
    // TODO implement
    // 实现 http 的初始化

    return nil
}
  1. OnStart() 方法中实现 http 的初始化

如何初始化?

  1. 通过 gooze 内置的 httpmodule 模块初始化

  2. 自行实现

内置的 httpmodule 模块

内置的 httpmodule 模块提供了几个关键的方法

  1. Init(caller interface{}, addr string, timeout int, engine *gin.Engine) 用来初始化基本参数

  2. OnStop(data *gzutil.OrderlyMap) 用来注册服务停机时需要执行的函数

gzutil.OrderlyMap 是什么?

它是一个有序 Map 严格按照 Append 的顺序执行,先进先出,同名会被覆盖,可以确保你停机时执行的函数的顺序

  1. Start() error 用来启动服务

  2. StartTLS(certFile, keyFile string) error 用来启动 https 服务

所以最终的实现方式就很简单了,如下

go
// server.go
func init() {
	gooze.RegisterService(&HttpServer{})
}

type HttpServer struct {
	*gooze.IServer

	httpModule httpmodule.IHttp // 使用内置的模块
}

func (self *HttpServer) OnStart() (err error) {
	// 添加回调函数
	self.httpModule.OnStop(self.exitCallback()) 

	self.httpModule.Init(self, gooze.Config.App.Addr, gooze.Config.App.Timeout, router.InitRouter()) 
	err = self.httpModule.Start() 

	return
}

// TODO 添加回调函数, 无逻辑可直接删除这个方法
func (self *HttpServer) exitCallback() *gzutil.OrderlyMap { 
	callback := gzutil.NewOrderlyMap() 
	callback.Append("exit", func() { 
		gooze.Log.Info("这是程序退出后的回调函数, 执行你想要执行的逻辑, 无逻辑可以直接删除这个方法") 
	}) 

	return callback 
} 

自行实现

这个的实现方式也有很多,但是常见的大概如下:

  1. 服务启动
go
// server.go

func (self *HttpServer) OnStart() (err error) {
    // 初始化路由
    route := router.InitRouter() 

    // 启动服务
    server := &http.Server{ 
        Addr:    ":8080", 
        Handler: route, 
    } 
    go func() { 
        if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { 
            fmt.Println("服务启动失败:", err) 
        } 
    }() 

    shutdown(server) 

    return nil
}
  1. 服务停机
go
// server.go

func shutdown(server *http.Server) {
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	fmt.Println("接收到退出信号,等待当前响应完成...")

	// 停机倒计时
	timeout := 5
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(timeout))
	defer cancel()
	tick := time.Tick(time.Duration(timeout) * time.Second)
	for countdown := timeout; countdown > 0; countdown-- {
		<-tick
	}

	if err := server.Shutdown(ctx); err != nil {
		fmt.Println("服务停机失败:", err)
	}
}

以上两种方式都经过了验证,是完全可用的,任君选择...

基于 MIT 许可发布