Malcolm Gladwell made popular the notion of spending 10000 hours to achieve mastery in any skill. However, this notion of 10000 hours is a built upon a body of research which studied how much time top performers of several fields spent in "deliberate training" to achieve their level of skill. The number represent world-class expertise.
However, when learning a new skill, this is not what we are targeting. We are looking at functional competence, just the basic ability to execute that skill. Playing chords well enough for 5 songs around a campfire qualifies as having learnt the guitar - it is not necessary to be able to play the Freebird solo with your teeth. Some have claimed that gaining this level of skill can taker as little as 24 hours.
Learning a new programming language is no different. It takes considerable time and effort to master a programming language, and even more to effectively use it in the wild. This is my story of learning Golang in 24 hours
I had previously tried to learn Golang by going through the rules (it's a language, so you gotta learn the grammar, right?) and using the excellent Go Tour. But even though Go has a very concise syntax (IIRC the entire Golang spec is ~55 pages, the Java spec can crush a grown man's skull with its weight), it still got boring after a while so I stopped. After this happened twice, I decided to see if the "learn a skill in 24 hours" thing worked and set myself a very specific goal.
I would build a MySQL+ORM backed, Swagger documented, REST service to perform CRUD operations over a simple entity using Go - no more, no less. The specificity of the goal allowed me to focus on what I wanted to learn (not the whole language, but hopefully the most commonly used parts). I must have built a bazillion CRUD services in my life by now, so there was no "domain" learning to worry about - I wasn't building something new, just the same old things with a new tool.
I am happy to announce now that this actually worked. I now have a functional understanding of Golang and can build some basic things with it. And it was fun too! Achieving each of those specific milestones kept the motivation strong, allowing me to become familiar with the language gradually, and engaged me enough that I ended up writing some logging and context propagation related middleware that I hadn't originally planned on doing (I can't help it! Why would someone just write a CRUD service when you can write a CRUD service framework).
I had a kept up a tweet stream through this whole exercise to document the happenings as they happened. Check it out here.
The complete code is on Github - feel free to play around with it and critique it.
Here are some of my takeaways from the process. Let me know what you think and if you had a different experience in the comments. These are not the pros and cons of Golang (or not just that), these are my notes on the whole experience of learning a new language by building something with it.
Always learn by Building
Learning by building something rather than learning the rules was so much more effective. The playground it really cool, but learning syntax after syntax gets old real quick. The motivation of seeing something tangible get built cannot be over-stated.
Blogo-sphere really helped
There are many more "how-to" resources for specific things than there are for just learning the language. The amount of resources available to a beginner via blogs and forums is extremely empowering. A big thank you to everyone whose writing facilitated my blazingly fast copy-paste. I have given credits in the code as well, but these two series of articles really helped me.
After I completed the service and started getting into the language, I stumbled upon several talks by Rob Pike who is one of the creators of Golang at Google. If you haven't yet had a chance to listen to him speak, you absolutely must. My favourites were his talks on "Concurrency is not Parallelism" and "Simplicity is Complicated"
Golang is Simple
Building CRUD applications is probably 90% of a programmer's work , and after this I can confidently say that it is banal in any language :). However, the simplicity of Golang made the experience really, well, simple. Things that take many lines in Java can be expressed so neatly and compactly in Golang that it was a pleasure to "find by id" and "insert a record" again. The fact that there aren't too many different ways to do something in code gives the confidence that what you are writing in a certain way will work, or the compiler will barf.
What I learnt : variable declaration and assignment, methods and functions, interfaces and implementations, code structuring using packages, basic deployment, array/list/map operations, loops and if conditions, goroutines and channels. While this looks very basic (except goroutines), it is actually a large subset of the language. There aren't too many things left to cover from the language perspective (obviously there is a whole lot more if you want to understand the internals of Golang).
Golang is Powerful
Golang is actually a NEW language developed to implement infrastructure related fesatures in the cloud. Instead of being an amalgamation of features from existing languages, it takes a fresh look at the most common needs of the world today and offers them out of the box.
Garbage Collector : GC is completely seamless in Go. There is no way for developers to tinker with it - no finalize() etc, it just works.
In built server packages : Golang is wise to today's API heavy world of today and give inbuilt package to start different types of servers. Firing up an HTTP server is about 5 lines of code.
Ground Up Concurrency: Concurrency management is baked right into the language, and the importance of this is impossible to exaggerate. Developers can build scalable concurrent systems without extra frameworks or programming paradigm shifts (as you would have to do in most languages when going from sync to async).
Circular Dependency detection : This was just awesome. Anyone who has dealt with keeping dependency graphs straight in large organizations will appreciate this. The compiler actually FAILS the build if it detects circular dependencies. This forces developers to be very careful about how the code is structured and what is upstream and what is downstream. This might cost some extra time during design, but definitely leads to more maintainable software in the long run.
All of this comes right out of the language - I haven't even checked out too many frameworks yet!
As usual, the open source community makes everything so much simpler! I used several frameworks as recommended by the blogs I was following, and without fault the documentation on each of them was top-notch. I often went from opening the documentation to feature completion in no more than a couple of hours.
Request Routing : Gorill mux
Context propagation : Gorilla context
ORM : gorm
Documentation : Swagger
Weak debugging instincts
As a beginner, debugging was hard because there was no visual intuition of what is happening when looking at the code. Nothing "looked wrong" because I didn't have a gut feel for what wrong looked like. IDE helps of course, and this diminished as I got more familiar with the layout of the code.
Forgoing Conciseness for Explicitness
I think Golang gets this right for the most part, but in some cases I felt that the syntax could be more explicit.
The upper/lower case convention for public/private access - It seems a little "magical" to me. I'd have liked something more explicit (e.g. putting an "_" before private methods).
It is difficult to tell which struct implements which interface(s). In large code bases, this might cause discovery problems.
The map.exists syntax is absolutely atrocious. Considering how many time this is done in any piece of code, I urge the language owners to clean this up.