为什么[]字符串无法在golang中转换为[] interface {}

时间:2014-01-24 05:32:00

标签: types interface go

我发现它很奇怪,为什么[]字符串无法转换为[] interface {}?

我认为应该可以,因为:

  1. 他们都是切片
  2. []字符串的每个元素都是字符串,当然是接口{}
  3. 但在下面的示例中,它将是编译错误

    func f(args ...interface{}){
    
    }
    s := []string{"ssd", "rtt"}
    f(s...)
    

    为什么语言无法自动完成转换?

2 个答案:

答案 0 :(得分:6)

因为[]string[]interface{}具有不同的内存布局。当您意识到interface{}变量需要知道它包含的值的类型时,这是显而易见的。

对于[]string切片,支持数组只需要保存单个字符串。对于[]interface{}切片,您既有类型信息又有字符串值(嗯,指向字符串值的指针,因为字符串大于单个内存字)。因此,从一种类型转换为另一种类型将涉及复制数据。

Go会自动执行转换会让人感到困惑,因为这会让代码难以推理。例如,函数调用f(s)可以修改切片s中的字符串,如果它被声明为采用[]string参数,但是如果它被声明为采用[]interface{}则不会}参数。

答案 1 :(得分:6)

Slice基本上只是对底层数组,启动指针,长度和容量的引用。如果有可能,请考虑以下内容:

sliceOfStrings := []string{"one", "two", "three"}
// prints ONE TWO THREE
for i := range sliceOfStrings {
    fmt.Println(strings.ToUpper(sliceOfStrings[i]))
}

// imagine this is possible
var sliceOfInterface = []interface{}(sliceOfStrings)
// since it's array of interface{} now - we can do anything
// let's put integer into the first position
sliceOfInterface[0] = 1
// sliceOfStrings still points to the same array, and now "one" is replaced by 1
fmt.Println(strings.ToUpper(sliceOfStrings[0])) // BANG!

Java和C#中存在此问题。在实践中,它很少发生,但仍然存在。鉴于Go中没有自动类型转换,如int32 - >如果你真的想将[]字符串发送为[] interface {},那么你有必要创建一个[] interface {}副本。这样就不足为奇了 - 你明确地写了它,你知道你在做什么。如果函数将修改[] interface {} - 它不会伤害原始的[]字符串。