hmnhmn
hmnhmn

Reputation: 173

Not seeing the expected side effects from goroutines

I'm trying to get a grasp on goroutines. Take this code:

package main
import "fmt"

var (
    b1 []float64
    b2 []float64
)

func main() {
    go fill(&b1, 10)
    go fill(&b2, 10)

    fmt.Println(b1,b2)

    var s string
    fmt.Scanln(&s)
}

func fill(a *[]float64, n int) {
    for i:=0; i<n; i++ {
        *a = append(*a, rand.Float64()*100)
    }
}

As you see, I'm trying to fill two slices. But when run this way (with go fill()), it prints two empty slices. Why is this not working?

Upvotes: 1

Views: 121

Answers (1)

twotwotwo
twotwotwo

Reputation: 30027

Any goroutines you start aren't guaranteed to have finished (or even started!) until you've explicitly waited on them using a sync.WaitGroup, channel, or other mechanism. This works:

package main

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

var (
    b1 []float64
    b2 []float64
)

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(2)
    go fill(&b1, 10, wg)
    go fill(&b2, 10, wg)
    wg.Wait()

    fmt.Println(b1)
    fmt.Println(b2)
}

func fill(a *[]float64, n int, wg *sync.WaitGroup) {
    for i := 0; i < n; i++ {
        *a = append(*a, rand.Float64()*100)
    }
    wg.Done()
}

(Just speaking of style, if it were me I'd make this function return the enlarged slice so it's similar to append() itself, and Go's Code Review Comments suggest passing values, though it's not at all unconventional to extend a slice passed as a pointer receiver ("this") parameter.)

Upvotes: 6

Related Questions