Go从入门到精通——类型别名(Type Alias)

类型别名(Type Alias)

  类型别名是 Go 1.9 版本添加的新功能。主要用于代码升级、迁移中类型的兼容性问题。

  在 C/C++ 语言中,代码重构升级可以使用宏快速定义新的一段代码。Go 语言中没有选择加入宏,而是将解决重构中最麻烦的类型名变更问题。

 1.1、区分类型别名与类型定义

  类型别名的写法:

type TypeAlias = Type

  类型别名规定:TypeAlias 只是 Type 的别名,本质上 TypeAlias 与 Type 是同一个类型。

  类型别名与类型定义表面上看只有一个等号的差异,那么它们的实际区别呢?

package main

import "fmt"

// 将 NewInt 定义为 int 类型
type NewInt int

// 将 int 取一个别名叫 IntAlias
type IntAlias = int

func main() {

	// 将 a 声明 NewInt 类型
	var a NewInt
	// 查看 a 的类型名
	fmt.Printf("a type: %T\n", a)

	// 将 a2 声明为 IntAlias 类型
	var a2 IntAlias
	// 查看 a2 的类型名
	fmt.Printf("a2 type: %T\n", a2)
}

  代码说明如下:

 

  a 的类型是 main.NewInt,表示 main 包下定义的 NewInt 类型。

  a2 类型是 int。

  IntAlias 类型只会在代码中存在,编译完成时,不会有 IntAlias 类型。

1.2、非本地类型不能定义方法

  能够随意地为各种类型起名字,是否意味着可以在自己包里为这些类型任意添加方法?答案:不能。

  举个例子:

package main

import (
	"fmt"
	"time"
)

// 定义 time.Duration 的别名为 MyDuration
type MyDuration = time.Duration

// 为 MyDuration 添加一个方法
func (m MyDuration) EasySet(a string){
}

func main() {
}

  代码输出如下:

  编译器提示:

  不能在一个非本地的类型 time.Duration 上定义新方法。非本地方法指的就是 time.Duration 的代码所在的包,也就是 main 包。

  因为 time.Duration 是在 time 包中定义的,在 main 包中使用。time.Duration 包与 main 包不在同一个包,因此不能为不在一个包中的类型定义方法。

  解决办法:

  • 将 "type MyDuration = time.Duration" 修改为 "type MyDuration time.Duration",从别名改为类型。
  • 将 MyDuration 的别名定义放在 time 包中。

1.3、在结构体成员嵌入时使用别名

  当类型别名作为结构体嵌入的成员时会发生什么情况?

package main

import (
	"fmt"
	"reflect"
)

//定义商标结构
type Brand struct {
}

//为商标结构添加 Show() 方法
func (t Brand) Show() {
}

// 为 Brand 定义一个别名 FakeBrand
type FakeBrand = Brand

// 定义车辆结构
type Vehicle struct {

	//嵌入两个结构
	FakeBrand
	Brand
}

func main() {

	// 声明变量 a 为车辆类型
	var a Vehicle

	// 指定调用 FakeBrand 的 Show
	a.FakeBrand.Show()

	// 取 a 的类型反射对象
	ta := reflect.TypeOf(a)

	// 遍历 a 的所有成员
	for i := 0; i < ta.NumField(); i++ {
		// a 的成员信息
		f := ta.Field(i)

		// 打印成员的字段名和类型
		fmt.Printf("FieldName: %v, FieldType: %v\n", f.Name, f.Type.Name())
	}
}

  代码输出如下:

  这个例子中,FakeBrand 是 Brand 的一个别名。在 Vehicle 中嵌入 FakeBrand 和 Brand 并不意味着嵌入两个 Brand。FakeBrand 的类型会以名字的方式保留在 Vehicle 的成员中。

  注意 FakeBrand 本质是 Brand 类型。

posted @ 2022-02-09 22:11  左扬  阅读(935)  评论(0编辑  收藏  举报
levels of contents