Skip to content

Instantly share code, notes, and snippets.

@progrium
Created February 17, 2015 14:19
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save progrium/d782e574bb2e97d5ebdc to your computer and use it in GitHub Desktop.
Save progrium/d782e574bb2e97d5ebdc to your computer and use it in GitHub Desktop.
Comparing natural brevity and concise expressiveness between Go and shell/Bash for certain tasks using each tool's "standard" library.
curl -s "$url" | tar -zxC "$dest"
func downloadAndInstall(url, dest string) error {
resp, err := http.Get(url)
if err != nil {
return error
}
defer resp.Body.Close()
zip, err := gzip.NewReader(resp.Body)
if err != nil {
return error
}
defer zip.Close()
archive := tar.NewReader(zip)
for {
header, err := archive.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
filename := fmt.Sprintf("%s/%s", dest, header.Name)
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err := io.Copy(file, archive)
if err != nil {
return err
}
}
}
@stephanheinze
Copy link

nit picking: curl and tar ARE 3rd party libraries and NOT bash-internals ... just for the records.

@progrium
Copy link
Author

Thank you for pointing that out, I guess. I was trying to communicate "effective" standard library, hence quoting "standard". Just for the record, http, gzip, tar, fmt, os, and io are not Go built-ins.

@alessiodm
Copy link

The comparison is impressive at the first glance, but I think it is a little bit unfair: we are comparing a higher-level declarative style of coding with a finer-grained imperative code. I think we can reach a similar brevity in Go if we introduce some concepts like streams, etc. and we write some higher-level functions handling that.

In the example above, for example, we have the ability to catch an error and handle it in Go, while the bash script probably just crashes or has a behavior with (uncontrolled/unexpected?) side-effects. The control/safety/behavior of the code is also another (hidden) factor in the comparison, that I loved, but perhaps it's hiding too many relevant considerations (even if it is not claiming that one is better than the other) :)

@andys
Copy link

andys commented Feb 17, 2015

I respectfully submit that you should write the corresponding program in C. That is the comparison that I think about most often when using Go 😉

@kef
Copy link

kef commented Feb 18, 2015

Would like to see examples of how the Go version could be improved, using the typical practices of an experienced Go programmer. Any takers?

@cablehead
Copy link

The bash example would need 'set -o pipefail' to replicate the error handling in the Go version through the HTTP download.

@msabramo
Copy link

This is what I struggle with in Go. I feel it has some interesting ideas, but it's not very nice to read.

This is I prefer Python. But I'd be curious to see how to improve the Go code to make it more succinct.

@abevoelker
Copy link

@cablehead set -o pipefail just deals with error code propagation. You can't replicate the immediate abort-on-failure of the Go code using just pipes (i.e. tar will still run no matter what w/ a pipes solution). You'd have to write a full script w/ separate commands to avoid running tar if curl errored.

@cablehead
Copy link

@abevoelker Thanks for the clarification. Oof, yeah, my understanding was that set -o pipefail would abort if the curl fails, before the tar runs. You're right though:

andy@hop:~/tmp$ cat 1.sh
#!/bin/bash

false | echo "foo"
echo $?

andy@hop:~/tmp$ ./1.sh 
foo
0

andy@hop:~/tmp$ cat 2.sh
#!/bin/bash

set -o pipefail

false | echo "foo"
echo $?

andy@hop:~/tmp$ ./2.sh
foo
1

@cablehead
Copy link

I definitely see @progrium's point, but in that case, once both versions are safe, the bash version wouldn't be as clearly terse.

@cablehead
Copy link

@msabramo Python's concurrency story is woeful though, and I fear that asyncio is a long winded wrong turn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment