Как использовать канал, чтобы уведомить goroutine, чтобы выйти должным образом - PullRequest
0 голосов
/ 23 мая 2018

Примечание: Я искал эту тему в Google и прочитал почти все, что смог найти, но все еще не могу получить правильный / разумный / готовый к работе ответ.

В основном все ответы похожиТочно так же, как этот: как остановить процедуру , все по одному шаблону, без исключения: настоящая работа - fmt.Println(1) напечатать что-то или просто // Do other stuff,

Но если держать реальную работу на for select default case branch, то она будет выполняться несколько раз, для печати чего-то это нормально, но, очевидно, она не готова к реальной работе.

Единственный верный подход, который я могу себе представить, этопоместите реальную работу в ветвь кейса, а затем отправьте только один сигнал к этому кейсу, чтобы уведомить его о начале, как здесь: детская площадка , но просто волнуйтесь, и при таком подходеэто может создать некоторые проблемы?

Добавлены фрагменты кода, чтобы показать, чего именно я пытаюсь достичь: https://play.golang.org/p/7xjjiW7XdoQ, Я хочу достичь, когда клиент закроет соединение, а затем немедленно прекратить мой обработчик, отпуститьиспользуйте ресурсы и выйдите безоговорочно.

1 Ответ

0 голосов
/ 23 мая 2018

Вместо использования петли for select вы хотите проверить наличие сигнала отмены в нескольких местах.Но чтобы не блокировать, вы все равно должны использовать select (с пустым регистром по умолчанию), что делает его немного неудобным.Я использую context.Context вместо «обычного канала отмены», но идея та же:

func doWork(ctx context.Context) {
    fmt.Println("Doing some work 1")
    time.Sleep(time.Second * 5)
    // check is the task cancelled
    select {
    case <-ctx.Done():
        fmt.Println("cancelled at checkpoint 1")
        return
    default:
    }
    fmt.Println("Doing some work 2")
    time.Sleep(time.Second * 5)
    // check is the task cancelled
    select {
    case <-ctx.Done():
        fmt.Println("cancelled at checkpoint 2")
        return
    default:
    }
    fmt.Println("Doing some work 3")
    time.Sleep(time.Second * 5)
}

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
    defer cancel()
    go func() {
        doWork(ctx)
        wg.Done()
    }()
    wg.Wait()
    fmt.Println("done")
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...