Как запустить / остановить функцию, вызвав метод struct - PullRequest
0 голосов
/ 30 ноября 2018

Пожалуйста, смотрите следующий пример.

Ссылка на игровую площадку

type runner struct{}

func (r *runner) StopProcessing() {
    // how to stop?
}

func (r *runner) StartProcessing() {

    go func() {
        for {
            fmt.Println("doing stuff")
            time.Sleep(1 * time.Second)
        }
    }()

}

Как вы можете видеть, у меня есть структура, которая делает вещи, она "работает".Он запускается, когда я вызываю метод run.StartProcessing().Затем он запускает бесконечный бегущий for{} -петл в goroutine.Отлично, но я также хочу иметь возможность остановить этот процесс.И я действительно не знаю, как этого добиться.Любая помощь высоко ценится.

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Вы можете попробовать что-то вроде этого ... Возможно, вам не нужен атомарный, но это работает.

package main

import (
    "fmt"
    "time"
    "sync/atomic"
)

var trip = int64(0)

type runner struct{}

func (r *runner) StopProcessing() {
    atomic.AddInt64(&trip, 1)
}

func (r *runner) StartProcessing() {
    go func() {
        for {
            if trip > 0 {
                break
            }
            fmt.Println("doing stuff")
            time.Sleep(1 * time.Second)
        }
    }()
}

func newRunner() *runner {
    return &runner{}
}

func main() {
    run := newRunner()
    run.StartProcessing() 

    // now wait 4 seconds and the kill the process
    time.Sleep(4 * time.Second)
    run.StopProcessing()
}
0 голосов
/ 30 ноября 2018

Вы можете использовать контекст для получения тайм-аутов и отмены, не требуя никакого дополнительного API.

type runner struct{}

func (r *runner) StartProcessing(ctx context.Context) {
    go func() {
        for {
            select {
            case <-ctx.Done():
                return
            default:
            }
            fmt.Println("doing stuff")
            time.Sleep(1 * time.Second)
        }
    }()
}

Это дает вам возможность установить тайм-аут или отменить его в любое время.Вы также можете использовать существующие контексты, которые могут потребовать таймаута или отмены раньше без вашего ведома.

// normal timeout after 10 seconds
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
run.StartProcessing(ctx)

// decide to cancel early
time.Sleep(3 * time.Second)
cancel()
0 голосов
/ 30 ноября 2018

Используя канал, чтобы сигнализировать о выходе из программы.Соответствующая часть вашего кода будет выглядеть примерно так:

type runner struct {
    stop chan bool
}

func (r *runner) StopProcessing() {
    r.stop <- true
}

func (r *runner) StartProcessing() {
    r.stop = make(chan bool)
    go func() {
        for {
            fmt.Println("doing stuff")
            time.Sleep(1 * time.Second)
            select {
            case _ = <-r.stop:
                close(r.stop)
                return
            default:
            }
        }
    }()
}

Полный пример вы можете увидеть здесь https://play.golang.org/p/OUn18Cprs0I

...