在下面的代码片段中,最后三个赋值产生编译错误:
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. [...]
结合这个,aliased assign 之所以不起作用,是因为最后三种情况的类型被命名了。这样就违反了规则:两个命名类型是赋值的一部分。
现在回答我的实际问题:
为什么不允许将别名字符串/ bool 值/数字分配给实际的字符串/ bool 值/数字,而不是像 slice 和数组这样的类型?
没有这个规则会导致什么样的问题?
将字符串指定为命名类型会导致哪些类型的问题?
提前谢谢你。
最佳答案
可分配性规则意味着您有时必须在命名类型之间进行转换以明确地说“是的,我的意思是这个 string
用作 Foo
”,即使它们共享相同的底层类型。这与 os.FileMode
之类的东西有关:它是下面的一个数字,但是类型检查可以防止您意外地将它传递给采用不相关的 foo uint32
的函数。 (可分配性规则也会影响函数调用:您可以传递可分配给参数类型的任何类型的参数。)
通常,这意味着如果您对基础类型有不同的、可能会混淆的用途,您可以为它们分配不同的名称。比如:底层类型 [][4]float32
可能有 RGBASlice
、HSVAslice
和 XYZWSlice
类型名称分配。您不能将 RGBASlice
传递给需要 XYZWSlice
的函数。但是所有这些都可以透明地传递给那些不关心数字含义的东西,就像你有一些通用的矢量数学例程一样。
因此,从广义上讲,通过强制您在命名类型之间进行转换,Go 可以帮助您区分在内存中可能具有相同表示的事物,即使它们具有不同的含义并且应该在不同的地方使用。
关于types - Go 中的别名类型仅在未命名时才可分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27630418/