自定义类型和类型别名

2026年9月6日

type 可以干两件事:做出一种新类型,或给已有类型起别名。结构体是自定义类型的一种;给状态码、ID 这类值单独起类型,调用处就不容易传错。


自定义类型

type Code int

const (
	CodeOK   Code = 0
	CodeFail Code = 1
)

func write(c Code) {
	fmt.Println(c)
}

write(CodeOK)
// write(0) // 编译错误:int 不是 Code
go

Codeint 底层一样,但在类型系统里是两种类型,互相要用必须显式转换:Code(0)int(c)

可以给它绑方法:

func (c Code) Text() string {
	if c == CodeOK {
		return "ok"
	}
	return "fail"
}
go

结构体、函数类型、切片都可以这样定义。响应码、用户 ID、带单位的数字,用自定义类型比满地 int 清楚。


类型别名

等号是别名,不是新类型:

type Code = int
go

和自定义类型差在三点:

  • 不能单独绑方法(方法算在原来的 int 上,你再绑会冲突或根本加不到「新类型」上)
  • %T 打出来还是原来的类型,比如 int
  • 和原类型比较、赋值不用转换
type Code = int

var c Code = 1
var n int = c // 可以直接赋
fmt.Printf("%T\n", c) // int
go

标准库里的例子:byteuint8 的别名,runeint32 的别名。type byte = uint8

需要「换个名字、还当原来那个用」时用别名;需要「看起来像 int、但不能随便拿 int 冒充」时用自定义类型。


参考文档