命名和未命名类型

Posted

技术标签:

【中文标题】命名和未命名类型【英文标题】:Named and Unnamed Types 【发布时间】:2016-01-04 04:08:12 【问题描述】:

问题:

我最近开始阅读 Golang Specification Manual 并在试图理解 relevant section 中的命名和未命名类型时陷入困境。我来自动态语言,这让我有点头疼。

手册说明

类型确定特定于该类型值的一组值和操作。类型可以被命名未命名。命名类型由(可能是 qualifiedtype name 指定;指定了未命名的类型 使用类型文字,它从现有类型组成新类型。

然后继续

布尔、数字和字符串类型的命名实例是 predeclared。复合类型——数组, 结构、指针、函数、接口、切片、映射和通道类型——可以使用类型文字来构造。

这里的问题是,在规范中,链接让我在页面之间跳来跳去,忘记了这么多概念向我抛出的太快是什么。


其他资源:

我已经四处寻找澄清这一点,除了规范手册,资源稀缺。我能找到的唯一相关材料是:

Learning Go - Types - 博客文章解释 Go 中类型系统的细微差别。

An issue here 关于和我问的差不多

不幸的是,我在 Stack Overflow 上找不到任何关于此的 relevant questions。 (如果它们存在,我需要修改我的搜索方法!)。我之所以这么问,是因为理解一门新语言的类型系统是基本概念之一,以便有效地学习它。


那么,问题来了:

谁能提供一个简洁明了的例子来说明命名类型和未命名类型的概念之间的区别?*

*此外,解释 qualifiedpre-declared 的概念有助于完整性,但显然没有必要。

【问题讨论】:

我不明白不清楚你在问什么近距离投票,因为我强调我正在寻找的是 一个简洁明了的示例,说明了命名类型和未命名类型的概念之间的区别 【参考方案1】:

一种简单的思考方式是,命名类型是您使用type 语句定义的类型,而未命名类型是由类型文字定义的复合类型。

例如变量x的类型是未命名的:

var x struct I int 

并且变量y的类型命名为:

type Foo struct I int 
var y Foo

这些变量中的每一个都被认为具有不同的类型,即使每个变量的基础类型相同(一个包含一个名为 I 的整数成员的结构)。

未命名类型的一个特性是使用相同未命名类型声明的所有变量都被认为具有相同的类型,而具有相同底层表示的两个命名类型是不同的。例如:

var x2 struct I int 
type Bar struct I int 
var z Bar

这里xx2 具有相同的类型,而yz 没有。

这些区别在语言中的一些地方发挥作用:

    禁止将一个命名类型的值分配给不同命名类型的变量,即使底层类型相同。但是,允许在相关的命名类型和未命名类型之间进行分配。也就是说,以下是可以的:

    x = y    // named type assigned to unnamed type
    y = x    // unnamed type assigned to named type
    

    但以下是错误:

    y = z    // assignment between different named types
    

    您可以为已命名的类型定义方法。因此,可以将方法添加到 Foo,但您无法将方法附加到变量 x

还请注意,命名类型可以在类型文字中用于定义新的未命名类型。例如,切片类型[]Foo 未命名,尽管使用了Foo。如果我们想将方法附加到这种切片类型(例如,与 sort 包一起使用),我们必须命名它:

type Baz []Foo

【讨论】:

转到关于 []Foo 和未命名类型组合成命名类型的要点。有趣的是,查看规范,有一些类型文字通常未命名(数组、切片、映射、通道、指针)和一些通常命名的类型文字(结构、函数和接口)。需要注意的是空结构和接口很常见,并且根据代码风格,未命名的函数也可能会出现。 感谢詹姆斯的精彩回答。 x = y; y=x; 不允许 golang.org/ref/spec#Type_identity @overexchange:规范中的第二个可分配性规则似乎允许这样做,编译器不会抱怨:play.golang.org/p/IzCCgBOvW6f【参考方案2】:

对于初学者来说,语言规范听起来就像是一个参考文档。这是一个很好的参考工具,但不能用于学习语言。你最好学习通过Go Tour,一个对语言各个方面的交互式介绍或通过Effective Go,它详细介绍了如何使用该语言。

未命名类型只是使用 类型文字 声明的没有名称的类型,换句话说,原始类型后跟在 中的其他类型列表。或者再次引用规范,一个类型文字“从现有类型组成一个新类型”一个带有结构的example,但是虽然未命名的结构可能很少见,但通道和映射(同样,它们自己做的很少必须是 composed 来自其他类型)很少被命名。

package main

import "fmt"

type Named struct 
    x int
    y int


func main() 
    a := Named1, 2
    fmt.Println(a)

    b := struct x, y int 1, 2
    fmt.Println(b)

【讨论】:

语言规范是学习语言的好方法。我已经读过很多遍了。可能与其他语言(例如 Java)不同,但 Go 的规范很好。但是,如果您已经稍微了解该语言并且已经了解其他语言,则更容易理解它。 Effective Go 不是学习语言的第一来源,它是为了更深入地理解它(因为它假设你已经知道 Go 并且没有提到很多重要的细节)。引自 Effective Go:“它扩充了语言规范、Go 之旅和如何编写 Go 代码,所有这些都是你应该首先阅读的。”

以上是关于命名和未命名类型的主要内容,如果未能解决你的问题,请参考以下文章

命名类型和未命名类型和基础类型

混合命名和未命名函数参数

命名和未命名匿名 Javascript 函数之间的区别

Java:将命名和未命名参数的组合传递给可执行的 jar/main 方法

读取 XML 和未声明的命名空间

[Journey with golang] 3. Type system