英文:
Golang underlying types
问题
在这段代码片段中:
type T1 string
type T2 T1
type T3 []T1
type T4 T3
规范中说:
> 字符串、T1
和T2
的底层类型是string
。
[]T1
、T3
和T4
的底层类型是[]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
在其类型声明中引用了底层类型为 string
的 T1
。
T2
的底层类型为 string
是很重要的,因为它有助于可赋值性,其中
> 值 x
可以赋值给类型为 T
的变量("x 可以赋值给 T")
> x
的类型 V
和 T
具有相同的底层类型,并且 V
或 T
中至少有一个不是命名类型。
这也在“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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论