I was a bit bored last night. So, like most sane people, I decided to try out a new language: Go. I'd been eyeing it for a while; I wasn't ready to try out C or C++, and Rust was too scary. But there was something so inviting, so... comforting, about that big, blue, bulbous-eyed gopher that finally got me to get my hands dirty with it (just to clarify, I'm talking about the language).
The goal was really simple: build something that would teach me a bunch of things about Go, its standard library, and maybe working with external libraries.
I'm not new to programming languages. I've spent the last couple of years on and off building web pages with TypeScript, so typed languages weren't new. I just wanted to see what Go was like, especially its speed.
Turns out, it was a lot of fun. Here are some things that clicked.
Familiar Syntax, Mostly
It's got curly braces! I love 'em. They make my code feel nice and contained, like nothing's leaking out. It's aesthetic, sure, but it is one thing I like. Definitely a welcome sight for eyes tired of Python's whitespace madness.
Type declarations feel familiar, too. If I want to declare a string in TypeScript, I'd write:
const whatAmI: string = "A String!";
But in Go:
unfortunately, my cke editor doesn't support Go syntax highlighting... so I'll be using code images for Go.
The difference is minute. You just move the type after the variable name and drop the colon. I will say that I do prefer TypeScript's syntax here. TypeScript's syntax reads, "The constant whatAmI, which is of type string, is equal to 'A String!'". Removing that colon in Go feels like removing the commas in that sentence. It's really a non-issue, more "aesthetic stuff," but it's the little things you notice.
Handling Errors
In the world of JavaScript, when we want to write some code that could fail, we wrap it in a try...catch block. So, we try something, and if something breaks, we catch and throw an error up the call stack.
Go is different. You deal with the error. NOW.
When you're doing something that can "fail," you must deal with the possibility of failure immediately:
It definitely feels "grown-up." You have to deal with your issues right now before you continue with whatever it is you are doing. Initially, I got a bit confused. A single function can have many if err != nil blocks, and by convention, the error variable is always just named err. Surely it's referencing the same variable, so how can you declare it more than once?
This comes down to a clever feature of Go's := (short variable declaration) operator. It can declare new variables and re-assign to existing ones in the same statement, as long as at least one variable on the left is new.
Take this example from my project:
It's a subtle bit of language design that keeps your error handling code clean and consistent without forcing you to invent new variable names like err1, err2, and so on.
It's Fast, Man
In my link checker, the initial version checked each URL one by one. Of course, it worked, but it was as fast as people paid by the hour. If there was a slow website it was waiting to respond to, everything else had to wait.
And then I was introduced to one of the main selling points of Go: goroutines and channels. And they are hilariously simple to implement.
Say I'm calling a function, checkLink(link). How do I make it a goroutine? The funny bastards: go checkLink(link).
That's it. This'll now run in the background while we get on with other things. If we want the results back, we'll need something called a channel, which is like a conveyor belt between the main function and all the background helpers.
The change wasn't just "noticeable," though. It's literally night and day. The initial script took a few seconds—it was still quick, don't get me wrong. But using Go's concurrency made this feel instantaneous.
It Just Feels Nice, Okay?
The code feels functional. You're encouraged to write small and simple functions that take in data, do one thing, handle errors, and return a result. There's less emphasis on complex classes or deep inheritance chains.
The compiler's also quite grumpy. It'll error if you have an unused variable. Its built-in formatting tool (gofmt) is great, too; it means every Go project on the planet looks and feels the same. There's just no clutter.
There's more to learn, of course, but for a first date, Go was brilliant. Wonder where she'll take me next.
If you use TypeScript, give Go a try! If you don't use TypeScript, give Go a try!