2017-03-02 8 views
-1

을 죽이는 방법은 다음 설치 유무 :goroutine

func startsMain(){ 
    go main() 
} 

fun stopMain(){ 
    //kill main 
} 

func main() { 
    //infinite loop 
} 

나는 오이 단계를 만드는 오전과 내가 시작 할 수 있어야하고 응용 프로그램을 격추합니다.

감사합니다.

+3

goroutine을 "외부"에서 멈출 수 없습니다. goroutine은 일종의 종료 신호 (일반적으로 채널)를 지원해야합니다. 그러나 그렇지 않으면 강제로 또는 죽일 수 없습니다. [이동에서 차단 작업 취소] (http://stackoverflow.com/questions/28240133/cancel-a-blocking-operation-in-go/28240299#28240299)와 중복 될 수 있습니다. – icza

+3

단순히 goroutine을 죽일 수는 없습니다. 해결하려는 문제의 예를 보여주십시오. – JimB

+0

@icza, goroutine이 아닌 다른 방법으로 주를 시작하고 중지 할 수 있습니까? – 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{}? 크기가 0 인 채널입니다. 빈 struct (즉, struct{}{}) 만 채울 수 있습니다. chan bool 일 수도 있고 다른 내용이 될 수도 있습니다. 채널의 콘텐츠를 사용하지 않기 때문입니다. 중요한 점은 quit 채널을 사용하여 goroutine의 무한 루프를 중지 할 때임을 알리는 것입니다.

select 문은 채널에서 나오는 것을 잡는 데 사용됩니다. default 문을 쓰지 않는 한 차단 문 (case에 의해 조사 된 채널 중 하나에 무언가가 입력 될 때까지 실행을 중단합니다)입니다. 이 상황에서 select이 실행될 때마다 무언가가 quit 안에 들어가거나 do_stuff()이 호출되면 루프가 끊어집니다. Go Tour을 경험했다면 이미 알고 계실 것입니다.

기타 멋진 동시성 패턴은 Go Blog에서 찾을 수 있습니다.

마지막으로, 더 재미를 위해, 당신은 당신의 do_stuff 기능을 요청할 수 있습니다 것은과 같이, Ticker의를 사용하는 대신 100 %의 CPU를 소모하여 일정한 시간 간격으로 실행되는 : select이 차단되어, 여기에

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() 
     } 
    } 
} 

, default 문을 삭제 한 이후입니다.

+2

종료 채널의 일반적인 스타일은 값을 보내지 않고'close()'하는 것입니다. 이 코드는 코드 에서뿐만 아니라, 닫힌 채널에서 한 번에 _ 리스너를 알리는 반면, 그렇지 않으면 각 리스너마다 채널을 통해 별도의 메시지를 보내야합니다. 또한,'main()'은 기본적으로 프로그램 진입 점이 호출되므로 다른 함수와 별도로 호출 할 필요가 없습니다. – Kaedys

+0

'close()'에 대해서 뭔가 들리 죠.'case '가 실행되도록했는데, 나는 비 논리적이라고 생각했습니다. 하지만 이제 알았습니다. 한 번에 모든 사람에게 신호를 보내면 매우 유용 할 것입니다. 감사합니다. –

+0

'context' 패키지가 더 좋습니다. https://golang.org/pkg/context/ 참조하십시오. 사용하기 위해 예제를 변경해야합니다. 'ctx, cancel : = context.WithCancel (context.Background())'. 그런 다음'main'은'defer cancel()'을 사용할 수 있습니다. goroutines는'ctx.Done()'채널에서'select'를 사용하여 종료 할 수 있습니다. –

관련 문제