When I first started writing Go code I was working on a relatively simple web application backed by an SQL database, so the first thing I did was Google “golang sql” which lead me to to the database/sql package.
While reading those docs I notice this line in particular.
The sql package must be used in conjunction with a database driver. See https://golang.org/s/sqldrivers for a list of drivers.
What? I need something else to go along with the
“No worries”, I thought to myself. “I’ll just follow the link and use one of the drivers.”
So I did just that. I clicked the link, found the driver I needed, installed it with
go get and then started looking for some code samples to get started. After a few minutes I ran into this little beauty.
import ( "database/sql" _ "github.com/lib/pq" )
At this point I stopped typing and just stared for a minute. Why the hell am I including a package that doesn’t get used? What purpose could that possibly serve? I thought Ruby on Rails had an exclusive license on being magical.
After that I kinda just let it go. I didn’t really need to understand what was going on for my code to work, so I just let it be.
Everything was jolly until I recently started writing the book Web Development with Go; I was working on a chapter that introduces using the
database/sql package and thought to myself, “How can I possibly expect every reader to just let this go? Surely some of them will be asking questions, and others will forget about this unused import. I need to address it.” So that is what I am doing today. Addressing the question on many developers mind when they start using SQL with Go:
Why am I including a package that never gets used in my code?
My first stop in understanding this was the
database/sql package, which quickly lead me to the database/sql/driver package.
Apparently this mystery had something to do with implementing the driver package, so it sounded like a sane place to start.
If you look through the
database/sql/driver package you will quickly notice that there really isn’t much functional code there. Instead we have a large variety of interfaces being declared without any implementations.
Every database would need to implement each interface a little differently, so it makes sense to provide a common interface that each SQL variant can implement, but nothing here seemed to answer my question. I still didnt know how my code was actually learning about the driver being imported, so I headed back to the
And then I saw it. The second function listed in the package answered all of my questions. Register(name string, driver driver.Driver) needed to be called to tell the
database/sql package about a driver.
After that all I needed was a simple search on the github.com/lib/pq package to verify my suspicions.
The reason we don’t actually need to do anything with an sql driver is because the
init() function gets run before our own
main() function ever gets run. This means means that before our code ever runs the lib/pq package registers an sql driver that our code then uses, regardless of whether or not we directly interact with the
That is why we need to pass a driver name as the first argument of the sql.Open() function.
Nothing magic is happening; Instead it is just looking up the driver from an internal map that stores all registered drivers along with their name.
I know this isn’t revolutionary by any means, but what really inspires me about this personal story is just how easy it is to navigate code written in Go. It took me less than 15 minutes of digging through both standard libraries and third party packages to find out what was going on and to truly understand what was happening.
It simply isn’t easy to dig through a complicated library or application that you didn’t write in most other languages, but in Go it truly is.
That simply blows my mind after so many years of using languages where it wasn’t true.
So I just want to say kudos to the people behind Go. I am both impressed and thankful that you work so hard to keep Go as approachable as it is. Oh, and you should try out Go if you haven’t already 😉
Sign up for my mailing list and I'll send you a FREE sample from my course - Web Development with Go. The sample includes three chapters from the book, and over 2.5 hours of screencasts.
You will also receive notifications when I release new articles, along with other freebies that I only share with my mailing list.
Jon Calhoun is a full stack web developer who also teaches about Go, web development, algorithms, and anything programming related. He also consults for other companies who have development needs. (If you need some development work done, get in touch!)
Jon is a co-founder of EasyPost, a shipping API that many fortune 500 companies use to power their shipping infrastructure, and prior to founding EasyPost he worked at google as a software engineer.
Spread the word
Did you find this page helpful? Let others know about it!
Sharing helps me continue to create both free and premium Go resources.
Want to discuss the article?
©2018 Jonathan Calhoun. All rights reserved.