Go语言中,Type Alias和Type Definition有何区别?

13

类型别名:

type A = string

类型定义:

type A string

它们之间有什么区别?从规范上我看不懂。

当我使用类型A = string时,A将完全像字符串一样运作,并且可以执行与字符串类型相同的操作,而无需进行任何类型转换,例如:var p A =“sfsdf”;p +“sdfds”是否有效?并且在类型A字符串中,创建了一个新类型吗? - Vikas Yadav
3
两种形式都是类型声明,第一种形式使用"别名声明",第二种形式使用"类型定义"。 - mkopriva
https://play.golang.com/p/jDiilL424d8 - mkopriva
1
类型别名在“编程”过程中没有任何作用,它们实际上什么都不做。它们在大规模重构代码时变得有用。你会发现在线上有关于它们引入之前的激烈辩论。除非你需要它们,否则基本上永远不需要使用它们(而且你不应该使用它们!)。 - Volker
4个回答

19

type A = string创建了一个string的别名A。当你在代码中使用A时,它的作用与string相同。例如,你不能在其上定义方法。

type A string定义了一个新类型,其表示方式与string相同。你可以在Astring之间进行零成本转换(因为它们是相同的),但是你可以在新类型上定义方法,并且反射会知道类型A

例如(在playground上)

package main

import (
    "fmt"
)

type A = string
type B string

func main() {
    var a A = "hello"
    var b B = "hello"
    fmt.Printf("a is %T\nb is %T\n", a, b)
}

输出:

a is string
b is main.B

仅用于编译时的别名?@paul-hankin - Vikas Yadav
我不相信别名在运行时反射数据中有任何表示,因此它可以被视为编译时别名。这回答了你的问题吗? - Paul Hankin
@PaulHankin 实际上,您可以在类型别名上定义方法,只是在这种特定情况下无法这样做。请参阅我的答案。 - Grigoriy Mikhalkin
@PaulHankin 啊,抱歉,我读错了。像字符串一样。例如,你不能在其上定义方法--我建议为了清晰表达重写它。 - Grigoriy Mikhalkin
@GrigoriyMikhalkin 或者你可以说在类型别名上不能定义方法,但有时候你可以使用别名在原始类型上定义方法。我认为我所写的是准确的(并且对问题的背景很有帮助),但我同意它并未涵盖所有边缘情况。 - Paul Hankin
@PaulHankin,我的理解正确吗:类型定义就像分叉一样。新类型与被分叉的类型具有相同的内存布局(字段),这使得它们可以相互转换。然而,在被分叉的类型上定义的新行为(方法)在分叉上不可用,反之亦然。 - undefined

6

明确术语,这两个都是类型声明

type A = string

这被称为别名声明。也就是说,你创建了一个类型的别名。基本上,类型和别名之间没有区别。你可以在别名上定义方法,它们将对初始类型实例可用。示例
type A struct {}

type B = A

func (B) print() {
    fmt.Println("B")
}

func main() {
    a := A{}
    b := B{}

    a.print()  // OUTPUT: B
    b.print()  // OUTPUT: B
}

虽然在你的例子中type A = string,你无法定义它的方法,因为string是非本地类型(曾经有一个提案添加为非本地类型创建方法的能力,但被拒绝了)。
你的第二种情况type A string是类型定义。基本上,它创建了一个具有原始类型所有字段但没有其方法的新类型。示例
type A struct {}

func (A) print() {
    fmt.Println("A")
}

type B A

func (B) print() {
    fmt.Println("B")
}

func main() {
    a := A{}
    b := B{}

    a.print()  // OUTPUT: A
    b.print()  // OUTPUT: B
}

3

type A = string 表示创建了两者之间的别名,它们在这个阶段是不能被扩展的。这样做有什么作用呢?对于 golang 来说,它们有助于进行代码库重构和修复,这里有一篇很棒的文章:https://talks.golang.org/2016/refactor.article

类型定义允许您在需要时将某个类型扩展为具有额外行为的类型,这通常是开发人员构建自定义数据类型所需的最有用的方法。


0

类型别名

type A = string

这是 别名声明。根据定义,别名给另一个名字。因此,在 Golang 中,它用于给类型(在此处为 'string')另一个名称(在此处为 'A')。然后你可以使用新的别名定义新变量来指向这种类型。
例如:
var myString A

类型定义

type A string

这是定义一种类型。
它非常类似于定义一个变量。

var randomNumber int

在这里,'A'是一个新类型。但是您可以通过向其添加新方法来操作新定义的类型A。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接