Golang实现程序优雅退出的方法 有哪些 ?

Golang实现程序优雅退出的方法 有哪些 ?
原创 磊丰 Go语言圈 2024-01-16 08:31 发表于广东 听全文
学习与交流:Go语言技术微信群
商务合作加微信:LetsFeng
 
 
 
现在就开始你的Go语言学习之旅吧!人生苦短,let’s Go.
 
 
 
 
 
 
Goland 全家桶激活码,永久有效,亲测可用,限时免费
 
获取链接地址:https://web.52shizhan.cn
 
在Go语言中,实现程序的优雅退出是一项重要的任务,特别是在涉及到HTTP服务器、gRPC服务器、以及其他后台工作的情况下。以下是一些常见的平滑关闭方法:
 
1. HTTP Server 平滑关闭
Go 1.8及以上版本提供了 http.Server 结构的 Shutdown 方法,用于平滑关闭HTTP服务器。
 
package main
 
import (
    "context"
    "net/http"
    "os"
    "os/signal"
    "time"
)
 
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World!"))
    })
 
    server := &http.Server{
        Addr: ":8080",
        Handler: mux,
    }
 
    go func() {
        if err := server.ListenAndServe(); err != nil {
            if err != http.ErrServerClosed {
                // 处理监听失败的错误
            }
        }
    }()
 
    // 等待中断信号来优雅地关闭服务器
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, os.Interrupt)
 
    <-stop // 等待中断信号
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
 
    if err := server.Shutdown(ctx); err != nil {
        // 处理关闭服务器时的错误
    }
}
 
 
 
 
 
2. gRPC Server 平滑关闭
gRPC服务器的平滑关闭可以通过 GracefulStop 方法实现。
 
package main
 
import (
    "context"
    "fmt"
    "net"
    "os"
    "os/signal"
 
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)
 
type Greeter struct{}
 
func (s *Greeter) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) {
    return &HelloReply{Message: "Hello " + in.Name}, nil
}
 
func main() {
    listener, err := net.Listen("tcp", ":50051")
    if err != nil {
        // 处理监听失败的错误
    }
 
    server := grpc.NewServer()
    RegisterGreeterServer(server, &Greeter{})
 
    // 在gRPC服务上启用反射服务
    reflection.Register(server)
 
    go func() {
        if err := server.Serve(listener); err != nil {
            // 处理gRPC服务启动错误
        }
    }()
 
    // 等待中断信号来优雅地关闭gRPC服务器
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, os.Interrupt)
 
    <-stop // 等待中断信号
    fmt.Println("Shutting down gRPC server...")
 
    server.GracefulStop()
    fmt.Println("gRPC server gracefully stopped")
}
3. Worker 协程平滑关闭
对于worker协程的平滑关闭,可以使用 context.Context 实现。
 
package main
 
import (
    "context"
    "fmt"
    "os"
    "os/signal"
    "sync"
    "time"
)
 
func worker(ctx context.Context, wg *sync.WaitGroup) {
    defer wg.Done()
 
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Worker received shutdown signal")
            return
        default:
            // 执行工作任务
            fmt.Println("Working...")
            time.Sleep(time.Second)
        }
    }
}
 
func main() {
    ctx, cancel := context.WithCancel(context.Background())
    var wg sync.WaitGroup
 
    // 启动worker协程
    wg.Add(1)
    go worker(ctx, &wg)
 
    // 等待中断信号来优雅地关闭worker协程
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, os.Interrupt)
 
    <-stop // 等待中断信号
    fmt.Println("Shutting down...")
 
    // 发送关闭信号给worker协程
    cancel()
    wg.Wait()
    fmt.Println("Shutdown complete")
}
 
4. 实现 `io.Closer` 接口的自定义服务平滑关闭
实现 io.Closer 接口的服务可以通过调用 Close 方法进行平滑关闭。
 
package main
 
import (
    "fmt"
    "os"
    "os/signal"
    "sync"
    "time"
)
 
type MyService struct {
    mu sync.Mutex
    // 其他服务相关的字段
}
 
func (s *MyService) Close() error {
    s.mu.Lock()
    defer s.mu.Unlock()
 
    // 执行关闭服务的操作
    fmt.Println("Closing MyService...")
    return nil
}
 
func main() {
    service := &MyService{}
 
    // 等待中断信号来优雅地关闭服务
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, os.Interrupt)
 
    <-stop // 等待中断信号
    fmt.Println("Shutting down...")
 
    // 调用Close方法进行平滑关闭
    if closer, ok := service.(interface{ Close() error }); ok {
        if err := closer.Close(); err != nil {
            fmt.Println("Error closing service:", err)
        }
    }
    fmt.Println("Shutdown complete")
}
以上是一些Golang中实现程序优雅退出的方法,具体的实现方式取决于你的应用程序结构和使用的库。
 
在实际应用中,你可能需要组合使用这些方法以确保整个应用程序在退出时都能够平滑关闭。
 
 
 
文章首发:
更多相关Go语言的技术文章或视频教程,请关注本公众号获取并查看,感谢你的支持与信任!
 
 
 
阅读 67
 
Go语言圈
 
 
 
人划线
 
 
posted @   技术颜良  阅读(634)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
历史上的今天:
2023-01-16 Docker数据目录迁移解决方案
2023-01-16 Docker迁移默认的/var/lib/docker目录
2023-01-16 golang 的fmt 包实现了格式化I/O函数,类似于C的 printf 和 scanf。
2023-01-16 CentOS8.5 下挂载大于2T的硬盘
2023-01-16 linux判断磁盘是否格式化(docker磁盘满解决方案)
点击右上角即可分享
微信分享提示