Golang 实现程序的优雅退出

iface.go

package GabrielConfig

import (
    "context"
    "sync"
)

type IGracefulExit interface {
    Cancel()
    GetCtx() context.Context
    GetWaitGroupInCtx() *sync.WaitGroup
}

graceful_exit.go

package GabrielConfig

import (
    "context"
    "sync"
)

var GabrielGracefulExit IGracefulExit // goroutine优雅退出使用的接口
var gabrielGracefulExitOnce sync.Once // goroutine优雅退出使用单例模式

type GracefulExit struct {
    ctx    context.Context    // ctx用于所有服务等待停止并回收资源
    cancel context.CancelFunc // 函数执行将通知所有服务停止并回收资源
}

const (
    ctxKeyWaitGroup = "WaitGroup"
)

func NewRoutineSync() IGracefulExit {
    if GabrielGracefulExit == nil {
        gabrielGracefulExitOnce.Do(func() {
            ctx, cancel := context.WithCancel(context.WithValue(context.Background(), ctxKeyWaitGroup, new(sync.WaitGroup)))
            GabrielGracefulExit = &GracefulExit{
                ctx:    ctx,
                cancel: cancel,
            }
        })
    }
    return GabrielGracefulExit
}

func (g *GracefulExit) Cancel() {
    g.cancel()
}

func (g *GracefulExit) GetCtx() context.Context {
    return g.ctx
}

func (g *GracefulExit) GetWaitGroupInCtx() *sync.WaitGroup {
    if wg, ok := g.ctx.Value(ctxKeyWaitGroup).(*sync.WaitGroup); ok {
        return wg
    }

    return nil
}

/*
使用方式如下:

func server(ge IGracefulExit) error{
    defer func(){
        // 提供服务
    }

    ... ...
    // 初始化服务配置
    ... ...

    ge.GetWaitGroupInCtx().Add(1)
    go func(){
        defer ge.GetWaitGroupInCtx().Done()
        <-ge.GetCtx().Done()
        ... ...
        // 执行服务关闭操作
        ... ...
    }
    return nil
}


func main(){
    defer func(){
        ge.Cancel()
        ge.GetWaitGroupInCtx().Wait()
    }

    server(ge)

    quit := make(chan os.Signal)
    // kill (no param) default send syscall.SIGTERM
    // kill -2 is syscall.SIGINT
    // kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit
}
*/

 

posted @ 2020-12-30 16:32  路璐  阅读(859)  评论(0编辑  收藏  举报