在这个例子中,我们要用goroutines并发地处理多张图片。这个过程包括按顺序上传、裁剪和保存。我们使用通道来告诉下一个步骤的开始。一旦图片处理的所有步骤完成,我们就关闭所有的通道。一旦所有的图像处理完毕,应用程序就存在了。由于这是一个并发的操作,你永远无法保证哪张图片会先被处理。顺便说一下,我们实际上不会上传、裁剪和保存图像
例子
main.go
package main
import (
"fmt"
"math/rand"
"sync"
"time"
"internal/image"
)
var (
wg sync.WaitGroup
files = []string{"image1.jpg", "image2.jpg", "image3.jpg", "image4.jpg"}
)
func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println("START")
wg.Add(len(files))
for _, file := range files {
// Start uploading asynchronously.
go image.New(&wg, file).Upload()
}
wg.Wait()
fmt.Println("FINISH")
}
upload.go
我们随机睡觉以模拟一些处理时间:
package image
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Image struct {
wg *sync.WaitGroup
name string
}
func New(wg *sync.WaitGroup, name string) Image {
return Image{
wg: wg,
name: name,
}
}
func (i Image) Upload() {
defer i.wg.Done()
fmt.Println("upload(str) -", i.name)
wait := rand.Intn(len([]int{0, 1, 2, 3, 4, 5, 6}))
time.Sleep(time.Duration(wait) * time.Second)
fmt.Println("upload(end) -", i.name, wait, "sec")
cropDone := make(chan bool)
saveDone := make(chan bool)
// Start cropping asynchronously.
go i.crop(cropDone, saveDone)
// Upload ending depends on completion of crop and save operations so blocking here.
<- cropDone
<- saveDone
}
func (i Image) crop(cropDone, saveDone chan <- bool) {
fmt.Println("crop(str) -", i.name)
wait := rand.Intn(len([]int{0, 1, 2, 3, 4, 5, 6}))
time.Sleep(time.Duration(wait) * time.Second)
fmt.Println("crop(end) -", i.name, wait, "sec")
// Instruct channel that crop is done.
cropDone <- true // close(cropDone)
// Start saving asynchronously.
go i.save(saveDone)
}
func (i Image) save(saveDone chan <- bool) {
fmt.Println("save(str) -", i.name)
wait := rand.Intn(len([]int{0, 1, 2, 3, 4, 5, 6}))
time.Sleep(time.Duration(wait) * time.Second)
fmt.Println("save(end) -", i.name, wait, "sec")
// Instruct channel that save is done.
saveDone <- true // close(saveDone)
}
测试
正如你在下面看到的,赢家是image3!
START
upload(str) - image1.jpg
upload(str) - image2.jpg
upload(str) - image3.jpg
upload(str) - image4.jpg
upload(end) - image1.jpg 2 sec
crop(str) - image1.jpg
crop(end) - image1.jpg 0 sec
save(str) - image1.jpg
upload(end) - image4.jpg 3 sec
upload(end) - image3.jpg 3 sec
crop(str) - image3.jpg
crop(str) - image4.jpg
upload(end) - image2.jpg 5 sec
crop(str) - image2.jpg
crop(end) - image2.jpg 2 sec
crop(end) - image3.jpg 4 sec
save(str) - image2.jpg
save(str) - image3.jpg
save(end) - image3.jpg 0 sec
save(end) - image1.jpg 6 sec
crop(end) - image4.jpg 5 sec
save(str) - image4.jpg
save(end) - image2.jpg 3 sec
save(end) - image4.jpg 6 sec
FINISH
Total time
image3 - 7 sec
image1 - 8 sec
image2 - 10 sec
image4 - 14 sec