Golang底层类型

huangapple go评论82阅读模式
英文:

Golang underlying types

问题

在这段代码片段中:

type T1 string
type T2 T1
type T3 []T1
type T4 T3

规范中说:

> 字符串、T1T2的底层类型是string
[]T1T3T4的底层类型是[]T1

为什么T2的底层类型不是T1,而是string呢?
如果T1的底层类型是string,那么T4的底层类型不应该是[]string而不是[]T1吗?
有点困惑。

英文:

In this code snippet from the spec

type T1 string
type T2 T1
type T3 []T1
type T4 T3

The spec says:

> The underlying type of string, T1, and T2 is string.
The underlying type of []T1, T3, and T4 is []T1.

Why is the underlying type of T2 not T1, but string?
Shouldn't the underlying type of T4 instead be []string and not []T1 if the underlying type of T1 is string?
Confused.

答案1

得分: 5

规范中提到:

> 每种类型 T 都有一个底层类型:如果 T 是预声明的布尔、数值或字符串类型,或者是一个类型字面量,则相应的底层类型就是 T 本身。
否则,T 的底层类型是其类型声明中 T 引用的类型的底层类型

T2 在其类型声明中引用了底层类型为 stringT1

T2 的底层类型为 string 是很重要的,因为它有助于可赋值性,其中

> 值 x 可以赋值给类型为 T 的变量("x 可以赋值给 T")
> x 的类型 VT 具有相同的底层类型,并且 VT 中至少有一个不是命名类型

这也在“Golang: Why can I type alias functions and use them without casting?”中有详细说明。


当涉及到 T4 的底层类型时,我们谈论的是一个未命名的底层类型 []T1

而且,可赋值性规则再次说明,你可以将 []T1 赋值给 T4(因为 []T1 不是一个命名类型):它的底层类型在第一个非命名类型([]T1)处停止。

playground上的这个例子中可以看到:

var t3 T3 = []T1{"a", "b"}
fmt.Println("t3='%+v'", t3)
// var t4 T4 = []string{}
// cannot use []string literal (type []string) as type T4 in assignment
var t4 T4 = T4(t3)
fmt.Println("t4='%+v'", t4)
t4 = []T1{T1("c"), T1("d")}
fmt.Println("t4='%+v'", t4)

输出:

t3='%+v' [a b]
t4='%+v' [a b]
t4='%+v' [c d]

Danny Rivers 在评论中补充道:

> 为什么 T4 的底层类型等于 []T1,而不是 []string
>
> T4 的底层类型被定义为 T3 的底层类型,而 T3 的底层类型是底层类型为 []T1 的类型字面量,由于 []T1 是一个类型字面量,这就是底层类型的最底层。
规范中的语言很容易让人忽略,即类型字面量不仅仅是预声明类型,也算作底层类型。

英文:

The spec mentions:

> Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself.
Otherwise, T's underlying type is the underlying type of the type to which T refers in its type declaration.

T2 refers in its type declaration to T1, which has the underlying type string.

It is important for the underlying type of T2 to be string, because it will help for Assignability where

> A value x is assignable to a variable of type T ("x is assignable to T")
> x's type V and T have identical underlying types and at least one of V or T is not a named type.

This is also detailed in "Golang: Why can I type alias functions and use them without casting?"


When it comes to the underlying type of T4, we are talking about an underlying unnamed type []T1.

And again, the assignability rule says you can assign []T1 to T4 (since []T1 is not a named type): its underlying type stops at the first not-named type ([]T1).

See this example on playground

var t3 T3 = []T1{"a", "b"}
fmt.Println("t3='%+v'", t3)
// var t4 T4 = []string{}
// cannot use []string literal (type []string) as type T4 in assignment
var t4 T4 = T4(t3)
fmt.Println("t4='%+v'", t4)
t4 = []T1{T1("c"), T1("d")}
fmt.Println("t4='%+v'", t4)

Output:

t3='%+v' [a b]
t4='%+v' [a b]
t4='%+v' [c d]

Danny Rivers adds in the comments:

> Why is the underlying type of T4 equal to []T1, not []string?
>
> The underlying type of T4 is defined to be the underlying of T3, which is underlying ([]T1), and since []T1 is a type literal, that is as far down as it goes.
The language of the spec makes it easy to miss that TYPE LITERALS, not just pre-declared types, count as an underlying type.

huangapple
  • 本文由 发表于 2015年3月30日 02:11:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/29332879.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定