golang full close check go synchronization goroutine

full - range of channel golang



Cómo esperar a que todos los goroutines terminen sin usar el tiempo. ¿Duerme? (3)

Puede usar sync.WaitGroup . Citando el ejemplo vinculado:

package main import ( "net/http" "sync" ) func main() { var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) // Launch a goroutine to fetch the URL. go func(url string) { // Decrement the counter when the goroutine completes. defer wg.Done() // Fetch the URL. http.Get(url) }(url) } // Wait for all HTTP fetches to complete. wg.Wait() }

Este código selecciona todos los archivos xml en la misma carpeta, como el ejecutable invocado y aplica de forma asíncrona el procesamiento a cada resultado en el método de devolución de llamada (en el ejemplo siguiente, solo se imprime el nombre del archivo).

¿Cómo evito usar el método de suspensión para evitar que el método principal se cierre? Tengo problemas para entender los canales (supongo que eso es lo que se necesita, para sincronizar los resultados) ¡así que cualquier ayuda es apreciada!

package main import ( "fmt" "io/ioutil" "path" "path/filepath" "os" "runtime" "time" ) func eachFile(extension string, callback func(file string)) { exeDir := filepath.Dir(os.Args[0]) files, _ := ioutil.ReadDir(exeDir) for _, f := range files { fileName := f.Name() if extension == path.Ext(fileName) { go callback(fileName) } } } func main() { maxProcs := runtime.NumCPU() runtime.GOMAXPROCS(maxProcs) eachFile(".xml", func(fileName string) { // Custom logic goes in here fmt.Println(fileName) }) // This is what i want to get rid of time.Sleep(100 * time.Millisecond) }


WaitGroups es definitivamente la forma canónica de hacer esto. Sin embargo, para completar, esta es la solución que se usaba comúnmente antes de que se introdujeran los WaitGroups. La idea básica es usar un canal para decir "He terminado", y hacer que la rutina principal espere hasta que cada rutina generada haya informado de su finalización.

func main() { c := make(chan struct{}) // We don''t need any data to be passed, so use an empty struct for i := 0; i < 100; i++ { go func() { doSomething() c <- struct{}{} // signal that the routine has completed }() } // Since we spawned 100 routines, receive 100 messages. for i := 0; i < 100; i++ { <- c } }


sync.WaitGroup puede ayudarlo aquí.

package main import ( "fmt" "sync" "time" ) func wait(seconds int, wg * sync.WaitGroup) { defer wg.Done() time.Sleep(time.Duration(seconds) * time.Second) fmt.Println("Slept ", seconds, " seconds ..") } func main() { var wg sync.WaitGroup for i := 0; i <= 5; i++ { wg.Add(1) go wait(i, &wg) } wg.Wait() }