Skip to content

Instantly share code, notes, and snippets.

@progrium
Created Feb 17, 2015
Embed
What would you like to do?
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
}
}
}
@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

cablehead commented Feb 18, 2015

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

@msabramo
Copy link

msabramo commented Feb 18, 2015

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

abevoelker commented Feb 18, 2015

@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

cablehead commented Feb 18, 2015

@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

cablehead commented Feb 18, 2015

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

cablehead commented Feb 18, 2015

@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