I’ve found in your bytes
So totally not used to
Having to declare types
On Monday I was trying to compile
On Wednesday I had read a file
On Thursday I just about knew
GoLang, I’d fallen for you
This week, I couldn’t step away. I programmed for about 6 hours each day, not wanting to stop, possibly unable to stop. It was fulfilling, exciting, challenging and fun. I can wear many hats and do different things, but I know my soul is strongly software engineer because I am so madly addicted to programming. When I possibly wanted to stop I didn’t; there was more to be done. It’s infatuation, and it’s addiction, and it’s the routine that drives my confidence and purpose. The result of this particular week of transfixion is a relatively complete library in GoLang, over 4K lines of beauty represented across 58 files. I had the best week ever, and this experience, I want to share with you, because ones like it are rare and hard to find.
I wrote the goLang Library for the Scientific Filesystem, and it totally rocked my socks. To be transparent, I finished the entire client along with containers and a simple continuous integration setup, but I have more work to do with Go specific documentation and writing tests. My first goal is to provide a library in GoLang to support adding the Scientific Filesystem to the OpenContainers Initiative as a specification.
There is more to do, but no matter! Today I want to tell you the story of learning a language. This was an interesting experience for me, because it’s not every day that you get to do this. If you want to jump into my head for a romantic story, see the next two sections, Background and Story. If you want more realistic details about what it actually means to learn a new language skip down to the Details.
A lot of people experience joy when they socialize, go to new places, or otherwise act as a consumer. I find that wherever I go, there I am. You do not find happiness by changing location, items that you own, or what you are adorned with. You can distract yourself from facing the present by thinking about the future or immersing yourself in pleasurable experiences, but I’ve found that these distractions make me feel empty. The meaning that I find is with me wherever I go, and it’s enabled when I touch my fingers to a keyboard. Learning new programming languages are consistently the most satisfying experiences that I can remember.
This is the story, the journey, of learning a new programming language.
You start with a goal. You want to build something that you have no idea how to build. It exists as a vision in your head, and you don’t have any skill to do it, so the most that you can do is decide to do it. You make this decision. You create an empty directory, GitHub repository, and then you just start.
It starts out confusing and twisty. Nothing has rule or reason, and you are largely wandering in a lost forest, and looking at the trees. You spend days on end trying to solve the tiniest problems like “Where do I put this? How does this build?” and you learn by looking at the other trees (examples) and trying things.
At some point you put two twigs together, and they don’t fall apart. Your eyes start to adjust, and you see things more clearly. It’s still dark, but you start to have vision for how you might construct a skeleton for a structure.
Your first little dwelling is rough around the edges. You are constantly putting sticks together, taking them apart, and sometimes the entire structure falls down. This is where it starts to get fun. You’ve seen enough different structures around the woods to have many things to try, and once you try them, you start to form preferences. You realize that the first structure was way too complicated for what you want to achieve. The second had an entire room that was expected, but completely unnecessary given your goals.
This is when you start to fall in love. Maybe love has a place in this little house, so we can say this is where you start to fall. The construction is no longer confusing and new, it’s turned into a rhythm. It beats with your heart, and it starts to flow from your fingers. The ideas that were just faint vision start to form in front of you. At this point your fear is fading, and you are intimately attached to your work. Hours, days, weeks can go buy, and the more that you build, the more that you learn. There is no forest, only this. You feel strong, empowered, and inspired.
This is largely what happens to me with learning a new language, and it most definitely happened with GoLang here. Before this, I had only done small pull requests to repositories. I had a really hard time understanding the organization and evokation pathways of most programs. I can’t say that I am now (or ever will be) an expert, but I can assert that I have grown. There are no apologies for being new, or doing anything suboptimal.
Throwing yourself in and accepting vulnerability for doing it wrong is a way to grow.
If you’ve never looked at, read about, or otherwise interacted with the language, then starting a library from nothing is not the first step you want to take. I most definitely didn’t start learning from zero to this. If this is true for you, you should go find a repository on GitHub with the language you want to learn, find a small issue such as adding a command line flag or anything flagged with “good first issue” and try working on small pieces first. When you do this, you’ll unconsciously be figuring out how the software flows, how files work together, and how to define variables and functions, and do basic for loops and if statements.
I was so confused, generally, by the organization of these projects, that I first found an empty project template and cloned it with a simple goal - to create a client entrypoint that then called some set of library functions. Since I was working with the scientific filesystem the client would be scif and the functions would be the commands to install, run, etc. So this is probably the first important advice:
You need to want to accomplish a goal that you care about.
If you find tutorials or similar online, how could that be so interesting if the person who created it has already solved it? How can it really challenge and help you learn if there is complete certainty? It won’t. Following tutorials is usually fairly dull, and nothing sticks because you aren’t the one asking the questions and deeply wanting answers. I chose this particular template repository because it didn’t give me any tutorial or questions - it gave me a starting structure. It would help to teach me about organization, but also shower me with different examples (each folder has a README.md that explains why it’s there, and a huge list of repos to look at as examples).
I’m one of those developers that spends an inordinate amount of time thinking about organization. I want the files to be located where they would intuitively be looked for. I want the organization to be simple and (as much as it could be) be self documented. Thus, I read through the (original) README.md for a high level overview of the structure, and started to rewrite sections (read here) to further develop my own understanding. This was a bit of a Rosetta stone - I was taking a strange and confusing thing and writing it into my own words. I also read through this post carefully to understand the repository structure, and what should go in each folder. For each section, I would inspect my cloned repository, and look at the README.md in the folder of inspection. The mindset I had was to try and understand the folder’s purpose, and then see a lot of examples to confirm or deny if this was logical. For each, I only stopped looking when I sort of “got it.”
We have the basic understanding that files are going to be compiled to generate an entrypoint. It actually doesn’t matter how broken your code is, you need to first have a build strategy for generating errors for you to work with. I wound up trying about 5-10 different building methods, but ultimately found a gist that was simple and easy to understand (and thus good to start with). Once I wrote my Makefile and was able to run a simple “make build” and spit out errors with the library, I was off to a start! This is the biggest difference between interpreted languages (e.g., Python) and compiled. You can’t test things interactively with a compiled language, you need to build every time, so it’s a little bit harder. Thus
You need to optimize your build->run steps to make development easy.
Once you have your Makefile and can compile to generate errors, make changes, and then do it again, you’re ready to start thinking about the code itself. This is where thinking about the evocation pathway of the program comes into play. I knew that I would want to call some binary “scif” and then have arguments processed, and the environment looked at, and then based on what the user requested, pass that on to client functions. To be fair, I had originally started development using the “best practices” example, such as putting minimal code in the cmd folder. As I was working on this, I was unhappy with the confusing organization of the folders. It was too scattered, and I could never find things where I expected them to be. Since this all gets compiled into a binary anyway, the organization should be for the human. So I decided on the following (more intuitive) structure:
This is where I expect to find commands, organized by folders. So the main scif entrypoint (scif) would be here:
cmd/ scif/ main.go ... docs run.go ---) entrypoint to call a function in pkg/client/run.go
I also moved the “docs” folder to be part of the main package above, because 100% of the content provided there was for the command entrypoint. Everything you see under “scif” above is package “main.” The flow then moves into the client package, where files are named to match the file with the calling function. I won’t go into further detail about where I put files, but generally, the point is that where a developer expects something to be is where it should be found.
When you start, your client is likely to include just one command group, and have a main execution function to print something to the screen. But the moment when the thing first compiles, and you can run that thing? It’s amazing. There is nothing that feels better. I kept the memory, for posterity.
After the first compile, your slowly rolling garden cart starts to pick up speed. You blink, and it’s now a tiny car, and then a slowly moving train! The point is that you suddenly get it. You no longer are struggling with basics of the language, but the ideas in your head start to flow from your fingers fluidly. The development workflow is comfortable and easy. Sure, you still do a lot of Googling to look up functions and usage, but that’s just a part of programming. You then start to make new milestones! For example, the first time you read in a file:
And then when you parse the thing, and create your filesystem!
And the first time you interact with the filesystem, and run an application!
Look at this beautiful thing! I can’t wait to test it against the equivalent Python version. I know Go will be faster :)
Now it gets easier, because you have a method. You can add something, build it, and then try running it. For details on strategies for this, see the development docs. I had it easy, because I had already developed the (general) flow of the library in Python, and simply was figuring out how to reproduce it in GoLang (without proper classes!) I largely stuck to developing on my local machine, and then added some Docker containers to mix things up.
The entire week went by in a blink. This experience is like running a race because you blink, and then you made it! You don’t remember when the language used to look like Chinese characters to you (because it did, just 5 days ago). My gosh, I am so in love with building this library. I am so in love with programming. I am so lucky to have found this love… it’s driven me to write stories and poems.
I’ll have none of that, insightful indented comment voice! I’ll have more in the coming weeks on this library, ohman, I can’t wait to dive into how to properly write Go Docs, and create some beautiful ones.