Как Go определяет контекст, в котором можно использовать несколько значений? - PullRequest
0 голосов
/ 29 января 2019
package main

import "fmt"

func multipleRets() (int, int, int, int) {
    return 11, 22, 33, 44
}

func main() {
    // Q1
    fmt.Println(multipleRets())    // This is fine.
    fmt.Println(1, multipleRets()) // But this one errors.

    // Q2
    s1 := append([]int{}, []int{11, 22, 33, 44}...) // This is fine.
    s2 := append([]int{}, multipleRets())           // But this one errors.

    // Q3
    lit1 := []int{11, 22, 33, 44} // This is fine.
    lit2 := []int{multipleRets()} // But this one errors.

    // Q4
    fmt.Println(1, []int{11, 22, 33, 44})    // This is fine.
    fmt.Println(1, []int{11, 22, 33, 44}...) // But this one errors.
}

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

Но, имея в виду другие примеры, я могу 'На самом деле нельзя найти причину, по которой эти ошибки можно считать ошибкой.

Разве они не должны быть в порядке?Что это значит, когда Go выдает ошибку вроде «множественное значение в контексте с одним значением»?

И как эти три пагубные точки работают, как это имеет смысл?Что именно делает ...?

1 Ответ

0 голосов
/ 29 января 2019

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

разделение фрагмента с помощью функции с переменными параметрами задокументировано здесь: https://golang.org/ref/spec#Passing_arguments_to_..._parameters, а ключевая деталь:

Если последний аргумент присваивается типу среза [] T, он может быть передан без изменений в качестве значения параметра ... T, если за аргументом следует .... В этом случае нетновый фрагмент создан.

fmt.Println - это функция с одним переменным параметром.Это означает, что вы можете передать ему отдельные элементы или один элемент , который является объявленным срезом с добавленным оператором взрыва ..., и в этом случае этот срез будет пропущен без изменений.Он не может быть литералом среза и не может следовать другим параметрам для использования этого помощника.

Другой документ описан здесь: https://golang.org/ref/spec#Calls, в частности:

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

Опять же, поскольку fmt.Println имеет единственный переменный параметр, вы можетеНе смешивайте и не сопоставляйте передаваемые конкретные значения с использованием вышеупомянутого синтаксического сахара для передачи возвращаемого значения нескольких значений прямо в параметры другой функции.

Как отмечает Питер: «А Q3 - литерал среза, который невообще не поддерживают переменные "параметры" (потому что значения не являются параметрами). "Приведенный выше синтаксический сахар для передачи множественных возвратов в функцию не применяется к литералу слайса просто потому, что он вообще не является функцией.

...