2017-03-02 56 views
-1

我有以下設置:怎麼殺夠程

func startsMain(){ 
    go main() 
} 

fun stopMain(){ 
    //kill main 
} 

func main() { 
    //infinite loop 
} 

我創建一個黃瓜的步驟,我需要能夠啓動和擊落的應用。

謝謝。

+3

你不能從「外部」停止一個門廳。 goroutine必須支持某種終止信號(通常是一個信道)。但如果沒有,你不能強迫它或殺死它。 [在Go中取消阻止操作]的可能重複(http://stackoverflow.com/questions/28240133/cancel-a-blocking-operation-in-go/28240299#28240299)。 – icza

+3

你不能簡單地殺死一個goroutine;請展示您嘗試解決的問題的示例。 – JimB

+0

@icza,是否可以使用任何其他方式而不是goroutine來啓動和停止main? – Michael

回答

3

你可以使用select和頻道殺死你的無限循環!

var quit chan struct{} 

func startLoop() { 
    quit := make(chan struct{}) 
    go loop() 
} 

func stopLoop() { 
    // As mentioned by Kaedys 
    //close(quit) 
    // permits signalling everyone havins such a `case <-quit:` 
    // statement to be stopped at once, which might be even better. 
    quit <- struct{}{} 
} 

// BTW, you cannot call your function main, it is reserved 
func loop() { 
    for { 
     select { 
     case <-quit: 
      break 
     default: 
      // do stuff. I'd call a function, for clarity: 
      do_stuff() 
     } 
    } 
} 

好的一塊圍棋,不是嗎?

現在,這是什麼奇怪的chan struct{}?這是一個零大小的頻道。我們只能填充空結構(即:struct{}{})。它可能是chan bool或其他任何內容,因爲我們不使用頻道的內容。重要的一點是,我們使用quit通道來通知我們goroutine中的無限循環,以便停下來。

select聲明用於捕捉來自聲道的內容。這是一個阻塞語句(將暫停執行,直到case所調查的某個通道被放入某個通道爲止),除非您輸入default語句。在這種情況下,每次執行select時,如果內部放入了quit或將調用do_stuff(),則循環將中斷。如果您已經通過Go Tour,您已經知道這一點。

其他很酷的併發模式可以在Go Blog上找到。

最後,對於進一步的樂趣,你可以問你的do_stuff功能是在固定的時間間隔使用Ticker S,而不是消耗100%的CPU,像這樣執行:

import "time" 

// [...] 

func loop() { 
    // This ticker will put something in its channel every 2s 
    ticker := time.NewTicker(2 * time.Second) 
    for { 
     select { 
     case <-quit: 
      // If you don't stop it, the ticker will cause memory leaks 
      ticker.Stop() 
      break 
     case <-ticker.C: 
      // do stuff. I'd call a function, for clarity: 
      do_stuff() 
     } 
    } 
} 

這裏,select阻止,因爲我們刪除了default聲明。

+2

值得注意的是,退出渠道的典型風格是「關閉()」它們,而不是通過它們發送值。這不僅在代碼中更清晰,而且封閉的通道會立即向所有偵聽器發出信號,而您必須通過通道爲每個偵聽器發送單獨的消息。另外,'main()'是默認調用的程序入口點,您不需要(我相信_can't_)將它與另一個函數分開調用。 – Kaedys

+0

我聽說關於'close()'讓'case'被執行,我認爲是不合邏輯的。但是現在我明白了:立即向所有人發信號對我非常有用,謝謝:) –

+0

更好的是'context'包,請參閱https://golang.org/pkg/context/您應該更改示例以使用'ctx,cancel:= context.WithCancel(context.Background())'。然後'main'可以使用'defer cancel()',goroutines可以在'ctx.Done()'通道上使用'select'來退出。 –