Naked returns

August 2, 2024

Now we’re going to look at the third and finaly way to return values from a function in Go.

But first a warning.

⚠️ NEVER DO THIS!! ⚠️

What we’re about to look at is commonly referred to as “naked returns” or “bare returns”, and it is widely (though, admittedly, not universally) considered bad practice. It’s honestly a mystery to me why this feature exists in Go, and I wish it didn’t. It hurts readability, sometimes very severely. For more on why not to do this, and alternatives, checkout my video on the subject.

Return statements

  1. The expression list may be empty if the function’s result type specifies names for its result parameters. The result parameters act as ordinary local variables and the function may assign values to them as necessary. The “return” statement returns the values of these variables.
func complexF3() (re float64, im float64) {
	re = 7.0
	im = 4.0
	return
}

func (devnull) Write(p []byte) (n int, _ error) {
	n = len(p)
	return
}

So in short, when you name your return values in the function’s result list, this implicitly creates the variables for you, with their respective zero values. So far, this might be seen as a minor convenience:

func foo() (name string) {

is a bit shorter than the (mostly) equivalent:

func foo() string {
	var name string

But, this also gives you the option (though let me stress: it’s not a requirement) to then omit the names of the return values in your return statement.

func foo() (name string) {
	name = "Bob"
	return
}

This is valid Go. This is ugly Go. Don’t do this.

For a short function like this, it’s not a big deal. But when you have a longer function, and you come across some code that looks like this:

		if thingyMajigIsValid() {
			return
		}

you don’t know what you’re returning. You could be returning from a function with no return values. Or you might be naked-returning 18 different values implicitly. The only way to be sure is to scroll up to the top of the function, to see how it’s defined.

And even that can be deceptive, if you’re inside of a closure:

func foo() { // No return values!
	x, y, z := func() (I, fooled, you string) {
		I = "this is an interesting string"
		fooled = "this one isn't so interesting"
		you = "mildly interesting. Maybe."
		if thingyMajigIsValid() {
			return
		}
		return "", "", ""
	}()
	fmt.Println(x, y, z)
}

Fortunately, even when using named return values (which have uses beyond naked returns), you can still name all your return values:

		if thingyMajigIsValid() {
			return I, fooled, you
		}

So if you want my advice, never use naked returns, even when it’s an option for you. Always name your return values, to make reading your code easier.

Quotes from The Go Programming Language Specification Language version go1.22 (Feb 6, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Return statements, conclusion

Just a couple small notes before we move on from return statements… Return statements … Regardless of how they are declared, all the result values are initialized to the zero values for their type upon entry to the function. A “return” statement that specifies results sets the result parameters before any deferred functions are executed. For the most part, this can be considered trivia, for Quiz night at your next Go meetup.


Returning from a function without a return value

Let’s continue our discussion of return statements by looking at functions that don’t actually return anything… Return statements … In a function without a result type, a “return” statement must not specify any result values. func noResult() { return } Simple enough. Within functions without return values, return must not include any result values. But that doesn’t actually mean the example code you see is good code. In the noResult function, the return statement is actually completely redundant, because the function simply ends on the next line.


Modifying return values in deferred functions

Oops! It seems that Friday’s email got stuck, and didn’t actually send until late Monday. Meaning you probably got two emails in the same day, and out of order. I hope it didn’t bother anyone too much. I should probably make a joke about how it was deferred… Nah! Today we’ll be finishing up the section on the defer keyword, with one special capability that it affords us. Defer statements …

Get daily content like this in your inbox!

Subscribe