Go接口通过结构体隐式满足,只需类型提供全部方法签名;接口仅声明方法(无实现、字段或构造函数),空接口interface{}可接收任意类型;实现时需注意接收者类型匹配及导出性。

Go 语言的接口不是用来“实现”的,而是通过结构体隐式满足——只要类型提供了接口声明的所有方法签名,就自动实现了该接口。
接口定义:只声明方法签名,不带实现
接口是方法签名的集合,用 type ... interface 定义。它不关心谁实现、怎么实现,只约定“能做什么”。
- 方法签名必须包含名称、参数列表(含类型)、返回值列表(含类型),不写函数体
- 接口中不能有字段、不能有构造函数、不能嵌套实现逻辑
- 空接口
interface{}表示可接收任意类型,底层对应reflect.Type和reflect.Value - 接口名推荐用单个名词或能表达能力的词,如
Reader、Stringer、Writer
例如:
type Speaker interface {
Speak() string
Volume() int
}
结构体如何“实现”接口:无需显式声明,靠方法集匹配
Go 中没有 implements 关键字。只要某个类型(通常是结构体指针或值)拥有接口要求的全部方法,且签名完全一致(包括参数名可不同,但类型和顺序必须相同),就视为实现了该接口。
立即学习“go语言免费学习笔记(深入)”;
- 注意接收者类型:若接口方法定义在
*T上,则只有*T满足;若定义在T上,则T和*T都满足(因为 Go 自动解引用) - 常见错误:给值类型定义了指针接收者方法,却试图用值变量赋值给接口 → 编译报错
cannot use ... (type T) as type X in assignment: T does not implement X (X method has pointer receiver) - 导出性很重要:接口方法名必须首字母大写,否则包外不可见;结构体字段也需导出,才能被外部包调用其方法
例如:
type Dog struct{ Name string }
func (d Dog) Speak() string { return "Woof!" }
func (d *Dog) Volume() int { return 80 } // 注意这是指针接收者
var d Dog
var s Speaker = d // ❌ 编译失败:Dog 值类型不满足 Speaker(Volume 要求 *Dog)
var s2 Speaker = &d // ✅ 正确
接口变量的使用:多态与运行时分发
接口变量存储两个信息:动态类型(具体值的类型)和动态值(具体值或指针)。调用方法时,Go 在运行时查表调度到对应类型的实现。
- 接口变量可以为
nil,但其底层动态值为nil时,调用方法会 panic(除非方法本身允许 nil 接收者) - 判断接口是否为空,应同时检查
== nil;仅判断动态值是否为 nil 不够(比如*int类型的接口变量,其值可能是(*int)(nil)) - 类型断言
v, ok := iface.(ConcreteType)是安全取值方式;强制转换v := iface.(ConcreteType)在失败时 panic - 用
switch v := iface.(type)可做多类型分支处理
容易忽略的细节:方法集、nil 接口与性能开销
接口不是零成本抽象。每次赋值、调用都会带来间接跳转和内存布局开销(两个 word:type + data)。高频路径慎用接口封装。










