Help us understand the problem. What is going on with this article?

Goroutine エクササイズ

More than 3 years have passed since last update.

先輩からお題が出されたので、忘れないように記載しておく

お題

Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

package main

import (
    "math/rand"
    "time"
    "fmt"
)

 func Sleep(i chan int) {
    r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
    time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
    fmt.Printf("I Slept %d millseconds. \n", r)
    i <- r
}

func main() {
    rand.Seed(time.Now().UnixNano())
    // Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください
}

自分の回答

package main

import (
    "math/rand"
    "time"
    "fmt"
    "sync"
    "strconv"
)

func Sleep(i chan int) {
    r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
    time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
    fmt.Printf("I Slept %d millseconds. \n", r)
    i <- r
}

func max(a []int) int {
    max := a[0]
    for _, i := range a {
        if i > max {
            max = i
        }
    }
    return max
}

func min(a []int) int {
    min := a[0]
    for _, i := range a {
        if i < min {
            min = i
        }
    }
    return min
}

func avg(a []int) int {
    len := len(a)
    sum := 0
    for _, i := range a {
        sum += i
    }
    return sum / len
}

func main() {
    rand.Seed(time.Now().UnixNano())
    // Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

    // チャネルを用意
    ch := make(chan int)
    finished := make(chan int)

    // Sleep関数を50回、並列処理で実行
    wg := &sync.WaitGroup{}
    for i := 0 ; i < 50 ; i++ {
        wg.Add(1)
        go func() {
            Sleep(ch)
            wg.Done()
        }()
    }

    // 全ての並行処理が完了するのを待つ、完了次第、本スレッドに通知
    go func(){
        wg.Wait()
        finished <- 1
    }()

    // 本スレッドで、並列で実行した結果を受け取る
    results := []int{}
    LOOP:
        for {
            select {
            case v := <- ch:
                results = append(results, v)
            case <- finished:
                break LOOP
            }
        }

    // 結果の集計
    fmt.Println("件数:" + strconv.Itoa(len(results)))
    fmt.Println("最大:" + strconv.Itoa(max(results)))
    fmt.Println("最小:" + strconv.Itoa(min(results)))
    fmt.Println("平均:" + strconv.Itoa(avg(results)))
}

実行結果

件数:50
最大:573
最小:108
平均:311

「ここはこうした方が良い」など、ありましたらコメントいただければ幸いです。

別の方法も考えてみた

チャネルに結果を溜め込んで、完了後に取り出して集計する、今回のはこれで十分っぽい。

package main

import (
    "math/rand"
    "time"
    "fmt"
    "sync"
    "strconv"
)

func Sleep(i chan int) {
    r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
    time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
    fmt.Printf("I Slept %d millseconds. \n", r)
    i <- r
}

func max(a []int) int {
    max := a[0]
    for _, i := range a {
        if i > max {
            max = i
        }
    }
    return max
}

func min(a []int) int {
    min := a[0]
    for _, i := range a {
        if i < min {
            min = i
        }
    }
    return min
}

func avg(a []int) int {
    l := len(a)
    sum := 0
    for _, i := range a {
        sum += i
    }
    return sum / l
}

func main() {
    rand.Seed(time.Now().UnixNano())
    // Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

    // チャネルを用意
    ch := make(chan int, 50)

    // Sleep関数を50回、並列処理で実行
    wg := &sync.WaitGroup{}
    for i := 0 ; i < 50 ; i++ {
        wg.Add(1)
        go func() {
            Sleep(ch)
            wg.Done()
        }()
    }

    // 全ての並行処理が完了するのを待つ
    wg.Wait()
    close(ch)

    // 並列で実行した結果を受け取る
    results := []int{}
    for v := range ch {
        results = append(results, v)
    }

    // 結果の集計
    fmt.Println("件数:" + strconv.Itoa(len(results)))
    fmt.Println("最大:" + strconv.Itoa(max(results)))
    fmt.Println("最小:" + strconv.Itoa(min(results)))
    fmt.Println("平均:" + strconv.Itoa(avg(results)))
}
fullspeed
独自のアドテクノロジーにより、DSP、ソーシャルメディア、SEO、リスティング、アフィリエイトを展開
https://www.fullspeed.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away