golang 处理超时常用的方法

267 阅读1分钟

超时处理的三种方法

1.context超时取消或者手动取消

func contextTest() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	// ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))
	go func(ctx context.Context) {
		for {
			time.Sleep(1 * time.Second)
			select {
			case <-ctx.Done():
				fmt.Printf("done")
				return
			default:
				fmt.Printf("work")
			}
		}
	}(ctx)

	time.Sleep(10 * time.Second)
	cancel()
}

2.超时返回

func tickerTest() {
	ticker := time.NewTicker(time.Second * 2)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			fmt.Println("aaa")
			return
		}
	}
}

3.超时返回

func tickerTest2() {
	for {
		select {
		case <-time.After(time.Second * 2):
			fmt.Println("bbb")
			return
		}
	}
}
func main() {
	//contextTest()
	//tickerTest()
	tickerTest2()
}

栗子: 实现带timeout的sync.Wait函数,在函数体内实现。

// WaitTimeout() 如果timeout到了超时时间返回true,如果WaitGroup自然结束返回false

func WaitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    ctx, cancel := context.WithCancel(context.Background())
    quit := make(chan bool)

    go func() {
        wg.Wait()
        quit <- false
    }()

    go func() {
        for {
            select {
            case <-ctx.Done():
                return
            case <-time.After(timeout):
                quit <- true
            }
        }
    }()

    ret := <-quit
    cancel()

    return ret
}

func main() {
    wg := sync.WaitGroup{}
    c := make(chan struct{})
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(num int, close <-chan struct{}) {
            defer wg.Done()
            ret := <-close
            fmt.Println(num, ret)
        }(i, c)
    }

    //for i := 0; i < 10; i++ {
    //  c<-struct{}{}
    //}

    if WaitTimeout(&wg, time.Second*2) {
        close(c)
        fmt.Println("timeout exit")
    }
    time.Sleep(time.Second * 5)