有没有办法阻止默认的golang程序完成

有没有办法阻止默认的golang程序完成,go,websocket,Go,Websocket,我有一个使用websocket连接的服务器和一个数据库。有些用户可以通过套接字连接,所以我需要在db中增加他们的“在线”;在他们断开连接的时候,我也减少了他们在db中的“在线”字段。但是如果服务器出现故障,我会使用一个本地变量replica map[string]int来表示在线用户。所以我需要推迟服务器关闭,直到它完成一个数据库请求,该请求根据我的变量副本减少所有用户的“在线”,因为这样套接字连接不会发送默认的“关闭”事件 我发现了一个包github.com/xlab/closer,它可以处理

我有一个使用websocket连接的服务器和一个数据库。有些用户可以通过套接字连接,所以我需要在db中增加他们的“在线”;在他们断开连接的时候,我也减少了他们在db中的“在线”字段。但是如果服务器出现故障,我会使用一个本地变量replica map[string]int来表示在线用户。所以我需要推迟服务器关闭,直到它完成一个数据库请求,该请求根据我的变量副本减少所有用户的“在线”,因为这样套接字连接不会发送默认的“关闭”事件

我发现了一个包github.com/xlab/closer,它可以处理一些系统调用,并且可以在程序完成之前执行一些操作,但是我的数据库请求不能以这种方式工作(下面的代码)


可能我使用不正确,或者可能有更好的方法来防止默认程序完成?

我认为您需要查看go例程频道
这里有一些(可能)有用的东西:

首先,当服务器如您所说“出现故障”时执行任务是相当复杂的,因为出现故障可能意味着很多事情,当服务器出现问题时,没有任何东西可以保证清理功能的执行

从工程角度来看(如果在故障时将用户设置为脱机非常重要),最好在另一台服务器上提供一个辅助服务,该服务接收用户连接和断开事件以及ping事件,如果在设置的超时时间内未收到任何更新,服务将认为您的服务器已关闭,并继续将每个用户设置为脱机

回到您的问题,使用延迟和等待终止信号应涵盖99%的情况。我对代码进行了注释以解释逻辑

// AllUsersOffline is called when the program is terminated, it takes a *sync.Once to make sure this function is performed only
// one time, since it might be called from different goroutines.
func AllUsersOffline(once *sync.Once) {
    once.Do(func() {
        fmt.Print("setting all users offline...")
        // logic to set all users offline
    })
}

// CatchSigs catches termination signals and executes f function at the end
func CatchSigs(f func()) {
    cSig := make(chan os.Signal, 1)
    // watch for  these signals
    signal.Notify(cSig, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP) // these are the termination signals in GNU =>  https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
    // wait for them
    sig := <- cSig
    fmt.Printf("received signal: %s", sig)
    // execute f
    f()
}
func main() {
    /* code */
    // the once is used to make sure AllUsersOffline is performed ONE TIME.
    usersOfflineOnce := &sync.Once{}
    // catch termination signals
    go CatchSigs(func() {
        // when a termination signal is caught execute AllUsersOffline function
        AllUsersOffline(usersOfflineOnce)
    })
    // deferred functions are called even in case of panic events, although execution is not to take for granted (OOM errors etc)
    defer AllUsersOffline(usersOfflineOnce)
    /* code */
    // run server
    err := server.Run()
    if err != nil {
        // error logic here
    }
    // bla bla bla
}
//当程序终止时调用AllUsersOffline,需要一次*sync.one以确保只执行此函数
//一次,因为它可能从不同的goroutine调用。
func Allusersofline(一次*同步一次){
once.Do(func(){
fmt.Print(“将所有用户设置为脱机…”)
//将所有用户设置为脱机的逻辑
})
}
//CatchSigs捕捉终止信号,并在结束时执行f函数
func CatchSigs(f func()){
cSig:=make(信道操作信号,1)
//注意这些信号
signal.Notify(cSig、syscall.SIGKILL、syscall.SIGTERM、syscall.SIGINT、syscall.SIGQUIT、syscall.SIGHUP)//这些是GNU中的终止信号=>https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
//等他们
信号:=
// AllUsersOffline is called when the program is terminated, it takes a *sync.Once to make sure this function is performed only
// one time, since it might be called from different goroutines.
func AllUsersOffline(once *sync.Once) {
    once.Do(func() {
        fmt.Print("setting all users offline...")
        // logic to set all users offline
    })
}

// CatchSigs catches termination signals and executes f function at the end
func CatchSigs(f func()) {
    cSig := make(chan os.Signal, 1)
    // watch for  these signals
    signal.Notify(cSig, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGHUP) // these are the termination signals in GNU =>  https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
    // wait for them
    sig := <- cSig
    fmt.Printf("received signal: %s", sig)
    // execute f
    f()
}
func main() {
    /* code */
    // the once is used to make sure AllUsersOffline is performed ONE TIME.
    usersOfflineOnce := &sync.Once{}
    // catch termination signals
    go CatchSigs(func() {
        // when a termination signal is caught execute AllUsersOffline function
        AllUsersOffline(usersOfflineOnce)
    })
    // deferred functions are called even in case of panic events, although execution is not to take for granted (OOM errors etc)
    defer AllUsersOffline(usersOfflineOnce)
    /* code */
    // run server
    err := server.Run()
    if err != nil {
        // error logic here
    }
    // bla bla bla
}