Skip to content

Instantly share code, notes, and snippets.

@dchenk
Created August 29, 2018 05:38
Show Gist options
  • Save dchenk/b22b5925ec3a86d555208d461ed58451 to your computer and use it in GitHub Desktop.
Save dchenk/b22b5925ec3a86d555208d461ed58451 to your computer and use it in GitHub Desktop.
Default error handlers

The draft proposal for better error handling is overall well thought-out and doesn't seem like it'll decrease readability of Go code very much. Readability can be understood a couple of different ways: we might say that conciseness is inherently condusive to readability, but on the other hand we may want explicitness in our code. Thus far Go has preferred the latter form of readability.

The proposed syntax with the check keyword will make the behavior of code slighly less obvious in some places, though not by much. If we've trained ourselves to glaze over each if err != nil { return err } when trying to understand what a function is doing, then with the new syntax we'll eventually get ourselves to glaze over the check keywords at the function calls. So when we see num := check parseNum(stringVar) we'll instinctively and momentarily be forgetting that parseNum returns an error along with the value of interest.

That said, I think that the benefits of the new syntax outweigh these drawbacks. And furthermore, I'd like error handling to be just a little more consise. I suggest that in:

func printSum(a, b string) error {
	handle err { return err }
	x := check strconv.Atoi(a)
	y := check strconv.Atoi(b)
	fmt.Println("result:", x + y)
	return nil
}

the line with handle err { return err } should not be required. A default handler should simply return the error unchanged.

So, for example, the printSum function should be:

func printSum(a, b string) error {
	x := check strconv.Atoi(a)
	y := check strconv.Atoi(b)
	fmt.Println("result:", x + y)
	return nil
}

where the default handler is implicitly:

handle err {
	return err
}

As for functions that do not return an error, the default handler should be just a return statement (or a panic). So instead of this:

func printSum(a, b string) {
	x, err := strconv.Atoi(a)
	if err != nil {
		return
	}
	y, err := strconv.Atoi(b)
	if err != nil {
		return
	}
	fmt.Println("result:", x + y)
}

the equivalent code should be:

func printSum(a, b string) {
	x := check strconv.Atoi(a)
	y := check strconv.Atoi(b)
	fmt.Println("result:", x + y)
}

where the default handler is implicitly:

handle _ {
	return
}

You might be thinking this latter form simply ignores the error, and we're trying to encourage handling errors. Indeed, my proposed syntax for functions that don't return an error thus doesn't seem to help. So another option would be to make panic(err) the default handler for functions that don't return an error (or even log.Fatal(err)). In this case, the default handler for that last printSum function would be:

handle err {
	panic(err)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment