1

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?

twotwotwo
  • 28,310
  • 8
  • 69
  • 56
hmnhmn
  • 173
  • 2
  • 9
  • 3
    Any goroutine you start isn't guaranteed to finish until you wait on it with a `sync.WaitGroup`, channel, or some other mechanism. – twotwotwo Apr 16 '15 at 17:58

1 Answers1

6

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.)

Community
  • 1
  • 1
twotwotwo
  • 28,310
  • 8
  • 69
  • 56