命名类型和未命名类型

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

Named and Unnamed Types

问题

问题:

我最近开始阅读Golang的规范手册,在理解相关部分中的命名和未命名类型时遇到了困难。我来自一种动态语言,这让我有点头疼。

手册中指出

> 类型确定了特定类型的值和操作的集合。类型可以是命名的或未命名的。命名类型由(可能是***限定的)类型名称***指定;未命名类型使用类型字面值指定,它由现有类型组成一个新类型。

并且继续说道

> 布尔、数值和字符串类型的命名实例是***预声明***的。可以使用类型字面值构造复合类型——数组、结构体、指针、函数、接口、切片、映射和通道类型。

问题在于,规范中的链接让我在页面之间跳来跳去,很难跟上这么多概念被快速介绍的节奏。


其他资源:

我已经搜索了一些相关的解释,除了规范手册之外,资源很少。我找到的唯一相关材料是:

不幸的是,我在Stack Overflow上没有找到任何关于这个问题的***相关问题。(如果有的话,我需要修改我的搜索方法!)我之所以提问,是因为理解一门新语言的类型系统是为了有效学习它的基本概念***之一。


所以,问题是:

有人能给出一个简明、清晰的示例,说明命名类型和未命名类型的区别吗?*

<sub>*此外,解释限定预声明的概念对于完整性来说是好的,但显然不是必需的。</sub>

英文:

The problem:

I recently started reading the Golang Specification Manual and got stuck trying to understand the named and unnamed types in the relevant section. I come from a dynamic language and this has given me a bit of a headache.

The manual states:

> A type determines the set of values and operations specific to values of that type. Types may be named or
unnamed. 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.

And continues:

> Named instances of the boolean, numeric, and string types are predeclared. Composite types—array,
struct, pointer, function, interface, slice, map, and channel types—may be constructed using type literals.

The problem here is that with the specification, the links make me jump around the pages and lose track of what is what with so many concepts thrown at me too fast.


Other Resources:

I have searched around for clarification on this and, other than the specification manual, resources are scarce. The only relevant material I could locate was:

Unfortunately, I couldn't find any relevant questions on Stack Overflow regarding this. (and if they exist, I need to revise my search methods!). I'm asking because understanding the type system of a new language is one of the basic concepts in order to efficiently learn it.


So, the question:

Can somebody present a concise, clear example illustrating the differences between the concepts of named and unnamed types?*

<sub>*Additionally, explaining the concepts of qualified and pre-declared would be good for completeness but obviously not necessary.</sub>

答案1

得分: 35

一个简单的思考方式是,命名类型是使用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则不同。

这些区别在语言的几个地方起作用:

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

     x = y    // 将命名类型赋给未命名类型
     y = x    // 将未命名类型赋给命名类型
    

    但以下赋值是错误的:

     y = z    // 在不同命名类型之间赋值
    
  2. 您可以为已命名的类型定义方法。因此,可以为Foo添加方法,但无法为变量x附加方法。

还要注意,命名类型可以在类型字面量中使用,以定义新的未命名类型。例如,切片类型[]Foo是未命名的,尽管使用了Foo。如果我们想要为该切片类型附加方法(例如与sort包一起使用),我们必须给它命名:

type Baz []Foo
英文:

A simple way of thinking about it is that named types are those you define with the type statement, and unnamed types are composite types defined by a type literal.

For example, the type of the variable x is unnamed:

var x struct{ I int }

And the type of the variable y is named:

type Foo struct{ I int }
var y Foo

Each of these variables is considered to have a distinct type, even though the underlying type of each is the same (a structure containing a single integer member named I).

One property of unnamed types is that all variables declared using the same unnamed type are considered to have the same type, while two named types with the same underlying representation are distinct. For example:

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

Here x and x2 have the same type, while y and z do not.

These distinctions come into play in a few places in the language:

  1. Assigning a value of one named type to variable of a different named type is forbidden, even if the underlying type is the same. Assignment between related named and unamed types is allowed though. That is, the following are okay:

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

    But the following is an error:

     y = z    // assignment between different named types
    
  2. You can define methods for a type you've named. So adding methods to Foo is possible but there is no way you can attach methods to the variable x.

Note also that named types can be used in type literals to define new unnamed types. For example, the slice type []Foo is unnamed despite using Foo. If we wanted to attach methods to this slice type (e.g. for use with the sort package), we'd have to name it:

type Baz []Foo

答案2

得分: 1

首先,语言规范就是它听起来的样子——一个参考文档。它是一个很好的工具,用于参考,但不适合学习语言。你最好通过Go之旅(Go Tour),一个交互式介绍语言各个方面的入门教程,或者通过《Effective Go》来学习如何使用该语言。

未命名类型是指使用类型字面量声明的没有名称的类型,换句话说,是原始类型后面跟着一个由其他类型组成的列表,这些类型放在{}中。引用规范的话,类型字面量“从现有类型组合成一个新类型”。下面是一个使用结构体的示例,但是虽然未命名结构体可能很少见,但通道和映射(再次强调,它们本身并不做太多事情,必须从其他类型中组合)很少被命名。

package main

import "fmt"

type Named struct {
    x int
    y int
}

func main() {
    a := Named{1, 2}
    fmt.Println(a)

    b := struct{ x, y int }{1, 2}
    fmt.Println(b)
}
英文:

For starters, the Language Specification is what it sounds like -- a reference document. It's a great tool to use for reference, but not for learning about the language. you're better off learning about Go through the Go Tour, an interactive introduction to various aspects of the language or through Effective Go, which details how to use the language.

An unnamed type, is just a type declared without a name by using a type literal, in other words, the primitive type followed by a list of other types that make it inside {}. Or to quote the spec again, a type literal "composes a new type from existing types" An example with structs follows, but while unnamed struct might be rare, channels and maps (which again, do little on their own must be composed from other types) are rarely named.

package main

import &quot;fmt&quot;

type Named struct {
    x int
    y int
}

func main() {
    a := Named{1, 2}
    fmt.Println(a)

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

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

发表评论

匿名网友

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

确定