英文:
Why can I not use an slice of a custom type as an empty interface slice when using append in Go?
问题
我对尝试将自定义类型的切片(即[]interface{}
)追加到空接口切片时使用的解包/扩展运算符的行为有些困惑。我原以为它可以工作,因为interface{}
可以容纳任何类型,但是当我尝试执行此操作时,我收到了错误信息。
下面的代码片段说明了这个问题:
package main
import (
"fmt"
)
type CustomType struct {
value int
}
func main() {
data := []interface{}{}
values := []CustomType{
{value: 0},
{value: 1},
}
// 这段代码无法编译通过:
// data = append(data, values...)
// 但是这段代码可以正常工作
data = append(data, values[0])
for _, value := range data {
fmt.Printf("Value: %v\n", value)
}
}
我原本期望能够解包values
切片并将其元素追加到data
切片中,因为data
可以容纳任何值,但是编译器不允许这样做,并抱怨values
数组不是[]interface{}
类型。当我逐个追加值时,编译器对此操作是可以接受的。
为什么在这种情况下不允许解包values
切片呢?
英文:
I'm slightly confused about the behavior of the unpack/spread operator when trying to append into a slice of empty interfaces (i.e. []interface{}
) from an slice of a custom type. I expected it to work since the interface{}
can hold any type, but I'm currently receiving errors when trying to do this operation.
The following snippet illustrates the issue:
package main
import (
"fmt"
)
type CustomType struct {
value int
}
func main() {
data := []interface{}{}
values := []CustomType{
{value: 0},
{value: 1},
}
// This does not compile:
// data = append(data, values...)
// But this works fine
data = append(data, values[0])
for _, value := range data {
fmt.Printf("Value: %v\n", value)
}
}
Go playground with the snippet above
I expected to be able to unpack the values
slice and append its elements into the data
slice since it can hold any values, but the compiler does not like that and complains about the values
array not being of []interface{}
type. When I append the values one by one, then compiler is OK with the operation.
Why is unpacking the values slice not allowed in this situation?
答案1
得分: 2
显然,代码data = append(data, values...)
可能会出现编译错误cannot use values (variable of type []CustomType) as type []interface{} in argument to append
。
根据常见问题 Can I convert a []T to an []interface{}?的说明:
直接转换是不允许的,因为这两种类型在内存中的表示不同。需要逐个复制元素到目标切片。下面的示例将一个int切片转换为interface{}切片:
t := []int{1, 2, 3, 4} s := make([]interface{}, len(t)) for i, v := range t { s[i] = v }
对于你的问题:
我希望能够解包values切片并将其元素追加到data切片中,因为它可以容纳任何值,但是编译器不喜欢这样,并且抱怨values数组不是[]interface{}类型。
元素类型CustomType
和interface
之间的区别在于:
- 类型
CustomType
在内存中的表示方式类似于value
- 类型
interface{}
在内存中的表示方式为- 指向类型
CustomType
的指针 - 值
- 指向类型
它们在内存中有不同的表示方式。
此外,将[]CustomType
转换为[]interface{}
的时间复杂度为O(n)
,因为必须将切片的每个值转换为interface{}
。这可能是一个复杂的操作。
英文:
Obviously, the code data = append(data, values...)
could be compiled error cannot use values (variable of type []CustomType) as type []interface{} in argument to append
Per faq Can I convert a []T to an []interface{}?
> Not directly. It is disallowed by the language specification because the two types do not have the same representation in memory. It is necessary to copy the elements individually to the destination slice. This example converts a slice of int to a slice of interface{}:
> go
> t := []int{1, 2, 3, 4}
> s := make([]interface{}, len(t))
> for i, v := range t {
> s[i] = v
> }
>
For your question
> I expected to be able to unpack the values slice and append its elements into the data slice since it can hold any values, but the compiler does not like that and complains about the values array not being of []interface{} type.
The difference between the element type CustomType
and interface
- type
CustomType
represented in memory likevalue
- type
interface{}
represented in memory- pointer to type
CustomType
- value
- pointer to type
They have different representations in memory.
Besides that, converting a []CustomType
to an []interface{}
is O(n)
time because each value of the slice must be converted to an interface{}
. It could be one complex operation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论