Как разобрать несколько возвратов в Голанге - PullRequest
0 голосов
/ 04 октября 2018

У меня есть функция Go, которая возвращает два целочисленных значения.Ниже приведена функция

func temp() (int, int){
 return 1,1
}

Можно ли поместить функцию temp непосредственно в Println и распечатать оба вывода, используя форматирование строки, как показано ниже:

fmt.Println("first= %d and second = %d", temp() ) // This doesn't work

В Python, Я могу сделать следующее:

def func():
    return 1,1
print("{0}={1}".format(*func())
>> '1=2'

Могу ли я сделать что-то подобное в Go тоже?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Я смог распечатать его, когда не использовал форматирование строки, как показано ниже

fmt.Println(temp())

Это поддерживалось только Println, но не printf

0 голосов
/ 04 октября 2018

Во-первых, для того, что вы пытаетесь сделать, вы должны использовать fmt.Printf() вместо fmt.Println(), поскольку только первое ожидает и использует строку формата.

В дальнейшем это не поддерживается по умолчанию, потому что цитирование из Spec: Вызовы:

Как особый случай, если возвращаются значения функции или метода g равны по числу и индивидуально присваиваются параметрам другой функции или метода f, тогда вызов f(g(parameters_of_g)) вызовет f после привязки возвращаемых значений g к параметрам f по порядку. Вызов f не должен содержать никаких параметров, кроме вызова g, а g должен иметь хотя бы одно возвращаемое значение. Если f имеет конечный параметр ..., онприсваиваются возвращаемые значения g, которые остаются после назначения обычных параметров.

И fmt.Printf() имеет подпись:

func Printf(format string, a ...interface{}) (n int, err error)

Вы не можете передавать другие параметры вfmt.Printf() помимо вызова функции (возвращаемые значения вызова).

Обратите внимание, что подпись fmt.Println():

func Println(a ...interface{}) (n int, err error)

Это означает, что fmt.Println(temp()) работает, иТо же самое относится и к любым другим функциям, которые имеют хотя бы одно возвращаемое значение, поскольку это позволяет последнее предложение части в кавычках ( "Если f имеет конечный параметр ..., ему присваиваются возвращаемые значения g которые остаются после назначения обычных параметров. ")

Но с небольшой хитростью мы можем достичь того, что вы хотите, с помощью fmt.Printf().

Примечаниечто если temp() вернет значение типа []interface{}, мы могли бы использовать ... чтобы передать его как значение некоторого параметра переменной.

Это означает, что работает:

func main() {
    fmt.Printf("1: %v, 2: %v\n", temp()...)
}

func temp() []interface{} { return []interface{}{1, 2} }

И он правильно печатает (попробуйте на Go Playground ):

1: 1, 2: 2

Итак, нам просто нужна служебная функция, которая упаковывает возвращаемые значения любой функции в []interface{}, и поэтому мы можем использовать ее для передачи fmt.Printf().

И это очень просто:

func wrap(vs ...interface{}) []interface{} {
    return vs
}

Как описано выше (с fmt.Println()), мы можем передать возвращаемые значения любой функции, которая имеет по крайней мере 1 возвращаемое значение, wrap() как значения еевходные параметры.

Теперь с помощью этой функции wrap() см. следующий пример:

func main() {
    fmt.Printf("1: %v\n", wrap(oneInt())...)
    fmt.Printf("1: %v, 2: %v\n", wrap(twoInts())...)
    fmt.Printf("1: %v, 2: %v, 3: %v\n", wrap(threeStrings())...)
}

func oneInt() int { return 1 }

func twoInts() (int, int) { return 1, 2 }

func threeStrings() (string, string, string) { return "1", "2", "3" }

Это работает и выводит данные (попробуйте на Go Playground ):

1: 1
1: 1, 2: 2
1: 1, 2: 2, 3: 3

Подробнее об этой теме см. Соответствующий вопрос:

Несколько значений в контексте с одним значением

Возвращает карту как 'ok' в Голанге для нормальных функций

0 голосов
/ 04 октября 2018

Нет, это невозможно.Вы должны назначить все значения из выражения с несколькими значениями отдельным переменным, чтобы использовать их, например:

a, b := temp()
fmt.Println("first = %d and second = %d", a, b)
// first = 1 and second = 1

[Изменить]

Интересно, что вВ некоторых случаях вы можете использовать многозначные выражения в качестве аргументов вызова функции, если типы аргументов и арность совпадают, или для чисто вариационных функций ( Go Playground ):

func oneTwo() (int, int) {
  return 1, 2
}

func incr2(x, y int) (int, int) {
  return x + 1, y + 1
}

func main() {
  incr2(oneTwo()) // OK: multi-value return and arguments match.

  fmt.Println(oneTwo()) // OK: pure variadic function.

  fmt.Printf("%d %d", oneTwo()) // ERR: mixed formal and variadic args.
}
...