

初めまして。  
現在goを勉強しておりまして、goroutineに関して勉強しています。  
以下のようにmapにいくつかstringのキーを入れて、値はboolでフラグ管理しております。  
値がtrueの時はsleep処理を入れて、falseのときはsleep無しの処理をしたいと思っております。  
しかし、以下実行しますと、mapのキー値がいくつか被ってしまいます。  
試しに変数のアドレスを確認すると、同じアドレスになっている場合があるのですが、なぜ同じアドレスになっているのでしょうか？  
また、どのようにしたら被らないようにmapに入っている全ての値を出力することができるようになりますでしょうか。

# ソース

[code]

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func goroutine(name string) {
        for {
            select {
            case <-sleep:
                fmt.Printf("---------------(sleep)name = %s, name of address = %p\n", name, &name)
                time.Sleep(5 * time.Second)
                fmt.Printf("---------------wake up name = %s", name)
            case <-start:
                fmt.Printf("---------------(start)name = %s, name of address = %p\n", name, &name)
            }
        }
    }
    
    var sleep chan bool
    var start chan bool
    
    func main() {
        sleep = make(chan bool)
        start = make(chan bool)
    
        names := make(map[string]bool)
        names["a"] = false
        names["b"] = false
        names["c"] = false
        names["d"] = true
        names["e"] = false
        for k, v := range names{
            if v {
                go goroutine(k)
                sleep <- true
            } else {
                go goroutine(k)
                start <- true
            }
        }
    
        time.Sleep(1000 * time.Second)
    }
    
[/code]

# 出力結果

[code]

    # go run main.go
    ---------------(start)name = a, name of address = 0xc00006e1c0
    ---------------(start)name = c, name of address = 0xc0000a2000
    ---------------(sleep)name = c, name of address = 0xc0000a2000
    ---------------(start)name = e, name of address = 0xc0000a2020
    ---------------(start)name = a, name of address = 0xc00006e1c0
    ---------------wake up name = c
    
[/code]


CC BY-SA 4.0
2019-10-21T11:09:23.077
59850
2020-07-15T19:07:10.750
17156
question
go goroutine
変数の値がgoroutine間で同じになってしまう。


`goroutine` 関数の中の `for` は `main` の `time.Sleep(1000 * time.Second)`
が終わるまで回り続けるからで  
一回目のループで `case <-start:` を通過したら次のループでタイミングによって `case <-start:` か `case
<-sleep:` を通ります。

単純に `for` を除けば意図した挙動に近いものになると思いますが、 `d` の時だけ `sleep` したいのであれば ↓ な感じでしょうか。

[code]

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func goroutine(name string, isSleep bool) {
        if isSleep {
            fmt.Printf("---------------(sleep)name = %s, name of address = %p\n", name, &name)
            time.Sleep(5 * time.Second)
            fmt.Printf("---------------wake up name = %s\n", name)
        } else {
            fmt.Printf("---------------(start)name = %s, name of address = %p\n", name, &name)
        }
    }
    
    func main() {
        names := map[string]bool{
            "a": false,
            "b": false,
            "c": false,
            "d": true,
            "e": false,
        }
    
        var wg sync.WaitGroup
        // 実行多重度を 2 とする場合
        semaphore := make(chan int, 2)
        for k, v := range names {
            wg.Add(1)
            go func(k string, v bool) {
                defer wg.Done()
                semaphore <- 1
                goroutine(k, v)
                <-semaphore
            }(k, v)
        }
    
        wg.Wait()
    }
    
[/code]


CC BY-SA 4.0
2019-10-26T13:58:00.530
59995
2019-10-26T13:58:00.530
31238
59850
answer