为啥 []string 不能在 golang 中转换为 []interface [重复]

Posted

技术标签:

【中文标题】为啥 []string 不能在 golang 中转换为 []interface [重复]【英文标题】:why []string can not be converted to []interface in golang [duplicate]为什么 []string 不能在 golang 中转换为 []interface [重复] 【发布时间】:2014-02-15 00:04:58 【问题描述】:

我觉得很奇怪,为什么[]string不能转换为[]interface?

我认为应该可以,因为:

    都是切片 []string的每个元素都是字符串,当然是interface

但在下面的例子中,这将是一个编译错误

func f(args ...interface)


s := []string"ssd", "rtt"
f(s...)

为什么语言不能自动完成转换?

【问题讨论】:

Golang 数组不支持协方差 - 见 ***.com/questions/3839335/… , ***.com/questions/19389629/… 这在常见问题解答golang.org/doc/faq#convert_slice_of_interface 中有描述。推荐阅读 golang.org 上提供的文档。 与***.com/q/12990338/727643重复 【参考方案1】:

因为[]string[]interface 有不同的内存布局。当您意识到interface 变量需要知道它包含的值的类型时,这一点就很明显了。

对于[]string 切片,后备数组只需要保存单个字符串。对于[]interface 切片,您已经获得了类型信息和字符串值(嗯,指向字符串值的指针,因为字符串大于内存中的单个单词)。因此,从一种类型转换为另一种类型将涉及复制数据。

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

【讨论】:

【参考方案2】:

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 -> int64 这样的自动类型转换,如果您真的想将 []string 作为 []interface 发送,那么您必须创建一个 []interface 副本是有道理的。这样就不会让人感到意外了——你明确地写了它,你知道你在做什么。如果函数会修改 []interface - 它不会伤害原始 []string。

【讨论】:

以上是关于为啥 []string 不能在 golang 中转换为 []interface [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥必须在 XML 属性中转义 <?

为啥我不能从 Golang 正确读取 C 常量?

Golang string和[]byte的对比

golang string和[]byte的对比

为啥在golang中不允许对切片指针进行索引

为啥 React Native WebView 在发布版本中转到 about:blank?