Why can I not use an slice of a custom type as an empty interface slice when using append in Go?

huangapple go评论67阅读模式
英文:

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{}类型。

元素类型CustomTypeinterface之间的区别在于:

  • 类型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 like value
  • type interface{} represented in memory
    • pointer to type CustomType
    • value

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.

huangapple
  • 本文由 发表于 2022年10月21日 07:03:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/74147161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定