Maxim Yefremov
Maxim Yefremov

Reputation: 14185

slice of channels and concurrent function execution

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

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
}

// 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 < 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[counter] <- double(number)
        }()
    }

    return
}

func main() {
    arr := []int{7, 8, 9}
    fmt.Printf("%d\n", notParallel(arr))
    fmt.Printf("%d\n", 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

Upvotes: 2

Views: 653

Answers (1)

mattn
mattn

Reputation: 7733

In this case, you don't need to use 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
}

// 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[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))
}

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.

Upvotes: 3

Related Questions