2015-04-15 7 views
1
package main 

import (
    "fmt" 
    //"runtime" 
) 

func say(s string) { 
    for i := 0; i < 5; i++ { 
     //runtime.Gosched() 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") // create a new goroutine 
    say("hello") // current goroutine 
} 

Почему результат:идут языки, зачем рутинную функцию никогда не называют

привет привет привет привет привет

Почему нет «мир» был

Ответ : (отредактировано) Если я это сделаю, это хорошо сейчас:

package main 

import (
    "fmt" 
    "runtime" 
) 

func say(s string) { 
    for i := 0; i < 5; i++ { 
     //runtime.Gosched() 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") // create a new goroutine 
    runtime.Gosched() 

    say("hello") // current goroutine 
} 
+3

Использование 'GoSched' не гарантирует, что другой goroutine будет запущен до завершения. Обычно вы не должны использовать это в своем коде. – JimB

+2

Этот вопрос является дубликатом http://stackoverflow.com/questions/15771232/why-is-time-sleep-required-to-run-certain-goroutines/15771560 и http://stackoverflow.com/questions/24425987/почему-это-не-исполняемых мой-goroutine/24426137 – snap

ответ

1

Вы не разрешаете goroutine работать до main() выходов.

Несмотря на то, что второй звонок say блокирует (коротко), нет гарантии, что первый горутин может работать. Вы должны ждать и возвращаться, который часто делается с WaitGroup

var wg sync.WaitGroup 

func say(s string) { 
    defer wg.Done() 
    for i := 0; i < 5; i++ { 
     //runtime.Gosched() 
     fmt.Println(s) 
    } 
} 

func main() { 
    wg.Add(1) 
    go say("world") // create a new goroutine 

    wg.Add(1) 
    say("hello") // current goroutine 
    wg.Wait() 
} 
1

Вы просто испытывающего вопрос времени, потому что вы не «координации» ваши пойдут подпрограммы. Обычный способ справиться с этим - с защитой ожидания. Другой вариант, который я вижу время от времени, используя каналы и блокировку. Реализация ожидания ожидания будет выглядеть примерно так:

func main() { 
    wg := sync.WaitGroup{} 
    wg.Add(1) 
    go say("world") // create a new goroutine 

    wg.Add(1) 
    say("hello") // current goroutine 
    wg.Wait() 
} 

В то время как опция канала (фактически не интересная или полезная в этом примере) не является чем-то более подобным;

func main() { 
    done := make(chan bool) 
    go say("world", done) // create a new goroutine 

    say("hello", done) // current goroutine 

    select { 
     case fin := <- done: 
      //on finished 
      return 
    } 
} 

func say(s string, chan bool) { 
for i := 0; i < 5; i++ { 
    fmt.Println(s) 
    } 
    done <- true 
} 

В приведенном выше примере, однако, первый вызов сказать завершение позволит программе завершить выполнение. Чтобы обеспечить оба конца, вам придется передавать разные каналы каждому и блокировать чтение на обоих. Это больше шаблон, который я бы использовал, когда ваши подпрограммы выполняли настоящую работу, и вы хотите, чтобы данные собирали данные из них или нуждались в более сложной координации (например, нерест новых goroutines по результатам предыдущих ect).

Смежные вопросы