types - Go 中的别名类型仅在未命名时才可分配?

标签 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
    )
}

这意味着,在这个例子中,只有 bool 值、字符串和 float 是不可赋值的。 原因可以在规范中找到:

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:

  • [...]
  • x's type V and T have identical underlying types and at least one of V or T is not a named type.
  • [...]

( Go Specification: Assignability )

[...] Named types are specified by a (possibly qualified) type name; unnamed types are specified using a type literal, which composes a new type from existing types. [...]

( Go Specification: Types )

结合这个,aliased assign 之所以不起作用,是因为最后三种情况的类型被命名了。这样就违反了规则:两个命名类型是赋值的一部分。

现在回答我的实际问题:

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

没有这个规则会导致什么样的问题?

将字符串指定为命名类型会导致哪些类型的问题?

提前谢谢你。

最佳答案

可分配性规则意味着您有时必须在命名类型之间进行转换以明确地说“是的,我的意思是这个 string 用作 Foo”,即使它们共享相同的底层类型。这与 os.FileMode 之类的东西有关:它是下面的一个数字,但是类型检查可以防止您意外地将它传递给采用不相关的 foo uint32 的函数。 (可分配性规则也会影响函数调用:您可以传递可分配给参数类型的任何类型的参数。)

通常,这意味着如果您对基础类型有不同的、可能会混淆的用途,您可以为它们分配不同的名称。比如:底层类型 [][4]float32 可能有 RGBASliceHSVAsliceXYZWSlice 类型名称分配。您不能将 RGBASlice 传递给需要 XYZWSlice 的函数。但是所有这些都可以透明地传递给那些不关心数字含义的东西,就像你有一些通用的矢量数学例程一样。

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

关于types - Go 中的别名类型仅在未命名时才可分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27630418/

相关文章:

go - 如何使用 `go-elasticsearch` 库在 Elasticsearch 中创建索引?

javascript - window.location.assign() 导航到用户输入的 url?

在不执行程序的情况下计算任意类型的大小

c++ - 如何比较 C++ 中 lambda 函数的返回类型?

go - 通过将空结构传递到 channel Go 来停止循环

JavaScript:将函数方法存储到变量

r - 如何在循环中更改数据框中的列名?

mysql - sql.DB.Exec 时对 SQL 中的自定义类型感到困惑

c++ - 字段的类型不完整 : int*[]

go - 如何遍历文件但跳过一个特定的文件名