Skip to content

Instantly share code, notes, and snippets.

@alexhornbake
Last active August 24, 2023 17:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexhornbake/6a4c1c6a0f2a063da6dda1bf6ec0f5f3 to your computer and use it in GitHub Desktop.
Save alexhornbake/6a4c1c6a0f2a063da6dda1bf6ec0f5f3 to your computer and use it in GitHub Desktop.
Golang 2 proposal. Refuse. A conditional return keyword.

refuse - a mini-proposal for conditional returns. This is an alternative proposal for try, check, check/handle.

So we want to simplify things like:

1: err, thing := newThing(name)
2: if err != nil {
3: 	return nil, err
4: }

Which says:

  • Line 1: call the function, and assign the return values of the function to local varaibles
  • Line 2-4: check if an error occured, and if so, return the error

line 1 is already concise, readable and expresses 2 ideas (function call and assignment). line 2-4 is arguably the same complexity as line 1.

Rather than try to express 4 ideas in 1 line. I would propose that we take a smaller baby step, and make lines 2-4 easy to express in 1 line.

To "refuse a package" (in the the real world) is to return it because it was sent in error. (Not a perfect analogy, but decent).

refuse would be the keyword for conditional return if the last value was non-nil (same signature as try, but no assignment of variables).

Examples:

net/http

net/http/request.go:readRequest

        mimeHeader, err := tp.ReadMIMEHeader()
        if err != nil {
                return nil, err
        }
        req.Header = Header(mimeHeader)
becomes:

       	mimeHeader, err := tp.ReadMIMEHeader()
       	refuse nil, err
        req.Header = Header(mimeHeader)

Because refuse does not handle assignment the error can still be wrapped. Note: This relies on errors.Wrapf returning nil for nil errors.

this:
	thing, err := newThing(name)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to make thing named: %s", name)
	}

becomes:
	thing, err := newThing(name)
	refuse nil, errors.Wrapf(err, "failed to make thing named: %s", name)

About the name...

It also works out nicely visually that it starts with an r, is also 6 characters long, so spotting exit points is seems like it would be still be easy.

Open to suggestions... It's not easy to express two ideas in 1 word. Alternatives considered

  • retroh, rutroh - the scooby doo version. Cute... but not really a universal reference...
  • reterr - made up words might be better than overloading existing words?
  • rilann - "return if last arg not nil" - does anyone wants to type that?
  • bail, bailout - lacking sense of "condition"?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment