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
}
}
}
@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