4 A log story: Creating a library

 

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?

4.1 Defining the API

4.1.1 Package summary

4.1.2 Exporting the supported levels

4.1.3 Object-oriented Go: “GoOOP”?

4.1.4 The New() function

4.1.5 What about testing?

4.1.6 Documenting code

4.2 Implementing the exported methods

4.2.1 Default implementation

4.2.2 Interfacing

4.2.3 Refactoring

4.3 The functional options pattern

4.3.1 Creating configurations

4.3.2 Testing our example

Summary