This chapter covers
- Implementing a three-level logger
- Using an integer-based new type to create an
enum
- Publishing a library with a stable exported API
- Implementing external and internal testing
- Package-level exposition
It’s late at night. You and your colleague Susan have been working on trying to fix a bug for 2 hours straight. You don’t understand what’s happening with a certain count
variable that should have the value 1
, but the result of the program seems to indicate that the value there is 2
instead. You try to read the code, but the problem isn’t obvious to your tired eyes. Is count
really 2
? You decide to add a small line in the code and relaunch everything to get a better idea of what’s going on. The line you add will help you at least understand what the variable’s value is. You use
fmt.Printf("counting entries, current value is %d\n", count)
We’ve all been there. Having the code say something we can understand at specific steps is our easiest way of following the program as it executes.
Then, Susan notes, “Wouldn’t it have been nice to have this information from the initial run, without needing to redeploy updated code?” But then, would we also want to deploy this unconditional fmt.Printf
? (Hint: The answer is absolutely not.) Were there other options that could have made our life simpler?