Race condition with a simple channel in Go?

channel, go

Solution

You should wait until your goroutine executes, and then your, for example, you can do it with `sync.WaitGroup`:

package main

import (
  "fmt"
  "sync"
)

func main() {
  var wg sync.WaitGroup

  channel := make(chan int)
  wg.Add(1)

  go func() {
    number := <-channel
    fmt.Printf("GOT IT: %d\n", number)
    wg.Done()
  }()

  fmt.Println("[+] putting num on channel")
  channel <- 42
  wg.Wait()
  fmt.Println("[-] putting num on channel")
}

(goplay: http://play.golang.org/p/VycxTw_4vu)

Also you can do it with a "notification channel", that indicates that job is done:

package main

import "fmt"

func main() {
  channel := make(chan int)
  done := make(chan bool)

  go func() {
    number := <-channel
    fmt.Printf("GOT IT: %d\n", number)
    done <- true
  }()

  fmt.Println("[+] putting num on channel")
  channel <- 42
  <-done
  fmt.Println("[-] putting num on channel")
}

(goplay: http://play.golang.org/p/fApWQgtr4D)

Problem

I'm new to Go and am stumped on what appears to be a somewhat-rare race condition with a very small block of code running on Linux with Go version 1.2. Basically, I create a channel for an `int`, start a go routine to read from the channel, and then write a single int to the channel. ``` package main import "fmt" func main() { channel := make(chan int) go func() { number := <- channel fmt.Printf("GOT IT: %d\n", number) }() fmt.Println("[+] putting num on channel") channel <- 42 fmt.Println("[-] putting num on channel") } ``` The output about 90% of the time is as expected: ``` $ go run test.go [+] putting num on channel GOT IT: 42 [-] putting num on channel ``` However, about 10% of the time, the go routine simply does not read the number from the channel and prints nothing: ``` $ go run test.go [+] putting num on channel [-] putting num on channel ``` I'm puzzled because this code is very similar to the example at https://gobyexample.com/channels, (which I do not have this problem with) except that I'm reading from the channel in my go routine instead of writing to the channel. Do I have a fundamental misunderstanding of how channels work or is there something else at play here?

Original source