Возврат карты как "хорошо" в Голанге на нормальных функциях

В Go следующие работы (обратите внимание, что одно использование карты имеет одно возвращение, другое имеет два возврата)

package main

import "fmt"

var someMap = map[string]string { "some key": "hello" }

func main() {
    if value, ok := someMap["some key"]; ok {
        fmt.Println(value)
    }

    value := someMap["some key"]
    fmt.Println(value)
}

Тем не менее, я понятия не имею, как сделать то же самое с моей собственной функцией. Возможно ли иметь подобное поведение с дополнительным возвратом, например map?

Например:

package main

import "fmt"

func Hello() (string, bool) {
    return "hello", true
}

func main() {
    if value, ok := Hello(); ok {
        fmt.Println(value)
    }

    value := Hello()
    fmt.Println(value)
}

Не компилируется (из-за ошибки multiple-value Hello() in single-value context)... есть ли способ заставить этот синтаксис работать для функции Hello()?

1 ответ

Решение

map отличается, потому что это встроенный тип, а не функция. 2 формы доступа к элементу map определяется спецификацией языка Go: индексные выражения.

С функциями вы не можете сделать это. Если функция имеет 2 возвращаемых значения, вы должны "ожидать" их обоих или вообще не ожидать.

Однако вы можете назначить любое из возвращаемых значений идентификатору пробела:

s, b := Hello()    // Storing both of the return values

s2, _ := Hello()   // Storing only the first

_, b3 := Hello()   // Storing only the second

Вы также можете не хранить никаких возвращаемых значений:

Hello()            // Just executing it, but storing none of the return values

Примечание: вы также можете назначить оба возвращаемых значения пустому идентификатору, хотя он бесполезен (кроме проверки того, что он имеет ровно 2 возвращаемых значения):

_, _ = Hello()     // Storing none of the return values; note the = instead of :=

Вы также можете попробовать их на игровой площадке Go.

Вспомогательная функция

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

func Hello2() string {
    s, _ := Hello()
    return s
}

И теперь вы можете сделать:

value := Hello2()
fmt.Println(value)

В дополнение к объяснению @icza:

  • Я не рекомендую использовать вспомогательную функцию там. Особенно если Hello функция ваша собственная функция.
  • Однако, если вы не можете это контролировать, тогда можно использовать помощника.
  • Если это ваша собственная функция, лучше изменить сигнатуру вашей функции. Возможно, вы где-то допустили ошибку проектирования.

Вы также можете сделать это:

package main

import "fmt"

func Hello() (string, bool) {
    return "hello", true
}

func main() {
    // Just move it one line above: don't use a short-if
    value, ok := Hello()
    if ok {
        fmt.Println(value)
    }
}
Другие вопросы по тегам