Data structure serialization in databases can be difficult with golang types.
For example, say we want to have a custom type as an attribute in a type. How
can we get this typed attribute inserted and read from a sql database. Golang
offers a mechanism to allow for this: Implement Scanner and Valuer database/sql
interfaces.
Imagine we have the simplest representation of customers on the face of the
planet, an identifier and a yes/no flag for active:
Now we have a dedicated YesNoEnum of which we have two constants, Yes and No.
Lets try to start storing some Customers in a database:
Sweet! Finally, we get to add some customers to our database, and set the to
active! Lets run it!
Okay, what is going on here. Go’s database/sql Exec is choking on our YesNoEnum custom
type. But it is just a bool right? No, by defining it as a Type, it is no longer a bool, it is a YesNoEnum type, and database/sql doesn’t know what to do with it. We can explain how database/sql should handle this type by implementing sql.Valuer.
Valuer is an interface where we can turn our type into a simpler type, a type the database will be able to understand, such as a boolean. Here is what it looks like:
Now we when we run our application we should get a little closer:
Muahahaha! Getting closer. If only we had created that customer table in the database. Alright, after creating the table and re-running we have a customer id in the database. Lets try to get it out of the database, and print the stored value to stdout.
The above queries our customer table for all customers, then for each customer the program makes a new customer (foundCustomer) and tries to put the data from the database into our customer data structure. When we run our program again we unsurprisingly get the following:
Shucks. I guess we need some glue to make database/sql understand how to put the value from the database into our data structure. That glue is the scanner interface. Much like the Valuer interface, we need to perform some conversions to get the data from the database into our structures. Below is our implementation of a valuer for our YesNoEnum type:
So, moment of truth… do we get a customer record printed out?