使用“...”运算符将切片元素传递给“fmt.Println”是行不通的。为什么?

Passing elements of a slice to `fmt.Println` using the `...` operator to spread arguments doesn't work. Why?

我有 array/slice 个元素(在我的示例中为字节),我想使用 ftm.Println 打印这些值。我当然可以只遍历数组中的元素并以这种方式打印它们,但我认为如果我只是使用 ... 运算符传递元素,那将是 nicer/shorter。

所以我尝试了这个:

    b := []byte{1,2,3,4}
    fmt.Println(b...)

这会导致错误:

cannot use b (variable of type []byte) as type []any in argument to fmt.Println"

有人可以解释为什么这不起作用吗?

我假设 fmt.Println 是一个可变参数函数,它能够处理任意数量的任意类型的元素(错误消息中的 []any 似乎表明是这种情况)。所以当我传递 4 个字节时 Println 似乎无法处理它,这让我有点惊讶。

确实,当我们像这样传递这些相同的字节时,它工作得很好:

    fmt.Println(b[0], b[1], b[2], b[3])

那么为什么当使用 b... 时它不起作用?这本质上不是一回事吗(即在这两种情况下,我们所做的都是将 4 个字节作为单独的参数传递给 fmt.Println

可变参数作为切片传递。在以下内容中:

fmt.Println(b[0], b[1], b[2], b[3])

编译器从四个元素创建一个切片 []any,并传递该切片。

然而,

b := []byte{1,2,3,4}
fmt.Println(b...)

尝试传递与函数签名不兼容的[]byte

这虽然有效:

b := []any{1,2,3,4}
fmt.Println(b...)

[]byte 不能替代 []any,因为字节数组在结构上不同于接口数组。因此,需要进行 element-by-element 转换,这可能很昂贵。通常,Go 语言不会执行开销很大的隐式转换。如果你需要做,那么你必须自己明确地做。