Coding Bits
Bits about code, or working with code.  Not so much about what's being worked on.
Subscribe via RSS here

Custom Import Paths In Go

One of the craziest ideas I had recently was to move all my code from Github to a self-hosted SCM system. The impetus for this was to have import paths with a custom domain name for all my Go packages, rather than have all them start with `github.com/lmika/(something)`. Fortunately, this proved to be unnecessary, as Go does allow one to customise the import path of packages hosted elsewhere. This area of the docs has all the details, but here's the process in short. Lets say you have a package hosted in Github at `github.com/example/mypkg` and you want to use the...

PostgreSQL LATERIAL Joins

Someone shared with me the `LATERIAL` join type supported by PostgreSQL. He described it as a "for each" built into SQL: “When a FROM item contains LATERAL cross-references, evaluation proceeds as follows: for each row of the FROM item providing the cross-referenced column(s), or set of rows of multiple FROM items providing the columns, the LATERAL item is evaluated using that row or row set's values of the columns. The resulting row(s) are joined as usual with the rows they were computed from. This is repeated for each row or set of rows from the column source table(s).” Here's an...

Changing gRPC Schemas

What changes can you make to a gRPC schema that's already in use? Honestly, I always forget these rules, or get paranoid when I'm touching messages that are already deployed, so it was time to find out what these rules are. I came across this Medium post by Toan Hoang which listed them, and I thought I'd make a note of them here. Here they are in brief. Non-Breaking ChangesThe following changes are completely safe, and will not break existing clients or servers using an earlier version of the schema: • Adding a new service • Adding a new method...

Go Unit Test Naming Conventions

You're working on a Go project (yay! 🎉) and you need to write a unit test. You decide to go with a table-driven approach. What names should you use for your variables? For a long while, I was writing tests using names like these: func TestSomething(t *testing.T) { scenarios := []struct { description string arg string expected string }{ { description: "Thing 1", arg: "this", expected: "that" } // more cases go here } for _, scenario := range scenarios { t.Run(scenario.description, func(t *testing.T) { // ... } } }The cases are "scenarios" and they are to produce "expected" values....

Moan-routine: Stripe Prices

I love coding and anything computers. I've spent, and continue to spend, a significant amount of my life writing code. And on the whole, it's been a magical experience. But not always. Sometimes I encounter something that makes me wonder why? Why was that designed that way? Why doesn't it work? Why couldn't this be easier? You encounter something that blocks you or puzzles you, maybe even questions how anything in computers can work at all. You've got things to do, and you try your best to work around the problem. Sometimes you succeed. Most times you get blocked and...

Rubber-ducking: On Context

I'm torn between extracting auth credentials in the handler from a Go Context and passing them as arguments to service methods, or just passing the context and having the service methods get it from the Context themselves. Previously, when the auth credentials just had a user ID, we were doing the former. But we're now using more information about what the user has access to and if we were to continue doing this, we'll need to pass more parameters through to the service layer. Not only does this make things a little less neater, it'll mean the next time we...