type alias(type T = U)不创建新类型,与原类型完全等价,无独立方法集,不可定义新方法;type definition(type T U)创建全新类型,方法集为空且独立,需显式实现。

type alias 完全不继承方法集,它只是换个名字
你写 type Res = http.ResponseWriter,Res 就不是新类型,而是和 http.ResponseWriter 一模一样的类型——包括方法集、底层结构、可赋值性。它没有“继承”这个动作,因为压根没创建新类型。所以别指望给 alias 加方法:func (r Res) Write(...) 编译直接报错:cannot define new methods on non-local type。
常见错误现象:cannot define method on type alias 或者误以为 type Res = []string 能复用 []string 的所有操作(其实能,但不是“继承”,是它本来就是同一类型)。
-
type Res = http.ResponseWriter→ 可以直接传给任何接受http.ResponseWriter的函数,无需转换 -
type Res = []string→Res{"a"}.Len()会失败,因为[]string本身就没有Len()方法;但len(Res{"a"})没问题,因为len是内置函数,不依赖方法集 - alias 不能加方法,也不能嵌入,更不能实现接口(除非原类型本来就实现)
自定义类型(type T U)的方法集完全独立
你写 type Res http.ResponseWriter(无等号),Go 就创建了一个新类型 Res,它和 http.ResponseWriter 不兼容——哪怕 http.ResponseWriter 是接口、字段完全一致,也必须显式转换:Res(w)。它的方法集初始为空,你得自己定义全部方法。
关键点在于:这个“空方法集”不是 bug,是设计。比如 type MyInt int,即使 int 有所有算术能力,MyInt 也不自动带 +、== 等操作符(这些不是方法),更不会自动获得任何你为 int 定义的扩展方法。
- 如果原类型是接口(如
http.ResponseWriter),新类型默认不实现该接口——除非你显式为新类型实现全部接口方法,或让新类型值能隐式满足(例如type Res http.ResponseWriter+ 所有实现http.ResponseWriter的具体值仍可赋给Res变量,但仅限于接口场景) - 如果原类型是 struct(如
type Res response.Response),那Res{}和response.Response{}字段再像也不能互换,必须Res(r) - 你可以为
type Res http.ResponseWriter单独定义Write、Header等方法,这些方法只属于Res,不影响原接口
想“复用方法”?得靠嵌入(embedding),不是 alias 或 type definition
真正能复用已有类型行为的方式,是结构体嵌入:type ResourceSet struct { Set }。这时 ResourceSet 的方法集会包含 Set 的所有导出方法(前提是接收者类型匹配)。这不是继承,是编译器自动提升(promotion)。
注意:嵌入只对 struct 有效;interface 不能嵌入;alias 和 type definition 都不支持嵌入语法。
- 嵌入
Set后,ResourceSet{}.AddId(1)可行,但前提是AddId是Set的导出方法,且接收者是值或指针(*ResourceSet调用指针接收者方法没问题) -
type Res = Set或type Res Set都无法触发方法提升——前者是同一类型,后者是全新类型,都不涉及字段结构 - 嵌入字段名若省略(匿名字段),才触发提升;写成
set Set就只是普通字段,方法不会自动暴露
容易被忽略的坑:接口 vs struct 场景下表现完全不同
很多人栽在 type Res http.ResponseWriter 能用,就以为 type Res response.Response 也能用——其实前者能用,是因为 http.ResponseWriter 是接口,Go 允许任何满足该接口的值赋给 Res 变量;后者是 struct,Go 严格按类型名判别,字段一样也不行。
最典型的报错:cannot use w (type http.ResponseWriter) as type Res in argument to handler,说明你写了 type Res response.Response 却试图传入 *http.response(一个 struct 实现),而 Go 认为这俩八竿子打不着。
- 接口类型做 type definition:可能“看起来能用”,实则是接口实现机制在起作用,不是类型兼容
- struct 类型做 type definition:零容忍,必须显式转换,哪怕
unsafe.Sizeof结果相同 - alias(
=语法)在两种场景下都严格保持等价性,但代价是彻底放弃封装和方法扩展能力











