Go 如何确定可以使用多个值的上下文?

How does Go determine the context in which multiple values can be used?

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个错误,都是抱怨一个function/literal不能放多个元素。

但是考虑到其他示例,我真的找不到将这些错误视为错误的原因。

他们应该没事吧?当 Go 给出类似 "multiple-value in single-value context" 的错误时,这意味着什么?

那三个有害点的工作方式,这有什么意义? ... 到底是做什么的?

这就是 Go 设计者避免使用语法糖的原因;当您期望的糖分比实际的多时,它会导致混淆。你在这里看到 Go 中的两种语法糖;展开切片以传递给可变函数,并将多个 return 值传递给函数。

将切片分解为可变参数函数记录在此处:https://golang.org/ref/spec#Passing_arguments_to_..._parameters,关键细节是:

If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

fmt.Println 是具有单个可变参数的函数。这意味着您可以将单个项目传递给它,或者 单个项目 这是一个已声明的切片,附加了 ... 爆炸运算符,在这种情况下,该切片将被原封不动地传递。不能是slice字面量,不能跟其他参数,才能使用这个helper。

另一个记录在此处:https://golang.org/ref/spec#Calls 具体来说:

As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

同样,因为 fmt.Println 有一个单一的可变参数,你不能混合和匹配传递特定值与使用上面的语法糖来传递多值 return 直接到另一个函数的参数。

正如 Peter 所说,"And Q3 is a slice literal, which doesn't support variadic "参数“完全没有(因为值不是参数)。”上面用于将多个 return 传递给函数的语法糖不适用于切片文字,因为它根本不是函数。