Go

Go context timeout 전까지 반복하기

4번독수리 2019. 8. 29. 16:13

package main

import (
	"context"
	"log"
	"os"
	"time"
)

func main() {
	logger := log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile)

	duration, _ := time.ParseDuration("1s")
	ticker := time.NewTicker(duration)
	defer ticker.Stop()
	for range ticker.C {
		ctx, cancel := context.WithTimeout(context.Background(), duration)
		go func(ctx context.Context) {
			ints := make([]int, 10)
			logger.Printf("%#v", ints)
		INTS:
			for i := range ints {
				select {
				case <-ctx.Done():
					logger.Printf("timeout. err:%#v", ctx.Err())
					break INTS
				default:
					time.Sleep(110 * time.Millisecond)
					logger.Printf("I am a long time job:%d", i)
				}
			}
		}(ctx)
		defer cancel()
	}
}

출력

2019/08/29 16:14:45 main.go:20: []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2019/08/29 16:14:45 main.go:29: I am a long time job:0
2019/08/29 16:14:45 main.go:29: I am a long time job:1
2019/08/29 16:14:45 main.go:29: I am a long time job:2
2019/08/29 16:14:45 main.go:29: I am a long time job:3
2019/08/29 16:14:45 main.go:29: I am a long time job:4
2019/08/29 16:14:45 main.go:29: I am a long time job:5
2019/08/29 16:14:45 main.go:29: I am a long time job:6
2019/08/29 16:14:46 main.go:29: I am a long time job:7
2019/08/29 16:14:46 main.go:20: []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2019/08/29 16:14:46 main.go:29: I am a long time job:8
2019/08/29 16:14:46 main.go:25: timeout. err:context.deadlineExceededError{}
2019/08/29 16:14:46 main.go:29: I am a long time job:0
2019/08/29 16:14:46 main.go:29: I am a long time job:1

...

 

마음에 들지 않는다...

1. 마지막 1회 실행이 timeout 뒤로 넘어감

 

주의

1. cancel()을 defer하지 않으면 for select에서 default로 넘어가지 못하고 바로 ctx.Done()을 수신