In this blog I talk about some of the personal programming I do as a hobby. From Java to Rust via Haskell, I've played around with a lot of technologies and still try to have fun with new languages and APIs!
I've put a littleproject on Github written in Go. It's a little database system that allows
writing and reading objects, and do GraphQL queries on them. The main principle
is that objects have a arbitrary String ID that is like a path, separated by
slashes, and deleting an item with a given ID deletes also items with
"children" ids.
For fun, I used
Cassandra as the main data store, since it's optimized for fast writes and
loads of data; we never delete anything, we just keep every state of an object
as history. Text searches are done on the last version of objects using
Elastic. GraphQL support allows to follow object namespace relationships.
I also provide
Dockerfiles to deploy either just the database systems for testing, or the
whole application.
I'm not sure this
can be useful as is for anybody, but this was for me to try Go on a real-life
project. Apart from the gotchas I've wrote about before, it was a rather
painless and enjoyable experience.
As I wrote my first non trivial project in Go, I had a few head-scratching moments. Nothing that a quick search could clear up, but worth keeping in mind...
You may run into that one quickly enough in tests. An instance of an interface can have a nil value but since it carries the interface type information, it does not equal to nil!! A lot has been written about it so make sure to read about it!
Redeclarations
The fact that you can use := to declare variables easily is a double edged sword, as declaring a variable with the same name as a previously declared one is allowed if it's in a different scope, and it shadows the original variable. So:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This code will only print True at the end. The "err" variable inside the if block has been redefined so even though it's not nil inside the if block, it IS nil once you exit it! So if you want to chain several operations that may return errors and then at the end handle whatever error occurred in a consistent way, you have to be careful.
Closures
This one gave more some Javascript PTSD:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This prints : 4 4 4 Which was not what I expected! One easy fix is to add a line saying i:=i before creating the func in the first loop, which by virtue of the previous gotcha redeclares a variable in the scope of the for loop body.
Errors
I'm not convinced in the end by the standard error reporting in Go. A lot has been written on that topic too. I feel that the code is peppered with error handling that gets in the way of readability and implementing cleanly the business logic. I'm sure there are some design tricks you can use, but you shouldn't have to resort to tricks to do clean error handling in a language, because at the end of the day it's how you handle errors that make up the quality of your software, not only how you handle the happy path.
These things you can watch out for and probably code around pretty easily, but they do impact a bit the ease of use of Go, even though I still think it's quite a simple elegant language to quickly be productive in.