Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| // Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. | |
| // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | |
| // This file is just a place to put example code from the book. | |
| // It does not actually run any code in gopl.io/ch8/thumbnail. | |
| package thumbnail_test | |
| import ( | |
| "log" | |
| "os" | |
| "sync" | |
| "gopl.io/ch8/thumbnail" | |
| ) | |
| //!+1 | |
| // makeThumbnails makes thumbnails of the specified files. | |
| func makeThumbnails(filenames []string) { | |
| for _, f := range filenames { | |
| if _, err := thumbnail.ImageFile(f); err != nil { | |
| log.Println(err) | |
| } | |
| } | |
| } | |
| //!-1 | |
| //!+2 | |
| // NOTE: incorrect! | |
| func makeThumbnails2(filenames []string) { | |
| for _, f := range filenames { | |
| go thumbnail.ImageFile(f) // NOTE: ignoring errors | |
| } | |
| } | |
| //!-2 | |
| //!+3 | |
| // makeThumbnails3 makes thumbnails of the specified files in parallel. | |
| func makeThumbnails3(filenames []string) { | |
| ch := make(chan struct{}) | |
| for _, f := range filenames { | |
| go func(f string) { | |
| thumbnail.ImageFile(f) // NOTE: ignoring errors | |
| ch <- struct{}{} | |
| }(f) | |
| } | |
| // Wait for goroutines to complete. | |
| for range filenames { | |
| <-ch | |
| } | |
| } | |
| //!-3 | |
| //!+4 | |
| // makeThumbnails4 makes thumbnails for the specified files in parallel. | |
| // It returns an error if any step failed. | |
| func makeThumbnails4(filenames []string) error { | |
| errors := make(chan error) | |
| for _, f := range filenames { | |
| go func(f string) { | |
| _, err := thumbnail.ImageFile(f) | |
| errors <- err | |
| }(f) | |
| } | |
| for range filenames { | |
| if err := <-errors; err != nil { | |
| return err // NOTE: incorrect: goroutine leak! | |
| } | |
| } | |
| return nil | |
| } | |
| //!-4 | |
| //!+5 | |
| // makeThumbnails5 makes thumbnails for the specified files in parallel. | |
| // It returns the generated file names in an arbitrary order, | |
| // or an error if any step failed. | |
| func makeThumbnails5(filenames []string) (thumbfiles []string, err error) { | |
| type item struct { | |
| thumbfile string | |
| err error | |
| } | |
| ch := make(chan item, len(filenames)) | |
| for _, f := range filenames { | |
| go func(f string) { | |
| var it item | |
| it.thumbfile, it.err = thumbnail.ImageFile(f) | |
| ch <- it | |
| }(f) | |
| } | |
| for range filenames { | |
| it := <-ch | |
| if it.err != nil { | |
| return nil, it.err | |
| } | |
| thumbfiles = append(thumbfiles, it.thumbfile) | |
| } | |
| return thumbfiles, nil | |
| } | |
| //!-5 | |
| //!+6 | |
| // makeThumbnails6 makes thumbnails for each file received from the channel. | |
| // It returns the number of bytes occupied by the files it creates. | |
| func makeThumbnails6(filenames <-chan string) int64 { | |
| sizes := make(chan int64) | |
| var wg sync.WaitGroup // number of working goroutines | |
| for f := range filenames { | |
| wg.Add(1) | |
| // worker | |
| go func(f string) { | |
| defer wg.Done() | |
| thumb, err := thumbnail.ImageFile(f) | |
| if err != nil { | |
| log.Println(err) | |
| return | |
| } | |
| info, _ := os.Stat(thumb) // OK to ignore error | |
| sizes <- info.Size() | |
| }(f) | |
| } | |
| // closer | |
| go func() { | |
| wg.Wait() | |
| close(sizes) | |
| }() | |
| var total int64 | |
| for size := range sizes { | |
| total += size | |
| } | |
| return total | |
| } | |
| //!-6 |