Контекст и отмена

К задачам
Средняя
Concurrency

Условие задачи

Реализуй воркер, который каждую секунду выводит сообщение: "Working...". Через 3 секунды основной поток должен отменить контекст, и воркер должен завершиться корректно.

package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context) {
    // TODO: работай до отмены
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go worker(ctx)

    // TODO: через 3 секунды вызвать cancel()
}
package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context) {
    // TODO: работай до отмены
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go worker(ctx)

    // TODO: через 3 секунды вызвать cancel()
}

Подсказка

- Используй <-ctx.Done() внутри воркера, чтобы узнать, когда контекст отменён. - Не забудь вызвать cancel() — это важно для освобождения ресурсов.

Решение

Контекст позволяет удобно передавать сигнал отмены между потоками. Это особенно важно для graceful shutdown.

package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Работа остановлена")
            return
        default:
            fmt.Println("Working...")
            time.Sleep(time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go worker(ctx)

    time.Sleep(3 * time.Second)
    cancel()

    time.Sleep(time.Second)
}
package main

import (
    "context"
    "fmt"
    "time"
)

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Работа остановлена")
            return
        default:
            fmt.Println("Working...")
            time.Sleep(time.Second)
        }
    }
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    go worker(ctx)

    time.Sleep(3 * time.Second)
    cancel()

    time.Sleep(time.Second)
}