Именованные возвращаемые значения и naked return

В golang есть naked return и именованные возвращаемые значения. Зачем их придумали?

func c() (i int) {
    return
}

Ответы (2 шт):

Автор решения: hedgehogues

Предположим, у меня функция на экран или больше. Тогда оказывается неудобным читать её без наличия возвращаемых переменных.

func c() (i int) {
    return
}

Если в коде функции возвращаемая переменная могла меняться, тогда становится некомфортно читать код. Следить за этим всем сложно.

Я её всегда старательно избегаю. Но часто вижу, как другие разработчики её используют. Несколько раз мне говорили, что используют эту конструкцию для сокращения кода. Только такой аргумент выглядит не очень разумным. Да и кода сокращается немного, а читаемость (опять же на мой взгляд) сильно падает.

При этом, следует отметить, что подход с именованными переменными хорош, так как позволяет указать, что за переменная возвращается. Подходу naked return он не противоречит:

func c() (i int) {
    return i
}

Данный подход может использоваться для [go code review comments][1].

В некоторых случаях без named error не обойтись, но по-прежнему не ясно назначение naked return:

func noMorePanics() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = r.(error)
        }
    }()

    potentiallyPanickingFunction()
}

Но с использованием именованных возвращаемых значений следует быть крайне аккуратным, так как могут быть сайд-эффекты, которые сильно затрудняют чтение кода:

package main

import "fmt"

func main() {
    f := fmt.Println
    f(a())
    f(b())
}

func a() int {
    i := 0
    defer func() {
        i += 1
        fmt.Println("a defer : ", i)
    }()

    return i
}

func b() (i int) {
    i = 0

    defer func() {
        i += 1
        fmt.Println("b defer : ", i)
    }()
    return i
}

Обращайте внимание на использование замыканий. Это может быть коварно. Во втором случае вернётся 1. А в первом 0. Это связано областью видимости и не интуитивно. i определяется внутри или снаружи функции. Но как мы видели выше, может быть полезно в специальных случаях. И быть выстрелом в ногу -- в других.

→ Ссылка
Автор решения: Pak Uula

Я бы разделял именованные возвращаемые значения и return без значений.

Первая фича очень полезна, когда возвращаются больше одного значения. Имена служат документацией, особенно если несколько возвращаемых значений одного типа:

func Divmod64(numerator, denominator int64) (quotient, remainder int64) { ... }

Сразу понятно, где тут частное, а где остаток.

Named values return - это логическое продолжение идеи переменных для возвращаемых значений. Если мы их уже объявили в сингнатуре функции и присвоили в теле функции, то зачем повторно указывать в return-е?

Несмотря на то, что такой return позволяет сэкономить несколько символов при печати на клавиатуре, я предпочитаю всегда указывать, что именно я возвращаю. Однажды я потратил полдня на поиск ошибки, вызванной таким неявным возвратом значений. Больше не хочу. Целее буду :)

→ Ссылка