Пример параллелизма - PullRequest
0 голосов
/ 11 июня 2018

Я изучаю параллелизм более подробно с Go.В книге, которую я читаю, приведен следующий пример, который в основном сжимает файлы из аргументов командной строки.

 package main

 import (
  "compress/gzip"
  "io"
  "os"
 )

 func main() {

     for _, file := range os.Args[1:] {
        compress(file)
     }

 }


 func compress(filename string) error {

     in, err := os.Open(filename)

     if err != nil {
      return err
     }

     defer in.Close()

     out, err := os.Create(filename + ".gz")

     if err != nil {
       return err
     }

     defer out.Close()

     gzout := gzip.NewWriter(out)

     _, err = io.Copy(gzout, in)

     gzout.Close()

     return err
}

Затем в книге объясняется, что если вы хотите обработать несколько сотен файлов, сохраните это такбудет определенно медленнее, чем если бы вы использовали goroutines, поэтому для их использования в функцию main() вносится следующая модификация:

var wg sync.WaitGroup 
var i int = -1
var file string
for i, file = range os.Args[1:] {
    wg.Add(1)
    go func(filename string) {
       compress(filename)
       wg.Done()
     }(file)
 }
 wg.Wait()
 fmt.Printf("Compressed %d files\n", i+1)

Затем следует отметить, что «обман» в отношениидля определения встроенной функции и ее параметра (имени файла) необходимо «потому что мы выполняем процедуры в цикле for».

Полагаю, я не понимаю, почему указанная выше встроенная функция необходима длязаставить это работать, разве нельзя использовать следующее, или я упускаю трюк?

for i, file = range os.Args[1:] {
    wg.Add(1)

    go compress(file)

    wg.Done()

 }
 wg.Wait()
 fmt.Printf("Compressed %d files\n", i+1)

1 Ответ

0 голосов
/ 11 июня 2018

Если вы просто выполните:

compress(file)

Это выполняется в той же самой процедуре, поэтому, пока этот вызов не завершится, вы больше ничего не будете делать.

Так что если вы хотитедля параллельной обработки, вам нужно запустить новую программу с помощью ключевого слова go.

Если вы сделаете это:

go compress(file)

Тогда будет запустите новую процедуру сжатия каждого файла.

Но как только функция main запустит все процедуры, она завершит выполнение (не будет ждать завершения всех программ).

Вот почему они включили вызовы wg.

Поскольку функция compress не получает WaitGroup для вызова Done через нее, они реализовали эту встроенную функцию для вызова wg.Done() сразу после того, как эта программа завершает сжатие этого файла.

Вот причина:

go func(filename string) {
    compress(filename)
    wg.Done()
}(file)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...