用Golang的goroutines和通道进行并行图像处理(附示例)

118 阅读1分钟

在这个例子中,我们要用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