通道的切片和并发函数执行

huangapple go评论89阅读模式
英文:

slice of channels and concurrent function execution

问题

如何创建通道切片并在切片迭代中并发运行函数double(i)

package main

import (
	"fmt"
	"time"
)

func double(i int) int {
	result := 2 * i
	fmt.Println(result)
	time.Sleep(500000000)
	return result
}

func notParallel(arr []int) (outArr []int) {
	for _, i := range arr {
		outArr = append(outArr, double(i))
	}
	return
}

// 如何以并行方式执行与notParallel函数相同的操作。
// 对于数组的每个元素,double函数应该并发地进行评估,
// 而不需要等待每个下一个元素进行评估。
func parallel(arr []int) (outArr []int) {

	var chans []chan int
	for i := 0; i < len(arr); i++ {
		chans = append(chans, make(chan int))
	}

	for counter, number := range arr {
		go func(counter, number int) {
			chans[counter] <- double(number)
		}(counter, number)
	}

	for _, ch := range chans {
		outArr = append(outArr, <-ch)
	}

	return
}

func main() {
	arr := []int{7, 8, 9}
	fmt.Printf("%d\n", notParallel(arr))
	fmt.Printf("%d\n", parallel(arr))
}

playground

由于函数double(i)休眠500毫秒,函数notParallel(arr []int)对于arr []int的3个元素需要工作1500毫秒,但是函数parallel(arr []int)将在大约500毫秒内完成。

在我的实现中有一个错误...

panic: runtime error: index out of range

...发生在以下行上...

chans[i] = make(chan int) // i = 0
英文:

How to create slice of channels and run function double(i) concurrently inside slice iteration:

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func double(i int) int {
	result := 2 * i
	fmt.Println(result)
	time.Sleep(500000000)
	return result
}

func notParallel(arr []int) (outArr []int) {
	for _, i := range arr {
		outArr = append(outArr, double(i))
	}
	return
}

// how to do the same as notParallel func in parallel way.
// For each element of array double func should evaluate concuruntly
// without waiting each next element to eval
func parallel(arr []int) (outArr []int) {

	var chans []chan int
	for i := 0; i &lt; len(arr); i++ {
		chans[i] = make(chan int) // i = 0 : panic: runtime error: index out of range
	}

	for counter, number := range arr {
		go func() {
			chans
0
+
网站访问量
&lt;- double(number) }() } return } func main() { arr := []int{7, 8, 9} fmt.Printf(&quot;%d\n&quot;, notParallel(arr)) fmt.Printf(&quot;%d\n&quot;, parallel(arr)) }

playground

As function double(i) sleeps for 500 ms function notParallel(arr []int) works for 1500 ms for 3 elements of arr []int but function parallel(arr []int) would work about 500 ms.

In my implementation have error...

panic: runtime error: index out of range

... on line ...

chans[i] = make(chan int) // i = 0

答案1

得分: 3

在这种情况下,你不需要使用 chan。

package main

import (
    "fmt"
    "sync"
    "time"
)

func double(i int) int {
    result := 2 * i
    fmt.Println(result)
    time.Sleep(500000000)
    return result
}

func notParallel(arr []int) (outArr []int) {
    for _, i := range arr {
        outArr = append(outArr, double(i))
    }
    return
}

// 如何以并行方式执行与 notParallel 函数相同的操作。
// 对于数组的每个元素,double 函数应该并发地进行评估,
// 而不需要等待每个下一个元素的评估。
func parallel(arr []int) (outArr []int) {
    outArr = make([]int, len(arr))
    var wg sync.WaitGroup
    for counter, number := range arr {
        wg.Add(1)
        go func(counter int, number int) {
            outArr[counter] = double(number)
            wg.Done()
        }(counter, number)
    }
    wg.Wait()

    return
}

func main() {
    arr := []int{7, 8, 9}
    fmt.Printf("%d\n", notParallel(arr))
    fmt.Printf("%d\n", parallel(arr))
}

因为并行必须等待所有 goroutine 完成。

我注意到你的代码无法工作,因为你在同一个函数作用域中引用了 counternumber

英文:

In this case, you don't need to use chan.

package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

func double(i int) int {
    result := 2 * i
    fmt.Println(result)
    time.Sleep(500000000)
    return result
}

func notParallel(arr []int) (outArr []int) {
    for _, i := range arr {
        outArr = append(outArr, double(i))
    }
    return
}

// how to do the same as notParallel func in parallel way.
// For each element of array double func should evaluate concuruntly
// without waiting each next element to eval
func parallel(arr []int) (outArr []int) {
	outArr = make([]int, len(arr))
	var wg sync.WaitGroup
    for counter, number := range arr {
		wg.Add(1)
        go func(counter int, number int) {
            outArr
0
+
网站访问量
= double(number) wg.Done() }(counter, number) } wg.Wait() return } func main() { arr := []int{7, 8, 9} fmt.Printf(&quot;%d\n&quot;, notParallel(arr)) fmt.Printf(&quot;%d\n&quot;, parallel(arr)) }

Because parallel must wait all of finish of goroutine(s).

And I notice your code doesn't work because you refer counter, number in same function scope.

huangapple
  • 本文由 发表于 2015年1月7日 11:43:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/27812085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定