Sleep () в цикле Tick () - PullRequest
       2

Sleep () в цикле Tick ()

0 голосов
/ 15 апреля 2020

У меня есть фрагмент:

func TestTicks(t *testing.T) {
    go func() {
        for range time.Tick(600 * time.Millisecond) {
            log.Println("Tick")
        }
    }()
    time.Sleep(5000 * time.Millisecond)
}

Имеет смысл напечатать 8 строк (5000 дел. 600 = 8):

2020/04/15 14:51:08 Tick
2020/04/15 14:51:09 Tick
2020/04/15 14:51:09 Tick
2020/04/15 14:51:10 Tick
2020/04/15 14:51:10 Tick
2020/04/15 14:51:11 Tick
2020/04/15 14:51:12 Tick
2020/04/15 14:51:12 Tick

Однако, это становится не слишком ясно когда я добавлю Sleep() внутрь:

func TestTicks(t *testing.T) {
    go func() {
        for range time.Tick(600 * time.Millisecond) {
            log.Println("Tick")
            time.Sleep(500 * time.Millisecond)
        }
    }()
    time.Sleep(5000 * time.Millisecond)
}

Я ожидаю, что он будет напечатан 4 раза (5000 дел. 1100 = 4). Но на самом деле он все равно печатается 8 раз:

2020/04/15 14:53:17 Tick
2020/04/15 14:53:18 Tick
2020/04/15 14:53:18 Tick
2020/04/15 14:53:19 Tick
2020/04/15 14:53:19 Tick
2020/04/15 14:53:20 Tick
2020/04/15 14:53:21 Tick
2020/04/15 14:53:21 Tick

Почему внутренний Sleep() не влияет на выполнение?

Если я изменю его еще больше:

func TestTicks(t *testing.T) {
    go func() {
        for range time.Tick(1000 * time.Millisecond) {
            log.Println("Tick")
            time.Sleep(1000 * time.Millisecond)
        }
    }()
    time.Sleep(5000 * time.Millisecond)
}

Он печатается 4 раза, хотя я ожидаю, что он будет напечатан только 2 (5000 дел. 2000 = 2).

Мне кажется, я не понимаю, как вещи Sleep() и for range time.Tick() работают вместе ...

1 Ответ

3 голосов
/ 15 апреля 2020

time.Tick создает таймер, который тикает с заданной частотой. Эти галочки отправляются на канал. time.Tick возвращает этот канал. Так что это более или менее эквивалентно:

func TestTicks(t *testing.T) {
    go func() {
        c := time.Tick(600 * time.Millisecond)
        for range c {
            log.Println("Tick")
        }
    }()
    time.Sleep(5000 * time.Millisecond)
}

Обратите внимание, что тики, которые поступают на канал c, отправляются с третьей (невидимой, предоставленной системой) программы.

Если вы теперь добавите свой time.Sleep вызов к своей анонимной программе, ожидаете ли вы, что это повлияет на системную процедуру, которая посылает тики на канал c? (Если так, то почему?)

Предполагая, что вы не ожидаете этого - вы ожидаете, что системная процедура будет продолжать просыпаться каждые 600 мс и пытаться вставить значение времени в c используя:

now = time.Now()
select {
    case c <- now:
    default:
}

- тогда почему вы ожидаете чего-то другого с вариантом for range time.Tick(arg)? Функция time.Tick(arg) вызывается только один раз, независимо от того, сохранено ли возвращаемое значение в переменной с именем c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...