Go接口是隐式实现的纯抽象类型,只声明方法签名不关心实现;只要类型方法集完全匹配接口要求(含名称、参数和返回类型),即自动实现,无需implements声明。

Go 接口不是“要实现它”,而是“只要方法签名对得上,它就自动算实现了”——这是理解 Golang 接口最核心的一句话。
接口定义:只写方法签名,不写实现,也不写变量
接口是纯抽象的类型,只声明「能做什么」,不关心「怎么做」或「是谁在做」。定义时用 type + interface 关键字,大括号里只列方法签名,参数名可省略(但类型和返回值必须严格匹配):
type Speaker interface {
Speak() string
}
type Shape interface {
Area() float64
Perimeter() float64
}
注意:Shape 接口里不能加字段(比如 name string),也不能有方法体;否则编译直接报错。
隐式实现:不写 implements,不声明,靠方法集自动匹配
这是 Go 和 Java/PHP 最根本的区别。你不需要、也不能写 func (p Person) implements Speaker 这类语句。只要某个类型(比如 Person 或 Dog)的**方法集**中,包含接口要求的所有方法(名称、参数类型、返回类型完全一致),就自动视为实现了该接口。
立即学习“go语言免费学习笔记(深入)”;
-
func (p Person) Speak() string✅ 匹配Speaker.Speak() -
func (p *Person) Speak() string✅ 也匹配(指针接收者也算该类型的方法集) -
func (p Person) speak() string❌ 首字母小写 → 不是导出方法 → 外部不可见 → 不参与接口匹配 -
func (p Person) Speak() int❌ 返回类型不一致 → 不匹配
空接口 interface{} 是万能容器,但要用类型断言还原
interface{} 是所有类型的超集,可以存任意值:
var x interface{} = 42
x = "hello"
x = []int{1, 2, 3}
但它本身不提供任何方法,想用具体类型的功能,必须用类型断言还原:
-
s := x.(string)—— 直接断言,失败 panic -
v, ok := x.(int)—— 安全断言,ok为false时不 panic,推荐用于不确定类型时
别忘了:nil 值赋给接口后,接口变量本身不等于 nil(如果底层是 *T 且指针为 nil),这是最容易踩的坑之一。
接口组合:用嵌套复用已有行为契约
接口支持组合,本质是“方法签名合并”。比如:
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }
type ReadWriter interface {
Reader
Writer
}
等价于手动写出 Read 和 Write 两个方法。组合让接口更正交、更易复用,但要注意:组合不是继承,没有父子关系,也没有方法重写概念。
真正难的从来不是怎么写接口,而是判断一个类型是否“真的实现了”某个接口——尤其当方法接收者是值类型还是指针类型、是否导出、是否带 error 参数时,稍不注意就会在运行时报 cannot use ... as ... value in argument to ...: wrong type for method ... 这类错误。










