How to use 'try'

Last updated 93 days ago by fai face

golang

The recent <code>try</code> proposal by Robert Griesemer sparked a lot of controversy. While the proposal is a subject to reasonable criticism, I didn’t feel like everyone was always on the same page.

This post isn’t pro-try or anti-try. It just shows how try could be used so that you can form a more informed opinion.

Suppose we are grad students of social sciences and need to come up with idea for a poll. Since we are programmers, too, we’ve come up with this poll: find correlations between person’s gender, favorite OS, and favorite programming language.

This is, of course, a contrived example. The goal of this post isn’t to solve a real-world scenario, but to show multiple aspects of try in a small program.

The data from the poll will look like this:

```language-go name: Boris Bateman gender: man os: Windows lang: PHP

name: Darin May gender: woman os: OSX lang: JavaScript

name: Shea Wilks gender: nonbinary os: Linux lang: Emacs LISP

name: Robert Griesemer gender: man os: Linux lang: Go ```

Each respondent has four required fields: name, gender, os, and lang. There is an obligatory empty line between respondents.

We want to parse this file into a slice of Respondent structs, defined like this:

language-go type Respondent struct { Name string Gender string OS string Lang string }

Let’s get on to it, step by step!

language-go func parseRespondents(path string) (resps []Respondent, err error) { return nil, nil }

I know, I could have used an io.Reader. But, for the purposes of demonstrating try, let’s keep it this way.

First, we’re gonna use a (not yet existing) function fmt.HandleErrorf:

language-go func parseRespondents(path string) (resps []Respondent, err error) { defer fmt.HandleErrorf(&err, "parse %s", path) return nil, nil }

It adds context to the returned error, if it’s not nil. It’s defined like this:

language-go func HandleErrorf(err *error, format string, args ...interface{}) { if *err != nil { *err = errors.Wrapf(*err, format, args...) } }

Every error returned from parseRespondents("respondents.txt") will now be prefixed with parse respondents.txt:.

```language-go func parseRespondents(path string) (resps []Respondent, err error) { defer fmt.HandleErrorf(&err, "parse %s", path)

f := try(os.Open(path))
defer f.Close()

return nil, nil

} ```

Normally, os.Open(path) returns two values: the file and an error. By wrapping it in try, we drop the error from the return values and get an automatic return if the error wasn’t nil.

What kind of error do we get now if the file doesn’t exist?

Read full Article