Reading stack traces
If you are lucky, your program panics when something goes wrong, and prints out lots of diagnostic information. You would be lucky because if you have the output of a panicked program, you can usually figure out what went wrong by just looking at it together with the source code. So, let’s take a look at some stack traces. The first example is a deadlock-prone implementation of the dining philosophers problem, with just two philosophers:
func philosopher(firstFork, secondFork *sync.Mutex) { for { firstFork.Lock() secondFork.Lock() // line: 10 secondFork.Unlock() firstFork.Unlock() } } func main() { forks := [2]sync.Mutex{} go philosopher(&forks[1], &forks[0]) // line: 18 go philosopher(&forks[0], &forks[1]) // line: 19 select {} // line...