10 Polymorphic storage

 

This chapter covers

  • Interacting with SQL databases
  • Understanding the driver pattern
  • Integration-testing external services
  • Using the consumer-driven interface approach

In earlier chapters, we built a link service for Bite. Now another team needs persistent storage so that links survive HTTP server restarts. We asked them to implement it and offered help with integration. This chapter shows how the team added persistence to the project.

We’ll start with the standard library’s sql package and use SQLite because it’s lightweight and needs no separate installation. The concepts apply equally to other SQL databases, such as PostgreSQL, because the sql package abstracts database interactions.

We’ll add a new Shortener service backed by SQLite and verify it using a test database. Finally, we’ll decouple HTTP handlers from this service using consumer-driven interfaces, an approach that requires a different mindset than traditional object-oriented languages. By the end of the chapter, we’ll know how to work with SQL databases using the sql package and use interfaces effectively to decouple implementations from the code that uses them.

10.1 Interacting with SQL databases

10.1.1 Registering a driver

10.1.2 Opening a connection pool

10.1.3 File embedding

10.2 Database-backed service

10.2.1 Insertion

10.2.2 Test database

10.2.3 Integration testing

10.2.4 errors.As

10.2.5 Retrieval

10.3 Valuer and Scanner

10.3.1 Supporting custom database types

10.3.2 Satisfying Valuer and Scanner

10.3.3 Encoding and decoding

10.4 Implicit interfaces

10.4.1 Consumers-first approach

10.4.2 Providing an interface

10.4.3 Activating the new implementation