欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

golang中实现select超时机制

程序员文章站 2022-05-29 22:36:21
...

对于c/c++开发来说,有和os最为贴切的api可以用,例如
带超时机制的互斥锁

       #include <pthread.h>
       #include <time.h>

       int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
           const struct timespec *restrict abstime);

带超时机制的epoll

       #include <sys/epoll.h>

       int epoll_wait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout);
       int epoll_pwait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout,
                      const sigset_t *sigmask);

等。

但是对于golang这样一个新的语言来说,需要完善的地方还有一些。例如一些开源组件的重写,cordis、mysql等用golang重写,有些api确实不那么完善。

对于多路复用来说,不可能一直等待信号。万一发信号的死掉了,经常岂不是傻傻的等着了吗。所以有超时机制。
golang 虽然没有原生的api可以满足条件,但是可以组合一下,在应用层实现这种功能。(这也符合linux微内核的设计思想)

package main
import (
        "fmt"
        "time"
        "strconv"
)
func main() {
        ch := make(chan string)
        quit := make(chan bool)
        go func() {
                for i := 0; i < 10; i++ {
                        ch <- strconv.Itoa(i)
                        time.Sleep(time.Second)
                }
        }()

        go func() {
                timeout := time.After(time.Second * 2)	// 注意,定时器必须放在select外面
                flagrun := true
                for ; flagrun == true ; {
                        select {
                        case <-timeout:
                                fmt.Println("2 second timout,then send one message to channel quit ,and exit for loop and goroutine")
                                flagrun = false
                                quit <- true
                        case str := <-ch:
                                fmt.Println("string: ", str)
                        }
                }
        }()
        <-quit
        close(ch)
        close(quit)
        fmt.Println("endof process")
}