dragam0217 2019-01-29 15:36
浏览 115
已采纳

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

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.
}

There are 4 errors in a source code above, all of which complaining that multiple elements cannot be put in a function/literal.

But having the other examples in my mind, I can't really find a reason for those errors to be considered error.

Shouldn't they be fine? What does it mean when Go gives an error like that saying "multiple-value in single-value context"?

And the way those three pernicious dots work, how does that make sense? What exactly does ... do?

  • 写回答

1条回答 默认 最新

  • duan19740319 2019-01-29 15:45
    关注

    This is why syntactic sugar is avoided by the Go designers; it leads to confusion when you expect more sugar than there is. You're seeing two types of syntactic sugar in Go here; exploding a slice to pass to a variadic function, and passing multiple return values to a function.

    Exploding a slice to a variadic function is documented here: https://golang.org/ref/spec#Passing_arguments_to_..._parameters and the key detail is:

    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 is a function with a single, variadic parameter. That means you can either pass it individual items, or a single item which is a declared slice with the ... explosion operator appended, in which case that slice will be passed unchanged. It can't be a slice literal, and it can't follow other parameters, in order to utilize this helper.

    The other is documented here: https://golang.org/ref/spec#Calls specifically:

    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.

    Again, because fmt.Println has a single, variadic parameter, you can't mix and match passing specific values with using the above syntactic sugar for passing a multi-value return straight through to the parameters of another function.

    As Peter notes, "And Q3 is a slice literal, which doesn't support variadic "parameters" at all (because the values are not parameters)." The syntactic sugar above for passing multiple returns to a function doesn't apply to a slice literal simply because it is not a function at all.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器