使用“...”运算符将切片元素传递给“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 语言不会执行开销很大的隐式转换。如果你需要做,那么你必须自己明确地做。
我有 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 语言不会执行开销很大的隐式转换。如果你需要做,那么你必须自己明确地做。