I’m studying concurrency in more depth with Go. A book I am reading gives the following example, which basically compresses files from command line argument(s).
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
}
The book then explains that if you wanted to process a few hundred files, keeping it like this would definitely be slower than if you were to utilise goroutines, so the following modification is made to the main()
function in order to use them:
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
", i+1)
It is then noted that the “trickery” with regard to the inline function definition and its parameter (file name), is necessary “because we are executing goroutines in a for loop”.
I guess what I don’t understand is why the above inline function is required to get this working, couldn’t the following be used instead, or am I missing a trick?
for i, file = range os.Args[1:] {
wg.Add(1)
go compress(file)
wg.Done()
}
wg.Wait()
fmt.Printf("Compressed %d files
", i+1)