Types 为什么[]字符串不能转换为golang中的[]接口{}

Types 为什么[]字符串不能转换为golang中的[]接口{},types,interface,go,Types,Interface,Go,我发现它很奇怪,为什么[]字符串不能转换为[]接口{} 我认为这应该是可能的,因为: 它们都是切片 []字符串的每个元素都是字符串,当然是接口{} 但在下面的示例中,这将是一个编译错误 func f(args ...interface{}){ } s := []string{"ssd", "rtt"} f(s...) 为什么语言不能自动完成转换?因为[]字符串和[]接口{}在内存中的布局不同。当您意识到接口{}变量需要知道它包含的值的类型时,这一点就很明显了 对于[]字符串切片,支持数组只需

我发现它很奇怪,为什么[]字符串不能转换为[]接口{}

我认为这应该是可能的,因为:

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

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

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

    因为
    []字符串
    []接口{}
    在内存中的布局不同。当您意识到
    接口{}
    变量需要知道它包含的值的类型时,这一点就很明显了

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


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

    片基本上只是对底层数组、起始指针、长度和容量的引用。因此,如果可能的话,请考虑以下内容:

    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这样的自动类型转换,如果您真的想将[]字符串作为[]接口{}发送,那么就必须创建[]接口{}副本。这样就不会有什么意外了——你明确地写了它,你知道你在做什么。如果函数将修改[]接口{},则不会损害原始[]字符串。

    Golang数组不支持协方差-请参阅常见问题解答中的说明。阅读golang.org上提供的文档不可过分推荐。重复