我是Golang的新手,我有一个使用WaitGroup
和Mutex
实现的任务,我想将其转换为使用Channels
。
对任务的非常简短的描述是:拒绝处理所需结果的go例程,并在main go例程中等待并收集所有结果。
我使用WaitGroup
和Mutex
的实现如下:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func process(input int, wg *sync.WaitGroup, result *[]int, lock *sync.Mutex) *[]int {
defer wg.Done()
defer lock.Unlock()
rand.Seed(time.Now().UnixNano())
n := rand.Intn(5)
time.Sleep(time.Duration(n) * time.Second)
lock.Lock()
*result = append(*result, input * 10)
return result
}
func main() {
var wg sync.WaitGroup
var result []int
var lock sync.Mutex
for i := range []int{1,2,3,4,5} {
wg.Add(1)
go process(i, &wg, &result, &lock)
}
}
如何使用Mutex
将内存同步替换为使用Channels
的内存同步?
我的主要问题是我不确定如何确定正在处理最终任务的最终执行例程,因此是否有一个例程可以关闭channel
。这个想法是,通过关闭channel
,主go例程可以在channel
上循环,检索结果,并在看到channel
已关闭时继续前进。
也可能是在这种情况下关闭渠道的方法是错误的,因此我在这里问为什么。
更有经验的程序员将如何使用channels
解决此问题?
我更改了您的代码以使用该渠道。还有许多其他使用渠道的方法。
package main
import (
"fmt"
"math/rand"
"time"
)
func process(input int, out chan<- int) {
rand.Seed(time.Now().UnixNano())
n := rand.Intn(5)
time.Sleep(time.Duration(n) * time.Second)
out <- input * 10
}
func main() {
var result []int
resultChan := make(chan int)
items := []int{1, 2, 3, 4, 5}
for _, v := range items {
go process(v, resultChan)
}
for i := 0; i < len(items); i++ {
res, _ := <-resultChan
fmt.Println("h", res)
result = append(result, res)
}
close(resultChan)
fmt.Println(result)
}
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func process(input int, wg *sync.WaitGroup, resultChan chan<- int) *[]int {
defer wg.Done()
rand.Seed(time.Now().UnixNano())
n := rand.Intn(5)
time.Sleep(time.Duration(n) * time.Second)
resultChan <- input * 10
}
func main() {
var wg sync.WaitGroup
resultChan := make(chan int)
for i := range []int{1,2,3,4,5} {
wg.Add(1)
go process(i, &wg, resultChan)
}
go func() {
wg.Wait()
close(resultChan)
}()
var result []int
for r := range resultChan {
result = append(result, r)
}
}