Hacker News new | ask | show | jobs
by decasia 501 days ago
I just rewrote a tangled 500 line shell script in go.

It was my first time writing a golang project at work, so I'm sure it could have been better. But writing it the naive way, with all the required golang error handling, it ended up taking about 10x more lines of code in golang than the original bash script.

It does have a dramatically better UX (largely thanks to spf13's cobra and viper), and is way faster than the original, and the codebase is a lot cleaner and more maintainable. So I think it was worthwhile for the users and maintainers.

But still, 10x more lines of code. I like the OP, but I'm still not sure I would reach for golang for short shell scripts.

4 comments

It depends. For single scripts its too much, but if there are dozen or so scripts with related/similar tasks, there can be common code or pattern to be shared. I have one Go project with ~3kloc and does 20 or so operations. But if were to do just single operation it would still need ~1.5K line of code.
Yeah, the original script I rewrote was doing about 15 different operations depending on the user input/arguments, so I guess it indeed reached the point you're describing where there were a lot of common patterns. It's just that instead of being 15 separate scripts, it was one gigantic one with a lot of conditionals and case statements.
This always seemed like the sweet spot for Perl.
500 lines of bash could have been rewritten as 50 lines of dense Perl. Pro: fewer lines of code. Con: even the author would find the Perl script inscrutable after a few weeks.
A more experienced Perl hacker would probably rewrite it as 100 lines of less dense code that people could actually read and comprehend.

I'd probably end up rewriting it as 50 lines of code that used a bunch of pure perl libraries and then use https://p3rl.org/App::FatPacker to bolt the dependencies onto the front for distribution so it was still a single file to install for everybody else.

(there's a lot of perl out there that uses techniques I would switch away from as soon as I got past a one liner in the middle of a pipeline, alas, but it doesn't have to be that way, perl just doesn't stop you blowing both feet off ;)

It is. Very much so.
One neat thing about Go that makes it superior to a shell script is that it compiles a statically-linked binary. One self-contained file! Or N if you support N platforms. Did I mention that cross-compilation is trivial?
As someone who once inherited a static binary (without debug symbols, gotta save those few bytes) that should have been a shellscript: Please don't. If your logic reasonably fits into a shell script, then put it there.

Posix shell-compatible scripts will also likely work on all platforms where you go program would've been run.

> Posix shell-compatible scripts will also likely work on all platforms where you go program would've been run.

While I see your point, writing a Posix compatible shell script is not trivial. Little errors creep in that "work on my machine" because /bin/sh is a symlink to /bin/bash, but break the script when someone runs it on macOS.

In my experience, you get a lot of cross-platform compatibility when writing Go for zero effort.

If a static binary's --help doesn't tell me where the repository lives then I hope the author steps on a lego.
This is a good idea, will add this to my cli tool :)
It is no help to you or your team if they step on the Lego, though.
I mean this entirely depends on how things are done where you work. I wouldn't think the back-reference is necessary if all projects have their own repo in some central location (and it's trivial to match the binary's name to a repo).
Or just make sure the source is available.
Did you do thorough error handling in Bash?