如何优雅的关闭net.Listeners

qinxiuchen · · 3251 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

使用golang做网络应用时,创建网络服务器时需要用到net.Listeners生成一个监听器,阻塞处理连接到服务器的请求,如下所示:

func main(){
    ln, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", 1234))
    if err != nil {
        log.Fatal(err)
    }
    log.Println("server start...")
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal(err)
        }
        handle(conn)
    }
}

但是ln.Accept()是一个阻塞函数,我们无法在某时刻通知并令其退出(处于一个for循环之中),并且有时我们需要在关闭监听器之后做一些收尾或清理的操作。对于一个常驻进程,只能通过杀进程的方式结束,无法满足这些需求,确实不是一个优雅的处理方式。
在这里我们使用channel的思想来解决这一问题,具体实现如下:

package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

var (
    quit = make(chan struct{})
    ln   net.Listener
)

func main() {

    ln, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", 1234))
    if err != nil {
        log.Fatal(err)
    }
    go start()
    time.Sleep(1 * time.Second)
    stop()
    time.Sleep(1 * time.Second)
}

func start() {
    log.Println("server start...")
    for {
        conn, err := ln.Accept()
        if err != nil {
            select {
            default:
            case <-quit:
                //do something
                return
            }
            fmt.Println(err)
        }
        handle(conn)
    }
}
func stop() {
    close(quit)
    ln.Close()
}

//handle connection
func handle(conn net.Conn) {
    //......
}

增加了一个叫quit的channel,当我们关闭listener的时候也关闭此channel,监听器报错以后检测到quit已经关闭可以做一些后续处理然后再返回,达到了优雅退出的效果。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:qinxiuchen

查看原文:如何优雅的关闭net.Listeners

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3251 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传