critonix
critonix

Reputation: 11

Go: Reading a file, goroutine deadlock

I have two sets of code - to read a file with random lines of text, and load each line to a channel. I am unable to understand why one returns an error. but the other doesn't. Case #1 returns "fatal error: all goroutines are asleep - deadlock!" but Case # works.

Case #1

func main () {

file, err := os.Open("/Users/sample/Downloads/wordlist")
if err != nil {
    log.Fatal(err)
}
lines := make (chan string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
    lines <- scanner.Text()
}
close(lines)

for line := range (lines) {
    fmt.Println(line)
}

}

Case #2

func main () {

file, err := os.Open("/Users/sample/Downloads/wordlist") 
if err != nil {
    log.Fatal(err)
}
lines := make (chan string)
go func() {
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines <- scanner.Text()
    }
    close(lines)
}()

for line := range (lines) {
    fmt.Println(line)
}

}

Upvotes: 0

Views: 628

Answers (1)

Kishore Karunakaran
Kishore Karunakaran

Reputation: 598

The sender blocks until the receiver has received the value in unbuffered channel.

In unbuffered channel writing to channel will not happen until there must be some receiver which is waiting to receive the data.

For Example:

queue := make(chan string)
queue <- "one" /* Here main function which is also a goroutine is blocked, because
there is no goroutine to receive the channel value, hence the deadlock*/
close(queue)
for elem := range queue {
    fmt.Println(elem)
}

This will leads to deadlock and it is exactly what happened in your Case #1 code.

Now In case where we have other go routine

queue := make(chan string)
go func() {
    queue <- "one" 
    close(queue)
}()
for elem := range queue {
    fmt.Println(elem)
}

This will work because main go routine is waiting for the data to be consumed before writes happen to unbuffered channel.

This is exactly happen in your Case #2

So in short, writes to unbuffered channel happens only when there is some routine waiting to read from channel, else the write operation is blocked forever and leads to deadlock.

Upvotes: 1

Related Questions