Go中的别名类型只有在未命名的情况下才可分配?

时间:2014-12-24 01:44:13

标签: types go assign

在以下代码段中,最后三个分配产生编译错误:

package main

type (
    Foo []float64
    Baz [2]float64
    Meh map[string]string
    Faq chan int
    Tet func()
    Hue interface{}
    Tai bool
    Foz string
    Bar float64
)

func main() {
    var ( 
        foo Foo = []float64{1, 2, 3}
        _ []float64 = foo

        baz Baz = [...]float64{1, 2}
        _ [2]float64 = baz

        meh Meh = make(map[string]string)
        _ map[string]string = meh

        faq Faq = make(chan int)
        _ chan int = faq

        tet Tet = func() { return }
        _ func() = tet

        hue Hue = "Hello, World"
        _ interface{} = hue

        tai Tai = true
        _ bool = tai // error

        foz Foz = "Hello, World"
        _ string = foz // error

        bar Bar = 1
        _ float64 = bar // error
    )
}

这意味着,在此示例中,只有bools,字符串和浮点数不可分配。 原因可以在规范中找到:

  

值x可赋值给T类型的变量(“x可赋值给   T“)在任何这些情况下:

     
      
  • [...]
  •   
  • x的类型V和T具有相同的基础类型,并且V或T中的至少一个不是命名类型。
  •   
  • [...]
  •   

Go Specification: Assignability

  

[...]命名类型由(可能是合格的)类型名称指定;使用类型文字指定未命名的类型,类型文字从现有类型组成新类型。 [...]

Go Specification: Types

结合这个,别名分配不起作用的原因是因为最后三个案例的类型被命名。通过此规则违反了规则:两个命名类型是分配的一部分。

现在我的实际问题:

为什么不允许将别名字符串/ bool / numeric分配给实际的字符串/ bool / numeric,而不是像片和数组这样的类型?

这条规则缺乏会导致什么样的问题?

作为命名类型的字符串规范会导致什么类型的问题?

提前谢谢。

1 个答案:

答案 0 :(得分:0)

可分配性规则意味着您有时必须在命名类型之间进行转换以明确说出"是的,我的意思是此string用作Foo,"即使他们共享相同的基础类型。这与os.FileMode之类的内容相关:它是下面的数字,但类型检查会让您不小心将其传递给带有不相关foo uint32的函数。 (可分配性规则也会影响函数调用:您可以传递可分配给参数类型的任何类型的参数。)

通常,这意味着如果您对基础类型有明确的,可能混淆的用法,则可以为它们指定不同的名称。例如:基础类型[][4]float32可能合理地分配了RGBASliceHSVASliceXYZWSlice类型名称。您无法将RGBASlice传递给期望XYZWSlice的函数。但是所有这些都可以透明地传递给那些不关心数字意义的事情,比如你有一些通用的矢量数学例程。

因此,广泛地说,通过强制您在命名类型之间进行转换,Go可以帮助您区分可能在内存中具有相同表示形式的内容,即使它们具有不同的含义并且应该在不同的位置使用。