Как запустить и остановить функцию - PullRequest
0 голосов
/ 07 октября 2019

У меня есть функция go processing, которая использует две разные функции. produce отправит некоторые данные в канал, а consume прочитает эти данные. Вот пример:

type MyObject struct{
    ...
}

func processing() {
    var wg sync.WaitGroup
    dataChannel := make(chan MyObject, 5)

    wg.Add(2)

    go produce(wg, dataChannel)
    go consume(wg, dataChannel)

    wg.Wait()
}

func produce (wg *sync.WaitGroup, dataChannel chan MyObject){
    for{
        // Produce data in dataChannel
    }
}

func consume (wg *sync.WaitGroup, dataChannel chan MyObject){
    for{
        // Consume data from dataChannel
    }
}

Я хочу, чтобы моя функция processing была запущена и остановлена ​​с помощью HTTP-вызова. Поэтому я собираюсь сделать что-то следующим образом:

func main() {

    // echo instance
    e := echo.New()
    e.GET("/", startProcessing)
    e.Logger.Fatal(e.Start(":8099"))
}

func startProcessing(c echo.Context) error{

    command := c.QueryParam("command")

    if(command == "start"){
        processing()
    }else if(command == "stop"){
        if (/* ? processing is running ? */){
            /* ? stop processing process? */
        }
    }       
}

Как правильно сделать это с помощью Go?

1 Ответ

3 голосов
/ 07 октября 2019

Здесь, как запустить и остановить функцию, используя контекст, попробуйте this :

package main

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

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    var wg sync.WaitGroup
    dataChannel := make(chan MyObject, 5)
    wg.Add(2)
    go produce(ctx, &wg, dataChannel)
    go consume(&wg, dataChannel)

    time.Sleep(1 * time.Second)
    cancel() // cancel when we are finished consuming data

    wg.Wait()
}

func produce(ctx context.Context, wg *sync.WaitGroup, dataChannel chan MyObject) {
    defer wg.Done()
    i := 1
    for {
        select {
        case <-ctx.Done():
            close(dataChannel)
            return // returning not to leak the goroutine
        case dataChannel <- MyObject{i}:
            i++
            time.Sleep(250 * time.Millisecond)
        }
    }
}

func consume(wg *sync.WaitGroup, dataChannel chan MyObject) {
    defer wg.Done()
    for v := range dataChannel {
        fmt.Println(v)
    }
}

type MyObject struct {
    i int
}


Для HTTP вам нужно сделать это самостоятельно!
Требуетсяу вас есть одновременный безопасный идентификатор или карта или что-то еще, чтобы отслеживать, сколько функций вы вызвали, а затем вызвать cancel(), чтобы остановить его.

...