Building Web Services: Go, Rust, or Swift?

Yep, it’s another technical episode. I promise soon I’ll tell y’all about Felix. He’s s good dog.

But today we’re talking about building services that run in data centers and provide some slice of the information you see when you log into a web site. How those services are made will mostly be felt to you by how fast the site responds.

A lot of this stuff is written Java, or Microsoft’s shameless copy C# (pronounced c-sharp). I was a fan of Java back in the day, but it failed in its core premise “write once, run everywhere” and became instead a not-awful language everyone used on servers. The only reason I can figure this is: It’s harder to make a terrible mistake in java than in C++.

I built a thing in Java that has yet to be reproduced. So I say this to Java with love: You are done. You did not fulfill your original promise, and there are much better languages to be running in servers. The absolute monstrosity that is SpringBoot reinforces that fact.

If you’re going to write a service that runs in the cloud, even PHP is better than Java. (We will not speak further of .NET). But the top three? You’ve got Go, Rust, and Swift. This is an opinionated comparison.

Go: Google’s baby. It is all about a simple syntax for tasks that can run in parallel. ‘go’ do this thing and give us the result when you are done.

Rust: Mozilla’s baby. It is all about memory management. It is uncompromising to the extent that “memory leak”, a bugaboo of services, is impossible. Because of its architecture, it’s a hard target for hackers.

Swift: Apple’s baby. Almost as hard-assed as Rust. With some effort you can apply the memory principles in Rust, but not at the deep compiler level. Running tasks in parallel is an add-on, rather than the effortless Go.

My biased opinion:

I have more than once looked at Go, and asked, “where’s the rest?” Surely I must be missing something. But apparently I’m not. There’s just not that much here. A well-considered language should encourage good patterns. Go has interface, at least, and now has picked up generics, but remains skimpy. “Simpler is better”, the Goog declares, and if that’s your bag of beans, then maybe Go is for you. But… no optionals?

Rust. Hardcore shit. They ask you to tune your thoughts to a different frequency and you will know the rewards. I’m not saying they’re wrong. If you will indulge me…

A Brief Aside — Memory. When a program runs, it puts data into memory in a place everyone who is interested can find it.

  • C/C++ requires that in your code, every place you allocate memory, you must have a matching process to free it up again. This is the single thing that made Java popular — it lifted that burden from the programmer.
  • Go has a garbage collector: each item in memory keeps a list of everyone who is interested in it. When no one is interested, the garbage collector comes along and releases that memory for use by anyone else. This means that everything stops for a very brief time for the garbage collector to do its work.
  • Swift also counts the number of things interested in a chunk of information, but when that count goes to zero it immediately frees the memory. This means whenever something goes out of scope checks must be made.
  • Rust, however, makes sure that only one thing owns that chunk of memory, and when that thing is done, the chunk is gone. Fast, simple, precise. But it means you have to code in a particular way. Who owns this? will eventually become second nature, but it’s a climb to get there.

So that’s Rust. It’s pretty cool. Big names are using Rust in critical services — including the people who invented Go.

That leaves Swift. Generally dismissed as the language to make iPhone apps, it is fundamentally grounded in the belief that a programming language should make it as difficult as possible to make mistakes. Common errors that cost the world billions of dollars a year simply won’t compile in Swift.

But Swift is bigger (in scope, not popularity) than the others. It has the semantics for running many things at once, and if they aren’t as native to Swift and Rust as they are to Go, they still work just fine. It also has deep semantics for inheritance and composition (strongly favoring composition), along with generics, closures, and of course type-safety. Even JavaScript has a type-safe version.

Mmm… delicious type-safe closures.

I’ve been writing Web services for a while now, and I choose Swift. Rust might be incrementally faster, but it might not; it depends on the specific application. Swift compiles up to be fast. Go just doesn’t have the constructs I need to make a good server. Maybe for simple CRUD it’s all right, but I wouldn’t want to write serious business logic using it. Too much not there.

1

Gimme Swift

As a computer programmer, I live in a familiar cycle: Write some code, then run it repeatedly to work out all the kinks. There is a moment when you hit “run” for the first time, already anticipating what the errors might be, thinking about next steps when the error inevitably presents itself.

It’s been weird writing server-side Swift. I do my hacking, adding a feature or refactoring or whatever, I make the compiler happy, then it’s time to get to the nitty-gritty. I roll up my sleeves, start the program… and it works. Just like that. I run the tests against the other systems. It works.

It’s like you’re all ready for a fight and the other guy doesn’t show up. NOW what are you going to do?

Swift can be annoying with how hard-assed it is about certain things, but that picky compiler that sometimes forces long-winded syntax is like that really picky English teacher who you realize after the fact gave you a command of words you didn’t have before. If you have a null pointer in Swift, you went out of your way to create it.

Programming languages exist for the convenience of humans, not machines. So if you can make a language that makes it harder for humans to make a mistake, why wouldn’t you?

Man I enjoy writing code in Swift. Of the four languages I use regularly, Swift is hands-down the one I’m most productive with, even though I’ve been using the others for far longer. And just today I remembered that functions could return tuples, and I was like, “Damn!” all over again, thinking how I can shrink my interfaces.

That and a performance profile comparable to C (each is better for certain sorts of operations), and you have a language with some mojo. This ain’t JavaScript, homey.

Most of my days are consumed writing code in other languages (at least for now), and what strikes me every day is that the mistakes I make would not have been possible in Swift. Think of that!

3

Time Not Well-Spent

Here it is, Whiskey-Exemption Thursday, and my weight is on-target so I can even have beer. The purpose of Thursday is to devote an evening to pushing the writing forward, and hang the consequences.

What have I been writing this fine evening? I’ve been trying to come up with the least-objectionable way to emulate Swift’s extensions to Protocols in php. The answer: there is no way.

Begin geek

Coding with php is coding with flint knives and bearskins; the power of php is in its wham-bam-thank-you-ma’am ability to do a quick task and then to go away.

Bless the movers behind php, they’re trying to evolve their language to catch up with the way people are using it these days. If they had known Drupal was coming along, they might not have been so quick-and-dirty before. Drupal might be slightly less awful as a result.

There are design patterns enabled by Swift that I get a little misty contemplating. Being able to add extensions (with executable code!) to protocols is enormously powerful. Having experienced that, I wanted to do the same thing in php, creating a trait “taggable” and having classes that used it automatically injected with the implementation. Injected, not inherited. Ain’t gonna happen.

End geek

At least now I’m writing prose about writing the code rather than writing the code itself. Progress, I guess.

3