Skip to main content

General Concepts

More Code Examples on Deadlock in Go

Deadlock Using for…range

Closing the channel is necessary to inform the receiver that no more values are to be received and that the loop should be terminated.

In a for..range loop utilizing a channel, it's crucial to explicitly close the channel once all values have been sent. If the channel is not closed, the for..range loop will persistently wait for additional values from the channel. If the channel stops receiving values without being closed, the for..range loop remains in a perpetual state of waiting, causing the goroutine or function containing the loop to become stuck. In such circumstances, no other function or goroutine can advance, resulting in a deadlock.

💡
Closing the channel appropriately ensures the termination of the loop, allowing for the normal progression of the program.

Code

Create a deadlock-using-for-range.go in your current directory.

package main

import "fmt"

func DeadlockUsingForRange() {
	channel := make(chan int)

	go func() {
		for i := 0; i < 100; i++ {
			channel <- i
		}
	}()

	for val := range channel {
		fmt.Printf("%d", val)
	}
}

Now, in your main.go file, call DeadlockUsingForRange() method.

package main

func main() {
	DeadlockUsingForRange()
}

Now run go run .to see the output.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.DeadlockUsingForRange()
        /Users/aakashverma/Documents/Learning/Go/go-concurrency/deadlock/deadlock.go:14 +0xd4
main.main()
        /Users/aakashverma/Documents/Learning/Go/go-concurrency/deadlock/main.go:4 +0x1c
exit status 2

Deadlock Using select

The select function randomly selects one of the case statements to execute from all the available statements
that have data to process. If no case statement is ready to process, the default statement will be executed.

Let's look at the below code.

Code

Create a deadlock-using-select.go in your current directory.

package main

func DeadlockUsingSelect() {
	channel := make(chan int)
	select {
	case <-channel:
	}
}

Now, in your main.go file, call DeadlockUsingSelect() method.

package main

func main() {
	DeadlockUsingForRange()
}

Now run go run .to see the output.

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.DeadlockUsingSelect(...)
        /Users/aakashverma/Documents/Learning/Go/go-concurrency/deadlock/deadlock.go:6
main.main()
        /Users/aakashverma/Documents/Learning/Go/go-concurrency/deadlock/main.go:4 +0x30
exit status 2

This code will throw a deadlock error because no case statement is ready to execute, and there’s no default statement.
The select function will wait forever, and since there are no other Goroutines,
the code will throw a deadlock error.